Compare commits

...

14 Commits

Author SHA1 Message Date
xuedongliang 49b20dfa6a Fix compilation errors for imxrt1176 from wuzheng
it is OK
2024-10-10 18:08:24 +08:00
xuedongliang 0fdf4f2ace AdapterLoraTest() is used to run a testcase for Lora, but it failed to work due to creating a thread with a wrong function, and this pull request fixed it
it is OK
2024-10-10 18:06:19 +08:00
xuedongliang 1c0edba5bd Support Inovance H3U-3232MT Modbus TCP connection
it is OK
2024-10-10 18:05:53 +08:00
WuZheng 22b980cc08 fix compliation errors for imxrt1176. 2024-09-26 06:35:27 +00:00
chen_zhengning 64b2117012 fix a bug that made `AdapterLoraTest` cannot work correctly. 2024-09-14 15:41:46 +08:00
TLBF 16a31c6739 feat(APP_Framework/control_app): Inovance H3U-3232MT Modbus TCP App. 2024-08-06 10:33:47 +08:00
xuedongliang d664e2298e Koyo PLC ModBus TCP Master Mode from Liu_yongkai
it is OK
2024-07-29 11:12:16 +08:00
xuedongliang 02c82025c8 support amp
it is OK
2024-07-29 11:11:32 +08:00
xuedongliang dbaffab140 Support O2 optimization; Support blocking task; Support better KPrintf from Tu_yuyang
it is OK
2024-07-29 11:10:51 +08:00
TLBF 1e59fd2a8d feat(Applications/control_app): add Koyo NK1CPU40 PLC ModBus TCP Master and test result png 2024-07-05 16:45:11 +08:00
树数在变干 2e11a31da3 support amp 2024-05-22 17:37:23 +08:00
树数在变干 446c3746a6 update stack size and heap size 2024-05-22 15:10:22 +08:00
xuedongliang bcd9835020 Support smp for softkernel. Support userland interrupt handler by using ipc. Assure that interrupt is close in kernel and one thread kernel state. Support userland dynamic memory allocation. Move elf image reader to usyscall level. Support blocking task in ipc procedure. Split free physical memory to kernel usage and userland usage. Support killing a other task, but will only freeing a task while it’s not in running state from Tuyuyang
it is OK
2024-04-29 14:12:06 +08:00
anguoyoula 293fd9fea9 update heap size 2024-03-12 16:28:50 +08:00
70 changed files with 4419 additions and 11 deletions

View File

@ -1,3 +1,3 @@
SRC_DIR := advantech beckhoff br delta mitsubishi omron schneider siemens ge xinje inovance keyence panasonic fatek ab abb
SRC_DIR := advantech beckhoff br delta mitsubishi omron schneider siemens ge xinje inovance keyence panasonic fatek ab abb koyo
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,3 +1,3 @@
SRC_FILES := inovance_am401_cpu1608tn_ethernet.c inovance_am401_cpu1608tn_uart.c
SRC_FILES := inovance_am401_cpu1608tn_ethernet.c inovance_am401_cpu1608tn_uart.c inovance_H3U_cpu3232MT_ethernet.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2024 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file inovance_H3U_cpu3232MT_ethernet.c
* @brief PLC Inovance H3U-3232MT app
* @version 3.0
* @author AIIT XUOS Lab
* @date 2024.08.06
*/
#include <control.h>
void ControlInovanceH3UCPU3232MTTest(void)
{
int i, j = 0;
int read_data_length = 0;
uint8_t read_data[128] = {0};
ControlProtocolType modbus_tcp_protocol = ControlProtocolFind();
if (NULL == modbus_tcp_protocol) {
printf("%s get modbus tcp protocol %p failed\n", __func__, modbus_tcp_protocol);
return;
}
printf("%s get modbus tcp protocol %p successfull\n", __func__, modbus_tcp_protocol);
if (CONTROL_REGISTERED == modbus_tcp_protocol->protocol_status) {
ControlProtocolOpen(modbus_tcp_protocol);
for (;;) {
read_data_length = ControlProtocolRead(modbus_tcp_protocol, read_data, sizeof(read_data));
printf("%s read [%d] modbus tcp data %d using receipe file\n", __func__, i, read_data_length);
if (read_data_length) {
for (j = 0; j < read_data_length; j++) {
printf("j %d data 0x%x\n", j, read_data[j]);
}
}
i++;
memset(read_data, 0, sizeof(read_data));
PrivTaskDelay(10000);
}
// ControlProtocolClose(modbus_tcp_protocol);
}
}
PRIV_SHELL_CMD_FUNCTION(ControlInovanceH3UCPU3232MTTest, Inovance PLC N3UCPU3232MT Demo, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -0,0 +1,30 @@
{
"device_id": 1,
"device_name": "Ino_H3U3232MT",
"communication_type": 0,
"socket_config": {
"plc_ip": "192.168.250.55",
"local_ip": "192.168.250.147",
"gateway": "192.168.250.252",
"netmask": "255.255.255.0",
"port": 502
},
"protocol_type": 2,
"read_period": 300,
"read_item_list": [
{
"value_name": "M8000",
"value_type": 1,
"function_code": 1,
"start_address": 8000,
"quantity": 1
},
{
"value_name": "D120",
"value_type": 3,
"function_code": 3,
"start_address": 120,
"quantity": 1
}
]
}

View File

@ -0,0 +1,3 @@
SRC_FILES := koyo_nk1cpu40.c
include $(KERNEL_ROOT)/compiler.mk

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2024 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file koyo_nk1cpu40.c
* @brief PLC AB MICRO850 app
* @version 3.0
* @author AIIT XUOS Lab
* @date 2024.07.03
*/
#include <control.h>
void ControlKoyoNK1CPU40Test(void)
{
int i, j = 0;
int read_data_length = 0;
uint8_t read_data[128] = {0};
ControlProtocolType modbus_tcp_protocol = ControlProtocolFind();
if (NULL == modbus_tcp_protocol) {
printf("%s get modbus tcp protocol %p failed\n", __func__, modbus_tcp_protocol);
return;
}
printf("%s get modbus tcp protocol %p successfull\n", __func__, modbus_tcp_protocol);
if (CONTROL_REGISTERED == modbus_tcp_protocol->protocol_status) {
ControlProtocolOpen(modbus_tcp_protocol);
for (;;) {
read_data_length = ControlProtocolRead(modbus_tcp_protocol, read_data, sizeof(read_data));
printf("%s read [%d] modbus tcp data %d using receipe file\n", __func__, i, read_data_length);
if (read_data_length) {
for (j = 0; j < read_data_length; j++) {
printf("j %d data 0x%x\n", j, read_data[j]);
}
}
i++;
memset(read_data, 0, sizeof(read_data));
PrivTaskDelay(10000);
}
// ControlProtocolClose(modbus_tcp_protocol);
}
}
PRIV_SHELL_CMD_FUNCTION(ControlKoyoNK1CPU40Test, Koyo Plc NK1CPU40 Demo, PRIV_SHELL_CMD_MAIN_ATTR);

View File

@ -977,7 +977,7 @@ int AdapterLoraTest(void)
char task_name_2[] = "adapter_lora_gateway";
args.pthread_name = task_name_2;
args.arg = (void *)adapter;
PrivTaskCreate(&lora_recv_data_task, &lora_gateway_attr, &LoraReceiveTask, (void *)&args);
PrivTaskCreate(&lora_gateway_task, &lora_gateway_attr, &LoraGatewayTask, (void *)&args);
#endif
PrivTaskStartup(&lora_gateway_task);

View File

@ -2,6 +2,10 @@ ifeq ($(CONFIG_BOARD_CORTEX_M7_EVB),y)
SRC_FILES := boot.S interrupt.c interrupt_vector.S
endif
ifeq ($(CONFIG_BOARD_IMXRT1176_SBC_EVB),y)
SRC_FILES := boot.S interrupt.c interrupt_vector.S
endif
ifeq ($(CONFIG_BOARD_CORTEX_V2M_EVB),y)
SRC_DIR += V2M
endif

View File

@ -231,6 +231,19 @@ void ethernetif_input(void *netif_arg)
}
}
/**
* This function should be called when a packet is ready to be read
* from the interface. It uses the function ethernetif_linkinput() that
* should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
void ethernetif_input2(void *netif_arg){
ethernetif_input(netif_arg);
}
void *ethernetif_get_enet_base(const uint8_t enetIdx)
{
ENET_Type *enets[] = ENET_BASE_PTRS;

View File

@ -160,6 +160,7 @@ err_t ethernetif1_init(struct netif *netif);
* @param netif the lwip network interface structure for this ethernetif
*/
void ethernetif_input( void *netif_arg);
void ethernetif_input2( void *netif_arg);
int ETH_BSP_Config(void);
void *ethernetif_config_enet_set(uint8_t enet_port);

View File

@ -1,5 +1,5 @@
SRC_FILES := $(wildcard *.c)
SRC_DIR := rzg rzg_gen src
SRC_DIR := rzg rzg_gen src amp
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the kernel character device drivers.
#
# obj-y += src/config.o
# obj-y += src/ipi_arm_mhu.o
# obj-y += src/msg_queue.o
SRC_DIR := src test_xiuos
SRC_FILES := $(wildcard *.c)
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __AMP_H__
#define __AMP_H__
#include "config/config.h"
#include "channel.h"
#include "client.h"
#include "msg.h"
#include "msgqueue.h"
#include "service.h"
#include "service/service_linux.h"
#include "service/service_xiuos.h"
#include "shm.h"
#include "spinlock.h"
#endif /* __AMP_H__ */

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "config/config.h"
#include "msgqueue.h"
#ifndef __AMP_CHANNEL_H__
#define __AMP_CHANNEL_H__
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
struct Channel /* 核间通道结构:应用层结构 */
{
struct ChannelInfo* channel_info; /* 通道配置信息 */
struct AmpMsgQueue* msg_queue; /* 发往远程核心的消息队列 */
struct MsgQueueMutex* msg_queue_mutex; /* 消息队列互斥体 */
uint32_t *reg_msg; /* 该地址写1触发核间消息通知 */
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER
void* msg_queue_mutex_start; /* 内核中的消息队列互斥体群 */
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER */
};
struct ChannelOps
{
/* 初始化所有的通道信息 */
int32_t (*channels_init)(void);
/* 检查指定通道是否已经可以使用 */
int32_t (*channel_is_ready)(struct Channel* channel);
/* 获取发往目标核心的通道 */
struct Channel* (*target_channel_get)(uint32_t target_core_id);
/* 向指定通道发送核间消息通知 */
int32_t (*channel_notify)(struct Channel* channel);
/* 从通道中获取一个空闲消息缓冲区 */
struct Msg* (*empty_msg_get)(struct Channel* channel);
/* 将一个不再使用的缓冲区归还到通道 */
int32_t (*empty_msg_put)(struct Channel* channel,struct Msg* msg);
/* 将一个填充过的消息缓冲区放入待处理消息队列 */
int32_t (*msg_send)(struct Channel* channel,struct Msg* msg);
/* 将一个填充过的消息缓冲区放入待处理消息队列并直接通知 */
int32_t (*msg_send_and_notify)(struct Channel* channel,struct Msg* msg);
};
extern struct ChannelOps channel_ops;
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
#endif /* __AMP_CHANNEL_H__ */

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "shm.h"
#include "channel.h"
#include "msg.h"
#ifndef __AMP_CLIENT_H__
#define __AMP_CLIENT_H__
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
/* 核间通信交互客户端 */
struct Client
{
uint32_t init_mark; /* 初始化标记 */
struct Channel* remote_channel; /* 当前客户端是与那个核心的连接通道在通信 */
uint32_t msg_cnt; /* 当前客户端申请了几个消息缓冲区 */
uint32_t shm_cnt; /* 当前客户端申请了几块内存 */
};
struct ClientOps
{
/* 初始化客户端 */
int32_t (*client_init)(struct Client* raw_client,uint32_t remote_core_id);
/* 销毁客户端 */
int32_t (*client_destory)(struct Client* client);
/* 获取一个空闲的消息缓冲区 */
struct Msg* (*empty_msg_get)(struct Client* client, uint32_t remote_service_id);
/* 归还空闲消息缓冲区:归任务管理的缓冲区才需要手动归还 */
int32_t (*empty_msg_put)(struct Client* client, struct Msg* empty_msg);
/* 将消息放入待处理消息队列*/
int32_t (*msg_send)(struct Client* client, struct Msg* full_msg);
/* 将消息放入待处理消息队列,并通知远程核心立即进行处理 */
int32_t (*msg_send_and_notify)(struct Client* client, struct Msg* full_msg);
/* 通知远程核心处理待处理消息队列 */
int32_t (*msg_notify)(struct Client* client);
/* 查看指定消息是否已经被处理过了 */
int32_t (*msg_poll)(struct Msg* aim_msg);
#if PROTOCOL_CHOICE == PROTOCOL_AMP
/* 从共享内存中分配内存,可以分配长期内存和短期内存 */
void* (*shm_malloc)(struct Client* client, uint32_t size,enum MallocType type);
/* 释放短期共享内存 */
void (*shm_free)(struct Client* client, void* ptr);
/* 地址转偏移量 */
uint32_t (*shm_addr_to_offset)(void* ptr);
/* 偏移量转地址 */
void* (*shm_offset_to_addr)(uint32_t offset);
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
};
extern struct ClientOps client_ops;
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_XIUOS */
#endif /* __AMP_CLIENT_H__ */

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "types_cfg.h"
#ifndef __AMP_ADDR_CFG_H__
#define __AMP_ADDR_CFG_H__
/* 特定核心地址空间下的内存块地址信息,范围为:[start, start + len) */
struct AddrInfo
{
uint64_t start; /* 内存块起始地址兼容32/64位 */
uint32_t len; /* 内存块长度 */
};
/* 所有核间通信可能会用到的内存块地址信息 */
extern struct AddrInfo addr_infos[];
/* 为方便配置而起的别名 */
#define LINUX_SHM_TOTAL_ADDR_INFO (&addr_infos[0])
#define LINUX_SHM_USED_ADDR_INFO (&addr_infos[1])
#define XIUOS_SHM_TOTAL_ADDR_INFO (&addr_infos[2])
#define XIUOS_SHM_USED_ADDR_INFO (&addr_infos[3])
#define LINUX_2_LINUX_MSG_QUEUE_ADDR_INFO (&addr_infos[4])
#define LINUX_2_XIUOS_MSG_QUEUE_ADDR_INFO (&addr_infos[5])
#define XIUOS_2_LINUX_MSG_QUEUE_ADDR_INFO (&addr_infos[6])
#define XIUOS_2_XIUOS_MSG_QUEUE_ADDR_INFO (&addr_infos[7])
#endif /* __AMP_ADDR_CFG_H__ */

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "addr_cfg.h"
#include "types_cfg.h"
#include "core_cfg.h"
#ifndef __AMP_CHANNEL_CFG_H__
#define __AMP_CHANNEL_CFG_H__
#if PLATFORM_CHOICE / PLATFORM_LINUX_BASE == 1 /* Linux平台 */
#define IOCTL_CMD_NOTIFY (0xAU) /* Linux用户程序向IPI驱动传递触发核间中断的命令 */
#endif /* PLATFORM_CHOICE / 10 == 1 */
/**
*
* :
*/
struct ChannelInfo
{
uint32_t channel_num; /* 通道编号 */
uint32_t irq_msg; /* 通道接受消息中断:中断号或者设备树中中断下标,由通道接收方负责实现 */
uint32_t irq_rsp; /* 通道响应消息中断:中断号或者设备树中中断下标,由通道发送方负责实现 */
uint64_t reg_msg; /* 该通道消息发送的触发寄存器地址 */
struct CoreInfo* src_core; /* 通道发送核心 */
struct CoreInfo* dst_core; /* 通道接收核心 */
struct AddrInfo* src_queue; /* 位于发送端地址空间:发送端向该消息队列发送信息,接收端从这个消息队列里面接收并处理信息,由接收端负责初始化 */
struct AddrInfo* dst_queue; /* 位于接收端地址空间:接收端从该消息队列获取消息,由接收端负责初始化 */
};
/* 所有的核间通信通道信息,每个通道都存在一个发送端和接收端,同时,每个核心既可以是发送端也可以是接收端*/
extern struct ChannelInfo channel_infos[];
/* 为方便配置而起的别名 */
#define LINUX_2_XIUOS_CHANNEL_INFO (&channel_infos[0])
#define XIUOS_2_LINUX_CHANNEL_INFO (&channel_infos[1])
#endif /* __AMP_CHANNEL_CFG_H__ */

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __AMP_COMMON_CFG_H__
#define __AMP_COMMON_CFG_H__
#define MAX_NAME_LENGTH (20U) /* 框架内可能存在的命名允许的最大长度 */
/* 内存大小单位相关宏定义 */
#define B (1U)
#define KB ((B) << 10)
#define MB ((KB) << 10)
#define GB ((MB) << 10)
#define MEMORY_ALIGN_SIZE (4U) /* 结构体字节对齐配置防止32/64位机器之间数据大小不一致 */
/* 初始化相关标记 */
#define INIT_MARK_INITIALIZED (0xFFFFFFFFU) /* 已正确初始化 */
#define INIT_MARK_RAW_STATE (0x00000000U) /* 未被初始化 */
#define INIT_MARK_INITIALIZING (0xAAAAAAAAU) /* 正在初始化 */
#define INIT_MARK_DESTORYED (0xDDDDDDDDU) /* 初始化失败 */
#endif /* __AMP_COMMON_CFG_H__ */

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "addr_cfg.h"
#include "channel_cfg.h"
#include "common_cfg.h"
#include "core_cfg.h"
#include "debug_cfg.h"
#include "ipi_cfg.h"
#include "msg_cfg.h"
#include "msgqueue_cfg.h"
#include "platform_cfg.h"
#include "shm_cfg.h"
#include "types_cfg.h"
#ifndef __CONFIG_H__
#define __CONFIG_H__
#endif /* __CONFIG_H__ */

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "common_cfg.h"
#include "types_cfg.h"
#ifndef __AMP_CORE_CFG_H__
#define __AMP_CORE_CFG_H__
#define CORE_NONE_ID (0U) /* 不存在的空节点 */
#define CORE_NONE_NAME "None"
#define CORE_LINUX_ID (10U) /* Linux 节点 */
#define CORE_LINUX_NAME "Linux"
#define CORE_XIUOS_ID (20U) /* XiUOS 节点 */
#define CORE_XIUOS_NAME "XiUOS"
/* 参与核间通信的核心信息,只要参与了,就需要说明 */
struct CoreInfo
{
uint32_t id; /* 节点ID */
char name[MAX_NAME_LENGTH]; /* 节点名字 */
};
/* 当前运行节点的节点信息:该信息随着允许平台的选择而变化 */
extern struct CoreInfo* core_info;
/* 所有支持核间通信的节点信息 */
extern struct CoreInfo core_infos[];
/* 为方便配置而起的别名 */
#define LINUX_CORE_INFO (&core_infos[0])
#define XIUOS_CORE_INFO (&core_infos[1])
#endif /* __AMP_CORE_CFG_H__ */

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "platform_cfg.h"
#ifndef __AMP_DEBUG_CFG_H__
#define __AMP_DEBUG_CFG_H__
/* 调试输出信息开关 */
#define DEBUG_ENABLE (1U)
#define DEBUG_DISABLE (0U)
#define DEBUG_CHOICE (DEBUG_DISABLE)
/* 错误输出接口:必输出,平台相关 */
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL
#include <linux/kernel.h>
#define INFOS(format, ...) (printk(format, ##__VA_ARGS__))
#elif PLATFORM_CHOICE == PLATFORM_LINUX_USER
#include <stdio.h>
#define INFOS(format, ...) (printf(format, ##__VA_ARGS__))
#elif PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
#include <xizi.h>
#define INFOS(format, ...) (KPrintf(format, ##__VA_ARGS__))
#else
#error please configure the standard output functions of this platform for error infos
#endif
/* 调试输出接口:受调试输出信息开关影响 */
#if DEBUG_CHOICE == DEBUG_ENABLE
#define LOGINFO(format, ...) (INFOS(format, ##__VA_ARGS__))
#else
#define LOGINFO(format, ...) { }
#endif
#endif /* __AMP_DEBUG_CFG_H__ */

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "platform_cfg.h"
#ifndef __AMP_IPI_CFG_H__
#define __AMP_IPI_CFG_H__
/* 核间中断硬件选择:硬件不一样需要的驱动不一样 */
#define IPI_MHU (1U) /* 使用MHU进行核间中断 */
#define IPI_IPCC (2U) /* 使用IPCC进行核间中断 */
#define IPI_CHOICE (IPI_MHU) /* 核间中断硬件选择 */
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER
#define IPI_DRIVER_NAME ("/dev/amp_ipi_dev") /* 驱动名称 */
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER */
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL
#define IPI_DEV_NAME ("amp_ipi_dev") /* 设备名称 */
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL */
#endif /* __AMP_IPI_CFG_H__ */

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __AMP_MSG_CFG_H__
#define __AMP_MSG_CFG_H__
/**
* 使
* 使
* 使
*/
#define PROTOCOL_AMP (100U)
/**
*
*/
#define PROTOCOL_PRIVATE (200U)
#define PROTOCOL_CHOICE (PROTOCOL_AMP) /* 消息协议选择 */
#if PROTOCOL_CHOICE == PROTOCOL_PRIVATE
/* 使用数据嵌入消息队列协议时允许用户嵌入的最大消息数量(字节) */
#define MSG_PAYLOAD_SIZE (256U)
#endif /* PROTOCOL_CHOICE == PROTOCOL_PRIVATE */
#endif /* __AMP_MSG_CFG_H__ */

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __AMP_MSG_QUEUE_CFG_H__
#define __AMP_MSG_QUEUE_CFG_H__
#define MSG_QUEUE_MUTEX_SIZE (128U) /* 位于内核中的消息队列互斥区域将按照这个大小进行划分 */
#define MSG_QUEUE_MARK_BUSY (0xFFFFFFFFU) /* 负责处理该消息队列的核心正在处理16位 */
#define MSG_QUEUE_MARK_IDLE (0xAAAAAAAAU) /* 负责处理该消息队列的核心正在闲置16位 */
#define MSG_QUEUE_MAX_ENTRY_CNT (0xFFFFU) /* 消息队列中能够管理的最大消息数量uint16_t */
#endif /* __AMP_MSG_QUEUE_CFG_H__ */

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __AMP_PLATFORM_CFG_H__
#define __AMP_PLATFORM_CFG_H__
#define PLATFORM_NONE_BASE (000U) /* 运行在裸机环境 */
#define PLATFORM_LINUX_BASE (100U) /* 运行在Linux节点 */
#define PLATFORM_LINUX_KERNEL (101U) /* 运行在Linux内核空间 */
#define PLATFORM_LINUX_USER (102U) /* 运行在Linux用户空间内核空间和用户空间存在区别但是Linux都是10开头 */
#define PLATFORM_RTOS_BASE (200U) /* 运行在RTOS环境 */
#define PLATFORM_RTOS_XIUOS (201U) /* 运行在XIUOS环境 */
#define PLATFORM_CHOICE (PLATFORM_RTOS_XIUOS) /* 运行环境选择 */
#if PLATFORM_CHOICE / PLATFORM_LINUX_BASE == 1 /* Linux平台 */
#define MEM_PAGE_SIZE (4096U) /* Linux 内存页的大小,在内核中申请内存时使用该大小,方便将其映射到用户空间 */
#endif /* PLATFORM_CHOICE / PLATFORM_LINUX_BASE == 1 */
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER
#define MEM_DRIVER ("/dev/mem") /* 内存全映射驱动名称,用于 mmap几乎所有的Linux系统都有该驱动 */
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER */
#endif /* __AMP_PLATFORM_CFG_H__ */

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "core_cfg.h"
#include "addr_cfg.h"
#include "types_cfg.h"
#include "platform_cfg.h"
#ifndef __AMP_SHM_CFG_H__
#define __AMP_SHM_CFG_H__
#if PROTOCOL_CHOICE == PROTOCOL_AMP /* 需要AMP协议 */
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL /* Linux平台 */
#define SHM_DEV_NAME ("amp_shm_dev") /* 设备名称 */
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL */
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER
#define SHM_DRIVER_NAME ("/dev/amp_shm_dev") /* 驱动名称 */
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER */
/* 短期块数量会影响到共享内存的使用效率,需要酌情考虑 */
#define SHM_VBLOCK_CNT (8U)
/* 共享内存配置信息:配置的时候保证字节对齐 */
struct ShmCfg
{
struct CoreInfo *core; /* 那个核心的共享内存配置 */
struct AddrInfo *total_shm; /* 全部共享内存的地址空间:用于偏移量计算 */
struct AddrInfo *core_shm; /* 属于本节点的共享内存地址空间:用于内存分配 */
uint32_t pblock_size; /* 长期区块总大小 */
uint32_t vblock_size; /* 短期区块总大小 */
uint32_t min_block_size; /* 最小区块大小,如果配置的块太多每个块小于该值时初始化失败 */
uint32_t bit_align; /* 该共享内存分配时的字节对齐配置: 2 4 8 16 ... 2^n*/
};
/* 所有配置有共享内存的核心配置信息(不是所有的核间通信核心都配置有共享内存) */
extern struct ShmCfg shm_cfgs[];
struct ShmCfgOps /* 共享内存配置信息操作集合 */
{
/* 通过核心ID获取核心的配置信息 */
struct ShmCfg* (*get_by_id)(uint16_t target_id);
};
extern struct ShmCfgOps shm_cfg_ops;
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
#endif /* __AMP_SHM_CFG_H__ */

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "platform_cfg.h"
#ifndef __AMP_TYPES_CFG_H__
#define __AMP_TYPES_CFG_H__
/* 保证允许在各个环境下的代码看到的数据结构大小一致编译链工具使用GCC */
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL
#include <linux/types.h>
#elif PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
#include <stdint.h>
#else
#error please configure std types header files
#endif
#endif /* __AMP_TYPES_CFG_H__ */

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "config/config.h"
#ifndef __AMP_MSG_H__
#define __AMP_MSG_H__
enum MsgDealState /* 消息是否被处理 */
{
MSG_DEAL_STATE_NO = 0, /* 未被处理 */
MSG_DEAL_STATE_YES = 1 /* 已被处理 */
};
enum MsgServiceResult /* 消息是否被正确处理 */
{
MSG_SERVICE_RET_NONE = 0, /* 消息还未被处理 */
MSG_SERVICE_RET_SUCCESS = 1, /* 服务正确响应 */
MSG_SERVICE_RET_FAIL = 2, /* 服务未曾正确服务,或参数错误等 */
MSG_SERVICE_RET_NOT_EXITS = 3 /* 请求的服务不存在 */
};
struct Msg
{
/* 消息标记:用于标记消息状态信息,共 16 位可使用位域进行扩展 */
struct MsgFlag
{
uint16_t deal_state : 1; /* 消息是否被处理 */
uint16_t service_result : 2; /* 消息对应的服务是否被正确服务 */
} flag;
uint16_t service_id; /* 请求的服务端服务ID */
#if PROTOCOL_CHOICE == PROTOCOL_AMP /* AMP协议 */
uint32_t offset; /* 共享内存起始偏移量 */
uint32_t length; /* 共享内存长度 */
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
#if PROTOCOL_CHOICE == PROTOCOL_PRIVATE /* 私有协议 */
uint32_t data_size; /* 本条消息携带的数据量 */
uint8_t data[MSG_PAYLOAD_SIZE]; /* 数据本身:配置消息大小时最好四字节对齐 */
#endif /* PROTOCOL_CHOICE == PROTOCOL_PRIVATE */
}__attribute__((aligned(MEMORY_ALIGN_SIZE)));
/* 消息支持的操作 */
struct MsgOps
{
/* 将消息中的相关信息清除,重置 */
void (*msg_reset)(struct Msg *msg);
/* 查看消息是否已经被处理了 */
int32_t (*msg_is_dealt)(struct Msg *msg);
};
extern struct MsgOps msg_ops;
#endif /* __AMP_COM_MSG_H__ */

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "config/config.h"
#include "msg.h"
#include "spinlock.h"
#ifndef __AMP_MSG_QUEUE_H__
#define __AMP_MSG_QUEUE_H__
/**
* Msg
* 使
*/
struct MsgEntry
{
struct Msg msg; /* 消息实体:必须放在第一个位置,相当于继承于 Msg */
uint16_t cur_idx; /* 消息实体在消息队列里面的下标 */
uint16_t nxt_idx; /* 消息实体所在消息队列的下一个消息实体的下标 */
}__attribute__((aligned(MEMORY_ALIGN_SIZE)));
/**
*
* Linux中
*/
struct AmpMsgQueue
{
volatile uint32_t working_mark; /* 标记该消息队列的接收者是否准备完毕 */
uint16_t buf_size; /* 缓冲区队列的缓冲区数量,必须大于 0 才算初始化成功,初始状态为 0 */
volatile uint16_t empty_h; /* 空闲缓冲区链头下标 */
volatile uint16_t wait_h; /* 待处理缓冲区链头下标 */
volatile uint16_t proc_ing_h; /* 服务端正在处理的缓冲区链头下标 */
struct MsgEntry entries[0]; /* 实际存放的消息 */
}__attribute__((aligned(MEMORY_ALIGN_SIZE)));
struct MsgQueueMutex /* 消息队列互斥结构:内核与用户空间共享该数据结构 */
{
/* 初始化标记需要由用户层进行初始化Linux内核无法进行初始化 */
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
atomic_char32_t mutex_init_mark;
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL
volatile uint32_t mutex_init_mark; /* 内核占位 */
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL */
/**
*
* MSG_QUEUE_MARK_BUSY
* MSG_QUEUE_MARK_IDLE
*/
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
atomic_char32_t msg_queue_mark;
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL
volatile uint32_t msg_queue_mark; /* 响应后修改 */
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL */
/**
*
*
*/
volatile uint16_t msg_wait_cnt;
/* 用户空间特有的互斥结构体 */
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
ByteFlag empty_lock; /* 空闲队列锁 */
ByteFlag wait_lock; /* 等待队列锁 */
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
};
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
struct MsgQueueMutexOps
{
/* 互斥体初始化 */
int32_t (*mutex_init)(struct MsgQueueMutex* mutex, uint16_t msg_queue_buf_size);
/* 互斥体是否初始化 */
int32_t (*mutex_is_init)(struct MsgQueueMutex* mutex);
};
extern struct MsgQueueMutexOps msg_queue_mutex_ops;
#endif /* #if PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
struct MsgQueueOps /* 消息队列操作集合:本层为基础层,不进行参数校验,由上层进行相关参数的有效性保证 */
{
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
/* 初始化消息队列 */
int32_t (*init)(struct AmpMsgQueue* msg_queue,uint32_t mem_len);
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
/* 判断消息队列的接收核心是否已经做好准备处理数据 */
int32_t (*is_ready)(struct AmpMsgQueue* msg_queue);
/* 从指定队列中拿出一个消息,这个消息会从链中摘除,返回 buf_size 表示摘取失败 */
uint16_t (*pop)(struct AmpMsgQueue* msg_queue,uint16_t* head);
/* 向队列中放入一个消息,这个消息会被压入链头 */
int32_t (*push)(struct AmpMsgQueue* msg_queue,uint16_t* head,uint16_t msg_index);
/* 将一个队列的数据覆盖到另外一个队列to_head 将被完全覆盖掉 */
int32_t (*transfer)(struct AmpMsgQueue* msg_queue, uint16_t* from_head, uint16_t* to_head);
};
extern struct MsgQueueOps msg_queue_ops;
#endif /* __AMP_KERNEL_MSG_QUEUE_H__ */

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "config/config.h"
#include "msg.h"
#ifndef __AMP_SERVICE_H__
#define __AMP_SERVICE_H__
/* 标识不指定特定服务 */
#define SERVICE_NONE_ID (0U)
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
struct AmpService /* 核间服务 */
{
uint32_t service_id; /* 服务编号 */
int (*service)(struct Msg *msg); /* 服务入口函数 */
};
extern struct AmpService services[]; /* 本节点所有的服务集合 */
struct AmpServiceOps
{
/* 通过服务ID 获取服务 */
struct AmpService* (*get_by_id)(uint32_t id);
};
extern struct AmpServiceOps amp_service_ops;
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
#endif /* __AMP_SERVICE_H__ */

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __AMP_SERVICE_LINUX_H__
#define __AMP_SERVICE_LINUX_H__
#define LINUX_SERVICE_ECHO_ID (101U) /* 回显服务 */
#define LINUX_SERVICE_FLIP_ID (102U) /* 翻转服务 */
#endif /* __AMP_SERVICE_LINUX_H__ */

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __AMP_SERVICE_XIUOS_H__
#define __AMP_SERVICE_XIUOS_H__
#define XIUOS_SERVICE_ECHO_ID (201U) /* 回显服务 */
#define XIUOS_SERVICE_FLIP_ID (202U) /* 翻转服务 */
#endif /* __AMP_SERVICE_LINUX_H__ */

View File

@ -0,0 +1,108 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "config/config.h"
#include "spinlock.h"
#ifndef __AMP_SHM_H__
#define __AMP_SHM_H__
/* 该模块需要AMP协议且位于Linux用户空间或者RTOS空间 */
#if PROTOCOL_CHOICE == PROTOCOL_AMP && (PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS)
enum MallocType /* 内存申请时用于表示在那个区块进行申请 */
{
MALLOC_TYPE_P = 1, /* 长期区块里面进行申请: 01 */
MALLOC_TYPE_V = 2, /* 短期区块里面进行申请: 10 */
};
struct PBlockInfo /* 长期内存块管理信息数据结构 */
{
volatile uint32_t available_size; /* 内存块还有多少空闲未分配内存,没有空闲空间时分配失败 */
volatile uint32_t next_alloc_offset; /* 下一次分配内存时从那个地址偏移量开始 */
} __attribute__((aligned(MEMORY_ALIGN_SIZE)));
enum VBlockState /* 短期内存块当前状态枚举 */
{
VBLOCK_STATE_DISENABLE = 0, /* 该块已经被分配完毕或者无法满足最近的一次内存分配请求且分配出去的内存尚未归还完毕 */
VBLOCK_STATE_ENABLE = 1, /* 存在可以分配的空闲内存 */
};
struct VBlockInfo /* 短期内存块管理信息 */
{
volatile uint32_t state; /* 当前内存块的分配情况:@VBlockState */
volatile uint32_t alloc_count; /* 当前块已经分配出去的块数 */
volatile uint32_t free_count; /* 当前块被分配出去的内存块已经有多少已经释放了 */
uint32_t alloc_start_offset; /* 区块起始地址相对于共享内存起始地址的偏移量 */
volatile uint32_t next_alloc_offset; /* 下一块内存分配起始地址相对于共享内存起始地址的偏移量 */
volatile uint32_t available_size; /* 当前最大可分配内存大小 */
uint32_t total_length; /* 记录分区的总长度,用于归还后的区块恢复 */
} __attribute__((aligned(MEMORY_ALIGN_SIZE)));
enum BlockState /* 内存管理区块的状态 */
{
BLOCK_STATE_UNUSED = 0, /* 共享内存划分失败 */
BLOCK_STATE_PERSISTENT = 1, /* 共享内存存在长期区块01 */
BLOCK_STATE_VOLATILE = 2, /* 共享内存存在短期区块10 */
BLOCK_STATE_BOTH_USED = 3, /* 共享内存存在长期和短期区块01 | 10 = 11 */
};
struct ShmInfos /* 总的区块管理信息数据结构:放在内核中 */
{
atomic_char32_t block_init_mark; /* 共享内存初始化标记 */
ByteFlag pblock_lock; /* 长期区块内存分配核间互斥标志 */
ByteFlag vblock_lock; /* 短期区块内存分配核间互斥标志 */
uint8_t block_state_info; /* 标记内存块的长期和短期划分状态: @BlockState */
struct PBlockInfo pblock_info; /* 存放长期区块的管理信息 */
uint32_t vblock_each_size; /* 每个短期块所占大小 */
volatile uint32_t vblock_current; /* 当前使用的虚拟块下标*/
struct VBlockInfo vblock_infos[SHM_VBLOCK_CNT]; /* 短期区块管理信息组 */
} __attribute__((aligned(MEMORY_ALIGN_SIZE)));
struct Shm /* 共享内存管理信息结构 */
{
struct ShmInfos* shm_infos; /* 共享内存的信息,该信息共享于内核中 */
struct ShmCfg *shm_cfg; /* 共享内存配置信息 */
void *shm_total_start; /* 全部共享内存起始地址 */
void *shm_core_start; /* 当前节点共享内存起始地址 */
};
struct ShmOps /* 共享内存操作集合 */
{
/* 通过传入的指向共享内存的地址计算出相对于总共享内存起始地址的偏移量 */
int32_t (*addr_to_offset)(void* ptr);
/* 通过相对于总共享内存起始地址的偏移量,获取一个指向共享内存的指针 */
void* (*offset_to_addr)(uint32_t offset);
/* 根据相关配置初始化共享内存 */
int32_t (*shm_init)(void);
/* 从共享内存中分配内存空间 */
void* (*shm_malloc)(uint32_t size,enum MallocType type);
/* 将申请的短期共享内存归还管理池管理 */
void (*shm_free)(void* ptr);
};
extern struct ShmOps shm_ops;
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP && (PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS) */
#endif /* __AMP_SHM_H__ */

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "config/config.h"
#ifndef __AMP_SPINLOCK_H__
#define __AMP_SPINLOCK_H__
/* 基于 stdatomic ,只能运行在有 stdatomic.h 的环境 */
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
#include <stdatomic.h>
#define BYTE_LOCKED_STATE (0xFU)
#define BYTE_UNLOCK_STATE (0xAU)
typedef atomic_uchar ByteFlag;
/* 不支持递归加锁 */
struct ByteFlagOps /* CAS原子锁操作集合 */
{
/* 初始化原子锁 */
void (*init)(ByteFlag* flag);
/* 查看原子锁是否被锁定 */
int32_t (*is_locked)(ByteFlag* flag);
/* 原子锁锁定 */
void (*lock)(ByteFlag* flag);
/* 原子锁释放 */
int32_t (*unlock)(ByteFlag* flag);
/* 原子锁试图加锁 */
int32_t (*try_lock)(ByteFlag* flag);
};
extern struct ByteFlagOps byte_flag_ops;
/* 适合存放在代码区的互斥量 */
typedef atomic_flag MarkFlag;
struct MarkFlagOps
{
/* 原子锁锁定 */
void (*lock)(MarkFlag* flag);
/* 原子锁释放 */
void (*unlock)(MarkFlag* flag);
/* 原子锁试图加锁 */
int32_t (*try_lock)(MarkFlag* flag);
};
extern struct MarkFlagOps mark_flag_ops;
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
#endif /* __AMP_SPINLOCK_H__ */

View File

@ -0,0 +1,4 @@
SRC_DIR := driver/xiuos service
SRC_FILES := $(wildcard *.c)
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,463 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../include/config/config.h"
#include "../include/channel.h"
#include "../include/spinlock.h"
#if PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
/* 这三个函数在XiUOS的驱动里面 */
extern int32_t channels_init(void);
extern struct Channel* target_channel_get(uint32_t target_core_id);
#endif /* PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <signal.h>
struct Channel channels[] =
{
{ /* 0: channel 1 -> Linux to XiUOS */
.channel_info = LINUX_2_XIUOS_CHANNEL_INFO,
.msg_queue = NULL,
.msg_queue_mutex = NULL,
.reg_msg = NULL,
.msg_queue_mutex_start = NULL,
},
{ /* 1: channel 4 -> XiUOS to Linux */
.channel_info = XIUOS_2_LINUX_CHANNEL_INFO,
.msg_queue = NULL,
.msg_queue_mutex = NULL,
.reg_msg = NULL,
.msg_queue_mutex_start = NULL,
},
{ /* 空 */
.channel_info = NULL
}
};
/* 通道初始化相关数据 */
static volatile uint32_t channel_init_mark = INIT_MARK_RAW_STATE;
static MarkFlag channel_init_lock = ATOMIC_FLAG_INIT;
/* IPI驱动、内存映射相关数据 */
static int mem_fd = -1;
static int ipi_fd = -1;
int32_t channels_init(void)
{
mark_flag_ops.lock(&channel_init_lock);
if (channel_init_mark == INIT_MARK_INITIALIZED)
{
mark_flag_ops.unlock(&channel_init_lock);
LOGINFO("channels_init_info: channels init before\n");
return 0;
}
if (channel_init_mark == INIT_MARK_DESTORYED)
{
mark_flag_ops.unlock(&channel_init_lock);
INFOS("channels_init_error: channels init error\n");
return -1;
}
mem_fd = open(MEM_DRIVER,O_RDWR | O_SYNC); /* 打开全映射驱动,用于映射消息队列 */
if (mem_fd < 0)
{
INFOS("channels_init_error: open mem dev fail %d\n",mem_fd);
goto fd_open_err;
}
LOGINFO("channels_init_info: open mem driver success\n");
ipi_fd = open(IPI_DRIVER_NAME,O_RDWR | O_SYNC); /* 打开IPI核间通信硬件驱动 */
if (ipi_fd < 0)
{
INFOS("channels_init_error: open ipi dev fail %d\n",ipi_fd);
goto fd_open_err;
}
LOGINFO("channels_init_info: open ipi driver success\n");
uint32_t self_core_id = core_info->id; /* 获取当前核心的ID */
int i = 0;
for (i = 0; channels[i].channel_info != NULL; i++)
{
struct Channel* channel = &channels[i];
if (self_core_id == channel->channel_info->src_core->id) /* 该通道起点是本节点 */
{
/* 映射消息队列,这个消息队列由目标核心进行处理 */
channel->msg_queue = mmap(NULL, channel->channel_info->src_queue->len,
PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd,
channel->channel_info->src_queue->start);
if (channel->msg_queue < 0) /* 映射失败 */
{
INFOS("channels_init_error: src msg_queue mmap = %p, mem_fd = %d, origin_start = %p, length = %u\n",
channel->msg_queue, mem_fd,
channel->channel_info->src_queue->start,
channel->channel_info->src_queue->len);
goto mmap_err;
}
LOGINFO("channels_init_info: src msg_queue mmap = %p, mem_fd = %d, origin_start = %p, length = %u\n",
channel->msg_queue, mem_fd,
channel->channel_info->src_queue->start,
channel->channel_info->src_queue->len);
/* 映射消息队列互斥体 */
channel->msg_queue_mutex_start = mmap(NULL, MEM_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, ipi_fd, 0);
if (channel->msg_queue_mutex_start == NULL)
{
INFOS("channels_init_error: msg queue mutex mmap\n");
goto mmap_err;
}
LOGINFO("channels_init_info: msg queue mutex mmap = %p\n",channel->msg_queue_mutex_start);
channel->msg_queue_mutex = channel->msg_queue_mutex_start + (channel->channel_info->channel_num - 1) * MSG_QUEUE_MUTEX_SIZE;
/* 初始化互斥体 */
if (msg_queue_mutex_ops.mutex_is_init(channel->msg_queue_mutex) != 0)
{
LOGINFO("channels_init_info: prepare msg queue mutex init\n");
if (msg_queue_mutex_ops.mutex_init(channel->msg_queue_mutex, channel->msg_queue->buf_size) != 0)
{
INFOS("channels_init_error: msg queue mutex init\n");
goto mmap_err;
}
}
LOGINFO("channels_init_info: msg queue mutex init\n");
uint64_t base_addr = (channel->channel_info->reg_msg / MEM_PAGE_SIZE) * MEM_PAGE_SIZE;
uint32_t offset = channel->channel_info->reg_msg - base_addr;
void* addr = mmap(NULL,MEM_PAGE_SIZE,PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, base_addr);
if (addr == NULL)
{
INFOS("channels_init_error: msg reg mmap fail\n");
goto mmap_err;
}
/* 映射通知寄存器 */
channel->reg_msg = (uint32_t*)(addr + offset);
LOGINFO("channels_init_info: reg_msg = %p\n",channel->reg_msg);
LOGINFO("src: msg queue mark = %u\n",channel->msg_queue->working_mark);
}
else /* 该通道终点是本节点 */
{
/* 映射消息队列,由本节点处理该消息队列,不需要消息队列互斥体 */
channel->msg_queue = mmap(NULL, channel->channel_info->dst_queue->len,
PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd,
channel->channel_info->dst_queue->start);
if (channel->msg_queue < 0) /* 映射失败 */
{
INFOS("channels_init_error: dst msg_queue mmap = %p, mem_fd = %d, origin_start = %p, length = %u\n",
channel->msg_queue, mem_fd,
channel->channel_info->dst_queue->start,
channel->channel_info->dst_queue->len);
goto mmap_err;
}
LOGINFO("channels_init_success: dst msg_queue mmap = %p, mem_fd = %d, origin_start = %p, length = %u\n",
channel->msg_queue, mem_fd,
channel->channel_info->dst_queue->start,
channel->channel_info->dst_queue->len);
LOGINFO("dst: msg queue mark = %u\n",channel->msg_queue->working_mark);
}
}
channel_init_mark = INIT_MARK_INITIALIZED;
mark_flag_ops.unlock(&channel_init_lock);
LOGINFO("channels_init_success: init channel success\n");
return 0;
mmap_err:
for (i = 0; channels[i].channel_info != NULL; i++)
{
struct Channel* channel = &channels[i];
if (self_core_id == channel->channel_info->src_core->id)
{ /* 该通道起点是本节点 */
if (channel->msg_queue != NULL)
{
munmap(channel->msg_queue,channel->channel_info->src_queue->len);
channel->msg_queue = NULL;
}
if (channel->msg_queue_mutex_start != NULL)
{
munmap(channel->msg_queue_mutex_start,MEM_PAGE_SIZE);
channel->msg_queue_mutex_start = NULL;
channel->msg_queue_mutex = NULL;
}
if (channel->reg_msg != NULL)
{
uint64_t addr = (uint64_t)channel->reg_msg;
munmap((void*)((addr / MEM_PAGE_SIZE) * MEM_PAGE_SIZE),sizeof(uint32_t));
channel->reg_msg = NULL;
}
}
else
{ /* 该通道终点是本节点 */
if (channel->msg_queue != NULL)
{
munmap(channel->msg_queue,channel->channel_info->dst_queue->len);
channel->msg_queue->working_mark = INIT_MARK_DESTORYED;
channel->msg_queue = NULL;
}
}
}
fd_open_err:
if (mem_fd > 0)
{
close(mem_fd);
mem_fd = -1;
}
if (ipi_fd > 0)
{
close(ipi_fd);
ipi_fd = -1;
}
channel_init_mark = INIT_MARK_DESTORYED;
mark_flag_ops.unlock(&channel_init_lock);
return -1;
}
struct Channel* target_channel_get(uint32_t target_core_id)
{
uint32_t self_core_id = core_info->id;
int i = 0;
for (i = 0; channels[i].channel_info != NULL; i++)
{
struct Channel* channel = &channels[i];
if (self_core_id == channel->channel_info->src_core->id && target_core_id == channel->channel_info->dst_core->id)
{
LOGINFO("channel_get_send_channel_success: target_core_id = %u\n",target_core_id);
return channel;
}
}
INFOS("channel_get_send_channel_error: target_core_id = %u\n",target_core_id);
return NULL;
}
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER */
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
static int32_t channel_is_ready(struct Channel* channel)
{
LOGINFO("channel_is_ready_info: enter mark = %u\n", channel->msg_queue->working_mark);
if (msg_queue_ops.is_ready(channel->msg_queue) == 0)
{
LOGINFO("channel_is_ready_info: msg queue is ready\n");
if (msg_queue_mutex_ops.mutex_is_init(channel->msg_queue_mutex) == 0)
{
LOGINFO("channel_is_ready_info: msg queue mutex is ready\n");
return 0;
}
}
return -1;
}
static int32_t channel_notify(struct Channel* channel)
{
if (msg_queue_ops.is_ready(channel->msg_queue) != 0)
{
INFOS("channel_notify_warn: msg queue is not ready\n");
return -1;
}
/* 锁定待处理消息队列,防止其他线程继续往里面添加数据 */
byte_flag_ops.lock(&channel->msg_queue_mutex->wait_lock);
if (channel->msg_queue_mutex->msg_wait_cnt == 0) /* 没有需要处理的消息 */
{
byte_flag_ops.unlock(&channel->msg_queue_mutex->wait_lock);
LOGINFO("channel_notify_info: have no wait msg\n");
return 0;
}
while (channel->msg_queue_mutex->msg_queue_mark != MSG_QUEUE_MARK_IDLE) /* 等待远程核心处理完上一批消息 */
{
;
}
LOGINFO("channel_notify_info: remote idel, prepare to notify\n");
/* 将待处理队列放入处理队列 */
if (msg_queue_ops.transfer(channel->msg_queue,&channel->msg_queue->wait_h,&channel->msg_queue->proc_ing_h) != 0)
{
byte_flag_ops.unlock(&channel->msg_queue_mutex->wait_lock);
INFOS("channel_notify_error: add wait msg to process queue\n");
return -1;
}
/* 清空等待消息队列,设置工作标志,防止重复通知 */
channel->msg_queue_mutex->msg_wait_cnt = 0;
channel->msg_queue_mutex->msg_queue_mark = MSG_QUEUE_MARK_BUSY;
/* 释放等待队列,其他线程可以继续往里面添加消息 */
byte_flag_ops.unlock(&channel->msg_queue_mutex->wait_lock);
/* 向可以触发核间中断的寄存器中写入数据以触发核间中断 */
*(channel->reg_msg) = 1U;
return 0;
}
static struct Msg* channel_empty_msg_get(struct Channel* channel) /* 从通道中获取一个空的消息缓冲区 */
{
struct Msg* empty_msg = NULL;
byte_flag_ops.lock(&channel->msg_queue_mutex->empty_lock); /* 对空闲队列加锁 */
uint16_t empty_index = msg_queue_ops.pop(channel->msg_queue,&channel->msg_queue->empty_h);
if (empty_index < channel->msg_queue->buf_size) /* 还有空闲消息 */
{
empty_msg = (struct Msg*)(&channel->msg_queue->entries[empty_index]);
msg_ops.msg_reset(empty_msg); /* 重置该消息 */
}
byte_flag_ops.unlock(&channel->msg_queue_mutex->empty_lock);
LOGINFO("empty_msg_get_info: result = %p\n",empty_msg);
return empty_msg;
}
static int32_t channel_empty_msg_put(struct Channel* channel,struct Msg* msg) /* 将一个不再使用的缓冲区归还给通道 */
{
struct MsgEntry* entry = (struct MsgEntry*)msg;
int ret = -1;
msg_ops.msg_reset(msg); /* 归还前重置该消息 */
byte_flag_ops.lock(&channel->msg_queue_mutex->empty_lock); /* 对空闲队列加锁 */
ret = msg_queue_ops.push(channel->msg_queue,&channel->msg_queue->empty_h,entry->cur_idx);
byte_flag_ops.unlock(&channel->msg_queue_mutex->empty_lock);
return ret;
}
static int32_t channel_msg_send(struct Channel* channel,struct Msg* msg)
{
struct MsgEntry* entry = (struct MsgEntry*)msg;
int ret = -1;
byte_flag_ops.lock(&channel->msg_queue_mutex->wait_lock); /* 对等待队列加锁 */
ret = msg_queue_ops.push(channel->msg_queue,&channel->msg_queue->wait_h,entry->cur_idx);
if (ret == 0)
{
channel->msg_queue_mutex->msg_wait_cnt ++;
}
else
{
LOGINFO("channel_send_msg_buffer_error: add msg fail, idx = %u\n",entry->cur_idx);
}
byte_flag_ops.unlock(&channel->msg_queue_mutex->wait_lock);
return ret;
}
static int32_t channel_msg_send_and_notify(struct Channel* channel,struct Msg* msg)
{
struct MsgEntry* entry = (struct MsgEntry*)msg;
int ret = -1;
byte_flag_ops.lock(&channel->msg_queue_mutex->wait_lock); /* 对等待队列加锁 */
ret = msg_queue_ops.push(channel->msg_queue,&channel->msg_queue->wait_h,entry->cur_idx);
if (ret == 0)
{
channel->msg_queue_mutex->msg_wait_cnt ++;
}
else
{
LOGINFO("channel_send_msg_buffer_error: add msg fail, idx = %u\n",entry->cur_idx);
}
if (channel->msg_queue_mutex->msg_wait_cnt == 0) /* 没有需要处理的消息 */
{
byte_flag_ops.unlock(&channel->msg_queue_mutex->wait_lock);
LOGINFO("msg_send_and_notify: have no wait msg\n");
return 0;
}
while (channel->msg_queue_mutex->msg_queue_mark != MSG_QUEUE_MARK_IDLE) /* 等待远程核心处理完上一批消息 */
{
;
}
LOGINFO("msg_send_and_notify: remote idel, prepare to notify\n");
/* 将待处理队列放入处理队列 */
if (msg_queue_ops.transfer(channel->msg_queue,&channel->msg_queue->wait_h,&channel->msg_queue->proc_ing_h) != 0)
{
byte_flag_ops.unlock(&channel->msg_queue_mutex->wait_lock);
INFOS("msg_send_and_notify: add wait msg to process queue\n");
return -1;
}
/* 清空等待消息队列,设置工作标志,防止重复通知 */
channel->msg_queue_mutex->msg_wait_cnt = 0;
channel->msg_queue_mutex->msg_queue_mark = MSG_QUEUE_MARK_BUSY;
/* 释放等待队列,其他线程可以继续往里面添加消息 */
byte_flag_ops.unlock(&channel->msg_queue_mutex->wait_lock);
/* 向可以触发核间中断的寄存器中写入数据以触发核间中断 */
*(channel->reg_msg) = 1U;
return 0;
}
struct ChannelOps channel_ops =
{
.channels_init = channels_init,
.channel_is_ready = channel_is_ready,
.target_channel_get = target_channel_get,
.channel_notify = channel_notify,
.empty_msg_get = channel_empty_msg_get,
.empty_msg_put = channel_empty_msg_put,
.msg_send = channel_msg_send,
.msg_send_and_notify = channel_msg_send_and_notify
};
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */

View File

@ -0,0 +1,224 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../include/client.h"
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
#define CHECK_PTR_NOT_NULL(ptr, ret) \
do \
{ \
if (ptr == NULL) \
{ \
INFOS("param is null\n"); \
return ret; \
} \
} while (0);
static int32_t client_init(struct Client* raw_client,uint32_t remote_core_id)
{
CHECK_PTR_NOT_NULL(raw_client,-1); /* 参数校验 */
if (raw_client->init_mark == INIT_MARK_INITIALIZED)
{
LOGINFO("client_init_info: client init before\n");
return 0;
}
if (raw_client->init_mark == INIT_MARK_DESTORYED)
{
INFOS("client_init_error: client is null or broken\n");
return -1;
}
if (channel_ops.channels_init() != 0) /* 初始化所有的通道 */
{
raw_client->init_mark = INIT_MARK_DESTORYED;
INFOS("client_init_error: channels init fail\n");
return -1;
}
LOGINFO("client_init_info: channels init success\n");
/* 获取目标通道 */
struct Channel* target_channel = channel_ops.target_channel_get(remote_core_id);
if (target_channel == NULL) /* 没有获取到目标核心的通道 */
{
raw_client->init_mark = INIT_MARK_DESTORYED;
INFOS("client_init_error: get target channel fail = %u\n",remote_core_id);
return -1;
}
LOGINFO("client_init_info: get target channel success = %u\n",remote_core_id);
while (channel_ops.channel_is_ready(target_channel) != 0) /* 检查目标通道是否已经被启用 */
{
;
}
LOGINFO("client_init_info: target channel [%u] is ready\n",remote_core_id);
raw_client->remote_channel = target_channel;
raw_client->msg_cnt = 0U;
raw_client->shm_cnt = 0U;
#if PROTOCOL_CHOICE == PROTOCOL_AMP /* 如果使用的共享内存,需要对共享内存进行初始化 */
if (shm_ops.shm_init() != 0)
{
raw_client->init_mark = INIT_MARK_DESTORYED;
INFOS("client_init_error: init shm fail\n");
return -1;
}
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
raw_client->init_mark = INIT_MARK_INITIALIZED;
return 0;
}
static int32_t client_destory(struct Client* client)
{
CHECK_PTR_NOT_NULL(client,-1);
if (client->init_mark == INIT_MARK_INITIALIZED)
{
if (client->msg_cnt > 0)
{
INFOS("client_destory: hold msg\n");
return -1;
}
#if PROTOCOL_CHOICE == PROTOCOL_AMP
if (client->shm_cnt > 0)
{
INFOS("client_destory: hold shm\n");
return -1;
}
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
client->init_mark = INIT_MARK_RAW_STATE;
}
return 0;
}
static struct Msg* client_empty_msg_get(struct Client* client,uint32_t remote_service_id)
{
CHECK_PTR_NOT_NULL(client,NULL);
struct Msg* msg = channel_ops.empty_msg_get(client->remote_channel);
if (msg != NULL)
{
msg->service_id = remote_service_id;
client->msg_cnt ++;
}
return msg;
}
static int32_t client_empty_msg_put(struct Client* client, struct Msg* empty_msg)
{
CHECK_PTR_NOT_NULL(client,-1);
CHECK_PTR_NOT_NULL(empty_msg, -1);
if (channel_ops.empty_msg_put(client->remote_channel,empty_msg) == 0)
{
client->msg_cnt --;
return 0;
}
return -1;
}
static int32_t client_msg_send(struct Client* client, struct Msg* full_msg)
{
CHECK_PTR_NOT_NULL(client,-1);
CHECK_PTR_NOT_NULL(full_msg, -1);
return channel_ops.msg_send(client->remote_channel,full_msg);
}
static int32_t client_msg_send_and_notify(struct Client* client, struct Msg* full_msg)
{
CHECK_PTR_NOT_NULL(client,-1);
CHECK_PTR_NOT_NULL(full_msg, -1);
return channel_ops.msg_send_and_notify(client->remote_channel,full_msg);
}
static int32_t client_msg_notify(struct Client* client)
{
CHECK_PTR_NOT_NULL(client,-1);
return channel_ops.channel_notify(client->remote_channel);
}
static int32_t client_msg_poll(struct Msg* aim_msg)
{
CHECK_PTR_NOT_NULL(aim_msg,-1);
return msg_ops.msg_is_dealt(aim_msg);
}
#if PROTOCOL_CHOICE == PROTOCOL_AMP
static void* client_shm_malloc(struct Client* client, uint32_t size,enum MallocType type)
{
void* result = NULL;
result = shm_ops.shm_malloc(size,type);
if (result != NULL)
{
client->shm_cnt ++;
}
return result;
}
static void client_shm_free(struct Client* client, void* ptr)
{
if (ptr != NULL)
{
client->shm_cnt --;
}
shm_ops.shm_free(ptr);
}
static uint32_t client_shm_addr_to_offset(void* ptr)
{
return shm_ops.addr_to_offset(ptr);
}
static void* client_shm_offset_to_addr(uint32_t offset)
{
return shm_ops.offset_to_addr(offset);
}
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
struct ClientOps client_ops =
{
.client_init = client_init,
.client_destory = client_destory,
.empty_msg_get = client_empty_msg_get,
.empty_msg_put = client_empty_msg_put,
.msg_send = client_msg_send,
.msg_send_and_notify = client_msg_send_and_notify,
.msg_notify = client_msg_notify,
.msg_poll = client_msg_poll,
#if PROTOCOL_CHOICE == PROTOCOL_AMP
.shm_malloc = client_shm_malloc,
.shm_free = client_shm_free,
.shm_addr_to_offset = client_shm_addr_to_offset,
.shm_offset_to_addr = client_shm_offset_to_addr
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
};
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */

View File

@ -0,0 +1,151 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../include/config/config.h"
/* addr_cfg.h */
struct AddrInfo addr_infos[] =
{
{ /* 0Linux 地址空间下所有的共享内存地址信息 8MB */
.start = 0x43000000U,
.len = 8 * MB
},
{ /* 1Linux 地址空间下使用的共享内存地址信息 4MB */
.start = 0x43000000U,
.len = 4 * MB
},
{ /* 2: XiUOS 地址空间下所有的共享内存地址信息 8MB*/
.start = 0x63000000U,
.len = 8 * MB
},
{ /* 3: XiUOS 地址空间下使用的共享内存地址信息 4MB*/
.start = 0x63400000U,
.len = 4 * MB
},
{ /* 4: Linux 地址空间下发送给Linux的环形缓冲区 4KB */
.start = 0x42F00000U,
.len = 4 * KB
},
{ /* 5: Linux 地址空间下发送给XiUOS的环形缓冲区 4KB */
.start = 0x42F01000U,
.len = 4 * KB
},
{ /* 6: XiUOS 地址空间下发送给Linux的环形缓冲区 4KB */
.start = 0x62F00000U,
.len = 4 * KB
},
{ /* 7: XiUOS 地址空间下发送给XiUOS的环形缓冲区 4KB */
.start = 0x62F01000U,
.len = 4 * KB
}
};
/* core_cfg.h */
struct CoreInfo core_infos[] =
{
{ /* 0: linux 节点信息 */
.name = CORE_LINUX_NAME,
.id = CORE_LINUX_ID
},
{ /* 1 xiuos 节点信息*/
.name = CORE_XIUOS_NAME,
.id = CORE_XIUOS_ID
},
{ /* 2: 虚无节点 */
.name = CORE_NONE_NAME,
.id = CORE_NONE_ID
}
};
#if (PLATFORM_CHOICE / PLATFORM_LINUX_BASE) == 1
struct CoreInfo* core_info = LINUX_CORE_INFO;
#elif (PLATFORM_CHOICE / PLATFORM_RTOS_XIUOS) == 1
struct CoreInfo* core_info = XIUOS_CORE_INFO;
#else
#error please configure right platform
#endif
/* channel_cfg.h */
struct ChannelInfo channel_infos[] =
{
{ /* 通道1 A55 -> M33 */
.channel_num = 1,
.irq_rsp = 0, /* Linux: 响应中断配置在设备树第一个中断 */
.irq_msg = 69, /* XiUOS: 接收中断配置为69号 */
.reg_msg = 0x10400000U + 0x24U,
.src_core = LINUX_CORE_INFO,
.dst_core = XIUOS_CORE_INFO,
.src_queue = LINUX_2_XIUOS_MSG_QUEUE_ADDR_INFO,
.dst_queue = XIUOS_2_XIUOS_MSG_QUEUE_ADDR_INFO
},
{ /* 通道4 M33 -> A55 */
.channel_num = 4,
.irq_msg = 1, /* Linux: 接收中断配置在设备树的第二个 */
.irq_rsp = 78, /* XiUOS: 响应中断配置为78号 */
.reg_msg = 0x40400000U + 0x84U,
.src_core = XIUOS_CORE_INFO,
.dst_core = LINUX_CORE_INFO,
.src_queue = XIUOS_2_LINUX_MSG_QUEUE_ADDR_INFO,
.dst_queue = LINUX_2_LINUX_MSG_QUEUE_ADDR_INFO
},
{ /* 尾 */
.src_core = NULL
}
};
/* shm_cfg.h */
#if PROTOCOL_CHOICE == PROTOCOL_AMP
struct ShmCfg shm_cfgs[] =
{
{ /* Linux 共享内存配置信息 */
.core = LINUX_CORE_INFO,
.total_shm = LINUX_SHM_TOTAL_ADDR_INFO,
.core_shm = LINUX_SHM_USED_ADDR_INFO,
.pblock_size = (2 * MB),
.vblock_size = (2 * MB),
.min_block_size = (512 * B),
.bit_align = MEMORY_ALIGN_SIZE
},
{ /* XiUOS 共享内存配置信息 */
.core = XIUOS_CORE_INFO,
.total_shm = XIUOS_SHM_TOTAL_ADDR_INFO,
.core_shm = XIUOS_SHM_USED_ADDR_INFO,
.pblock_size = (2 * MB),
.vblock_size = (2 * MB),
.min_block_size = (512 * B),
.bit_align = MEMORY_ALIGN_SIZE
},
{
.core = NULL
}
};
static struct ShmCfg* shm_cfg_get_by_id(uint16_t target_id)
{
int i = 0;
for (i = 0; shm_cfgs[i].core != NULL; i++)
{
if (shm_cfgs[i].core->id == target_id)
{
LOGINFO("shm_cfg_get_by_id_info: find shm cfg success, target id = %u\n",target_id);
return &shm_cfgs[i];
}
}
return NULL;
}
struct ShmCfgOps shm_cfg_ops =
{
.get_by_id = shm_cfg_get_by_id
};
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */

View File

@ -0,0 +1,445 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../../../include/config/config.h"
#include "../../../include/msgqueue.h"
#include "../../../include/service.h"
#include "../../../include/service/service_linux.h"
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL /* Linux内核态代码 */
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/errno.h>
#include <linux/of_address.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <linux/types.h> /* 类型\输出 */
#include <linux/kernel.h>
#include <linux/module.h> /* 模块相关 */
#include <linux/init.h>
#include <linux/slab.h> /* kmalloc */
#include <linux/mm.h> /* remap_pfn_range */
#include <linux/miscdevice.h> /* 混杂驱动 */
#include <linux/of.h> /* 设备树解析函数 */
#include <linux/of_irq.h>
#include <linux/interrupt.h> /* 中断相关函数 */
#include <linux/irq.h>
#include <asm/io.h> /* virt_to_phy */
#include <linux/io.h>
#include <asm/uaccess.h>
#define REG_BASE (0x10400000U) /* 寄存器基地址 */
struct RegGroup /* 寄存器组 */
{
uint32_t STS; /* 中断状态寄存器,只读 */
uint32_t SET; /* 中断触发寄存器,只写 1 */
uint32_t CLR; /* 中断清除寄存器只写1 */
};
struct MhuChannel /* 内核空间的通道信息抽象 */
{
struct ChannelInfo* channel_info; /* 通道配置信息 */
struct AmpMsgQueue* msg_queue; /* 发往远程核心的消息队列 */
struct MsgQueueMutex* msg_queue_mutex; /* 消息队列互斥体 */
uint64_t msg_reg_start; /* 消息发送寄存器组起始地址 */
struct RegGroup *msg_reg; /* 消息发送寄存器组 */
uint64_t rsp_reg_start; /* 消息响应寄存器组起始地址 */
struct RegGroup *rsp_reg; /* 消息响应寄存器组 */
int32_t irq_num; /* 通道处理中断的中断号 */
irqreturn_t (*interrupt_handler)(int irq_num, void *mhu_channel); /* 通道中断处理函数 */
};
int channel_msg_recv_interrupt(struct MhuChannel* mhu_channel); /* 通道接受消息的中断处理函数 */
int channel_msg_rsp_interrupt(struct MhuChannel* mhu_channel); /* 通道消息响应的中断处理函数 */
static irqreturn_t msg_ch4_ns(int irq_num, void* mhu_channel); /* 通道4数据接收中断 */
static irqreturn_t rsp_ch1_ns(int irq_num, void* mhu_channel); /* 通道1数据响应接收中断 */
static int mhu_open(struct inode *inode, struct file *filp); /* 设备打开 */
static int mhu_release(struct inode *inode, struct file *filp); /* 设备释放 */
static long mhu_ioctl(struct file *file, unsigned int cmd, unsigned long arg); /* 设备控制 */
static int mhu_mmap(struct file *file, struct vm_area_struct *vma); /* 内存映射 */
static void* msg_mutex_area; /* 映射到用户空间的内存,用于存放各个通道的消息队列互斥体,大小 @MEM_PAGE_ZISE */
static struct MhuChannel mhu_channels[] =
{
{ /* 0: channel 1 -> Linux to XiUOS */
.channel_info = LINUX_2_XIUOS_CHANNEL_INFO,
.msg_queue = NULL,
.msg_queue_mutex = NULL,
.msg_reg_start = REG_BASE + 0x20U,
.msg_reg = NULL,
.rsp_reg_start = REG_BASE + 0x30U,
.rsp_reg = NULL,
.irq_num = 0,
.interrupt_handler = rsp_ch1_ns
},
{ /* 1: channel 4 -> XiUOS to Linux */
.channel_info = XIUOS_2_LINUX_CHANNEL_INFO,
.msg_queue = NULL,
.msg_queue_mutex = NULL,
.msg_reg_start = REG_BASE + 0x80U,
.msg_reg = NULL,
.rsp_reg_start = REG_BASE + 0x90U,
.rsp_reg = NULL,
.irq_num = 0,
.interrupt_handler = msg_ch4_ns
},
{ /* 2: 空*/
.channel_info = NULL
}
};
static struct file_operations arm_mhu_ops =
{
.owner = THIS_MODULE,
.open = mhu_open,
.release = mhu_release,
.unlocked_ioctl = mhu_ioctl,
.mmap = mhu_mmap
};
static struct miscdevice arm_mhu_dev =
{
.minor = MISC_DYNAMIC_MINOR, /* 次设备号自动生成 */
.name = IPI_DEV_NAME, /* 设备名称 */
.fops = &arm_mhu_ops /* 设备操作合集 */
};
/* 通道接收到发送的消息时调用 */
int channel_msg_recv_interrupt(struct MhuChannel* channel)
{
LOGINFO("channel_msg_recv_interrupt_info: enter\n");
struct AmpMsgQueue* msg_queue = channel->msg_queue;
struct Msg* msg = NULL;
struct AmpService* aim_service = NULL;
/* 获取消息队列中待处理的第一个消息:不能破坏链接结构 */
uint16_t head_index = msg_queue_ops.pop(msg_queue,&msg_queue->proc_ing_h);
int service_result = -1;
while (1)
{
if (head_index != msg_queue->buf_size)
{
msg = &msg_queue->entries[head_index].msg; /* 需要进行处理的消息 */
aim_service = amp_service_ops.get_by_id(msg->service_id); /* 获取需要调用的服务 */
if (aim_service == NULL)
{
LOGINFO("channel_msg_recv_interrupt_warn: service not hit, msg_index = %u, service_id = %u\n",head_index,msg->service_id);
/* 该消息已经被处理,但是消息请求的服务不存在 */
msg->flag.deal_state = MSG_DEAL_STATE_YES;
msg->flag.service_result = MSG_SERVICE_RET_NOT_EXITS;
}
else
{
LOGINFO("channel_msg_recv_interrupt_info: service hit, msg_index = %u, service_id = %u\n",head_index,msg->service_id);
service_result = aim_service->service(msg); /* 将消息转交给服务进行处理 */
if (service_result == 0) /* 设置服务响应的结果 */
{
msg->flag.service_result = MSG_SERVICE_RET_SUCCESS;
}
else
{
msg->flag.service_result = MSG_SERVICE_RET_FAIL;
}
msg->flag.deal_state = MSG_DEAL_STATE_YES; /* 标记该条信息已经被处理,发送核心可以直接开始下一步的操作 */
LOGINFO("channel_msg_recv_interrupt_info: service processed, msg_index = %u, service_id = %u, result = %s\n",head_index, msg->service_id,service_result == 0 ? "success" : "fail");
}
}
else
{
LOGINFO("channel_msg_recv_interrupt_info: no more msg exist, head_index = %u\n",head_index);
break;
}
head_index = msg_queue_ops.pop(msg_queue,&msg_queue->proc_ing_h);
}
/* 响应对方已经处理完毕 */
((struct MhuChannel*)channel)->rsp_reg->SET = 1U;
LOGINFO("channel_msg_recv_interrupt_info: exit\n");
return 0;
}
/* 通道接收到响应的消息时调用 */
int channel_msg_rsp_interrupt(struct MhuChannel* channel)
{
LOGINFO("channel_msg_rsp_interrupt_info: enter\n");
/* 可以继续发送数据了 */
channel->msg_queue_mutex->msg_queue_mark = MSG_QUEUE_MARK_IDLE;
LOGINFO("channel_msg_rsp_interrupt_info: exit\n");
return 0;
}
/* XiUOS发送给Linux的消息由该中断负责处理 */
static irqreturn_t msg_ch4_ns(int irq_num, void* chan)
{
LOGINFO("msg_ch4_ns_info: enter\n");
struct MhuChannel* mhu_channel = (struct MhuChannel*) chan;
mhu_channel->msg_reg->CLR = 1U; /* 清除中断标志 */
channel_msg_recv_interrupt(mhu_channel); /* 处理消息接受处理 */
LOGINFO("msg_ch4_ns_info: exit\n");
return IRQ_RETVAL(IRQ_HANDLED);
}
/* Linux发送给XiUOS的数据响应消息由该中断处理 */
static irqreturn_t rsp_ch1_ns(int irq_num, void* chan)
{
LOGINFO("rsp_ch1_ns: enter\n");
struct MhuChannel* mhu_channel = (struct MhuChannel*) chan;
mhu_channel->rsp_reg->CLR = 1U; /* 清除中断标志 */
channel_msg_rsp_interrupt(mhu_channel); /* 处理消息接受处理 */
LOGINFO("rsp_ch1_ns: exit\n");
return IRQ_RETVAL(IRQ_HANDLED);
}
/* 打开 MHU 设备 */
static int mhu_open(struct inode *inode, struct file *filp)
{
filp->private_data = &arm_mhu_dev;
LOGINFO("mhu_open_info: mhu open\n");
return 0;
}
/* 关闭 MHU 设备 */
static int mhu_release(struct inode *inode, struct file *filp)
{
LOGINFO("mhu_release_info: mhu release\n");
return 0;
}
/* MHU 设备指令 */
static long mhu_ioctl(struct file* file, unsigned int cmd, unsigned long arg)
{
LOGINFO("mhu_ioctl_info: cmd = %u, arg = %u\n",cmd,arg);
switch (cmd)
{
case IOCTL_CMD_NOTIFY: /* 通知具体消息通道 */
{
int i = 0;
uint32_t channel_num = (uint32_t) arg;
for (i = 0; mhu_channels[i].channel_info != NULL; i++)
{
struct MhuChannel *mhu_channel = &mhu_channels[i];
if (mhu_channel->channel_info->channel_num == channel_num)
{
mhu_channel->msg_reg->SET = 1U; /* 触发核间中断 */
LOGINFO("mhu_ioctl_info: channel notify, num = %u\n",channel_num);
return 0;
}
}
INFOS("mhu_ioctl_warn: channel not exist, num = %u\n",channel_num);
return -ENOTTY;
}
default:
{
INFOS("mhu_ioctl_warn: unknown cmd = %u, arg = %u\n",cmd,arg);
return -ENOTTY;
}
}
return 0;
}
static int mhu_mmap(struct file* file, struct vm_area_struct* vma)
{
LOGINFO("mhu_mmap_info: enter\n");
if (remap_pfn_range(vma, /* 虚拟内存区域 */
vma->vm_start, /* 虚拟空间起始地址 */
virt_to_phys(msg_mutex_area) >> PAGE_SHIFT, /* 于物理内存对应的页帧号 */
vma->vm_end - vma->vm_start, /* 映射区域大小 */
vma->vm_page_prot /* 页面保护属性 */))
{
return -EAGAIN;
}
LOGINFO("mhu_mmap_info: exit\n");
return 0;
}
static int arm_mhu_init(void)
{
int result_ret,i = 0;
struct device_node* dev_node = of_find_node_by_name(NULL,"mhu"); /* 从设备树中找到MHU节点 */
if (dev_node == NULL)
{
INFOS("arm_mhu_init_error: find node(mhu) fail\n");
return -EINVAL;
}
const char* dev_status = NULL;
result_ret = of_property_read_string(dev_node,"status",&dev_status); /* 读取设备的状态 */
if (result_ret < 0 || strcmp(dev_status,"okay") != 0)
{
INFOS("arm_mhu_init_error: get status or status is not okay\n");
return -EINVAL;
}
const char* dev_compat = NULL;
result_ret = of_property_read_string(dev_node,"compatible",&dev_compat); /* 读取设备匹配属性并匹配 */
if (result_ret < 0 || strcmp(dev_compat,"arm,rzg2ul-mhu") != 0)
{
INFOS("arm_mhu_init_error: get compatible or compatible match fail\n");
return -EINVAL;
}
/* 开辟消息队列的互斥公共内存 */
msg_mutex_area = kzalloc(MEM_PAGE_SIZE,GFP_KERNEL);
if (msg_mutex_area == NULL)
{
INFOS("arm_mhu_init_error: malloc msg_mutex_area fail\n");
return -EINVAL;
}
/* 设置内存页常驻 */
SetPageReserved(msg_mutex_area);
*((uint32_t*)msg_mutex_area) = 0U; /* 第一个字节非0需要清零 */
for (i = 0; mhu_channels[i].channel_info != NULL; i++) /* 初始化设备的中断 */
{
struct MhuChannel* mhu_channel = &mhu_channels[i];
/* 物理地址映射 */
mhu_channel->msg_reg = ioremap(mhu_channel->msg_reg_start,sizeof(struct RegGroup));
mhu_channel->rsp_reg = ioremap(mhu_channel->rsp_reg_start,sizeof(struct RegGroup));
uint32_t self_core_id = core_info->id;
/* 注册相关中断 */
uint32_t irq_index = -1;
if (self_core_id == mhu_channel->channel_info->src_core->id) /* 如果当前核心是通道的发送方 */
{
irq_index = mhu_channel->channel_info->irq_rsp;
}
else
{
irq_index = mhu_channel->channel_info->irq_msg;
}
int irq_num = irq_of_parse_and_map(dev_node, irq_index); /* 读取通道的中断号 */
if (irq_num <= 0)
{
INFOS("mhu_init_error: get irq_num fail = %d\n",irq_num);
return -EINVAL;
}
mhu_channel->irq_num = irq_num; /* 记录下当前通道的中断号 */
unsigned long irq_flags = irq_get_trigger_type(irq_num); /* 读取设备的中断触发类型 */
const char* irq_name = NULL;
of_property_read_string_index(dev_node,"interrupt-names",irq_index,&irq_name); /* 读取中断的名称 */
result_ret = request_irq(irq_num,mhu_channel->interrupt_handler,irq_flags,irq_name,mhu_channel); /* 申请中断 */
if (result_ret != 0)
{
INFOS("mhu_init_error: request irq_num = %d, irq_name = %s fail\n",irq_num,irq_name);
return result_ret;
}
LOGINFO("mhu_init_info: request irq_num = %d, irq_name = %s success\n",irq_num,irq_name);
struct AddrInfo* msg_queue_addr_info = NULL;
if (self_core_id == mhu_channel->channel_info->src_core->id) /* 如果当前核心是通道的发送方 */
{
msg_queue_addr_info = mhu_channel->channel_info->src_queue;
mhu_channel->msg_queue = ioremap(msg_queue_addr_info->start, msg_queue_addr_info->len);
LOGINFO("arm_mhu_init_info: before msg_working = %u\n",mhu_channel->msg_queue->working_mark);
/* 初始化消息队列 */
if (0 != msg_queue_ops.init(mhu_channel->msg_queue,msg_queue_addr_info->len))
{
INFOS("arm_mhu_init_error: msg_queue_init fail\n");
return -EINVAL;
}
LOGINFO("arm_mhu_init_info: after msg_working = %u\n",mhu_channel->msg_queue->working_mark);
/* 计算互斥体位置:这里没有初始化,需要用户空间进行初始化 */
mhu_channel->msg_queue_mutex = msg_mutex_area + (mhu_channel->channel_info->channel_num - 1) * MSG_QUEUE_MUTEX_SIZE;
}
else /* 当前核心是通道的接收方 */
{
msg_queue_addr_info = mhu_channel->channel_info->dst_queue;
mhu_channel->msg_queue = ioremap(msg_queue_addr_info->start, msg_queue_addr_info->len);
/* 接收方没有互斥体结构: 告知发送方可以发送数据了 */
mhu_channel->msg_queue->working_mark = INIT_MARK_INITIALIZED;
}
}
misc_register(&arm_mhu_dev); /* 注册杂项驱动 */
LOGINFO("mhu_init_success: mhu init success!\n");
return 0;
}
static void arm_mhu_exit(void)
{
int i;
for (i = 0; mhu_channels[i].channel_info != NULL; i++) /* 取消映射物理地址信息 */
{
struct MhuChannel* mhu_channel = &mhu_channels[i];
iounmap(mhu_channel->msg_reg);
iounmap(mhu_channel->rsp_reg);
iounmap(mhu_channel->msg_queue);
free_irq(mhu_channel->irq_num,mhu_channel);
}
ClearPageReserved(msg_mutex_area);
kfree(msg_mutex_area);
misc_deregister(&arm_mhu_dev); /* 注销杂项设备 */
LOGINFO("arm_mhu_exit_success: mhu exit success!\n");
}
module_init(arm_mhu_init);
module_exit(arm_mhu_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("anguoyoula");
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL */

View File

@ -0,0 +1,153 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../../../include/amp.h"
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL && PROTOCOL_CHOICE == PROTOCOL_AMP /* Linux内核态代码没有开启AMP协议时该模块也会被加载到内核 */
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/errno.h>
#include <linux/of_address.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <linux/types.h> /* 类型\输出 */
#include <linux/kernel.h>
#include <linux/module.h> /* 模块相关 */
#include <linux/init.h>
#include <linux/slab.h> /* kmalloc */
#include <linux/mm.h> /* remap_pfn_range */
#include <linux/miscdevice.h> /* 混杂驱动 */
#include <linux/of.h> /* 设备树解析函数 */
#include <linux/of_irq.h>
#include <linux/interrupt.h> /* 中断相关函数 */
#include <linux/irq.h>
#include <asm/io.h> /* virt_to_phy */
#include <linux/io.h>
#include <asm/uaccess.h>
static void* shm_block_info = NULL; /* 映射到用户空间的内存大小MEM_PAGE_SIZE */
static void* shm_total_start = NULL; /* 共享内存总的起始地址信息 */
void* kshm_offset_to_addr(uint32_t offset) /* 给内核中的服务从消息中提取出地址信息 */
{
LOGINFO("kshm_offset_to_addr: offset = %u\n",offset);
return shm_total_start + offset;
}
EXPORT_SYMBOL(shm_total_start);
EXPORT_SYMBOL(kshm_offset_to_addr);
static int shm_open(struct inode *inode, struct file *filp); /* 设备打开 */
static int shm_release(struct inode *inode, struct file *filp); /* 设备释放 */
static int shm_mmap(struct file *file, struct vm_area_struct *vma); /* 内存映射 */
static struct file_operations arm_shm_ops =
{
.owner = THIS_MODULE,
.open = shm_open,
.release = shm_release,
.mmap = shm_mmap
};
static struct miscdevice arm_shm_dev =
{
.minor = MISC_DYNAMIC_MINOR, /* 次设备号自动生成 */
.name = SHM_DEV_NAME, /* 设备名称 */
.fops = &arm_shm_ops /* 设备操作合集 */
};
static int shm_open(struct inode *inode, struct file *filp)
{
filp->private_data = &arm_shm_dev;
LOGINFO("shm_open_info: shm open\n");
return 0;
}
static int shm_release(struct inode *inode, struct file *filp)
{
LOGINFO("shm_release_info: shm release\n");
return 0;
}
static int shm_mmap(struct file* file, struct vm_area_struct* vma)
{
LOGINFO("shm_mmap_info: enter\n");
if (remap_pfn_range(vma, /* 虚拟内存区域 */
vma->vm_start, /* 虚拟空间起始地址 */
virt_to_phys(shm_block_info) >> PAGE_SHIFT, /* 于物理内存对应的页帧号 */
vma->vm_end - vma->vm_start, /* 映射区域大小 */
vma->vm_page_prot /* 页面保护属性 */))
{
return -EAGAIN;
}
LOGINFO("shm_mmap_info: exit\n");
return 0;
}
static int arm_shm_init(void)
{
/* 申请的同时直接清零 */
shm_block_info = kzalloc(MEM_PAGE_SIZE,GFP_KERNEL);
if (shm_block_info == NULL)
{
INFOS("arm_shm_init_error: malloc shm_block_info fail\n");
return -EINVAL;
}
LOGINFO("arm_shm_init_info: shm_block_info = %p [%u]\n",shm_block_info,(uint64_t)shm_block_info);
/* 管理信息常驻内存 */
SetPageReserved(virt_to_page(shm_block_info));
/* 映射全局共享内存 */
struct ShmCfg *shm_cfg = shm_cfg_ops.get_by_id(core_info->id);
shm_total_start = ioremap(shm_cfg->total_shm->start,shm_cfg->total_shm->len);
if (shm_total_start == NULL)
{
INFOS("arm_shm_init_error: remap shm total fail\n");
return -EINVAL;
}
LOGINFO("arm_shm_init_info: shm_total_start = %p [%u]\n",shm_total_start,(uint64_t)shm_total_start);
misc_register(&arm_shm_dev); /* 注册杂项驱动 */
LOGINFO("arm_shm_init_success: shm init success!\n");
return 0;
}
static void arm_shm_exit(void)
{
ClearPageReserved(virt_to_page(shm_block_info));
kfree(shm_block_info); /* 归还映射内存区域 */
iounmap(shm_total_start);
misc_deregister(&arm_shm_dev); /* 注销杂项设备 */
LOGINFO("arm_shm_exit_success: shm exit success!\n");
}
module_init(arm_shm_init);
module_exit(arm_shm_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("anguoyoula");
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL */

View File

@ -0,0 +1,3 @@
SRC_FILES := $(wildcard *.c)
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,285 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../../../include/config/config.h"
#include "../../../include/msgqueue.h"
#include "../../../include/channel.h"
#include "../../../include/spinlock.h"
#include "../../../include/service.h"
/* XiUOS的MHU驱动 */
#if PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
#include <bsp_api.h>
#include <fsp_features.h>
#include "vector_data.h"
struct RegGroup /* 寄存器组 */
{
uint32_t STS; /* 中断状态寄存器,只读 */
uint32_t SET; /* 中断触发寄存器,只写 1 */
uint32_t CLR; /* 中断清除寄存器只写1 */
};
struct MhuChannel
{
struct Channel channel; /* 通道信息:必须放在第一个成员位置 */
struct RegGroup* msg_reg; /* 消息发送寄存器组 */
struct RegGroup* rsp_reg; /* 消息响应寄存器组 */
};
/* 寄存器基地址 */
#define REG_BASE (0x40400000U)
/* 消息队列互斥锁 */
static struct MsgQueueMutex xiuos_to_linux_msg_queue_mutex = { 0 };
struct MhuChannel mhu_channels[] =
{
{ /* 0: channel 1 -> Linux to XiUOS */
.channel =
{
.channel_info = LINUX_2_XIUOS_CHANNEL_INFO,
.msg_queue = NULL,
.msg_queue_mutex = NULL,
.reg_msg = NULL
},
.msg_reg = (struct RegGroup*) (REG_BASE + 0x20U),
.rsp_reg = (struct RegGroup*) (REG_BASE + 0x30U)
},
{ /* 1: channel 4 -> XiUOS to Linux */
.channel =
{
.channel_info = XIUOS_2_LINUX_CHANNEL_INFO,
.msg_queue = NULL,
.msg_queue_mutex = &xiuos_to_linux_msg_queue_mutex,
.reg_msg = NULL,
},
.msg_reg = (struct RegGroup*) (REG_BASE + 0x80U),
.rsp_reg = (struct RegGroup*) (REG_BASE + 0x90U)
},
{ /* 2: 空*/
.channel =
{
.channel_info = NULL
}
}
};
#define MHU_LINUX_2_XIUOS_CHANNEL (&mhu_channels[0])
#define MHU_XIUOS_2_LINUX_CHANNEL (&mhu_channels[1])
/* 通道初始化只能由一个任务完成 */
static volatile uint32_t channels_init_mark = INIT_MARK_RAW_STATE;
static MarkFlag channels_init_lock = ATOMIC_FLAG_INIT;
int32_t channels_init(void)
{
mark_flag_ops.lock(&channels_init_lock);
if (channels_init_mark == INIT_MARK_INITIALIZED)
{
mark_flag_ops.unlock(&channels_init_lock);
LOGINFO("xiuos_channels_init_info: init before\n");
return 0;
}
if (channels_init_mark == INIT_MARK_DESTORYED)
{
mark_flag_ops.unlock(&channels_init_lock);
INFOS("xiuos_channels_init_error: init fail before\n");
return -1;
}
uint32_t self_core_id = core_info->id;
int i = 0;
for (i = 0; mhu_channels[i].channel.channel_info != NULL; i++)
{
struct MhuChannel* channel = &mhu_channels[i];
/* 该通道起点是本节点 */
if (self_core_id == channel->channel.channel_info->src_core->id)
{
/* 映射出该通道的消息队列 */
channel->channel.msg_queue = (struct AmpMsgQueue *)(channel->channel.channel_info->src_queue->start);
/* 初始化该消息队列:在目标核心没有准备好之前,可以缓存,不能直接通知 */
if (msg_queue_ops.init(channel->channel.msg_queue, channel->channel.channel_info->src_queue->len) != 0)
{
channels_init_mark = INIT_MARK_DESTORYED;
mark_flag_ops.unlock(&channels_init_lock);
INFOS("xiuos_channels_init_error: init msg_queue fail\n");
return -1;
}
/* 初始化消息队列的互斥结构 */
if (msg_queue_mutex_ops.mutex_init(channel->channel.msg_queue_mutex, channel->channel.msg_queue->buf_size) != 0)
{
channels_init_mark = INIT_MARK_DESTORYED;
mark_flag_ops.unlock(&channels_init_lock);
INFOS("xiuos_channels_init_error: init msg_queue_mutex fail\n");
return -1;
}
/* 映射可以直接进行通知的寄存器地址 */
channel->channel.reg_msg = (uint32_t*)channel->channel.channel_info->reg_msg;
/* 开启通道中断 */
R_BSP_IrqEnable(channel->channel.channel_info->irq_rsp);
LOGINFO("src: msg queue mark = %u\n",channel->channel.msg_queue->working_mark);
}
else /* 该通道终点是本节点 */
{
/* 映射需要本通道处理的消息队列 */
channel->channel.msg_queue = (struct AmpMsgQueue *)(channel->channel.channel_info->dst_queue->start);
/* 告知该消息队列的发送方该消息队列可以进行通知了 */
channel->channel.msg_queue->working_mark = INIT_MARK_INITIALIZED;
/* 开启通道中断 */
R_BSP_IrqEnable(channel->channel.channel_info->irq_msg);
LOGINFO("dst: msg queue mark = %u\n",channel->channel.msg_queue->working_mark);
}
/* 开启通道时钟 */
R_BSP_MODULE_START(FSP_IP_MHU, channel->channel.channel_info->channel_num);
}
channels_init_mark = INIT_MARK_INITIALIZED;
mark_flag_ops.unlock(&channels_init_lock);
LOGINFO("xiuos_channels_init_success: init channel success\n");
return 0;
}
struct Channel* target_channel_get(uint32_t target_core_id)
{
int i = 0;
uint32_t self_core_id = core_info->id;
for (i = 0; mhu_channels[i].channel.channel_info != NULL; i++)
{
struct MhuChannel* channel = &mhu_channels[i];
if (self_core_id == channel->channel.channel_info->src_core->id && target_core_id == channel->channel.channel_info->dst_core->id)
{
LOGINFO("get_send_channel_success: self = %u, target = %u\n",self_core_id,target_core_id);
return &mhu_channels[i].channel;
}
}
INFOS("get_send_channel_error: self = %u, target = %u\n",self_core_id,target_core_id);
return NULL;
}
/* 通道接收到发送的消息时调用 */
int channel_msg_recv_interrupt(struct Channel* channel)
{
LOGINFO("channel_msg_recv_interrupt_info: enter\n");
struct AmpMsgQueue* msg_queue = channel->msg_queue;
struct Msg* msg = NULL;
struct AmpService* aim_service = NULL;
/* 获取消息队列中待处理的第一个消息:不能破坏链接结构 */
uint16_t head_index = msg_queue_ops.pop(msg_queue,&msg_queue->proc_ing_h);
int service_result = -1;
while (1)
{
if (head_index != msg_queue->buf_size)
{
msg = &msg_queue->entries[head_index].msg; /* 需要进行处理的消息 */
aim_service = amp_service_ops.get_by_id(msg->service_id); /* 获取需要调用的服务 */
if (aim_service == NULL)
{
LOGINFO("channel_msg_recv_interrupt_warn: service not hit, msg_index = %u, service_id = %u\n",head_index,msg->service_id);
/* 该消息已经被处理,但是消息请求的服务不存在 */
msg->flag.deal_state = MSG_DEAL_STATE_YES;
msg->flag.service_result = MSG_SERVICE_RET_NOT_EXITS;
}
else
{
LOGINFO("channel_msg_recv_interrupt_info: service hit, msg_index = %u, service_id = %u\n",head_index,msg->service_id);
service_result = aim_service->service(msg); /* 将消息转交给服务进行处理 */
if (service_result == 0) /* 设置服务响应的结果 */
{
msg->flag.service_result = MSG_SERVICE_RET_SUCCESS;
}
else
{
msg->flag.service_result = MSG_SERVICE_RET_FAIL;
}
msg->flag.deal_state = MSG_DEAL_STATE_YES; /* 标记该条信息已经被处理,发送核心可以直接开始下一步的操作 */
LOGINFO("channel_msg_recv_interrupt_info: service processed, msg_index = %u, service_id = %u, result = %s\n",
head_index, msg->service_id,
service_result == 0 ? "success" : "fail");
}
}
else
{
LOGINFO("channel_msg_recv_interrupt_info: no more msg exist, head_index = %u\n",head_index);
break;
}
head_index = msg_queue_ops.pop(msg_queue,&msg_queue->proc_ing_h);
}
/* 响应对方已经处理完毕 */
((struct MhuChannel*)channel)->rsp_reg->SET = 1U;
LOGINFO("channel_msg_recv_interrupt_info: exit\n");
return 0;
}
/* 通道接收到响应的消息时调用 */
int channel_msg_rsp_interrupt(struct Channel* channel)
{
LOGINFO("channel_msg_rsp_interrupt_info: enter\n");
/* 可以继续发送消息通知了 */
channel->msg_queue_mutex->msg_queue_mark = MSG_QUEUE_MARK_IDLE;
LOGINFO("channel_msg_rsp_interrupt_info: exit\n");
return 0;
}
void msg_ch1_ns(void)
{
LOGINFO("msg_ch1_ns_info: xiuos recv linux msg interrupt enter\n");
/* 通道1消息接收中断Linux给XiUOS发消息时触发 */
MHU_LINUX_2_XIUOS_CHANNEL->msg_reg->CLR = 1U; /* 清除中断 */
channel_msg_recv_interrupt(&MHU_LINUX_2_XIUOS_CHANNEL->channel); /* 处理接收到的消息 */
LOGINFO("msg_ch1_ns_info: xiuos recv linux msg interrupt over\n");
}
void rsp_ch4_ns(void)
{
LOGINFO("rsp_ch4_ns_info: xiuos recv linux rsp interrupt enter\n");
/* 通道4响应接收中断Linux给XiUOS消息响应时触发*/
MHU_XIUOS_2_LINUX_CHANNEL->rsp_reg->CLR = 1U; /* 清除中断 */
channel_msg_rsp_interrupt(&MHU_XIUOS_2_LINUX_CHANNEL->channel); /* 处理通道响应信息*/
LOGINFO("rsp_ch4_ns_info: xiuos recv linux rsp interrupt over\n");
}
#endif /* PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS*/

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../include/msg.h"
#include "../include/service.h"
static void msg_reset(struct Msg *msg)
{
msg->flag.deal_state = MSG_DEAL_STATE_NO; /* 设置当前消息未被处理 */
msg->flag.service_result = MSG_SERVICE_RET_NONE; /* 设置当前消息未被服务 */
/* 重置消息数据标记 */
#if PROTOCOL_CHOICE == PROTOCOL_AMP
msg->length = 0; /* 数据标记清空 */
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
#if PROTOCOL_CHOICE == PROTOCOL_PRIVATE
msg->data_size = 0; /* 数据标记清空 */
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
}
static int32_t msg_is_dealt(struct Msg *msg)
{
return msg->flag.deal_state == MSG_DEAL_STATE_YES ? 0 : -1;
}
struct MsgOps msg_ops =
{
.msg_reset = msg_reset,
.msg_is_dealt = msg_is_dealt
};

View File

@ -0,0 +1,207 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../include/msgqueue.h"
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
static int32_t msg_queue_mutex_init(struct MsgQueueMutex* mutex, uint16_t msg_queue_buf_size)
{
/* 是否已经被初始化过了 */
if (atomic_load(&mutex->mutex_init_mark) == INIT_MARK_INITIALIZED)
{
LOGINFO("msg_queue_mutex_init_info: mutex init before\n");
return 0;
}
uint32_t expected_mark = INIT_MARK_RAW_STATE; /* 期望该互斥体还未被初始化 */
uint32_t aim_mark = INIT_MARK_INITIALIZING; /* 期望将其切换为初始化中 */
/* 尝试获取互斥体的初始化权 */
if (!atomic_compare_exchange_strong(&mutex->mutex_init_mark, &expected_mark, aim_mark))
{
/* 当前互斥体的状态不是初始状态 */
while (1)
{
uint32_t now_mark = atomic_load(&mutex->mutex_init_mark);
LOGINFO("msg_queue_mutex_init_info: now_mark = %u\n",now_mark);
if (now_mark == INIT_MARK_INITIALIZING) /* 其他任务正在初始化:等待 */
{
LOGINFO("msg_queue_mutex_init_info: waiting others task init over\n");
}
else if (now_mark == INIT_MARK_INITIALIZED) /* 其他任务已经初始化完毕 */
{
LOGINFO("msg_queue_mutex_init_info: mutex init by others\n");
return 0;
}
else if (now_mark == INIT_MARK_DESTORYED) /* 互斥体初始化失败 */
{
INFOS("msg_queue_mutex_init_error: mutex init fail by others before\n");
return -1;
}
else /* 其他原因导致标志位损坏或未被初始化 */
{
INFOS("msg_queue_mutex_init_error: unknown init mark\n");
return -1;
}
}
}
/* 获取到了互斥体的初始化权 */
atomic_store(&mutex->msg_queue_mark,MSG_QUEUE_MARK_IDLE); /* 目标核心空闲 */
mutex->msg_wait_cnt = 0U; /* 待处理消息队列为空 */
/* 初始化相关的锁 */
byte_flag_ops.init(&mutex->empty_lock);
byte_flag_ops.init(&mutex->wait_lock);
/* 互斥体初始化完毕 */
atomic_store(&mutex->mutex_init_mark, INIT_MARK_INITIALIZED);
LOGINFO("msg_queue_mutex_init_info: mutex init success by this task\n");
return 0;
}
int32_t msg_queue_mutex_is_init(struct MsgQueueMutex* mutex)
{
return atomic_load(&mutex->mutex_init_mark) == INIT_MARK_INITIALIZED ? 0 : -1;
}
struct MsgQueueMutexOps msg_queue_mutex_ops =
{
.mutex_init = msg_queue_mutex_init,
.mutex_is_init = msg_queue_mutex_is_init
};
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
static int32_t msg_queue_init(struct AmpMsgQueue* msg_queue,uint32_t mem_len)
{
int i;
/* 相关结构空间大小计算*/
uint32_t infos_length = sizeof(struct AmpMsgQueue);
uint32_t buf_length = sizeof(struct MsgEntry);
if (mem_len < infos_length + buf_length) /* 消息队列至少要可以放入一个消息 */
{
INFOS("msg_queue_init_error: memmory size too small = %u, at least = %u\n", mem_len, buf_length + infos_length);
return -1;
}
uint32_t buf_size = (mem_len - infos_length) / buf_length; /* 计算可用的消息个数 */
if (buf_size > MSG_QUEUE_MAX_ENTRY_CNT)
{
INFOS("msg_queue_init_error: too much msg entry size = %u, max = %u\n", buf_size, MSG_QUEUE_MAX_ENTRY_CNT);
return -1;
}
msg_queue->empty_h = 0; /* 初始时全部缓冲区空闲 */
for (i = 0; i < buf_size; i++) /* 将空闲缓冲区链接为链表 */
{
msg_queue->entries[i].cur_idx = i;
msg_queue->entries[i].nxt_idx = i + 1;
}
msg_queue->wait_h = buf_size; /* 待处理消息队列为空 */
msg_queue->proc_ing_h = buf_size; /* 正在处理的消息队列为空 */
msg_queue->buf_size = buf_size; /* 标记该消息队列可用 */
LOGINFO("buffer_queue_init_success: mem_len = %u, infos_length = %u, buf_length = %u, buf_size = %u, unused = %u\n",
mem_len, infos_length, buf_length, buf_size,
mem_len - infos_length - buf_length * buf_size);
return 0;
}
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
static int32_t msg_queue_is_ready(struct AmpMsgQueue* msg_queue)
{
LOGINFO("msg_queue_is_ready_info: enter mark = %u\n",msg_queue->working_mark);
return msg_queue->working_mark == INIT_MARK_INITIALIZED ? 0 : -1;
}
static uint16_t msg_queue_pop(struct AmpMsgQueue* msg_queue,uint16_t* head)
{
uint16_t ret = msg_queue->buf_size;
if (*head >= msg_queue->buf_size) /* 链空 */
{
LOGINFO("msg_queue_pop_warn: have no more msg, end = %u\n",*head);
return ret;
}
ret = *head;
*head = msg_queue->entries[*head].nxt_idx;
msg_queue->entries[ret].nxt_idx = msg_queue->buf_size; /* 摘链 */
LOGINFO("msg_queue_pop_success: pop msg index = %u\n",ret);
return ret;
}
static int32_t msg_queue_push(struct AmpMsgQueue* msg_queue,uint16_t* head,uint16_t msg_index)
{
if (msg_index >= msg_queue->buf_size)
{
INFOS("msg_queue_push_error: msg index error = %u\n",msg_index);
return -1;
}
if (*head == msg_queue->buf_size) /* 链表为空 */
{
*head = msg_index;
msg_queue->entries[msg_index].nxt_idx = msg_queue->buf_size; /* 防止意外链接 */
}
else /* 链表非空 */
{
msg_queue->entries[msg_index].nxt_idx = *head; /* 头插法:相当于压栈 */
*head = msg_index;
}
LOGINFO("msg_queue_push_success: msg index = %u\n",msg_index);
return 0;
}
static int32_t msg_queue_transfer(struct AmpMsgQueue* msg_queue, uint16_t* from_head, uint16_t* to_head)
{
if (*from_head >= msg_queue->buf_size)
{
INFOS("msg_queue_transfer_error: from_head error = %u\n",*from_head);
return -1;
}
LOGINFO("msg_queue_transfer_info: from_head = %u, to_head = %u\n",*from_head, *to_head);
*to_head = *from_head;
*from_head = msg_queue->buf_size;
return 0;
}
struct MsgQueueOps msg_queue_ops =
{
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
.init = msg_queue_init,
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
.is_ready = msg_queue_is_ready,
.pop = msg_queue_pop,
.push = msg_queue_push,
.transfer = msg_queue_transfer
};

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../include/service.h"
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
static struct AmpService* get_service_by_id(uint32_t id)
{
int i = 0;
for (i = 0; services[i].service != NULL; i++)
{
if (services[i].service_id == id)
{
LOGINFO("get_service_by_id_success: id = %u\n",id);
return &services[i];
}
}
INFOS("get_service_by_id_error: have not such service, id = %u\n",id);
return NULL;
}
struct AmpServiceOps amp_service_ops =
{
.get_by_id = get_service_by_id
};
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */

View File

@ -0,0 +1,4 @@
SRC_DIR := xiuos
SRC_FILES := service_xiuos.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../../../include/amp.h"
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL
extern void* kshm_offset_to_addr(uint32_t offset);
int linux_echo_service(struct Msg *msg)
{
LOGINFO("linux_echo_service: enter\n");
#if PROTOCOL_CHOICE == PROTOCOL_PRIVATE
LOGINFO("linux_echo_service recv: pri data = %s,data_size = %u\n",msg->data,msg->data_size);
#endif /* PROTOCOL_CHOICE == PROTOCOL_PRIVATE */
#if PROTOCOL_CHOICE == PROTOCOL_AMP
char* data = kshm_offset_to_addr(msg->offset);
LOGINFO("linux_echo_service recv: amp data = %s, data_size = %u, offset = %u\n",data,msg->length,msg->offset);
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
LOGINFO("linux_echo_service: over\n");
return 0;
}
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL */

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../../../include/amp.h"
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL
extern void* kshm_offset_to_addr(uint32_t offset);
int linux_flip_service(struct Msg *msg)
{
LOGINFO("linux_flip_service: enter\n");
int i = 0;
uint8_t* data = NULL;
uint32_t data_length = 0;
#if PROTOCOL_CHOICE == PROTOCOL_PRIVATE
data = msg->data;
data_length = msg->data_size;
#endif /* PROTOCOL_CHOICE == PROTOCOL_PRIVATE */
#if PROTOCOL_CHOICE == PROTOCOL_AMP
data = kshm_offset_to_addr(msg->offset);
data_length = msg->length;
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
for (i = 0; i < data_length; i++)
{
data[i] = ~data[i];
}
LOGINFO("linux_flip_service: over\n");
return 0;
}
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL */

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../../include/amp.h"
#if PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL
extern int linux_echo_service(struct Msg *msg);
extern int linux_flip_service(struct Msg *msg);
struct AmpService services[] =
{
{
.service_id = LINUX_SERVICE_ECHO_ID,
.service = linux_echo_service
},
{
.service_id = LINUX_SERVICE_FLIP_ID,
.service = linux_flip_service
},
{
.service = NULL
}
};
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_KERNEL */

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../../include/amp.h"
#if PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
extern int xiuos_echo_service(struct Msg *msg);
extern int xiuos_flip_service(struct Msg *msg);
struct AmpService services[] =
{
{
.service_id = XIUOS_SERVICE_ECHO_ID,
.service = xiuos_echo_service
},
{
.service_id = XIUOS_SERVICE_FLIP_ID,
.service = xiuos_flip_service
},
{
.service = NULL
}
};
#endif /* PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */

View File

@ -0,0 +1,3 @@
SRC_FILES := $(wildcard *.c)
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../../../include/amp.h"
#if PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
int xiuos_echo_service(struct Msg *msg)
{
LOGINFO("xiuos_echo_service: enter\n");
#if PROTOCOL_CHOICE == PROTOCOL_PRIVATE
LOGINFO("xiuos_echo_service recv: pri data = %s\n",msg->data);
#endif /* PROTOCOL_CHOICE == PROTOCOL_PRIVATE */
#if PROTOCOL_CHOICE == PROTOCOL_AMP
char* data = shm_ops.offset_to_addr(msg->offset);
LOGINFO("xiuos_echo_service recv: amp data = %s\n",data);
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
LOGINFO("xiuos_echo_service: over\n");
return 0;
}
#endif /* PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../../../include/amp.h"
#if PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
int xiuos_flip_service(struct Msg *msg)
{
LOGINFO("xiuos_flip_service: enter\n");
uint8_t* data = NULL;
uint32_t data_length = 0;
#if PROTOCOL_CHOICE == PROTOCOL_PRIVATE
data = msg->data;
data_length = msg->data_size;
#endif /* PROTOCOL_CHOICE == PROTOCOL_PRIVATE */
#if PROTOCOL_CHOICE == PROTOCOL_AMP
data = shm_ops.offset_to_addr(msg->offset);
data_length = msg->length;
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
for (int i = 0; i < data_length; i++)
{
data[i] = ~data[i];
}
LOGINFO("xiuos_flip_service: over\n");
return 0;
}
#endif /* PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */

View File

@ -0,0 +1,477 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../include/shm.h"
#include "../include/spinlock.h"
#if PROTOCOL_CHOICE == PROTOCOL_AMP && (PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS)
/* 共享内存管理信息 */
static struct Shm shm = { 0 };
/* 初始化相关标记信息 */
static volatile uint32_t shm_init_mark = INIT_MARK_RAW_STATE;
static MarkFlag shm_init_lock = ATOMIC_FLAG_INIT;
static int32_t shm_addr_to_offset(void* ptr)
{
/* 指针范围不对 */
if (ptr < shm.shm_total_start || ptr > shm.shm_total_start + shm.shm_cfg->total_shm->len)
{
INFOS("shm_addr_to_offset_error: error range\n");
return -1;
}
return ptr - shm.shm_total_start;
}
static void* shm_offset_to_addr(uint32_t offset)
{
if (offset > shm.shm_cfg->total_shm->len)
{
INFOS("shm_offset_to_addr_error: error range\n");
return NULL;
}
return (void*)(shm.shm_total_start + offset);
}
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <signal.h>
/* SHM模块、内存映射相关数据 */
static int mem_fd = -1;
static int shm_fd = -1;
#endif /* #if PLATFORM_CHOICE == PLATFORM_LINUX_USER */
#if PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
/* XiUOS的直接放在这里 */
static struct ShmInfos shm_infos = { 0 };
#endif /* PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
static int32_t malloc_from_volatile_block(int start_index,int end_index,int size)
{
for (int i = start_index; i < end_index; i++)
{
if (shm.shm_infos->vblock_infos[i].state == VBLOCK_STATE_ENABLE) /* 当前区块还可以尝试继续进行分配 */
{
if (size <= shm.shm_infos->vblock_infos[i].available_size) /* 当前块可以满足此次内存分配请求 */
{
int32_t result = shm.shm_infos->vblock_infos[i].next_alloc_offset;
shm.shm_infos->vblock_infos[i].available_size -= size;
shm.shm_infos->vblock_infos[i].alloc_count += 1;
shm.shm_infos->vblock_infos[i].next_alloc_offset += size;
shm.shm_infos->vblock_current = i;
return result;
}
else /* 当前块无法满足分配要求 */
{
shm.shm_infos->vblock_infos[i].state = VBLOCK_STATE_DISENABLE; /* 当前块弃用,开始启用下一块 */
}
}
else /* 查看当前块能不能重新加入分配 */
{
if (shm.shm_infos->vblock_infos[i].free_count == shm.shm_infos->vblock_infos[i].alloc_count)
{
shm.shm_infos->vblock_infos[i].next_alloc_offset = shm.shm_infos->vblock_infos[i].alloc_start_offset;
shm.shm_infos->vblock_infos[i].available_size = shm.shm_infos->vblock_infos[i].total_length;
shm.shm_infos->vblock_infos[i].free_count = 0;
shm.shm_infos->vblock_infos[i].alloc_count = 0;
shm.shm_infos->vblock_infos[i].state = VBLOCK_STATE_ENABLE;
i --; /* 当前块重新加入分配 */
}
}
}
return -1; /* 分配未成功 */
}
static int32_t shm_init(void)
{
mark_flag_ops.lock(&shm_init_lock); /* 这个锁在RTOS上可以锁全部线程但是在Linux只能锁同一个进程内的线程 */
if (shm_init_mark == INIT_MARK_INITIALIZED) /* 已初始化过了 */
{
mark_flag_ops.unlock(&shm_init_lock);
LOGINFO("shm_init_info: shm init before\n");
return 0;
}
if (shm_init_mark == INIT_MARK_DESTORYED) /* 已经初始化损坏 */
{
mark_flag_ops.unlock(&shm_init_lock);
INFOS("shm_init_error: shm init error before\n");
return -1;
}
struct ShmCfg* shm_cfg = shm_cfg_ops.get_by_id(core_info->id); /* 获取当前核心的共享内存配置信息 */
if (shm_cfg == NULL)
{
shm_init_mark = INIT_MARK_DESTORYED;
mark_flag_ops.unlock(&shm_init_lock);
INFOS("shm_init_error: have no shm cfg for core = %u\n",core_info->id);
return -1;
}
shm.shm_cfg = shm_cfg;
if (shm_cfg->total_shm == NULL)
{
shm_init_mark = INIT_MARK_DESTORYED;
mark_flag_ops.unlock(&shm_init_lock);
INFOS("shm_init_error: must have total shm addr info even have no core shm\n");
return -1;
}
/* 提取各项共享内存配置信息 */
uint64_t total_shm_start = shm_cfg->total_shm->start;
uint32_t total_shm_length = shm_cfg->total_shm->len;
uint64_t total_shm_end = total_shm_start + total_shm_length;
INFOS("shm_init_info: total_shm [start = %p, length = %u KB]\n",(void*)total_shm_start,total_shm_length / KB);
uint64_t core_shm_start = 0U;
uint32_t core_shm_length = 0U;
uint64_t core_shm_end = 0U;
if (shm_cfg->core_shm == NULL) /* 当前节点没有共享内存 */
{
LOGINFO("shm_init_warn: have no core shm\n");
}
else /* 当前节点存在共享内存 */
{
core_shm_start = shm_cfg->core_shm->start;
core_shm_length = shm_cfg->core_shm->len;
core_shm_end = core_shm_start + core_shm_length;
LOGINFO("shm_init_info: core_shm [start = %p, length = %u KB]\n",(void*)core_shm_start,core_shm_length / KB);
}
/* 初始化共享内存管理指针 */
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER
mem_fd = open(MEM_DRIVER, O_RDWR | O_SYNC); /* 打开全映射驱动 */
if (mem_fd < 0)
{
shm_init_mark = INIT_MARK_DESTORYED;
mark_flag_ops.unlock(&shm_init_lock);
INFOS("shm_init_error: open mem dev fail %d\n", mem_fd);
return -1;
}
LOGINFO("shm_init_info: open mem dev success %d\n", mem_fd);
shm_fd = open(SHM_DRIVER_NAME, O_RDWR | O_SYNC); /* 打开SHM模块 */
if (shm_fd < 0)
{
shm_init_mark = INIT_MARK_DESTORYED;
mark_flag_ops.unlock(&shm_init_lock);
INFOS("shm_init_error: open shm dev fail %d\n", shm_fd);
return -1;
}
LOGINFO("shm_init_info: open shm dev success %d\n", shm_fd);
/* 将内核中的共有管理信息映射到用户空间 */
shm.shm_infos = mmap(NULL, MEM_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (shm.shm_infos == NULL)
{
shm_init_mark = INIT_MARK_DESTORYED;
mark_flag_ops.unlock(&shm_init_lock);
INFOS("shm_init_error: mmap shm manage info fail\n");
return -1;
}
/* 映射出内核中的管理信息块 */
shm.shm_total_start = mmap(NULL, total_shm_length, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, total_shm_start);
shm.shm_core_start = shm.shm_total_start + (core_shm_start - total_shm_start);
if (shm.shm_total_start == NULL)
{
shm_init_mark = INIT_MARK_DESTORYED;
mark_flag_ops.unlock(&shm_init_lock);
INFOS("shm_init_error: mmap shm fail\n");
return -1;
}
LOGINFO("shm_init_info: virtual addr [total_start = %p, core_start = %p]\n",shm.shm_total_start,shm.shm_core_start);
#endif /* #if PLATFORM_CHOICE == PLATFORM_LINUX_USER */
#if PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
shm.shm_infos = &shm_infos;
shm.shm_total_start = (void *)total_shm_start;
shm.shm_core_start = (void *)core_shm_start;
#endif /* PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */
if (atomic_load(&shm.shm_infos->block_init_mark) == INIT_MARK_INITIALIZED) /* 在整个节点内存探测是否已经被初始化过了 */
{
shm_init_mark = INIT_MARK_INITIALIZED;
mark_flag_ops.unlock(&shm_init_lock);
LOGINFO("shm_init_info: shm init before 2\n");
return 0;
}
uint32_t except_state = INIT_MARK_RAW_STATE; /* 假定该共享内存还未被初始化 */
/* 试图获取初始化权 */
if (!atomic_compare_exchange_strong(&shm.shm_infos->block_init_mark,&except_state,INIT_MARK_INITIALIZING))
{
while (1)
{
uint8_t init_state = atomic_load(&shm.shm_infos->block_init_mark);
if (init_state == INIT_MARK_INITIALIZING)
{
LOGINFO("shm_init_info: wait others shm init over\n");
}
else if (init_state == INIT_MARK_INITIALIZED)
{
shm_init_mark = INIT_MARK_INITIALIZED;
mark_flag_ops.unlock(&shm_init_lock);
LOGINFO("shm_init_info: init by others\n");
return 0;
}
else if (init_state == INIT_MARK_DESTORYED)
{
shm_init_mark = INIT_MARK_DESTORYED;
mark_flag_ops.unlock(&shm_init_lock);
INFOS("shm_init_error: init shm error by others or init mark error\n");
return -1;
}
}
}
/* 开始进行共享内存的初始化 */
shm.shm_infos->block_state_info = BLOCK_STATE_UNUSED; /* 初始共享内存状态 */
if (core_shm_length == 0) /* 当前节点没有共享内存 */
{
atomic_store(&shm.shm_infos->block_init_mark,INIT_MARK_INITIALIZED); /* 通知其他线程共享内存初始化完毕 */
shm_init_mark = INIT_MARK_INITIALIZED;
mark_flag_ops.unlock(&shm_init_lock);
LOGINFO("shm_init_info: init success ,but have no core shm\n");
return 0;
}
/* 初始化当前节点的共享内存 */
uint32_t min_block_size = shm_cfg->min_block_size < MEMORY_ALIGN_SIZE ? MEMORY_ALIGN_SIZE : shm_cfg->min_block_size; /* 短期区块最小区块大小 */
uint32_t pblock_size = shm_cfg->pblock_size > min_block_size ? shm_cfg->pblock_size : 0; /* 长期区块总大小 */
if (pblock_size > 0)
{
shm.shm_infos->block_state_info = shm.shm_infos->block_state_info | BLOCK_STATE_PERSISTENT; /* 共享内存里面有长期块 */
}
uint32_t vblock_size = shm_cfg->vblock_size > min_block_size ? shm_cfg->vblock_size : 0; /* 短期区块总大小 */
uint32_t vblock_each_size = 0U;
if (vblock_size > 0 && SHM_VBLOCK_CNT > 0)
{
shm.shm_infos->block_state_info = shm.shm_infos->block_state_info | BLOCK_STATE_VOLATILE; /* 共享内存里面有短期块 */
vblock_each_size = vblock_size / SHM_VBLOCK_CNT;
if (vblock_each_size < min_block_size) /* 查看内存配置是否合理 */
{
atomic_store(&shm.shm_infos->block_init_mark,INIT_MARK_DESTORYED); /* 告知其他线程共享内存初始化失败 */
shm_init_mark = INIT_MARK_DESTORYED;
mark_flag_ops.unlock(&shm_init_lock);
INFOS("shm_init_error: each vblock is too small vblock_each_size =%u, min_block_size = %u, vblock_size = %u, vblock_count = %u\n",vblock_each_size, min_block_size, vblock_size, SHM_VBLOCK_CNT);
return -1;
}
shm.shm_infos->vblock_each_size = vblock_each_size;
}
INFOS("shm_init_info: pblock_size = %u KB, vblock_size = %u KB, vblock_each_size = %u KB, min_block_size = %u B\n", pblock_size / KB, vblock_size / KB, vblock_each_size / KB, min_block_size);
/* 初始化互斥标记 */
byte_flag_ops.init(&shm.shm_infos->pblock_lock);
byte_flag_ops.init(&shm.shm_infos->vblock_lock);
uint32_t init_offset = core_shm_start - total_shm_start; /* 开始初始化共享内存的管理信息 */
/* 先初始化长期区 */
shm.shm_infos->pblock_info.next_alloc_offset = init_offset;
shm.shm_infos->pblock_info.available_size = pblock_size;
init_offset += pblock_size;
/* 初始化短期区 */
if (vblock_each_size > min_block_size) /* 存在短期区 */
{
for (int i = 0; i < SHM_VBLOCK_CNT; i++)
{
shm.shm_infos->vblock_infos[i].state = VBLOCK_STATE_ENABLE;
shm.shm_infos->vblock_infos[i].alloc_count = 0U;
shm.shm_infos->vblock_infos[i].free_count = 0U;
shm.shm_infos->vblock_infos[i].alloc_start_offset = init_offset;
shm.shm_infos->vblock_infos[i].next_alloc_offset = init_offset;
if (i != SHM_VBLOCK_CNT - 1) /* 非最后一个短期块 */
{
shm.shm_infos->vblock_infos[i].total_length = vblock_each_size;
shm.shm_infos->vblock_infos[i].available_size = vblock_each_size;
init_offset += vblock_each_size;
}
else /* 最后一个短期块 */
{
shm.shm_infos->vblock_infos[i].total_length = vblock_each_size + vblock_size % SHM_VBLOCK_CNT;
shm.shm_infos->vblock_infos[i].available_size = shm.shm_infos->vblock_infos[i].total_length;
init_offset += shm.shm_infos->vblock_infos[i].total_length;
}
INFOS("shm_init_info: index = %d, start_offset = %u, total_length = %u KB\n", i, shm.shm_infos->vblock_infos[i].alloc_start_offset, shm.shm_infos->vblock_infos[i].total_length / KB);
}
if (init_offset != core_shm_end - total_shm_start) /* 是否正确初始化 */
{
atomic_store(&shm.shm_infos->block_init_mark,INIT_MARK_DESTORYED);
shm_init_mark = INIT_MARK_DESTORYED;
mark_flag_ops.unlock(&shm_init_lock);
INFOS("shm_init_error: core_shm_end = %u, init_offset = %u\n", core_shm_end, init_offset);
return -1;
}
}
atomic_store(&shm.shm_infos->block_init_mark,INIT_MARK_INITIALIZED); /* 通知其他线程共享内存初始化完毕 */
shm_init_mark = INIT_MARK_INITIALIZED;
mark_flag_ops.unlock(&shm_init_lock);
LOGINFO("shm_init_success: init shm success\n");
return 0;
}
static void* shm_malloc(uint32_t size,enum MallocType type)
{
if (shm_init_mark != INIT_MARK_INITIALIZED)
{
INFOS("shm_malloc_error: init shm before use\n");
return NULL;
}
if (size == 0 || (shm.shm_infos->block_state_info & type) == 0)
{
INFOS("shm_malloc_warn: malloc size = 0 or unsupport malloc type\n");
return NULL;
}
/* 按照配置信息进行字节对齐 */
size = (size + shm.shm_cfg->bit_align -1) & (~(shm.shm_cfg->bit_align - 1));
switch (type)
{
case MALLOC_TYPE_P:
{
byte_flag_ops.lock(&shm.shm_infos->pblock_lock); /* 长期区锁 */
if (size > shm.shm_infos->pblock_info.available_size) /* 申请的内存大小超过了最大内存限制 */
{
byte_flag_ops.unlock(&shm.shm_infos->pblock_lock); /* 解锁 */
INFOS("shm_malloc_warn: the size is large than max avi size, size = %d, avi size = %d\n", size, shm.shm_infos->pblock_info.available_size);
return NULL;
}
void* result = shm.shm_total_start + shm.shm_infos->pblock_info.next_alloc_offset; /* 记录下需要返回的地址 */
shm.shm_infos->pblock_info.available_size -= size; /* 减去已经被分配的空间大小 */
shm.shm_infos->pblock_info.next_alloc_offset += size; /* 将待分配地址指向下一个位置 */
byte_flag_ops.unlock(&shm.shm_infos->pblock_lock); /* 解锁 */
LOGINFO("shm_malloc_success: MALLOC_TYPE_P [start address: %p, length = %d B]\n", result, size);
return result;
}
case MALLOC_TYPE_V:
{
byte_flag_ops.lock(&shm.shm_infos->vblock_lock); /* 短期锁 */
uint32_t current_volatile_block_index = shm.shm_infos->vblock_current; /* 记录开始查找前短期块的当前位置下标 */
int32_t result = malloc_from_volatile_block(current_volatile_block_index,SHM_VBLOCK_CNT,size); /* 从当前位置往后找 */
if (result < 0) /* 没找到 */
{
result = malloc_from_volatile_block(0,current_volatile_block_index,size); /* 从前往当前位置找 */
}
if (result < 0) /* 无法分配空间 */
{
byte_flag_ops.unlock(&shm.shm_infos->vblock_lock); /* 解锁 */
INFOS("shm_malloc_warn: have no such size space free now!\n");
return NULL;
}
byte_flag_ops.unlock(&shm.shm_infos->vblock_lock); /* 解锁 */
LOGINFO("shm_malloc_success: MALLOC_TYPE_V [start address: %p, length = %d B]\n", shm.shm_total_start + result, size);
return shm.shm_total_start + result;
}
default:
{
INFOS("shm_malloc_warn: not suported alloc type!\n");
return NULL;
}
}
}
static void shm_free(void* ptr)
{
if (shm_init_mark != INIT_MARK_INITIALIZED)
{
INFOS("shm_free: shm not init\n");
return ;
}
if (shm.shm_infos->block_state_info & BLOCK_STATE_VOLATILE == 0)
{
INFOS("shm_free_error: have no volatile blocks\n");
return;
}
if (ptr < shm.shm_core_start || ptr >= shm.shm_core_start + shm.shm_cfg->core_shm->len)
{
INFOS("shm_free_error: not such shm\n");
return ;
}
uint32_t data_offset = ptr - shm.shm_core_start - shm.shm_cfg->pblock_size;
uint32_t block_index = data_offset / shm.shm_infos->vblock_each_size; /* 读取短期块的控制信息 */
byte_flag_ops.lock(&shm.shm_infos->vblock_lock);
shm.shm_infos->vblock_infos[block_index].free_count += 1;
LOGINFO("shm_free_success: start = %p, index = %u, free_count = %u\n",ptr ,block_index, shm.shm_infos->vblock_infos[block_index].free_count);
byte_flag_ops.unlock(&shm.shm_infos->vblock_lock);
}
struct ShmOps shm_ops =
{
.addr_to_offset = shm_addr_to_offset,
.offset_to_addr = shm_offset_to_addr,
.shm_init = shm_init,
.shm_malloc = shm_malloc,
.shm_free = shm_free
};
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP && (PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS) */

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../include/spinlock.h"
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
static void byte_flag_init(ByteFlag* flag)
{
atomic_init(flag,BYTE_UNLOCK_STATE);
}
static int32_t byte_flag_is_locked(ByteFlag* flag)
{
return atomic_load(flag) == BYTE_LOCKED_STATE ? 0 : -1;
}
static void byte_flag_lock(ByteFlag* flag)
{
uint8_t expected_state = BYTE_UNLOCK_STATE; /* 只有处于未加锁状态的锁才能被加锁 */
uint8_t aim_state = BYTE_LOCKED_STATE; /* 需要将锁设置为已加锁状态 */
/* 尝试:直至加锁成功 */
while (!atomic_compare_exchange_strong(flag, &expected_state, aim_state))
{
/* 一次尝试后需要重置期望值 */
expected_state = BYTE_UNLOCK_STATE;
LOGINFO(".");
}
}
static int32_t byte_flag_unlock(ByteFlag* flag)
{
uint8_t expected_state = BYTE_LOCKED_STATE; /* 只有处于加锁状态的锁才能被解锁 */
uint8_t aim_state = BYTE_UNLOCK_STATE; /* 需要将锁设置为未加锁状态 */
/* 只有处于加锁状态的锁才能解锁:不支持递归加锁 */
if (!atomic_compare_exchange_strong(flag, &expected_state, aim_state))
{
LOGINFO("byte_flag_unlock_error: unexpected lock state\n");
return -1;
}
return 0;
}
static int32_t byte_flag_try_lock(ByteFlag* flag)
{
uint8_t expected_state = BYTE_UNLOCK_STATE; /* 只有处于未加锁状态的锁才能被加锁 */
uint8_t aim_state = BYTE_LOCKED_STATE; /* 需要将锁设置为已加锁状态 */
/* 只有处于加锁状态的锁才能解锁:不支持递归加锁 */
if (!atomic_compare_exchange_strong(flag, &expected_state, aim_state))
{
LOGINFO("byte_flag_try_lock_warn: byte flag is locked before\n");
return -1;
}
return 0;
}
struct ByteFlagOps byte_flag_ops =
{
.init = byte_flag_init,
.is_locked = byte_flag_is_locked,
.lock = byte_flag_lock,
.unlock = byte_flag_unlock,
.try_lock = byte_flag_try_lock
};
static void mark_flag_lock(MarkFlag* flag)
{
/* 尝试:直至加锁成功 */
while (atomic_flag_test_and_set(flag))
{
LOGINFO(".");
}
}
static void mark_flag_unlock(MarkFlag* flag)
{
atomic_flag_clear(flag);
}
static int32_t mark_flag_try_lock(MarkFlag* flag)
{
if (atomic_flag_test_and_set(flag))
{
LOGINFO("lock_flag_try_lock_warn: lock flag is locked\n");
return -1;
}
return 0;
}
struct MarkFlagOps mark_flag_ops =
{
.lock = mark_flag_lock,
.unlock = mark_flag_unlock,
.try_lock = mark_flag_try_lock
};
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER || PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */

View File

@ -0,0 +1,158 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../include/amp.h"
#if PLATFORM_CHOICE == PLATFORM_LINUX_USER
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include "stdint.h"
#include "sys/mman.h"
#include "sys/ioctl.h"
#include "sys/times.h"
/**
* 1
* 2
*/
int main(int argc, char *argv[])
{
clock_t ticks_start = times(NULL);
int send_count = atoi(argv[1]); /* 获取需要发送的次数 */
char *data = (char*)argv[2]; /* 需要发送的数据 */
int data_size = strlen(data); /* 需要发送数据的大小 */
INFOS("info : send [data = %s, times = %d, data_size = %d]\n", data, send_count, data_size);
struct Client amp_client = { 0 };
/* 初始化客户端连接Linux核心 */
if (client_ops.client_init(&amp_client, CORE_XIUOS_ID) != 0)
{
INFOS("error : client init [target_channel = %u]\n",CORE_XIUOS_ID);
return;
}
LOGINFO("info : client init [target_channel = %u]\n",CORE_XIUOS_ID);
/* 从通道中拿取一个发送给回显服务的长期消息缓冲区 */
struct Msg *msg = client_ops.empty_msg_get(&amp_client,XIUOS_SERVICE_ECHO_ID);
if (msg == NULL)
{
INFOS("error : empty msg get [service_id = %u]\n",XIUOS_SERVICE_ECHO_ID);
return;
}
LOGINFO("info : empty msg get [service_id = %u]\n",XIUOS_SERVICE_ECHO_ID);
/* 开始循环发送测试 */
for (int i = 0; i < send_count; i++) /* 准备多次发送 */
{
/* 重置该消息体 */
msg_ops.msg_reset(msg);
/* 数据填充 */
#if PROTOCOL_CHOICE == PROTOCOL_PRIVATE
int j = 0;
for (j = 0; j < data_size; j++)
{
msg->data[j] = data[j];
}
msg->data[data_size] = '\0';
msg->data_size = data_size + 1;
/* 消息发送 */
if (client_ops.msg_send_and_notify(&amp_client,msg) != 0)
{
INFOS("error : msg send [idx = %d, data_size = %u]\n",i, data_size + 1);
return;
}
LOGINFO("info : msg send [idx = %d, data_size = %u]\n",i, data_size + 1);
/* 等待消息响应 */
while (client_ops.msg_poll(msg) != 0)
{
;
}
LOGINFO("info : msg result [idx = %d, service_id = %u, result = %u]\n",i, msg->service_id,msg->flag.service_result);
#endif /* PROTOCOL_CHOICE == PROTOCOL_PRIVATE */
#if PROTOCOL_CHOICE == PROTOCOL_AMP
/* 共享内存分配 */
char* shm_data = (char*)client_ops.shm_malloc(&amp_client,data_size + 1,MALLOC_TYPE_V);
if (shm_data == NULL)
{
INFOS("error : shm malloc [idx = %d, size = %u, type = %u, ptr = NULL]\n",i, data_size + 1,MALLOC_TYPE_V);
return;
}
LOGINFO("info : shm malloc [idx = %d, size = %u, type = %u, ptr = %p]\n",i, data_size + 1,MALLOC_TYPE_V,shm_data);
/* 数据填充 */
int j = 0;
for (j = 0; j < data_size; j++)
{
shm_data[j] = data[j];
}
shm_data[data_size] = '\0';
/* 消息构建 */
msg->offset = client_ops.shm_addr_to_offset(shm_data);
msg->length = data_size + 1;
LOGINFO("info : msg fill [idx = %d, offset = %u, length = %u]\n",i, msg->offset,msg->length);
/* 消息发送 */
if (client_ops.msg_send_and_notify(&amp_client,msg) != 0)
{
INFOS("error : msg send [idx = %d, offset = %u, length = %u]\n",i, msg->offset,msg->length);
return;
}
LOGINFO("info : msg send [idx = %d, offset = %u, length = %u]\n",i, msg->offset,msg->length);
/* 等待消息响应 */
while (client_ops.msg_poll(msg) != 0)
{
;
}
LOGINFO("info : msg result [idx = %d, service_id = %u, result = %u]\n",i, msg->service_id,msg->flag.service_result);
/* 释放临时共享内存 */
client_ops.shm_free(&amp_client,shm_data);
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
}
if (client_ops.empty_msg_put(&amp_client, msg) != 0)
{
LOGINFO("error : return empty msg\n");
return;
}
LOGINFO("info : return empty msg\n");
if (client_ops.client_destory(&amp_client) != 0)
{
INFOS("error : client destory\n");
return ;
}
LOGINFO("info : client destory\n");
INFOS("info : test over\n");
clock_t ticks_end = times(NULL);
INFOS("ticks = %u\n",ticks_end - ticks_start);
return 0;
}
#endif /* PLATFORM_CHOICE == PLATFORM_LINUX_USER */

View File

@ -0,0 +1,24 @@
source /usr/local/arm/arm64/environment-setup-aarch64-poky-linux
aarch64-poky-linux-gcc \
-mtune=cortex-a55 -fstack-protector-strong -D_FORTIFY_SOURCE=2 \
-Wformat -Wformat-security -Werror=format-security \
--sysroot=/usr/local/arm/arm64/sysroots/aarch64-poky-linux \
-o amp_echo_test \
amp_echo_test.c \
../src/channel.c \
../src/client.c \
../src/config.c \
../src/msgqueue.c \
../src/msg.c \
../src/shm.c \
../src/spinlock.c \
-Wall -O2 -g -DCFG_CA5X -pthread
sudo chmod 755 amp_echo_test
set +e
sudo rm /media/ubuntu/RZ_ext/home/root/amp_echo_test
set -e
sudo mv amp_echo_test /media/ubuntu/RZ_ext/home/root

View File

@ -0,0 +1,4 @@
SRC_FILES := $(wildcard *.c)
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "../include/amp.h"
#if PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS
#include <xizi.h>
#include <shell.h>
/**
* 1
* 2
*/
void amp_echo_test(int send_count, char* data)
{
x_ticks_t ticks_start = CurrentTicksGain();
int data_size = strlen(data); /* 需要发送数据的大小 */
INFOS("info : send [data = %s, times = %d, data_size = %d]\n", data, send_count, data_size);
struct Client amp_client = { 0 };
/* 初始化客户端连接Linux核心 */
if (client_ops.client_init(&amp_client, CORE_LINUX_ID) != 0)
{
INFOS("error : client init [target_channel = %u]\n",CORE_LINUX_ID);
return;
}
LOGINFO("info : client init [target_channel = %u]\n",CORE_LINUX_ID);
/* 从通道中拿取一个发送给回显服务的长期消息缓冲区 */
struct Msg *msg = client_ops.empty_msg_get(&amp_client,LINUX_SERVICE_ECHO_ID);
if (msg == NULL)
{
INFOS("error : empty msg get [service_id = %u]\n",LINUX_SERVICE_ECHO_ID);
return;
}
LOGINFO("info : empty msg get [service_id = %u]\n",LINUX_SERVICE_ECHO_ID);
/* 开始循环发送测试 */
for (int i = 0; i < send_count; i++) /* 准备多次发送 */
{
/* 重置该消息体 */
msg_ops.msg_reset(msg);
/* 数据填充 */
#if PROTOCOL_CHOICE == PROTOCOL_PRIVATE
int j = 0;
for (j = 0; j < data_size; j++)
{
msg->data[j] = data[j];
}
msg->data[data_size] = '\0';
msg->data_size = data_size + 1;
/* 消息发送 */
if (client_ops.msg_send_and_notify(&amp_client,msg) != 0)
{
INFOS("error : msg send [idx = %d, data_size = %u]\n",i, data_size + 1);
return;
}
LOGINFO("info : msg send [idx = %d, data_size = %u]\n",i, data_size + 1);
/* 等待消息响应 */
while (client_ops.msg_poll(msg) != 0)
{
;
}
LOGINFO("info : msg result [idx = %d, service_id = %u, result = %u]\n",i, msg->service_id,msg->flag.service_result);
#endif /* PROTOCOL_CHOICE == PROTOCOL_PRIVATE */
#if PROTOCOL_CHOICE == PROTOCOL_AMP
/* 共享内存分配 */
char* shm_data = (char*)client_ops.shm_malloc(&amp_client,data_size + 1,MALLOC_TYPE_V);
if (shm_data == NULL)
{
INFOS("error : shm malloc [idx = %d, size = %u, type = %u, ptr = NULL]\n",i, data_size + 1,MALLOC_TYPE_V);
return;
}
LOGINFO("info : shm malloc [idx = %d, size = %u, type = %u, ptr = %p]\n",i, data_size + 1,MALLOC_TYPE_V,shm_data);
/* 数据填充 */
memcpy(shm_data,data,data_size + 1);
/* 消息构建 */
msg->offset = client_ops.shm_addr_to_offset(shm_data);
msg->length = data_size + 1;
LOGINFO("info : msg fill [idx = %d, offset = %u, length = %u]\n",i, msg->offset,msg->length);
/* 消息发送 */
if (client_ops.msg_send_and_notify(&amp_client,msg) != 0)
{
INFOS("error : msg send [idx = %d, offset = %u, length = %u]\n",i, msg->offset,msg->length);
return;
}
LOGINFO("info : msg send [idx = %d, offset = %u, length = %u]\n",i, msg->offset,msg->length);
/* 等待消息响应 */
while (client_ops.msg_poll(msg) != 0)
{
;
}
LOGINFO("info : msg result [idx = %d, service_id = %u, result = %u]\n",i, msg->service_id,msg->flag.service_result);
/* 释放临时共享内存 */
client_ops.shm_free(&amp_client,shm_data);
#endif /* PROTOCOL_CHOICE == PROTOCOL_AMP */
}
if (client_ops.empty_msg_put(&amp_client, msg) != 0)
{
LOGINFO("error : return empty msg\n");
return;
}
LOGINFO("info : return empty msg\n");
if (client_ops.client_destory(&amp_client) != 0)
{
INFOS("error : client destory\n");
return ;
}
LOGINFO("info : client destory\n");
INFOS("info : test over\n");
x_ticks_t ticks_end = CurrentTicksGain();
INFOS("ticks = %u\n",ticks_end - ticks_start);
return;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(2)|SHELL_CMD_DISABLE_RETURN, AmpEchoTest, amp_echo_test, echo test [send_count] [char_data]);
#endif /* PLATFORM_CHOICE == PLATFORM_RTOS_XIUOS */

View File

@ -0,0 +1,35 @@
echo "cd make dir"
cd /home/ubuntu/Desktop/XiUOS/gitlink-xiuos/xiuos
echo "start make"
make BOARD=rzg2ul-m33 clean
make BOARD=rzg2ul-m33
echo "end make"
cd /home/ubuntu/Desktop/XiUOS/gitlink-xiuos/xiuos/Ubiquitous/XiZi_IIoT/board/rzg2ul-m33/amp/test_xiuos
echo "Post build script started"
inputfilename=/home/ubuntu/Desktop/XiUOS/gitlink-xiuos/xiuos/Ubiquitous/XiZi_IIoT/build/XiZi-rzg2ul-m33.elf
filebody=rzg2ul_cm33_rpmsg_demo
tool_chain_dir=/usr/local/arm/gcc-arm-none-eabi-10.3-2021.10
${tool_chain_dir}/bin/arm-none-eabi-objcopy -O binary -j .text.secure_vector ${inputfilename} ${filebody}_secure_vector.bin
${tool_chain_dir}/bin/arm-none-eabi-objcopy -O binary -j .text.non_secure_vector ${inputfilename} ${filebody}_non_secure_vector.bin
${tool_chain_dir}/bin/arm-none-eabi-objcopy -O binary -j .text.secure_code ${inputfilename} ${filebody}_secure_code.bin
${tool_chain_dir}/bin/arm-none-eabi-objcopy -O binary -j .text.non_secure_code -j .data ${inputfilename} ${filebody}_non_secure_code.bin
echo "Post build script complete"
set +e
rm /media/ubuntu/RZ_FAT/${filebody}_secure_vector.bin
rm /media/ubuntu/RZ_FAT/${filebody}_non_secure_vector.bin
rm /media/ubuntu/RZ_FAT/${filebody}_secure_code.bin
rm /media/ubuntu/RZ_FAT/${filebody}_non_secure_code.bin
set -e
mv ${filebody}_secure_vector.bin /media/ubuntu/RZ_FAT/
mv ${filebody}_non_secure_vector.bin /media/ubuntu/RZ_FAT/
mv ${filebody}_secure_code.bin /media/ubuntu/RZ_FAT/
mv ${filebody}_non_secure_code.bin /media/ubuntu/RZ_FAT/

View File

@ -9,7 +9,7 @@ export CROSS_COMPILE ?=/usr/local/arm/gcc-arm-none-eabi-10.3-2021.10/bin/arm-non
# RELEASE
CFLAGS := -mthumb -mcpu=cortex-m33+nodsp+nofp -fdiagnostics-parseable-fixits -Og -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections
CFLAGS += -Wunused -Wuninitialized -Wall -Wextra -Wmissing-declarations -Wconversion -Wpointer-arith -Wshadow -Wlogical-op
CFLAGS += -Waggregate-return -Wfloat-equal -Wnull-dereference -g -std=c99 -mcmse
CFLAGS += -Waggregate-return -Wfloat-equal -Wnull-dereference -g -std=c11 -mcmse
export CFLAGS

View File

@ -17,8 +17,8 @@
#undef FSP_NOT_DEFINED
#define BSP_CFG_MCU_VCC_MV (3300)
#define BSP_CFG_S_STACK_MAIN_BYTES (0x200)
#define BSP_CFG_STACK_MAIN_BYTES (0x5000)
#define BSP_CFG_HEAP_BYTES (0xf000)
#define BSP_CFG_STACK_MAIN_BYTES (2048000)
#define BSP_CFG_HEAP_BYTES (20480000)
#define BSP_CFG_PARAM_CHECKING_ENABLE (0)
#define BSP_CFG_ASSERT (0)
#define BSP_CFG_ERROR_LOG (0)

View File

@ -74,7 +74,8 @@ BSP_DONT_REMOVE fsp_vector_t g_vector_table[BSP_ICU_VECTOR_MAX_ENTRIES] BSP_PLAC
Default_Handler, /* IRQ:66 */
Default_Handler, /* IRQ:67 */
Default_Handler, /* IRQ:68 */
metal_irq_isr_wrapper, /* IRQ:69 MHU1 MSG_INT_NS (Non-Secure Message Interrupt ch1) */
// metal_irq_isr_wrapper, /* IRQ:69 MHU1 MSG_INT_NS (Non-Secure Message Interrupt ch1) */
msg_ch1_ns, /* IRQ:69 */
Default_Handler, /* IRQ:70 */
Default_Handler, /* IRQ:71 */
Default_Handler, /* IRQ:72 */
@ -83,7 +84,8 @@ BSP_DONT_REMOVE fsp_vector_t g_vector_table[BSP_ICU_VECTOR_MAX_ENTRIES] BSP_PLAC
Default_Handler, /* IRQ:75 */
Default_Handler, /* IRQ:76 */
Default_Handler, /* IRQ:77 */
Default_Handler, /* IRQ:78 */
// Default_Handler, /* IRQ:78 */
rsp_ch4_ns, /* IRQ:78 */
Default_Handler, /* IRQ:79 */
Default_Handler, /* IRQ:80 */
Default_Handler, /* IRQ:81 */

View File

@ -11,13 +11,15 @@ FSP_HEADER
/* ISR prototypes */
void gtm_int_isr(void);
void metal_irq_isr_wrapper(void);
// void metal_irq_isr_wrapper(void);
void scif_uart_eri_isr(void);
void scif_uart_bri_isr(void);
void scif_uart_rxi_isr(void);
void scif_uart_txi_isr(void);
void scif_uart_tei_isr(void);
void msg_ch1_ns(void);
void rsp_ch4_ns(void);
/** Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */
FSP_FOOTER

View File

@ -17,6 +17,7 @@
* LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS.
**********************************************************************************************************************/
#define USE_AMP
#include "hal_data.h"
#include <board.h>
@ -24,6 +25,8 @@
#include <xizi.h>
#include <arch_interrupt.h>
#include <rpmsg_task.h>
#include <channel.h>
#include <shm.h>
// FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
@ -70,6 +73,18 @@ void hal_entry(void)
/* system irq table must be inited before initialization of Hardware irq */
SysInitIsrManager();
/* init sharememory */
memset(XIUOS_SHM_TOTAL_ADDR_INFO->start,0,XIUOS_SHM_TOTAL_ADDR_INFO->len);
memset(XIUOS_2_LINUX_MSG_QUEUE_ADDR_INFO->start,0,XIUOS_2_LINUX_MSG_QUEUE_ADDR_INFO->len);
memset(XIUOS_2_XIUOS_MSG_QUEUE_ADDR_INFO->start,0,XIUOS_2_XIUOS_MSG_QUEUE_ADDR_INFO->len);
/* 初始化通道信息 */
channel_ops.channels_init();
#if PROTOCOL_CHOICE == PROTOCOL_AMP
/* 初始化共享内存 */
shm_ops.shm_init();
#endif /* PROTOCOL_CHOICE == PROTOCOL_PRIVATE */
InitBoardMemory((void *)HEAP_START, (void *)HEAP_END);
KPrintf("hal_entry: InitBoardMemory -- HEAP_START = %p, HEAP_END = %p, Size = %dKB !\n"
,(void *)HEAP_START,(void *)HEAP_END,(((void *)HEAP_END) - ((void *)HEAP_START)) / 1024);

View File

@ -42,6 +42,10 @@ endif
ifeq ($(BSP_ROOT),$(KERNEL_ROOT)/board/rzg2ul-m33)
KERNELPATHS += \
-I$(KERNEL_ROOT)/arch/arm/cortex-m33 \
-I$(BSP_ROOT)/amp/include \
-I$(BSP_ROOT)/amp/include/config \
-I$(BSP_ROOT)/amp/include/config/ipi \
-I$(BSP_ROOT)/amp/include/config/service \
-I$(BSP_ROOT)/rzg/arm/CMSIS_5/CMSIS/Core/Include \
-I$(BSP_ROOT)/rzg/board/rzg2ul_smarc \
-I$(BSP_ROOT)/rzg/fsp/inc \

View File

@ -506,7 +506,9 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums
#define IP_REASSEMBLY 1
#define IP_FRAG 1
#define IP_REASS_MAX_PBUFS 10
#ifndef MEMP_NUM_REASSDATA
#define MEMP_NUM_REASSDATA 10
#endif
#else
#define IP_REASSEMBLY 0
#define IP_FRAG 0