From d8ac0998b27d950f15e6a09552556145e6e1f9be Mon Sep 17 00:00:00 2001 From: wuzheng Date: Mon, 28 Nov 2022 09:38:35 +0800 Subject: [PATCH 01/33] fix configure network problem and configure fpio for w5500 --- .../ethernet/connect_w5500.c | 65 ++++++++++++------- .../third_party_driver/gpio/drv_io_config.c | 5 ++ .../include/drv_io_config.h | 3 +- .../third_party_driver/spi/Kconfig | 8 +-- 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c index 22803ee9e..ba1e0b810 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c @@ -26,9 +26,9 @@ const uint32_t socket_tcp = 0; const uint32_t g_wiznet_buf_size = 2048; static wiz_NetInfo g_wiz_netinfo = {.mac = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11}, - .ip = {192, 168, 31, 13}, - .sn = {255, 255, 255, 0}, - .gw = {192, 168, 31, 1}, + .ip = {192, 168, 131, 42}, + .sn = {255, 255, 254, 0}, + .gw = {192, 168, 130, 1}, .dns = {0, 0, 0, 0}, .dhcp = NETINFO_STATIC}; @@ -473,33 +473,52 @@ void ifconfig() { SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), ifconfig, ifconfig, printf w5500 configurations); -void char_arr_assign(uint8_t **dst, uint32_t *src, uint32_t len) { +void char_arr_assign(uint8_t *dst, uint32_t *src, int len) { for (int i = 0; i < len; ++i) { - (*dst)[i] = (uint8_t)(src[i]); + dst[i] = (uint8_t)(src[i]); } } -void config_w5500_network(char *mac, char *ip, char *sn, char *gw, char *dns) { +char *network_param_name[] = {"ip", "sn", "gw"}; + +void config_w5500_network(int argc, char *argv[]) { + if (argc < 2) { + KPrintf("[W5500] Network config require params.\n"); + return; + } + wiz_NetInfo wiz_netinfo; - uint32_t tmp_arr[4]; - // config netinfo - sscanf(mac, "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1], &tmp_arr[2], - &tmp_arr[3]); - char_arr_assign((uint8_t **)&wiz_netinfo.mac, tmp_arr, 4); - sscanf(ip, "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1], &tmp_arr[2], &tmp_arr[3]); - char_arr_assign((uint8_t **)&wiz_netinfo.ip, tmp_arr, 4); - sscanf(sn, "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1], &tmp_arr[2], &tmp_arr[3]); - char_arr_assign((uint8_t **)&wiz_netinfo.sn, tmp_arr, 4); - sscanf(gw, "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1], &tmp_arr[2], &tmp_arr[3]); - char_arr_assign((uint8_t **)&wiz_netinfo.gw, tmp_arr, 4); - sscanf(dns, "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1], &tmp_arr[2], - &tmp_arr[3]); - char_arr_assign((uint8_t **)&wiz_netinfo.dns, tmp_arr, 4); - // set new netinfo + memcpy(&wiz_netinfo, &g_wiz_netinfo, sizeof(wiz_NetInfo)); + + int cur_arg_idx = 1; + + while (argv[cur_arg_idx] != NULL) { + if (argv[cur_arg_idx + 1] == NULL) { + KPrintf("[W5500] Network config %s requires value.\n", argv[cur_arg_idx]); + return; + } + uint32_t tmp_arr[4]; + sscanf(argv[cur_arg_idx + 1], "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1], + &tmp_arr[2], &tmp_arr[3]); + if (memcmp(argv[cur_arg_idx], network_param_name[0], 2 * sizeof(char)) == + 0) { + char_arr_assign(wiz_netinfo.ip, tmp_arr, 4); + } else if (memcmp(argv[cur_arg_idx], network_param_name[1], + 2 * sizeof(char)) == 0) { + char_arr_assign(wiz_netinfo.sn, tmp_arr, 4); + } else if (memcmp(argv[cur_arg_idx], network_param_name[2], + 2 * sizeof(char)) == 0) { + char_arr_assign(wiz_netinfo.gw, tmp_arr, 4); + } else { + KPrintf("[W5500] Invalid network param.\n"); + } + cur_arg_idx += 2; + } + ctlnetwork(CN_SET_NETINFO, (void *)&wiz_netinfo); + KPrintf("[W5500] Network config success.\n", argv[cur_arg_idx]); ifconfig(); } -SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | - SHELL_CMD_PARAM_NUM(5), +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), config_w5500_network, config_w5500_network, set w5500 configurations); \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c index 0c7167441..33bf5bd75 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c @@ -50,6 +50,11 @@ static struct io_config IOCONFIG(BSP_LCD_RST_PIN, HS_GPIO(FPIOA_LCD_RST)), #endif +#ifdef BSP_USING_W5500 + IOCONFIG(BSP_WIZ_RST_PIN, HS_GPIO(WIZ_RST_PIN)), + IOCONFIG(BSP_WIZ_INT_PIN, HS_GPIO(WIZ_INT_PIN)), +#endif + #ifdef BSP_USING_SPI1 IOCONFIG(BSP_SPI1_CLK_PIN, FUNC_SPI1_SCLK), IOCONFIG(BSP_SPI1_D0_PIN, FUNC_SPI1_D0), diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h index 4c4f86972..2ff8356b0 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h @@ -47,7 +47,8 @@ enum HS_GPIO_CONFIG { SPI1_CS3_PIN, #endif #ifdef BSP_USING_W5500 - WIZ_RST_PIN, WIZ_INT_PIN, + WIZ_RST_PIN, + WIZ_INT_PIN, #endif GPIO_ALLOC_START /* index of gpio driver start */ } diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Kconfig index d1ebdeb3c..19f485458 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Kconfig @@ -12,13 +12,13 @@ if BSP_USING_SPI1 default "spi1_drv" config BSP_SPI1_CLK_PIN int "spi1 clk pin number" - default 6 + default 9 config BSP_SPI1_D0_PIN int "spi1 d0 pin number" - default 8 + default 11 config BSP_SPI1_D1_PIN int "spi1 d1 pin number" - default 7 + default 10 menuconfig BSP_SPI1_USING_SS0 bool "SPI1 Enable SS0" default y @@ -28,7 +28,7 @@ if BSP_USING_SPI1 default "spi1_dev0" config BSP_SPI1_SS0_PIN int "spi1 ss0 pin number" - default 9 + default 12 menuconfig RESOURCES_SPI_LORA bool "Using spi lora function" default n From 100fe8c2d014b29e3b711858901714fabf80ddde Mon Sep 17 00:00:00 2001 From: wuzheng Date: Tue, 29 Nov 2022 09:30:48 +0800 Subject: [PATCH 02/33] add w5500 test example --- APP_Framework/Applications/app_test/Kconfig | 4 + APP_Framework/Applications/app_test/Makefile | 6 +- .../Applications/app_test/test_loraE220.c | 4 +- .../Applications/app_test/test_w5500.c | 81 +++++++++++++++++++ .../transform_layer/xizi/transform.h | 5 ++ 5 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 APP_Framework/Applications/app_test/test_w5500.c diff --git a/APP_Framework/Applications/app_test/Kconfig b/APP_Framework/Applications/app_test/Kconfig index 1c2965bd2..e25b29155 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -192,6 +192,10 @@ menu "test app" bool "Config test lcd device" default n + config USER_TEST_W5500 + select BSP_USING_W5500 + bool "Config test W5500 only for edu-riscv64" + default n endif endmenu diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 68801066a..830c40916 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -83,7 +83,11 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y) ifeq ($(CONFIG_USER_TEST_CAMERA),y) SRC_FILES += test_camera.c - endif + endif + + ifeq ($(CONFIG_USER_TEST_W5500),y) + SRC_FILES += test_w5500.c + endif include $(KERNEL_ROOT)/compiler.mk endif diff --git a/APP_Framework/Applications/app_test/test_loraE220.c b/APP_Framework/Applications/app_test/test_loraE220.c index c4409dd21..78c27f305 100644 --- a/APP_Framework/Applications/app_test/test_loraE220.c +++ b/APP_Framework/Applications/app_test/test_loraE220.c @@ -67,7 +67,6 @@ void TestLora(int argc, char *argv[]) printf("pin configure success\n"); struct SerialDataCfg uart_cfg; - memset(&uart_cfg, 0, sizeof(struct SerialDataCfg)); // loraE220 support only 9600bps with 8N1 during initializing uart_cfg.serial_baud_rate = BAUD_RATE_9600; @@ -96,7 +95,8 @@ void TestLora(int argc, char *argv[]) printf("lora configure into sleep(configure) mode\n"); // send configure data, and receive the same length of data - char sendbuff[] = {0xC0, 0x00, 0x05, 0x19, 0x49, 0xE6, 0x00, 0x17}; // config as address 1949 CH17 36.8kps + // configure loraE220 as address 1949 CH17 36.8kps + char sendbuff[] = {0xC0, 0x00, 0x05, 0x19, 0x49, 0xE6, 0x00, 0x17}; PrivTaskDelay(2000); diff --git a/APP_Framework/Applications/app_test/test_w5500.c b/APP_Framework/Applications/app_test/test_w5500.c new file mode 100644 index 000000000..2a589171f --- /dev/null +++ b/APP_Framework/Applications/app_test/test_w5500.c @@ -0,0 +1,81 @@ +#include +#include +#include + +#include + +#define BUFF_SIZE 128 +#define RECV_SIZE 16 +#define TCP_PORT 12345 + +const static uint32_t sn = 0; +const static uint32_t socket_tcp = 0; + +static int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, + uint16_t port, enum TCP_OPTION opt) { + int32_t ret = 0; + uint16_t size = 0, sentsize = 0; + switch (getSn_SR(sn)) { + case SOCK_ESTABLISHED: + if (getSn_IR(sn) & Sn_IR_CON) { + printf("%d:Connected\r\n", sn); + setSn_IR(sn, Sn_IR_CON); + } + if (opt == SEND_DATA) { + uint32_t sent_size = 0; + memset(buf,0,buf_size); + strcpy(buf,"The message has been recved"); + ret = wiz_sock_send(socket_tcp, buf, buf_size); + if (ret < 0) { + wiz_sock_close(socket_tcp); + return ret; + } + } else if (opt == RECV_DATA) { + uint32_t size = 0; + if ((size = getSn_RX_RSR(sn)) > 0) { + if (size > buf_size) size = buf_size; + memset(buf,0,buf_size); + ret = wiz_sock_recv(sn, buf, size); + printf("Recv message: %s\n",buf); + return ret; + } + } + break; + case SOCK_CLOSE_WAIT: + printf("%d:CloseWait\r\n", sn); + if ((ret = wiz_sock_disconnect(sn)) != SOCK_OK) return ret; + printf("%d:Closed\r\n", sn); + break; + case SOCK_INIT: + printf("%d:Listen, port [%d]\r\n", sn, port); + if ((ret = wiz_sock_listen(sn)) != SOCK_OK) return ret; + break; + case SOCK_CLOSED: + printf("%d:LBTStart\r\n", sn); + if ((ret = wiz_socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret; + printf("%d:Opened\r\n", sn); + break; + default: + break; + } + return 0; +} + +void TestSocketInW5500(int argc, char *argv[]) +{ + x_err_t ret; + uint8_t buf[BUFF_SIZE] = {0}; + + while (1) { + ret = wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, RECV_DATA); + if (ret > 0) { + wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, SEND_DATA); + }; + } + + return ; + +} + + +PRIV_SHELL_CMD_FUNCTION(TestSocketInW5500, a w5500 test sample, PRIV_SHELL_CMD_MAIN_ATTR); \ No newline at end of file diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.h b/APP_Framework/Framework/transform_layer/xizi/transform.h index 7514d9297..9cb3be855 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.h +++ b/APP_Framework/Framework/transform_layer/xizi/transform.h @@ -227,6 +227,11 @@ struct RtcDrvConfigureParam time_t *time; }; +enum TCP_OPTION { + SEND_DATA = 0, + RECV_DATA, +}; + #define PRIV_SYSTICK_GET (CurrentTicksGain()) #define PRIV_LCD_DEV "/dev/lcd_dev" #define MY_DISP_HOR_RES BSP_LCD_Y_MAX From 0b49dd1a3cdcb32e17c839e07ee33869efae6d5c Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Tue, 29 Nov 2022 17:11:51 +0800 Subject: [PATCH 03/33] feat add melsec protocol for control framework --- .../Framework/control/plc_protocol/Kconfig | 12 + .../control/plc_protocol/include/melsec.h | 97 ++- .../control/plc_protocol/melsec/Kconfig | 18 + .../control/plc_protocol/melsec/Makefile | 2 +- .../control/plc_protocol/melsec/melsec.c | 669 ++++++++++++++++++ .../Framework/control/shared/control_def.c | 11 + 6 files changed, 806 insertions(+), 3 deletions(-) create mode 100644 APP_Framework/Framework/control/plc_protocol/melsec/melsec.c diff --git a/APP_Framework/Framework/control/plc_protocol/Kconfig b/APP_Framework/Framework/control/plc_protocol/Kconfig index 9839fe26e..11d498f81 100755 --- a/APP_Framework/Framework/control/plc_protocol/Kconfig +++ b/APP_Framework/Framework/control/plc_protocol/Kconfig @@ -1,15 +1,27 @@ config CONTROL_PROTOCOL_FINS bool "Using fins control protocol" default n +if CONTROL_PROTOCOL_FINS + source "$APP_DIR/Framework/control/plc_protocol/fins/Kconfig" +endif config CONTROL_PROTOCOL_MELSEC bool "Using melsec control protocol" default n +if CONTROL_PROTOCOL_MELSEC + source "$APP_DIR/Framework/control/plc_protocol/melsec/Kconfig" +endif config CONTROL_PROTOCOL_OPCUA bool "Using opcua control protocol" default n +if CONTROL_PROTOCOL_OPCUA + source "$APP_DIR/Framework/control/plc_protocol/opcua/Kconfig" +endif config CONTROL_PROTOCOL_S7 bool "Using s7 control protocol" default n +if CONTROL_PROTOCOL_S7 + source "$APP_DIR/Framework/control/plc_protocol/s7/Kconfig" +endif diff --git a/APP_Framework/Framework/control/plc_protocol/include/melsec.h b/APP_Framework/Framework/control/plc_protocol/include/melsec.h index 2586fdd4e..bdefbc33f 100644 --- a/APP_Framework/Framework/control/plc_protocol/include/melsec.h +++ b/APP_Framework/Framework/control/plc_protocol/include/melsec.h @@ -15,5 +15,98 @@ * @brief plc protocol melsec * @version 3.0 * @author AIIT XUOS Lab - * @date 2022-10-08 - */ \ No newline at end of file + * @date 2022-11-29 + */ + +#ifndef MELSEC_H +#define MELSEC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define SUB_HEADER 0x5000 +#define NETWORK_NUMBER 0x00 +#define PC_NUMBER 0xFF +#define QEQUEST_DESTINSTION_MODULE_IO_NUMBER 0x03FF +#define QEQUEST_DESTINSTION_MODULE_STATION_NUMBER 0x00 +#define STATION_NUMBER 0x00 +#define FRAME_NUMBER 0x4639 +#define SELF_STATION_NUMBER 0x00 + +#define MELSEC_NAK 0x15 +#define MELSEC_STX 0x02 +#define MELSEC_ETX 0x03 +#define MELSEC_ENQ 0x05 + +#define MELSEC_1E_FRAME_RB 0x00 +#define MELSEC_1E_FRAME_RW 0x01 +#define MELSEC_1E_FRAME_WB 0x02 +#define MELSEC_1E_FRAME_WW 0x03 + +#define MELSEC_1C_FRAME_RB 0x4252 +#define MELSEC_1C_FRAME_RW 0x5752 +#define MELSEC_1C_FRAME_WB 0x4257 +#define MELSEC_1C_FRAME_WW 0x5757 + +//same as MELSEC_3E_Q_L_FRAME +#define MELSEC_3C_FRAME_RB 0x04010001 +#define MELSEC_3C_FRAME_RW 0x04010000 +#define MELSEC_3C_FRAME_WB 0x14010001 +#define MELSEC_3C_FRAME_WW 0x14010000 + +//same as MELSEC_3C_FRAME +#define MELSEC_3E_Q_L_FRAME_RB 0x04010001 +#define MELSEC_3E_Q_L_FRAME_RW 0x04010000 +#define MELSEC_3E_Q_L_FRAME_WB 0x14010001 +#define MELSEC_3E_Q_L_FRAME_WW 0x14010000 + +#define MELSEC_3E_IQ_R_FRAME_RB 0x04010003 +#define MELSEC_3E_IQ_R_FRAME_RW 0x04010002 +#define MELSEC_3E_IQ_R_FRAME_WB 0x14010003 +#define MELSEC_3E_IQ_R_FRAME_WW 0x14010002 + +typedef enum { + READ_IN_BITS, + READ_IN_WORD, + WRITE_IN_BITS, + WRITE_IN_WORD, + TEST_IN_BIT, + TEST_IN_WORD +}MelsecCommandType; + +typedef enum { + MELSEC_1E_FRAME, + MELSEC_3E_Q_L_FRAME, + MELSEC_3E_IQ_R_FRAME, + MELSEC_1C_FRAME, + MELSEC_3C_FRAME +}MelsecFrameType; + +typedef struct +{ + BasicPlcDataInfo base_data_info; + MelsecCommandType command_type; + MelsecFrameType frame_type; +}MelsecDataInfo; + +typedef struct +{ + MelsecDataInfo data_info; + + UniformValueType value_type; + uint8_t value_name[20]; + + uint16_t monitoring_timer; + uint16_t device_code; + uint8_t head_device_number_string[6]; + uint16_t device_points_count; +}MelsecReadItem; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig b/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig index 139597f9c..93392b091 100755 --- a/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig +++ b/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig @@ -1,2 +1,20 @@ +choice + prompt "select melsec protocol" + default CONTROL_PROTOCOL_MELSEC_1E + config CONTROL_PROTOCOL_MELSEC_1E + bool "support melsec_1e protocol, using TCP" + + config CONTROL_PROTOCOL_MELSEC_3E_Q_L + bool "support melsec_3e_q_l protocol, using TCP" + + config CONTROL_PROTOCOL_MELSEC_3E_IQ_R + bool "support melsec_3e_iq_r protocol, using TCP" + + config CONTROL_PROTOCOL_MELSEC_1C + bool "support melsec_1c protocol, using SERIAL" + + config CONTROL_PROTOCOL_MELSEC_3C + bool "support melsec_3c protocol, using SERIAL" +endchoice diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/Makefile b/APP_Framework/Framework/control/plc_protocol/melsec/Makefile index 608656f03..9f60e0cf7 100755 --- a/APP_Framework/Framework/control/plc_protocol/melsec/Makefile +++ b/APP_Framework/Framework/control/plc_protocol/melsec/Makefile @@ -1,4 +1,4 @@ -SRC_FILES := +SRC_FILES := melsec.c include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c new file mode 100644 index 000000000..9d95485eb --- /dev/null +++ b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c @@ -0,0 +1,669 @@ +/* +* Copyright (c) 2022 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 melsec.c + * @brief plc protocol melsec, support 1E、3E_Q_L、3E_IQ_R、1C、3C + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2022-11-29 + */ + +#include + +static BasicSocketPlc plc_socket = {0}; +static uint8_t recv_buff[1024] = {0}; + +/** + * @description: Melsec Get Check Sum + * @param p_command - p_command pointer + * @param command_length - command length + * @return checksum + */ +static uint8_t GetCheckSum(uint8_t *p_command, uint16_t command_length) +{ + uint8_t checksum = 0; + for (uint16_t i = 0; i < command_length; i++) { + checksum += p_command[i]; + } + return checksum; +} + +/** + * @description: Melsec Transform from Hex to Ascii + * @param hex - hex + * @return ascii + */ +static uint8_t TransformHexToAscii(uint8_t hex) +{ + hex %= 0x10; + return hex < 0xA ? hex + '0' : hex - 10 + 'A'; +} + +/** + * @description: Melsec Transform from Ascii to Hex + * @param ascii - ascii + * @return hex + */ +static uint8_t TransformAsciiToHex(uint8_t ascii) +{ + if (ascii > 'F' || ascii < '0' || (ascii > '9' && ascii < 'A')) + return 0; + else + return ascii < 'A' ? ascii - '0' : ascii - 'A' + 10; +} + +/** + * @description: Melsec Get Device Code + * @param frame_type - melsec frame type + * @param device_string - device string + * @return device code + */ +static int MelsecGetDeviceCode(MelsecFrameType frame_type, char device_string[2]) +{ + switch (frame_type) { + case MELSEC_1C_FRAME: + if (strcmp(device_string, "M") == 0) + return 0x4D; + if (strcmp(device_string, "D") == 0) + return 0x44; + if (strcmp(device_string, "B") == 0) + return 0x22; + if (strcmp(device_string, "W") == 0) + return 0x57; + if (strcmp(device_string, "X") == 0) + return 0x58; + if (strcmp(device_string, "Y") == 0) + return 0x59; + case MELSEC_1E_FRAME: + if (strcmp(device_string, "M") == 0) + return 0x4D20; + if (strcmp(device_string, "D") == 0) + return 0x4420; + if (strcmp(device_string, "B") == 0) + return 0x2220; + if (strcmp(device_string, "W") == 0) + return 0x5720; + if (strcmp(device_string, "X") == 0) + return 0x5820; + if (strcmp(device_string, "Y") == 0) + return 0x5920; + case MELSEC_3C_FRAME: + if (strcmp(device_string, "M") == 0) + return 0x4D2A; + if (strcmp(device_string, "D") == 0) + return 0x442A; + if (strcmp(device_string, "B") == 0) + return 0x222A; + if (strcmp(device_string, "W") == 0) + return 0x572A; + case MELSEC_3E_IQ_R_FRAME: + if (strcmp(device_string, "M") == 0) + return 0x0090; + if (strcmp(device_string, "D") == 0) + return 0x00A8; + if (strcmp(device_string, "B") == 0) + return 0x00A0; + if (strcmp(device_string, "W") == 0) + return 0x00B4; + if (strcmp(device_string, "X") == 0) + return 0x009C; + if (strcmp(device_string, "Y") == 0) + return 0x009D; + case MELSEC_3E_Q_L_FRAME: + if (strcmp(device_string, "M") == 0) + return 0x90; + if (strcmp(device_string, "D") == 0) + return 0xA8; + if (strcmp(device_string, "B") == 0) + return 0xA0; + if (strcmp(device_string, "W") == 0) + return 0xB4; + if (strcmp(device_string, "X") == 0) + return 0x9C; + if (strcmp(device_string, "Y") == 0) + return 0x9D; + } +} + +/** + * @description: Melsec Get Command Base Length + * @param frame_type - melsec frame type + * @return command length + */ +static int MelsecGetCommandBaseLength(MelsecFrameType frame_type) +{ + switch (frame_type) { + case MELSEC_1C_FRAME: + return 17; + case MELSEC_1E_FRAME: + return 12; + case MELSEC_3C_FRAME: + return 33; + case MELSEC_3E_IQ_R_FRAME: + case MELSEC_3E_Q_L_FRAME: + return 21; + default: + return -1; + } +} + +/** + * @description: Melsec Get Command Code + * @param frame_type - melsec frame type + * @param command_type - melsec command type + * @return command code + */ +static uint32_t MelsecGetCommandCode(MelsecFrameType frame_type, MelsecCommandType command_type) +{ + switch (frame_type) { + case MELSEC_1C_FRAME: + switch (command_type) { + case READ_IN_BITS: + return MELSEC_1C_FRAME_RB; + case READ_IN_WORD: + return MELSEC_1C_FRAME_RW; + case WRITE_IN_BITS: + return MELSEC_1C_FRAME_WB; + case WRITE_IN_WORD: + return MELSEC_1C_FRAME_WW; + } + case MELSEC_1E_FRAME: + return command_type; + case MELSEC_3C_FRAME: + case MELSEC_3E_Q_L_FRAME: + switch (command_type) { + case READ_IN_BITS: + return MELSEC_3E_Q_L_FRAME_RB; + case READ_IN_WORD: + return MELSEC_3E_Q_L_FRAME_RW; + case WRITE_IN_BITS: + return MELSEC_3E_Q_L_FRAME_WB; + case WRITE_IN_WORD: + return MELSEC_3E_Q_L_FRAME_WW; + } + case MELSEC_3E_IQ_R_FRAME: + switch (command_type) { + case READ_IN_BITS: + return MELSEC_3E_IQ_R_FRAME_RB; + case READ_IN_WORD: + return MELSEC_3E_IQ_R_FRAME_RW; + case WRITE_IN_BITS: + return MELSEC_3E_IQ_R_FRAME_WB; + case WRITE_IN_WORD: + return MELSEC_3E_IQ_R_FRAME_WW; + } + } +} + +/** + * @description: Melsec_1E Cmd Genetare + * @param p_command - command pointer + * @param command_code - command code + * @param p_read_item - p_read_item pointer + * @return success : index error : 0 + */ +static uint16_t Melsec1eGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item) +{ + uint16_t index = 0; + + p_command[index++] = command_code; + p_command[index++] = PC_NUMBER; + p_command[index++] = p_read_item->monitoring_timer / 250; + p_command[index++] = (p_read_item->monitoring_timer / 250) >> 8; + + uint16_t head_device_number = 0; + for (uint8_t i = 0; i < 6; i++) { + if (0 != p_read_item->head_device_number_string[i]) + head_device_number = TransformAsciiToHex(p_read_item->head_device_number_string[i]) + head_device_number * (((0x5820 == p_read_item->device_code) || (0x5920 == p_read_item->device_code)) ? 8 : 10); + else + break; + } + p_command[index++] = head_device_number; + p_command[index++] = head_device_number >> (8 * 1); + p_command[index++] = head_device_number >> (8 * 2); + p_command[index++] = head_device_number >> (8 * 3); + p_command[index++] = p_read_item->device_code; + p_command[index++] = p_read_item->device_code >> 8; + p_command[index++] = p_read_item->device_points_count; + p_command[index++] = 0x00; + return index; +} + +/** + * @description: Melsec_3E_Q_L Cmd Genetare + * @param p_command - command pointer + * @param command_code - command code + * @param p_read_item - p_read_item pointer + * @return success : index error : 0 + */ +static uint16_t Melsec3eqlGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item) +{ + p_read_item->monitoring_timer /= 250; + uint16_t index = 0; + + p_command[index++] = SUB_HEADER >> 8; + p_command[index++] = (uint8_t)SUB_HEADER; + p_command[index++] = NETWORK_NUMBER; + p_command[index++] = PC_NUMBER; + p_command[index++] = (uint8_t)QEQUEST_DESTINSTION_MODULE_IO_NUMBER; + p_command[index++] = (uint8_t)(QEQUEST_DESTINSTION_MODULE_IO_NUMBER >> 8); + p_command[index++] = QEQUEST_DESTINSTION_MODULE_STATION_NUMBER; + p_command[index++] = 0x0c; + p_command[index++] = 0x00; + p_command[index++] = p_read_item->monitoring_timer; + p_command[index++] = p_read_item->monitoring_timer >> 8; + p_command[index++] = command_code >> (8 * 2); + p_command[index++] = command_code >> (8 * 3); + p_command[index++] = command_code; + p_command[index++] = command_code >> (8 * 1); + + uint16_t head_device_number = 0; + for (uint8_t i = 0; i < 6; i++) { + if (0 != p_read_item->head_device_number_string[i]) + head_device_number = TransformAsciiToHex(p_read_item->head_device_number_string[i]) + head_device_number * (((0x9c == (uint8_t)p_read_item->device_code) || (0x9d == (uint8_t)p_read_item->device_code)) ? 16 : 10); + else + break; + } + p_command[index++] = head_device_number; + p_command[index++] = head_device_number >> (8 * 1); + p_command[index++] = head_device_number >> (8 * 2); + p_command[index++] = p_read_item->device_code; + p_command[index++] = p_read_item->device_points_count; + p_command[index++] = p_read_item->device_points_count >> 8; + return index; +} + +/** + * @description: Melsec_3E_IQ_R Cmd Genetare + * @param p_command - command pointer + * @param command_code - command code + * @param p_read_item - p_read_item pointer + * @return success : index error : 0 + */ +static uint16_t Melsec3eiqrGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item) +{ + uint16_t index = Melsec3eqlGenerateCommand(p_command, command_code, p_read_item) - 6; + + uint16_t head_device_number = 0; + for (uint8_t i = 0; i < 6; i++) { + if (0 != p_read_item->head_device_number_string[i]) + head_device_number = TransformAsciiToHex(p_read_item->head_device_number_string[i]) + head_device_number * (((0x9c == (uint8_t)p_read_item->device_code) || (0x9d == (uint8_t)p_read_item->device_code)) ? 16 : 10); + else + break; + } + p_command[index++] = head_device_number; + p_command[index++] = head_device_number >> (8 * 1); + p_command[index++] = head_device_number >> (8 * 2); + p_command[index++] = head_device_number >> (8 * 3); + p_command[index++] = p_read_item->device_code; + p_command[index++] = p_read_item->device_code >> 8; + p_command[index++] = p_read_item->device_points_count; + p_command[index++] = p_read_item->device_points_count >> 8; + return index; +} + +/** + * @description: Melsec_1C Cmd Genetare + * @param p_command - command pointer + * @param command_code - command code + * @param p_read_item - p_read_item pointer + * @return success : index error : 0 + */ +static uint16_t Melsec1cGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item) +{ + p_read_item->monitoring_timer /= 10; + uint16_t index = 0; + uint8_t checksum = 0; + + p_command[index++] = MELSEC_ENQ; + p_command[index++] = TransformHexToAscii(STATION_NUMBER >> 4); + p_command[index++] = TransformHexToAscii(STATION_NUMBER); + p_command[index++] = TransformHexToAscii(PC_NUMBER >> 4); + p_command[index++] = TransformHexToAscii(PC_NUMBER); + p_command[index++] = command_code >> 8; + p_command[index++] = command_code; + p_command[index++] = TransformHexToAscii(p_read_item->monitoring_timer); + p_command[index++] = p_read_item->device_code; + uint8_t head_device_number_string_length = 0; + for (uint8_t i = 0; i < 6; i++) { + if (0 == p_read_item->head_device_number_string[i]) + break; + else + head_device_number_string_length++; + } + p_command[index++] = (head_device_number_string_length - 4 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 4]; + p_command[index++] = (head_device_number_string_length - 3 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 3]; + p_command[index++] = (head_device_number_string_length - 2 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 2]; + p_command[index++] = (head_device_number_string_length - 1 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 1]; + p_command[index++] = TransformHexToAscii(p_read_item->device_points_count >> 4); + p_command[index++] = TransformHexToAscii(p_read_item->device_points_count); + checksum = GetCheckSum(p_command + 1, index - 1); + p_command[index++] = TransformHexToAscii(checksum >> 4); + p_command[index++] = TransformHexToAscii(checksum); + return index; +} + +/** + * @description: Melsec_3C Cmd Genetare + * @param p_command - command pointer + * @param command_code - command code + * @param p_read_item - p_read_item pointer + * @return success : index error : 0 + */ +static uint16_t Melsec3cGenerateCommand(uint8_t* p_command, uint32_t command_code, MelsecReadItem *p_read_item) +{ + uint16_t index = 0; + uint8_t checksum = 0; + + p_command[index++] = MELSEC_ENQ; + p_command[index++] = FRAME_NUMBER >> 8; + p_command[index++] = (uint8_t)FRAME_NUMBER; + p_command[index++] = TransformHexToAscii(STATION_NUMBER >> 4); + p_command[index++] = TransformHexToAscii(STATION_NUMBER); + p_command[index++] = TransformHexToAscii(NETWORK_NUMBER >> 4); + p_command[index++] = TransformHexToAscii(NETWORK_NUMBER); + p_command[index++] = TransformHexToAscii(PC_NUMBER >> 4); + p_command[index++] = TransformHexToAscii(PC_NUMBER); + p_command[index++] = TransformHexToAscii(SELF_STATION_NUMBER >> 4); + p_command[index++] = TransformHexToAscii(SELF_STATION_NUMBER); + p_command[index++] = TransformHexToAscii(command_code >> (7 * 4)); + p_command[index++] = TransformHexToAscii(command_code >> (6 * 4)); + p_command[index++] = TransformHexToAscii(command_code >> (5 * 4)); + p_command[index++] = TransformHexToAscii(command_code >> (4 * 4)); + p_command[index++] = TransformHexToAscii(command_code >> (3 * 4)); + p_command[index++] = TransformHexToAscii(command_code >> (2 * 4)); + p_command[index++] = TransformHexToAscii(command_code >> (1 * 4)); + p_command[index++] = TransformHexToAscii(command_code); + p_command[index++] = p_read_item->device_code >> 8; + p_command[index++] = p_read_item->device_code; + uint8_t head_device_number_string_length = 0; + for (uint8_t i = 0; i < 6; i++) { + if (0 == p_read_item->head_device_number_string[i]) + break; + else + head_device_number_string_length++; + } + p_command[index++] = (head_device_number_string_length - 6 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 6]; + p_command[index++] = (head_device_number_string_length - 5 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 5]; + p_command[index++] = (head_device_number_string_length - 4 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 4]; + p_command[index++] = (head_device_number_string_length - 3 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 3]; + p_command[index++] = (head_device_number_string_length - 2 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 2]; + p_command[index++] = (head_device_number_string_length - 1 < 0) ? 0x30 : p_read_item->head_device_number_string[head_device_number_string_length - 1]; + p_command[index++] = TransformHexToAscii(p_read_item->device_points_count >> (3 * 8)); + p_command[index++] = TransformHexToAscii(p_read_item->device_points_count >> (2 * 8)); + p_command[index++] = TransformHexToAscii(p_read_item->device_points_count >> (1 * 8)); + p_command[index++] = TransformHexToAscii(p_read_item->device_points_count); + checksum = GetCheckSum(p_command + 1, index - 1); + p_command[index++] = TransformHexToAscii(checksum >> 4); + p_command[index++] = TransformHexToAscii(checksum); + return index; +} + +/** + * @description: Melsec Cmd Genetare + * @param p_command - command pointer + * @param command_code - command code + * @param p_read_item - p_read_item pointer + * @return success : index error : 0 + */ +static uint16_t MelsecGenerateCommand(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item) +{ + uint16_t (*GenerateMelsecCommandFunction)(uint8_t *p_command, uint32_t command_code, MelsecReadItem *p_read_item); + + switch (p_read_item->data_info.frame_type) { + case MELSEC_1E_FRAME: + GenerateMelsecCommandFunction = Melsec1eGenerateCommand; + break; + case MELSEC_3E_IQ_R_FRAME: + GenerateMelsecCommandFunction = Melsec3eiqrGenerateCommand; + break; + case MELSEC_3E_Q_L_FRAME: + GenerateMelsecCommandFunction = Melsec3eqlGenerateCommand; + break; + case MELSEC_1C_FRAME: + GenerateMelsecCommandFunction = Melsec1cGenerateCommand; + break; + case MELSEC_3C_FRAME: + GenerateMelsecCommandFunction = Melsec3cGenerateCommand; + break; + default: + return 0; + } + return GenerateMelsecCommandFunction(p_command, command_code, p_read_item); +} + +/** + * @description: Melsec Data Info Init + * @param p_read_item - read item pointer + * @param p_data - control-data pointer + * @return success : 0 error : -1 + */ +int MelsecInitialDataInfo(MelsecReadItem *p_read_item, uint8_t *p_data) +{ + uint8_t check_sum = 0; + BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info); + + int command_base_length = MelsecGetCommandBaseLength(p_read_item->data_info.frame_type); + if (command_base_length < 0) { + printf("%s Not supported device code!\n", __func__); + return -1; + } + + switch (p_read_item->data_info.command_type) { + case READ_IN_BITS: + p_base_data_info->command_length = command_base_length; + p_base_data_info->p_command = PrivMalloc(command_base_length); + p_base_data_info->data_size = p_read_item->device_points_count; + p_base_data_info->p_data = p_data; + break; + case READ_IN_WORD: + p_base_data_info->command_length = command_base_length; + p_base_data_info->p_command = PrivMalloc(command_base_length); + p_base_data_info->data_size = p_read_item->device_points_count * 2; + p_base_data_info->p_data = p_data; + break; + case WRITE_IN_BITS: + p_base_data_info->command_length = command_base_length + p_read_item->device_points_count; + p_base_data_info->p_command = PrivMalloc(command_base_length + p_read_item->device_points_count); + command_base_length -= (p_read_item->data_info.frame_type >= MELSEC_1C_FRAME) ? 2 : 0; + memcpy(p_base_data_info->p_command + command_base_length, p_data, p_read_item->device_points_count); + break; + case WRITE_IN_WORD: + p_base_data_info->command_length = command_base_length + p_read_item->device_points_count * 2; + p_base_data_info->p_command = PrivMalloc(command_base_length + p_read_item->device_points_count * 2); + command_base_length -= (p_read_item->data_info.frame_type >= MELSEC_1C_FRAME) ? 2 : 0; + memcpy(p_base_data_info->p_command + command_base_length, p_data, p_read_item->device_points_count * 2); + break; + default: + return -1; + } + + uint32_t command_code = MelsecGetCommandCode(p_read_item->data_info.frame_type, p_read_item->data_info.command_type); + MelsecGenerateCommand(p_base_data_info->p_command, command_code, p_read_item); + + return 0; +} + +/** + * @description: Melsec Data Transform from Receive Buffer To Control-Data + * @param p_read_item - read item pointer + * @param recv_buff - receive buff + * @return success : 0 error : -1 + */ +static int MelsecTransformRecvBuffToData(MelsecReadItem *p_read_item, uint8_t *recv_buff) +{ + +} + +/** + * @description: Melsec Get Data From Socket + * @param socket - socket + * @param p_read_item - read item pointer + * @return success : 0 error : -1 -2 + */ +static int MelsecGetDataBySocket(int32_t socket, MelsecReadItem *p_read_item) +{ + +} + +/** + * @description: Melsec Get Data From Serial + * @param p_read_item - read item pointer + * @return success : 0 error : -1 -2 + */ +static int MelsecGetDataBySerial(MelsecReadItem *p_read_item) +{ + +} + +/** + * @description: Melsec Receive Plc Data Task + * @param parameter - parameter pointer + * @return + */ +void *ReceivePlcDataTask(void *parameter) +{ + int i = 0; + uint8_t try_count = 0; + uint16_t data_length = 0; + uint8_t *melsec_data; + uint16_t read_item_size = sizeof(MelsecReadItem); + + struct ControlProtocol *control_protocol = (struct ControlProtocol *)parameter; + struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args; + MelsecReadItem *melsec_read_item = (MelsecReadItem *)control_protocol->recipe->read_item; + melsec_data = control_protocol->recipe->protocol_data.data; + data_length = control_protocol->recipe->protocol_data.data_length; + + memset(&plc_socket, 0, sizeof(BasicSocketPlc)); + memcpy(plc_socket.ip, control_protocol->recipe->socket_config.plc_ip, 4); + plc_socket.port = control_protocol->recipe->socket_config.port; + plc_socket.socket = -1; + + while (1) { + for (i = 0; i < control_protocol->recipe->read_item_count; i ++) { + /*only connect socket when close socket or init*/ + while (ControlConnectSocket(&plc_socket) < 0) { + PrivTaskDelay(1000); + } + + MelsecGetDataBySocket(plc_socket.socket, (MelsecReadItem *)melsec_read_item + i); + } + + /*read all variable item data, put them into circular_area*/ + if (i == control_protocol->recipe->read_item_count) { + printf("%s get %d item %d length\n", __func__, i, data_length); + CircularAreaAppWrite(circular_area, melsec_data, data_length, 0); + } + + /*read data every single read_period*/ + PrivTaskDelay(control_protocol->recipe->read_period); + } +} + +/** + * @description: Melsec Protocol Open + * @param control_protocol - control protocol pointer + * @return success : 0 error + */ +int MelsecOpen(struct ControlProtocol *control_protocol) +{ + ControlProtocolOpenDef(control_protocol); + + return 0; +} + +/** + * @description: Melsec Protocol Close + * @param control_protocol - control protocol pointer + * @return success : 0 error + */ +int MelsecClose(struct ControlProtocol *control_protocol) +{ + ControlDisconnectSocket(&plc_socket); + + ControlProtocolCloseDef(); + + return 0; +} + +/** + * @description: Melsec Protocol Read Data + * @param control_protocol - control protocol pointer + * @param buf - read data buffer + * @param len - read data length + * @return success : data length error : 0 + */ +int MelsecRead(struct ControlProtocol *control_protocol, void *buf, size_t len) +{ + struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args; + return CircularAreaAppRead(circular_area, buf, len); +} + +static struct ControlDone melsec_protocol_done = +{ + ._open = MelsecOpen, + ._close = MelsecClose, + ._read = MelsecRead, + ._write = NULL, + ._ioctl = NULL, +}; + +/** + * @description: Melsec Protocol Cmd Generate + * @param p_recipe - recipe pointer + * @param protocol_format_info - protocol format info pointer + * @return success : 0 error : -1 + */ +int MelsecProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info) +{ + int ret = 0; + MelsecReadItem *melsec_read_item = (MelsecReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index; + + melsec_read_item->value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint; + strncpy(melsec_read_item->value_name, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_name")->valuestring, 20); + melsec_read_item->data_info.command_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "command_type")->valueint; + melsec_read_item->data_info.frame_type = p_recipe->protocol_type - PROTOCOL_MELSEC_1E; + melsec_read_item->monitoring_timer = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "monitoring_timer")->valueint; + melsec_read_item->device_code = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "device_code")->valuestring; + strncpy(melsec_read_item->head_device_number_string, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "head_device_number_string")->valuestring, 6); + melsec_read_item->device_points_count = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "device_points_count")->valueint; + + ret = MelsecInitialDataInfo(melsec_read_item, + protocol_format_info->p_read_item_data + protocol_format_info->last_item_size); + + ControlPrintfList("CMD", melsec_read_item->data_info.base_data_info.p_command, melsec_read_item->data_info.base_data_info.command_length); + protocol_format_info->last_item_size = GetValueTypeMemorySize(melsec_read_item->value_type); + + return ret; +} + +/** + * @description: Melsec Protocol Init + * @param p_recipe - recipe pointer + * @return success : 0 error : -1 + */ +int MelsecProtocolInit(struct ControlRecipe *p_recipe) +{ + p_recipe->read_item = PrivMalloc(sizeof(MelsecReadItem) * p_recipe->read_item_count); + if (NULL == p_recipe->read_item) { + PrivFree(p_recipe->read_item); + return -1; + } + + p_recipe->ControlProtocolFormatCmd = MelsecProtocolFormatCmd; + + p_recipe->done = &melsec_protocol_done; + + return 0; +} diff --git a/APP_Framework/Framework/control/shared/control_def.c b/APP_Framework/Framework/control/shared/control_def.c index 27ab2d761..fbc33225c 100644 --- a/APP_Framework/Framework/control/shared/control_def.c +++ b/APP_Framework/Framework/control/shared/control_def.c @@ -33,6 +33,10 @@ extern void *ReceivePlcDataTask(void *parameter); extern int FinsProtocolInit(struct ControlRecipe *p_recipe); #endif +#ifdef CONTROL_PROTOCOL_MELSEC +extern int MelsecProtocolInit(struct ControlRecipe *p_recipe); +#endif + /* CONTROL FRAMEWORK READ DATA FORMAT: | HEAD |device_id|read data length|read item count| data | @@ -55,6 +59,13 @@ static struct ControlProtocolInitParam protocol_init[] = #ifdef CONTROL_PROTOCOL_FINS { PROTOCOL_FINS, FinsProtocolInit }, #endif +#ifdef CONTROL_PROTOCOL_MELSEC + { PROTOCOL_MELSEC_1E, MelsecProtocolInit }, + { PROTOCOL_MELSEC_3E_Q_L, MelsecProtocolInit }, + { PROTOCOL_MELSEC_3E_IQ_R, MelsecProtocolInit }, + { PROTOCOL_MELSEC_1C, MelsecProtocolInit }, + { PROTOCOL_MELSEC_3C, MelsecProtocolInit }, +#endif { PROTOCOL_END, NULL }, }; From a782b53423571c67b1eca1666254618c1bb62c50 Mon Sep 17 00:00:00 2001 From: wuzheng Date: Thu, 1 Dec 2022 09:37:43 +0800 Subject: [PATCH 04/33] adapt qs-fs and qs-fx for edu-riscv64 --- .../sensor_app/winddirection_qs_fx.c | 11 +++- .../Applications/sensor_app/windspeed_qs_fs.c | 11 +++- .../Framework/sensor/winddirection/Kconfig | 8 +++ .../sensor/winddirection/qs-fx/qs-fx.c | 50 +++++++++++++++++-- .../Framework/sensor/windspeed/Kconfig | 10 +++- .../Framework/sensor/windspeed/qs-fs/qs-fs.c | 50 ++++++++++++++++++- .../third_party_driver/gpio/drv_io_config.c | 12 +++-- .../include/drv_io_config.h | 6 ++- 8 files changed, 143 insertions(+), 15 deletions(-) diff --git a/APP_Framework/Applications/sensor_app/winddirection_qs_fx.c b/APP_Framework/Applications/sensor_app/winddirection_qs_fx.c index 26d53601a..70c78f067 100644 --- a/APP_Framework/Applications/sensor_app/winddirection_qs_fx.c +++ b/APP_Framework/Applications/sensor_app/winddirection_qs_fx.c @@ -29,7 +29,14 @@ void WindDirectionQsFx(void) struct SensorQuantity *wind_direction = SensorQuantityFind(SENSOR_QUANTITY_QS_FX_WINDDIRECTION, SENSOR_QUANTITY_WINDDIRECTION); SensorQuantityOpen(wind_direction); PrivTaskDelay(2000); - uint16_t result = SensorQuantityReadValue(wind_direction); - printf("wind direction : %d degree\n", result); + int result = 0; + for(int i=0;i<2000;i++) + { + result = 0; + PrivTaskDelay(1000); + result = SensorQuantityReadValue(wind_direction); + if(result > 0) + printf("wind direction : %d degree\n", result); + } SensorQuantityClose(wind_direction); } diff --git a/APP_Framework/Applications/sensor_app/windspeed_qs_fs.c b/APP_Framework/Applications/sensor_app/windspeed_qs_fs.c index d9ec38f5f..b55f4e3ea 100644 --- a/APP_Framework/Applications/sensor_app/windspeed_qs_fs.c +++ b/APP_Framework/Applications/sensor_app/windspeed_qs_fs.c @@ -29,7 +29,14 @@ void WindSpeedQsFs(void) struct SensorQuantity *wind_speed = SensorQuantityFind(SENSOR_QUANTITY_QS_FS_WINDSPEED, SENSOR_QUANTITY_WINDSPEED); SensorQuantityOpen(wind_speed); PrivTaskDelay(2000); - uint16_t result = SensorQuantityReadValue(wind_speed); - printf("wind speed : %d.%d m/s\n", result/10, result%10); + int result = 0; + for(int i=0;i<2000;i++) + { + result = 0; + PrivTaskDelay(1000); + result = SensorQuantityReadValue(wind_speed); + if(result > 0) + printf("wind speed : %d.%d m/s\n", result/10, result%10); + } SensorQuantityClose(wind_speed); } diff --git a/APP_Framework/Framework/sensor/winddirection/Kconfig b/APP_Framework/Framework/sensor/winddirection/Kconfig index 726bfea8a..7fdbd7bd4 100644 --- a/APP_Framework/Framework/sensor/winddirection/Kconfig +++ b/APP_Framework/Framework/sensor/winddirection/Kconfig @@ -22,6 +22,14 @@ config SENSOR_QS_FX default "/dev/uart2_dev2" depends on !SENSOR_QS_FX_DRIVER_EXTUART + config SENSOR_DEVICE_QS_FX_PIN_DEV + string "qs-fx pin device name" + default "/dev/pin_dev" + + config SENSOR_DEVICE_QS_FX_PIN_NUMBER + int "qs-fx pin device number" + default 24 + if SENSOR_QS_FX_DRIVER_EXTUART config SENSOR_DEVICE_QS_FX_DEV string "qs-fx device extra uart path" diff --git a/APP_Framework/Framework/sensor/winddirection/qs-fx/qs-fx.c b/APP_Framework/Framework/sensor/winddirection/qs-fx/qs-fx.c index e521b9f7e..72cb4da02 100644 --- a/APP_Framework/Framework/sensor/winddirection/qs-fx/qs-fx.c +++ b/APP_Framework/Framework/sensor/winddirection/qs-fx/qs-fx.c @@ -53,6 +53,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) cfg.serial_parity_mode = PARITY_NONE; cfg.serial_bit_order = 0; cfg.serial_invert_mode = 0; + cfg.serial_timeout = 1000; cfg.is_ext_uart = 0; #ifdef SENSOR_QS_FX_DRIVER_EXTUART cfg.is_ext_uart = 1; @@ -66,7 +67,34 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) result = PrivIoctl(sdev->fd, OPE_INT, &ioctl_cfg); return result; -} +} + +static int PinOpen(void){ + int pin_fd = PrivOpen(SENSOR_DEVICE_QS_FX_PIN_DEV, O_RDWR); + if (pin_fd < 0) { + printf("open %s error\n", SENSOR_DEVICE_QS_FX_PIN_DEV); + return -1; + } + + //config led pin in board + struct PinParam pin_parameter; + memset(&pin_parameter, 0, sizeof(struct PinParam)); + pin_parameter.cmd = GPIO_CONFIG_MODE; + pin_parameter.pin = SENSOR_DEVICE_QS_FX_PIN_NUMBER; + pin_parameter.mode = GPIO_CFG_OUTPUT; + + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = PIN_TYPE; + ioctl_cfg.args = (void *)&pin_parameter; + + if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg)) { + printf("ioctl pin fd error %d\n", pin_fd); + PrivClose(pin_fd); + return -1; + } + + return pin_fd; +} /** * @description: Read sensor device @@ -76,12 +104,25 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) */ static int SensorDeviceRead(struct SensorDevice *sdev, size_t len) { + int pin_fd=PinOpen(); + struct PinStat pin_dir; + pin_dir.pin = SENSOR_DEVICE_QS_FX_PIN_NUMBER; + + pin_dir.val = GPIO_HIGH; + if (PrivWrite(pin_fd,&pin_dir,0) < 0) // pull-up pin to configure as tx mode + return -1; + PrivTaskDelay(20); if (PrivWrite(sdev->fd, instructions, sizeof(instructions)) < 0) return -1; + + PrivTaskDelay(20); + pin_dir.val = GPIO_LOW; + if (PrivWrite(pin_fd,&pin_dir,0) < 0) // pull-down pin to configure as rx mode + return -1; if (PrivRead(sdev->fd, sdev->buffer, len) < 0) return -1; - + PrivClose(pin_fd); return 0; } @@ -124,7 +165,10 @@ static int32_t ReadWindDirection(struct SensorQuantity *quant) short result; if (quant->sdev->done->read != NULL) { if (quant->sdev->status == SENSOR_DEVICE_PASSIVE) { - quant->sdev->done->read(quant->sdev, 6); + quant->sdev->done->read(quant->sdev, 7); + if(Crc16(quant->sdev->buffer,7)!=0x00){ + return -1; + } result = (quant->sdev->buffer[3] << 8) | quant->sdev->buffer[4]; return (int32_t)result; diff --git a/APP_Framework/Framework/sensor/windspeed/Kconfig b/APP_Framework/Framework/sensor/windspeed/Kconfig index 91bc1fb92..96dfabf27 100644 --- a/APP_Framework/Framework/sensor/windspeed/Kconfig +++ b/APP_Framework/Framework/sensor/windspeed/Kconfig @@ -19,9 +19,17 @@ config SENSOR_QS_FS config SENSOR_DEVICE_QS_FS_DEV string "qs-fx device name" - default "/dev/uart2_dev2" + default "/dev/uart1_dev1" depends on !SENSOR_QS_FS_DRIVER_EXTUART + config SENSOR_DEVICE_QS_FS_PIN_DEV + string "qs-fx pin device name" + default "/dev/pin_dev" + + config SENSOR_DEVICE_QS_FS_PIN_NUMBER + int "qs-fs pin device number" + default 24 + if SENSOR_QS_FS_DRIVER_EXTUART config SENSOR_DEVICE_QS_FS_DEV string "qs-fx device extra uart path" diff --git a/APP_Framework/Framework/sensor/windspeed/qs-fs/qs-fs.c b/APP_Framework/Framework/sensor/windspeed/qs-fs/qs-fs.c index 0ff9c6f18..025dc5d87 100644 --- a/APP_Framework/Framework/sensor/windspeed/qs-fs/qs-fs.c +++ b/APP_Framework/Framework/sensor/windspeed/qs-fs/qs-fs.c @@ -21,7 +21,7 @@ #include static struct SensorDevice qs_fs; -static const unsigned char instructions[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A}; +static const unsigned char instructions[] = {0x02,0x03,0x00,0x00,0x00,0x01,0x84,0x39}; static struct SensorProductInfo info = { @@ -68,6 +68,34 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) return result; } + +static int PinOpen(void){ + int pin_fd = PrivOpen(SENSOR_DEVICE_QS_FS_PIN_DEV, O_RDWR); + if (pin_fd < 0) { + printf("open %s error\n", SENSOR_DEVICE_QS_FS_PIN_DEV); + return -1; + } + + //config led pin in board + struct PinParam pin_parameter; + memset(&pin_parameter, 0, sizeof(struct PinParam)); + pin_parameter.cmd = GPIO_CONFIG_MODE; + pin_parameter.pin = SENSOR_DEVICE_QS_FS_PIN_NUMBER; + pin_parameter.mode = GPIO_CFG_OUTPUT; + + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = PIN_TYPE; + ioctl_cfg.args = (void *)&pin_parameter; + + if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg)) { + printf("ioctl pin fd error %d\n", pin_fd); + PrivClose(pin_fd); + return -1; + } + + return pin_fd; +} + /** * @description: Read sensor device * @param sdev - sensor device pointer @@ -76,12 +104,27 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) */ static int SensorDeviceRead(struct SensorDevice *sdev, size_t len) { + int pin_fd=PinOpen(); + struct PinStat pin_dir; + pin_dir.pin = SENSOR_DEVICE_QS_FS_PIN_NUMBER; + + pin_dir.val = GPIO_HIGH; + if (PrivWrite(pin_fd,&pin_dir,0) < 0) // pull-up pin to configure as tx mode + return -1; + PrivTaskDelay(20); if (PrivWrite(sdev->fd, instructions, sizeof(instructions)) < 0) return -1; + PrivTaskDelay(20); + + + pin_dir.val = GPIO_LOW; + if (PrivWrite(pin_fd,&pin_dir,0) < 0) // pull-down pin to configure as rx mode + return -1; if (PrivRead(sdev->fd, sdev->buffer, len) < 0) return -1; + PrivClose(pin_fd); return 0; } @@ -124,7 +167,10 @@ static int32_t ReadWindSpeed(struct SensorQuantity *quant) short result; if (quant->sdev->done->read != NULL) { if (quant->sdev->status == SENSOR_DEVICE_PASSIVE) { - quant->sdev->done->read(quant->sdev, 6); + quant->sdev->done->read(quant->sdev, 7); + if(Crc16(quant->sdev->buffer,7)!=0x00){ + return -1; + } result = (quant->sdev->buffer[3] << 8) | quant->sdev->buffer[4]; return (int32_t)result; diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c index 33bf5bd75..1e847c453 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c @@ -111,16 +111,20 @@ static struct io_config IOCONFIG(BSP_E220_M1_PIN, HS_GPIO(FUNC_GPIOHS11)), #endif -#ifdef BSP_USING_RS485 - IOCONFIG(BSP_485_DIR_PIN,HS_GPIO(FUNC_GPIOHS12)); +#ifdef USER_TEST_RS485 + IOCONFIG(BSP_485_DIR_PIN,HS_GPIO(FUNC_GPIOHS12)), +#elif defined SENSOR_QS_FX + IOCONFIG(BSP_485_DIR_PIN,HS_GPIO(FUNC_GPIOHS12)), +#elif defined SENSOR_QS_FS + IOCONFIG(BSP_485_DIR_PIN,HS_GPIO(FUNC_GPIOHS12)), #endif #ifdef BSP_USING_LED - IOCONFIG(BSP_LED_PIN,FUNC_GPIO5); + IOCONFIG(BSP_LED_PIN,FUNC_GPIO5), #endif #ifdef BSP_USING_KEY - IOCONFIG(BSP_KEY_PIN,FUNC_GPIO6); + IOCONFIG(BSP_KEY_PIN,FUNC_GPIO6), #endif }; diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h index 2ff8356b0..94257d4ed 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h @@ -98,7 +98,11 @@ enum HS_GPIO_CONFIG { #define BSP_E220_M1_PIN 33 #endif -#ifdef BSP_USING_RS485 +#ifdef USER_TEST_RS485 +#define BSP_485_DIR_PIN 24 +#elif defined SENSOR_QS_FX +#define BSP_485_DIR_PIN 24 +#elif defined SENSOR_QS_FS #define BSP_485_DIR_PIN 24 #endif From 6fa996d132301bef04497ead7bf811ce5e5eab47 Mon Sep 17 00:00:00 2001 From: wuzheng Date: Fri, 2 Dec 2022 11:04:46 +0800 Subject: [PATCH 05/33] add ethernet test fro edu-riscv64 --- APP_Framework/Applications/app_test/Kconfig | 19 +- APP_Framework/Applications/app_test/Makefile | 4 +- .../Applications/app_test/test_ethernet.c | 171 ++++++++++++++++++ .../Applications/app_test/test_w5500.c | 81 --------- 4 files changed, 189 insertions(+), 86 deletions(-) create mode 100644 APP_Framework/Applications/app_test/test_ethernet.c delete mode 100644 APP_Framework/Applications/app_test/test_w5500.c diff --git a/APP_Framework/Applications/app_test/Kconfig b/APP_Framework/Applications/app_test/Kconfig index e25b29155..12537ed19 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -192,10 +192,23 @@ menu "test app" bool "Config test lcd device" default n - config USER_TEST_W5500 - select BSP_USING_W5500 - bool "Config test W5500 only for edu-riscv64" + menuconfig USER_TEST_ETHERNET + bool "Config test ethernet only for edu-riscv64" default n + if USER_TEST_ETHERNET + if ADD_XIZI_FETURES + choice + prompt "set ethernet role as client or server" + default ETHERNET_AS_SERVER + + config ETHERNET_AS_SERVER + bool "test as server" + + config ETHERNET_AS_CLIENT + bool "test as client" + endchoice + endif + endif endif endmenu diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 830c40916..74d981eac 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -85,8 +85,8 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y) SRC_FILES += test_camera.c endif - ifeq ($(CONFIG_USER_TEST_W5500),y) - SRC_FILES += test_w5500.c + ifeq ($(CONFIG_USER_TEST_ETHERNET),y) + SRC_FILES += test_ethernet.c endif include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Applications/app_test/test_ethernet.c b/APP_Framework/Applications/app_test/test_ethernet.c new file mode 100644 index 000000000..5574d2fcb --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ethernet.c @@ -0,0 +1,171 @@ +#include +#include +#include + +#include + +#define BUFF_SIZE 128 +#define RECV_SIZE 16 +#define TCP_PORT 12345 + +const static uint32_t sn = 0; +const static uint32_t socket_tcp = 0; + +#ifdef ETHERNET_AS_SERVER +static int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, + uint16_t port, enum TCP_OPTION opt) { + int32_t ret = 0; + uint16_t size = 0, sentsize = 0; + switch (getSn_SR(sn)) { + case SOCK_ESTABLISHED: + if (getSn_IR(sn) & Sn_IR_CON) { + printf("%d:Connected\r\n", sn); + setSn_IR(sn, Sn_IR_CON); + } + if (opt == SEND_DATA) { + uint32_t sent_size = 0; + memset(buf,0,buf_size); + strcpy(buf,"The message has been recved"); + ret = wiz_sock_send(socket_tcp, buf, buf_size); + if (ret < 0) { + wiz_sock_close(socket_tcp); + return ret; + } + } else if (opt == RECV_DATA) { + uint32_t size = 0; + if ((size = getSn_RX_RSR(sn)) > 0) { + if (size > buf_size) size = buf_size; + memset(buf,0,buf_size); + ret = wiz_sock_recv(sn, buf, size); + printf("Recv message: %s\n",buf); + return ret; + } + } + break; + case SOCK_CLOSE_WAIT: + printf("%d:CloseWait\r\n", sn); + if ((ret = wiz_sock_disconnect(sn)) != SOCK_OK) return ret; + printf("%d:Closed\r\n", sn); + break; + case SOCK_INIT: + printf("%d:Listen, port [%d]\r\n", sn, port); + if ((ret = wiz_sock_listen(sn)) != SOCK_OK) return ret; + break; + case SOCK_CLOSED: + printf("%d:LBTStart\r\n", sn); + if ((ret = wiz_socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret; + printf("%d:Opened\r\n", sn); + break; + default: + break; + } + return 0; +} + +void TestSocketAsServer(int argc, char *argv[]) +{ + x_err_t ret; + uint8_t buf[BUFF_SIZE] = {0}; + + while (1) { + ret = wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, RECV_DATA); + if (ret > 0) { + wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, SEND_DATA); + }; + } + + return ; + +} + +PRIV_SHELL_CMD_FUNCTION(TestSocketAsServer, a w5500 server test sample, PRIV_SHELL_CMD_MAIN_ATTR); + +#elif defined ETHERNET_AS_CLIENT + +static uint32_t wiz_client_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, + uint8_t dst_ip[4], uint16_t dst_port, + enum TCP_OPTION opt) { + // assert(buf_size <= g_wiznet_buf_size); + int32_t ret; + switch (getSn_SR(socket_tcp)) { + case SOCK_CLOSE_WAIT: + wiz_sock_disconnect(socket_tcp); + break; + case SOCK_CLOSED: + wiz_socket(socket_tcp, Sn_MR_TCP, 5000, 0x00); + break; + case SOCK_INIT: + KPrintf("[SOCKET CLIENT] sock init.\n"); + wiz_sock_connect(socket_tcp, dst_ip, dst_port); + break; + case SOCK_ESTABLISHED: + if (getSn_IR(socket_tcp) & Sn_IR_CON) { + printf("[SOCKET CLIENT] %d:Connected\r\n", socket_tcp); + setSn_IR(socket_tcp, Sn_IR_CON); + } + if (opt == SEND_DATA) { + uint32_t sent_size = 0; + ret = wiz_sock_send(socket_tcp, buf, buf_size); + if (ret < 0) { + wiz_sock_close(socket_tcp); + return ret; + } + } else if (opt == RECV_DATA) { + uint32_t size = 0; + if ((size = getSn_RX_RSR(sn)) > 0) { + if (size > buf_size) size = buf_size; + ret = wiz_sock_recv(sn, buf, size); + if (ret <= 0) return ret; + } + } + break; + default: + break; + } +} + + +void TestSocketAsClient(int argc, char *argv[]) +{ + x_err_t ret; + uint8_t buf[BUFF_SIZE] = {0}; + uint32_t tmp_ip[4]; + uint32_t port; + const uint8_t client_sock = 2; + + if(argc<3){ + printf("Please enter command like TestSocketAsClient ip:port msg\n"); + } + + sscanf(argv[1],"%d.%d.%d.%d:%d",tmp_ip,tmp_ip+1,tmp_ip+2,tmp_ip+3,&port); + printf("Client to %d.%d.%d.%d:%d\n",tmp_ip[0],tmp_ip[1],tmp_ip[2],tmp_ip[3],port); + uint8_t destination_ip[4]={0}; + for(int i=0;i<4;i++){ + destination_ip[i]=tmp_ip[i]; + } + + while(1){ + ret = wiz_client_op(client_sock, argv[2], sizeof(argv[2]), destination_ip, port,SEND_DATA); + PrivTaskDelay(10); + if (ret > 0) { + ret=wiz_client_op(client_sock, buf, BUFF_SIZE, destination_ip, port, RECV_DATA); + printf("client recv msg successfully!\n"); + printf("%s\n",buf); + break; + }; + PrivTaskDelay(100); + } + + + + + return ; + +} + +PRIV_SHELL_CMD_FUNCTION(TestSocketAsClient, a w5500 client-ip-port-msg test sample, PRIV_SHELL_CMD_MAIN_ATTR); + + +#endif + + diff --git a/APP_Framework/Applications/app_test/test_w5500.c b/APP_Framework/Applications/app_test/test_w5500.c deleted file mode 100644 index 2a589171f..000000000 --- a/APP_Framework/Applications/app_test/test_w5500.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include - -#include - -#define BUFF_SIZE 128 -#define RECV_SIZE 16 -#define TCP_PORT 12345 - -const static uint32_t sn = 0; -const static uint32_t socket_tcp = 0; - -static int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, - uint16_t port, enum TCP_OPTION opt) { - int32_t ret = 0; - uint16_t size = 0, sentsize = 0; - switch (getSn_SR(sn)) { - case SOCK_ESTABLISHED: - if (getSn_IR(sn) & Sn_IR_CON) { - printf("%d:Connected\r\n", sn); - setSn_IR(sn, Sn_IR_CON); - } - if (opt == SEND_DATA) { - uint32_t sent_size = 0; - memset(buf,0,buf_size); - strcpy(buf,"The message has been recved"); - ret = wiz_sock_send(socket_tcp, buf, buf_size); - if (ret < 0) { - wiz_sock_close(socket_tcp); - return ret; - } - } else if (opt == RECV_DATA) { - uint32_t size = 0; - if ((size = getSn_RX_RSR(sn)) > 0) { - if (size > buf_size) size = buf_size; - memset(buf,0,buf_size); - ret = wiz_sock_recv(sn, buf, size); - printf("Recv message: %s\n",buf); - return ret; - } - } - break; - case SOCK_CLOSE_WAIT: - printf("%d:CloseWait\r\n", sn); - if ((ret = wiz_sock_disconnect(sn)) != SOCK_OK) return ret; - printf("%d:Closed\r\n", sn); - break; - case SOCK_INIT: - printf("%d:Listen, port [%d]\r\n", sn, port); - if ((ret = wiz_sock_listen(sn)) != SOCK_OK) return ret; - break; - case SOCK_CLOSED: - printf("%d:LBTStart\r\n", sn); - if ((ret = wiz_socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret; - printf("%d:Opened\r\n", sn); - break; - default: - break; - } - return 0; -} - -void TestSocketInW5500(int argc, char *argv[]) -{ - x_err_t ret; - uint8_t buf[BUFF_SIZE] = {0}; - - while (1) { - ret = wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, RECV_DATA); - if (ret > 0) { - wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, SEND_DATA); - }; - } - - return ; - -} - - -PRIV_SHELL_CMD_FUNCTION(TestSocketInW5500, a w5500 test sample, PRIV_SHELL_CMD_MAIN_ATTR); \ No newline at end of file From 2df54e7f41a0c3ebd916ca65c45c1c68a3d81384 Mon Sep 17 00:00:00 2001 From: wuzheng Date: Fri, 9 Dec 2022 13:57:01 +0800 Subject: [PATCH 06/33] fix some bugs for sd read --- .../kpu/k210_yolov2_detect_procedure/Kconfig | 4 + .../kpu/k210_yolov2_detect_procedure/Makefile | 4 + .../k210_yolov2_detect.h | 3 + .../Framework/knowing/kpu/yolov2/Makefile | 4 + .../knowing/kpu/yolov2/region_layer.c | 2 +- .../knowing/kpu/yolov2_json/Makefile | 4 + .../knowing/kpu/yolov2_json/json_parser.c | 7 +- .../user_api/posix_support/include/pthread.h | 6 + .../xizi/user_api/posix_support/pthread.c | 25 + .../XiZi_IIoT/board/edu-riscv64/board.c | 1 + .../edu-riscv64/third_party_driver/Kconfig | 10 +- .../edu-riscv64/third_party_driver/Makefile | 4 + .../third_party_driver/include/kpu.h | 930 ++++++++++ .../third_party_driver/kpu/Kconfig | 1 + .../third_party_driver/kpu/Makefile | 4 + .../edu-riscv64/third_party_driver/kpu/kpu.c | 1634 +++++++++++++++++ Ubiquitous/XiZi_IIoT/path_kernel.mk | 7 + .../resources/spi/sd_card_spi/sd_spi.c | 1 - 18 files changed, 2646 insertions(+), 5 deletions(-) create mode 100644 APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Makefile create mode 100644 APP_Framework/Framework/knowing/kpu/yolov2/Makefile create mode 100644 APP_Framework/Framework/knowing/kpu/yolov2_json/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/kpu.h create mode 100644 Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig create mode 100644 Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig index fa5819f4f..2d25a5710 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig @@ -3,5 +3,9 @@ menuconfig USING_K210_YOLOV2_DETECT depends on USING_KPU_PROCESSING default n +config CAMERA_DEV_DRIVER + string "Set camera dev path" + default "/dev/ov2640" + diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Makefile b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Makefile new file mode 100644 index 000000000..767322091 --- /dev/null +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := k210_yolov2_detect.c + +include $(KERNEL_ROOT)/compiler.mk + diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.h b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.h index 47427e734..935b23067 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.h +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.h @@ -1,7 +1,10 @@ #ifndef _K210_DETECT_H_ #define _K210_DETECT_H_ +#include +#include #include +#include "sleep.h" void k210_detect(char *json_file_path); diff --git a/APP_Framework/Framework/knowing/kpu/yolov2/Makefile b/APP_Framework/Framework/knowing/kpu/yolov2/Makefile new file mode 100644 index 000000000..6ebd0b800 --- /dev/null +++ b/APP_Framework/Framework/knowing/kpu/yolov2/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := region_layer.c + +include $(KERNEL_ROOT)/compiler.mk + diff --git a/APP_Framework/Framework/knowing/kpu/yolov2/region_layer.c b/APP_Framework/Framework/knowing/kpu/yolov2/region_layer.c index 255bf82a0..32a6a08dc 100644 --- a/APP_Framework/Framework/knowing/kpu/yolov2/region_layer.c +++ b/APP_Framework/Framework/knowing/kpu/yolov2/region_layer.c @@ -224,7 +224,7 @@ static void get_region_boxes(region_layer_t *rl, float *predictions, float **pro correct_region_boxes(rl, boxes); } -static int nms_comparator(void *pa, void *pb) +static int nms_comparator(const void *pa,const void *pb) { sortable_box_t a = *(sortable_box_t *)pa; sortable_box_t b = *(sortable_box_t *)pb; diff --git a/APP_Framework/Framework/knowing/kpu/yolov2_json/Makefile b/APP_Framework/Framework/knowing/kpu/yolov2_json/Makefile new file mode 100644 index 000000000..50b092a60 --- /dev/null +++ b/APP_Framework/Framework/knowing/kpu/yolov2_json/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := json_parser.c + +include $(KERNEL_ROOT)/compiler.mk + diff --git a/APP_Framework/Framework/knowing/kpu/yolov2_json/json_parser.c b/APP_Framework/Framework/knowing/kpu/yolov2_json/json_parser.c index 9a3167f64..ada573872 100644 --- a/APP_Framework/Framework/knowing/kpu/yolov2_json/json_parser.c +++ b/APP_Framework/Framework/knowing/kpu/yolov2_json/json_parser.c @@ -1,6 +1,9 @@ #include "json_parser.h" -#include +// #include +#include +#include +#include #include "cJSON.h" @@ -31,9 +34,9 @@ yolov2_params_t param_parse(char *json_file_path) } else { printf("Reading config from: %s\n", json_file_path); } + read(fin, buffer, sizeof(buffer)); close(fin); - // read json string json_obj = cJSON_Parse(buffer); // free(buffer); diff --git a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/include/pthread.h b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/include/pthread.h index efe995dc7..acebf067f 100644 --- a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/include/pthread.h +++ b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/include/pthread.h @@ -73,6 +73,12 @@ typedef int pid_t; int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)); int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); +int pthread_attr_init(pthread_attr_t *attr); +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size); +int pthread_attr_setschedparam(pthread_attr_t *attr,struct sched_param const *param); +int pthread_attr_setstack(pthread_attr_t *attr, + void *stack_base, + size_t stack_size); void pthread_exit(void *value_ptr); int pthread_detach(pthread_t thread); int pthread_join(pthread_t thread, void **retval); diff --git a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c index 3b8b170fd..ce33b259a 100644 --- a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c +++ b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c @@ -22,6 +22,10 @@ #include #include "include/pthread.h" +#define DEFAULT_STACK_SIZE 2048 +#define DEFAULT_PRIORITY (KTASK_PRIORITY_MAX/2 + KTASK_PRIORITY_MAX/4) + + int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) { @@ -55,6 +59,27 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr, } +int pthread_attr_init(pthread_attr_t *attr) +{ + return 0; +} + +int pthread_attr_setschedparam(pthread_attr_t *attr, + struct sched_param const *param) +{ + NULL_PARAM_CHECK(attr != NULL); + NULL_PARAM_CHECK(param != NULL); + + attr->schedparam.sched_priority = param->sched_priority; + + return 0; +} + +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size) +{ + return 0; +} + void pthread_exit(void *value_ptr){ //todo add exit value UserTaskQuit(); diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c index ad4ec5406..1a76f26c6 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c @@ -70,6 +70,7 @@ extern int HwLcdInit(void); extern int HwSpiInit(void); extern int HwSoftSPIInit(void); extern int HwWiznetInit(void); +extern int HwDvpInit(void); #include #ifdef MOUNT_USB diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Kconfig index f6322f544..31d42d085 100755 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Kconfig @@ -123,9 +123,17 @@ menuconfig BSP_USING_WIZCHIP menuconfig BSP_USING_CAMERA bool "Using camera device" - default y + default n select RESOURCES_CAMERA if BSP_USING_CAMERA source "$BSP_DIR/third_party_driver/dvp/Kconfig" endif +menuconfig BSP_USING_KPU + bool "Using kpu device" + default n + select RESOURCES_KPU + if BSP_USING_KPU + source "$BSP_DIR/third_party_driver/kpu/Kconfig" + endif + diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Makefile b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Makefile index 7c5f9ad84..51804af84 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Makefile @@ -59,9 +59,13 @@ endif ifeq ($(CONFIG_BSP_USING_WIZCHIP),y) SRC_DIR += ethernet endif + ifeq ($(CONFIG_BSP_USING_CAMERA),y) SRC_DIR += dvp endif +ifeq ($(CONFIG_BSP_USING_KPU),y) + SRC_DIR += kpu +endif include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/kpu.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/kpu.h new file mode 100644 index 000000000..1bf683c90 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/kpu.h @@ -0,0 +1,930 @@ +/* Copyright 2018 Canaan Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _KPU_H +#define _KPU_H + +#include +#include +#include "dmac.h" + +#define kpu_matmul_begin kpu_conv2d_output + +typedef int (*plic_irq_callback_t)(void *ctx); + +typedef struct +{ + union + { + uint64_t reg; + struct + { + uint64_t int_en:1; + uint64_t ram_flag:1; + uint64_t full_add:1; + uint64_t depth_wise_layer:1; + uint64_t reserved:60; + } data; + } interrupt_enabe; + + union + { + uint64_t reg; + struct + { + uint64_t image_src_addr:15; + uint64_t reserved0:17; + uint64_t image_dst_addr:15; + uint64_t reserved1:17; + } data; + } image_addr; + + union + { + uint64_t reg; + struct + { + uint64_t i_ch_num:10; + uint64_t reserved0:22; + uint64_t o_ch_num:10; + uint64_t reserved1:6; + uint64_t o_ch_num_coef:10; + uint64_t reserved2:6; + } data; + } image_channel_num; + + union + { + uint64_t reg; + struct + { + uint64_t i_row_wid:10; + uint64_t i_col_high:9; + uint64_t reserved0:13; + uint64_t o_row_wid:10; + uint64_t o_col_high:9; + uint64_t reserved1:13; + } data; + } image_size; + + union + { + uint64_t reg; + struct + { + uint64_t kernel_type:3; + uint64_t pad_type:1; + uint64_t pool_type:4; + uint64_t first_stride:1; + uint64_t bypass_conv:1; + uint64_t load_para:1; + uint64_t reserved0:5; + uint64_t dma_burst_size:8; + uint64_t pad_value:8; + uint64_t bwsx_base_addr:32; + } data; + } kernel_pool_type_cfg; + + union + { + uint64_t reg; + struct + { + uint64_t load_coor:1; + uint64_t load_time:6; + uint64_t reserved0:8; + uint64_t para_size:17; + uint64_t para_start_addr:32; + } data; + } kernel_load_cfg; + + union + { + uint64_t reg; + struct + { + uint64_t coef_column_offset:4; + uint64_t coef_row_offset:12; + uint64_t reserved0:48; + } data; + } kernel_offset; + + union + { + uint64_t reg; + struct + { + uint64_t channel_switch_addr:15; + uint64_t reserved:1; + uint64_t row_switch_addr:4; + uint64_t coef_size:8; + uint64_t coef_group:3; + uint64_t load_act:1; + uint64_t active_addr:32; + } data; + } kernel_calc_type_cfg; + + union + { + uint64_t reg; + struct + { + uint64_t wb_channel_switch_addr:15; + uint64_t reserved0:1; + uint64_t wb_row_switch_addr:4; + uint64_t wb_group:3; + uint64_t reserved1:41; + } data; + } write_back_cfg; + + union + { + uint64_t reg; + struct + { + uint64_t shr_w:4; + uint64_t shr_x:4; + uint64_t arg_w:24; + uint64_t arg_x:24; + uint64_t reserved0:8; + } data; + } conv_value; + + union + { + uint64_t reg; + struct + { + uint64_t arg_add:40; + uint64_t reserved:24; + } data; + } conv_value2; + + union + { + uint64_t reg; + struct + { + uint64_t send_data_out:1; + uint64_t reserved:15; + uint64_t channel_byte_num:16; + uint64_t dma_total_byte:32; + } data; + } dma_parameter; +} kpu_layer_argument_t; + +typedef struct +{ + union + { + uint64_t reg; + struct + { + uint64_t shift_number:8; + uint64_t y_mul:16; + uint64_t x_start:36; + } data; + } activate_para[16]; + + union + { + uint64_t reg; + struct + { + uint8_t result_bias[8]; + } data; + } activate_para_bias0; + + union + { + uint64_t reg; + struct + { + uint8_t result_bias[8]; + } data; + } activate_para_bias1; +} kpu_activate_table_t; + +typedef struct +{ + union + { + uint64_t reg; + struct + { + uint64_t norm_mul:24; + uint64_t norm_add:32; + uint64_t norm_shift:4; + } data; + } batchnorm; +} kpu_batchnorm_argument_t; + + +typedef struct +{ + union + { + uint64_t reg; + struct + { + uint16_t weight[9]; + } data; + } weights; +} kpu_weights_kernel_16_3x3_t; + +typedef struct +{ + uint64_t calc_done_int:1; + uint64_t layer_cfg_almost_empty_int:1; + uint64_t layer_cfg_almost_full_int:1; + uint64_t reserved:61; +} kpu_config_interrupt_t; + +typedef struct +{ + uint64_t fifo_full_threshold:4; + uint64_t fifo_empty_threshold:4; + uint64_t reserved:56; +} kpu_config_fifo_threshold_t; + +typedef struct +{ + uint64_t dma_fifo_flush_n:1; + uint64_t gs_fifo_flush_n:1; + uint64_t cfg_fifo_flush_n:1; + uint64_t cmd_fifo_flush_n:1; + uint64_t resp_fifo_flush_n:1; + uint64_t reserved:59; +} kpu_config_fifo_ctrl_t; + +typedef struct +{ + uint64_t eight_bit_mode:1; + uint64_t reserved:63; +} kpu_config_eight_bit_mode_t; + + +typedef struct +{ + volatile uint64_t layer_argument_fifo; + + volatile union + { + uint64_t reg; + kpu_config_interrupt_t data; + } interrupt_status; + + volatile union + { + uint64_t reg; + kpu_config_interrupt_t data; + } interrupt_raw; + + volatile union { + uint64_t reg; + kpu_config_interrupt_t data; + } interrupt_mask; + + volatile union + { + uint64_t reg; + kpu_config_interrupt_t data; + } interrupt_clear; + + volatile union + { + uint64_t reg; + kpu_config_fifo_threshold_t data; + } fifo_threshold; + + volatile uint64_t fifo_data_out; + + volatile union + { + uint64_t reg; + kpu_config_fifo_ctrl_t data; + } fifo_ctrl; + + volatile union + { + uint64_t reg; + kpu_config_eight_bit_mode_t data; + } eight_bit_mode; +} kpu_config_t; + +typedef struct +{ + kpu_layer_argument_t *layers; + kpu_layer_argument_t *remain_layers; + plic_irq_callback_t callback; + void *ctx; + uint64_t *src; + uint64_t *dst; + uint32_t src_length; + uint32_t dst_length; + uint32_t layers_length; + uint32_t remain_layers_length; + dmac_channel_number_t dma_ch; + uint32_t eight_bit_mode; + float output_scale; + float output_bias; + float input_scale; + float input_bias; +} kpu_task_t; + +typedef struct +{ + uint32_t version; + uint32_t flags; + uint32_t arch; + uint32_t layers_length; + uint32_t max_start_address; + uint32_t main_mem_usage; + uint32_t output_count; +} kpu_kmodel_header_t; + +typedef struct +{ + uint32_t version; + uint32_t flags; + uint32_t layers_length; + uint32_t max_start_address; + uint32_t layers_argument_start; +} kpu_model_header_t; + +typedef struct +{ + uint32_t address; + uint32_t size; +} kpu_model_output_t; + +typedef enum +{ + KL_INVALID = 0, + KL_ADD, + KL_QUANTIZED_ADD, + KL_GLOBAL_MAX_POOL2D, + KL_QUANTIZED_GLOBAL_MAX_POOL2D, + KL_GLOBAL_AVERAGE_POOL2D, + KL_QUANTIZED_GLOBAL_AVERAGE_POOL2D, + KL_MAX_POOL2D, + KL_QUANTIZED_MAX_POOL2D, + KL_AVERAGE_POOL2D, + KL_QUANTIZED_AVERAGE_POOL2D, + KL_QUANTIZE, + KL_DEQUANTIZE, + KL_REQUANTIZE, + KL_L2_NORMALIZATION, + KL_SOFTMAX, + KL_CONCAT, + KL_QUANTIZED_CONCAT, + KL_FULLY_CONNECTED, + KL_QUANTIZED_FULLY_CONNECTED, + KL_TENSORFLOW_FLATTEN, + KL_QUANTIZED_TENSORFLOW_FLATTEN, + KL_RESIZE_NEAREST_NEIGHBOR, + KL_QUANTIZED_RESIZE_NEAREST_NEIGHBOR, + KL_CHANNELWISE_DEQUANTIZE, + KL_K210_CONV = 10240, + KL_K210_ADD_PADDING, + KL_K210_REMOVE_PADDING, + KL_K210_UPLOAD +} kpu_model_layer_type_t; + +typedef struct +{ + uint32_t type; + uint32_t body_size; +} kpu_model_layer_header_t; + +typedef enum +{ + KLF_NONE = 0, + KLF_MAIN_MEM_OUT = 1 +} kpu_model_layer_flags_t; + +typedef enum +{ + KLP_SAME = 0, + KLP_VALID = 1 +} kpu_model_padding_t; + +typedef enum +{ + KLA_LINEAR = 0, + KLA_RELU = 1, + KLA_RELU6 = 2 +} kpu_model_activation_t; + +typedef struct +{ + float scale; + float bias; +} kpu_model_quant_param_t; + +typedef struct +{ + uint32_t width; + uint32_t height; + uint32_t channels; +} kpu_model_shape_t; + +typedef struct +{ + uint32_t start; + uint32_t size; +} kpu_model_memory_range_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_out_address; + uint32_t layer_offset; + uint32_t weights_offset; + uint32_t bn_offset; + uint32_t act_offset; +} kpu_model_conv_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_a_address; + uint32_t main_mem_in_b_address; + uint32_t main_mem_out_address; + uint32_t count; +} kpu_model_add_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_a_address; + uint32_t main_mem_in_b_address; + uint32_t main_mem_out_address; + uint32_t count; + int32_t in_a_offset; + int32_t in_a_mul; + int32_t in_a_shift; + int32_t in_b_offset; + int32_t in_b_mul; + int32_t in_b_shift; + int32_t out_offset; + int32_t out_mul; + int32_t out_shift; +} kpu_model_quant_add_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t kernel_size; + uint32_t channels; +} kpu_model_gap2d_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + kpu_model_shape_t in_shape; + kpu_model_shape_t out_shape; + uint32_t kernel_width; + uint32_t kernel_height; + uint32_t stride_width; + uint32_t stride_height; + uint32_t padding_width; + uint32_t padding_height; +} kpu_model_quant_max_pool2d_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + kpu_model_shape_t in_shape; + kpu_model_shape_t out_shape; + uint32_t kernel_width; + uint32_t kernel_height; + uint32_t stride_width; + uint32_t stride_height; + uint32_t padding_width; + uint32_t padding_height; + kpu_model_activation_t act; +} kpu_model_ave_pool2d_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t mem_out_address; + uint32_t count; + kpu_model_quant_param_t quant_param; +} kpu_model_quantize_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t count; + kpu_model_quant_param_t quant_param; +} kpu_model_dequantize_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t count; + uint8_t table[256]; +} kpu_model_requantize_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t kpu_mem_out_address; + uint32_t channels; +} kpu_model_add_padding_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t channels; +} kpu_model_remove_padding_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t kpu_mem_out_address; + uint32_t width; + uint32_t height; + uint32_t channels; +} kpu_model_upload_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t channels; +} kpu_model_l2_norm_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t channels; +} kpu_model_softmax_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_out_address; + uint32_t input_count; + kpu_model_memory_range_t inputs_mem[0]; +} kpu_model_concat_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t in_channels; + uint32_t out_channels; + kpu_model_activation_t act; + float weights[0]; +} kpu_model_fully_connected_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + kpu_model_shape_t shape; +} kpu_model_tf_flatten_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + kpu_model_shape_t in_shape; + uint32_t out_width; + uint32_t out_height; + uint32_t align_corners; +} kpu_model_resize_nearest_neighbor_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t channels; + uint32_t channel_size; + kpu_model_quant_param_t quant_params[0]; +} kpu_model_channelwise_dequant_argument_t; + +typedef void(*kpu_done_callback_t)(void* userdata); + +typedef struct +{ + const uint8_t *model_buffer; + uint8_t *main_buffer; + uint32_t output_count; + const kpu_model_output_t *outputs; + const kpu_model_layer_header_t *layer_headers; + const uint8_t *body_start; + uint32_t layers_length; + volatile uint32_t current_layer; + const uint8_t * volatile current_body; + dmac_channel_number_t dma_ch; + kpu_done_callback_t done_callback; + void *userdata; +} kpu_model_context_t; + +typedef struct +{ + uint32_t weigths_offset; + uint32_t bn_offset; + uint32_t act_offset; + float input_scale; + float input_bias; + float output_scale; + float output_bias; +} kpu_model_layer_metadata_t; + +typedef struct _quantize_param +{ + float scale; + float bias; +} quantize_param_t; + +extern volatile kpu_config_t *const kpu; + +/** + * @brief Modle complier init kpu handler + * + * @param[in] task Kpu handler + * + * @return Kpu handler + */ +extern kpu_task_t *kpu_task_init(kpu_task_t* task); + +/** + * @brief Kpu run for AI + * + * @param[in] task Kpu handler + * @param[in] dma_ch DMA for kpu + * @param[in] src The picture data + * @param[in] dest The result of kpu + * @param[in] callback The callback of kpu + * + * @return result + * - 0 Success + * - Other Fail.Kpu is busy. + */ +int kpu_run(kpu_task_t* task, dmac_channel_number_t dma_ch, const void *src, void* dest, plic_irq_callback_t callback); + +/** + * @brief Get kpu result buf + * + * @param[in] task Kpu handler + * + * @return Kpu result buf + */ +uint8_t *kpu_get_output_buf(kpu_task_t* task); + +/** + * @brief Release kpu output buf + * + * @param[in] output_buf Kpu output buf + * + */ +void kpu_release_output_buf(uint8_t *output_buf); + +/** + * @brief Kpu run for AI + * + * @param[in] task Kpu handler +* +* @return result +* - 0 Success +* - Other Fail.Kpu is busy. +*/ +int kpu_start(kpu_task_t *task); + +/** + * @brief Initialize kpu handler + * + * @param[in] task Kpu handler + * + * @return result + * - 0 Success + * - Other Fail. + */ +int kpu_single_task_init(kpu_task_t *task); + +/** + * @brief Uninitialize kpu handler + * + * @param[in] task Kpu handler + * + * @return result + * - 0 Success + * - Other Fail. + */ +int kpu_single_task_deinit(kpu_task_t *task); + +/** + * @brief Load kmodel and init kpu task + * + * @param[in] task Kpu handler + * @param[in] buffer Kmodel + * @param[in] meta Test data + * + * @return result + * - 0 Success + * - Other Fail. + */ +int kpu_model_load_from_buffer(kpu_task_t *task, uint8_t *buffer, kpu_model_layer_metadata_t **meta); + +/** + * @brief Kpu initialize + * + * @param[in] eight_bit_mode 0:16bit mode 1:8bit mode + * @param[in] callback Callback of kpu + * @param[in] userdata Data of callback + * + */ +void kpu_init(int eight_bit_mode, plic_irq_callback_t callback, void *userdata); + +/** + * @brief Kpu input data by dma + * + * @param[in] layer Kpu task layer + * @param[in] src Image data + * @param[in] dma_ch Dmac channel + * @param[in] callback Dmac complete callback + * @param[in] userdata Data of callback + * + */ +void kpu_input_dma(const kpu_layer_argument_t *layer, const uint8_t *src, dmac_channel_number_t dma_ch, plic_irq_callback_t callback, void *userdata); + +/** + * @brief Kpu input data by cpu + * + * @param[in] layer Kpu task layer + * @param[in] src Image data + * @param[in] width Image width + * @param[in] height Image heigth + * @param[in] channels Color channel, RGB is 3 + * + */ +void kpu_input_with_padding(kpu_layer_argument_t *layer, const uint8_t *src, int width, int height, int channels); + +/** + * @brief Kpu run only one layer + * + * @param[in] layer Kpu task layer + * + */ +void kpu_conv2d(kpu_layer_argument_t *layer); + +/** + * @brief Kpu run only one layer then get the result by dma + * + * @param[in] layer Kpu task layer + * @param[in] dma_ch Dmac channel + * @param[in] dest Result + * @param[in] callback Dmac complete callback + * @param[in] userdata Data of callback + * + */ +void kpu_conv2d_output(kpu_layer_argument_t *layer, dmac_channel_number_t dma_ch, uint8_t *dest, plic_irq_callback_t callback, void *userdata); + +/** + * @brief Kpu pooling + * + * @param[in] src Source + * @param[in] src_param Source param + * @param[in] kernel_size Kernel size, 7*7 is 49 + * @param[in] channels Channels + * @param[in] dest Dest + * @param[in] dest_param Dest param + * + */ +void kpu_global_average_pool(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, uint8_t *dest, const quantize_param_t *dest_param); + +/** + * @brief Kpu pooling + * + * @param[in] src Source + * @param[in] src_param Source param + * @param[in] kernel_size Kernel size, 7*7 is 49 + * @param[in] channels Channels + * @param[in] dest Dest + * + */ +void kpu_global_average_pool_float(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, float *dest); + +/** + * @brief Kpu fullly connected by cpu + * + * @param[in] src Source + * @param[in] weights Weight + * @param[in] biases Biases + * @param[in] dest Dest + * @param[in] input_channels Input channels + * @param[in] output_channels Output channels + * + */ +void kpu_fully_connected(const float *src, const float *weights, const float *biases, float *dest, int input_channels, int output_channels); + +/** + * @brief Kpu matrix multiplication + * + * @param[in] src Source + * @param[in] channels Channels + * @param[in] dest Dest + * @param[in] dest_param Dest param + * + */ +void kpu_matmul_end(const uint8_t *src, int channels, float *dest, const quantize_param_t *dest_param); + +/** + * @brief Kpu dequantize + * + * @param[in] src Source + * @param[in] src_param Source param + * @param[in] count Dequantize count + * @param[in] dest Dest + * + */ +void kpu_dequantize(const uint8_t *src, const quantize_param_t *src_param, size_t count, float *dest); + +/** + * @brief Kpu load kmodel + * + * @param[in] ctx Kmodel object + * @param[in] buffer Kmodel buffer + * + * @return result + * - 0 Success + * - Other Fail. + */ +int kpu_load_kmodel(kpu_model_context_t *ctx, const uint8_t *buffer); + +/** + * @brief Kpu free kmodel buffer + * + * @param[in] ctx kmodel object + * + */ +void kpu_model_free(kpu_model_context_t *ctx); + +/** + * @brief Kpu load kmodel + * + * @param[in] ctx Kmodel object + * @param[in] index Output index + * @param[in] data Output data + * @param[in] size Output data size + * + * @return result + * - 0 Success + * - Other Fail. + */ +int kpu_get_output(kpu_model_context_t *ctx, uint32_t index, uint8_t **data, size_t *size); + +/** + * @brief Kpu run kmodel + * + * @param[in] ctx Kmodel object + * @param[in] src Source data + * @param[in] dma_ch Dma channel + * @param[in] done_callback Kpu complete callback + * @param[in] userdata Data of callback + * + * @return result + * - 0 Success + * - Other Fail. + */ +int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_number_t dma_ch, kpu_done_callback_t done_callback, void *userdata); + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig @@ -0,0 +1 @@ + diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile new file mode 100644 index 000000000..cedabd673 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := kpu.c + + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c new file mode 100644 index 000000000..4926c8d6a --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c @@ -0,0 +1,1634 @@ +#include "kpu.h" +#include +#include +#include +#include +#include +#include "printf.h" +#include "dmac.h" +#include +#include "bsp.h" +#include +#include + +#define LAYER_BURST_SIZE 12 + +#define KPU_DEBUG 0 +#define USE_CACHED_AI_RAM 0 + +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define ALIGN_UP(x, align) ((x + (align - 1)) & (~(align - 1))) + +static int ai_step(void *userdata); +static int kpu_kmodel_done(kpu_model_context_t *ctx); + +volatile kpu_config_t *const kpu = (volatile kpu_config_t *)AI_BASE_ADDR; +static volatile uint32_t kpu_status; + +typedef struct kpu_context +{ + kpu_task_t kpu_task; + uint32_t kpu_status; +} kpu_context_t; + +volatile kpu_context_t g_kpu_context; + +static int kpu_run_all_done(void* _task) +{ + atomic_swap(&g_kpu_context.kpu_status, 0); + kpu_task_t* task = (kpu_task_t*)_task; + task->callback(task); + return 0; +} + +int kpu_continue(void* _task) +{ + kpu_task_t* task = (kpu_task_t*)_task; + int layer_burst_size = 1; + + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int=1, + .layer_cfg_almost_empty_int=1, + .layer_cfg_almost_full_int=1 + }; + + if(task->remain_layers_length == 0) + { + return 0; + } + if(task->remain_layers_length <= layer_burst_size) + { + for(uint32_t i=0; iremain_layers_length; i++) + { + kpu->layer_argument_fifo = task->remain_layers[i].interrupt_enabe.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_addr.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_channel_num.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_size.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_pool_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_load_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_offset.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_calc_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].write_back_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value2.reg; + kpu->layer_argument_fifo = task->remain_layers[i].dma_parameter.reg; + } + task->remain_layers_length = 0; + } + else + { + for(uint32_t i=0; ilayer_argument_fifo = task->remain_layers[i].interrupt_enabe.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_addr.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_channel_num.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_size.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_pool_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_load_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_offset.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_calc_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].write_back_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value2.reg; + kpu->layer_argument_fifo = task->remain_layers[i].dma_parameter.reg; + } + task->remain_layers += layer_burst_size; + task->remain_layers_length -= layer_burst_size; + } + return 0; +} + +static int kpu_run_dma_output(uint32_t dma_ch, void* dst, uint32_t length, plic_irq_callback_t cb, void* _task) +{ + sysctl_dma_select(dma_ch, SYSCTL_DMA_SELECT_AI_RX_REQ); + dmac_irq_register(dma_ch, kpu_run_all_done, _task, 1); + dmac_set_single_mode(dma_ch, (void *)(&kpu->fifo_data_out), (void *)(dst), DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, (length+7)/8); + return 0; +} + +static int kpu_run_dma_input_done_push_layers(void* _task) +{ + kpu_task_t* task = (kpu_task_t*)_task; + kpu->interrupt_clear.reg = 7; + dmac->channel[task->dma_ch].intclear = 0xFFFFFFFF; + kpu->fifo_threshold.data = (kpu_config_fifo_threshold_t) + { + .fifo_full_threshold = 10, .fifo_empty_threshold=1 + }; + kpu->eight_bit_mode.data = (kpu_config_eight_bit_mode_t) + { + .eight_bit_mode=task->eight_bit_mode + }; + + kpu_layer_argument_t* last_layer = &task->layers[task->layers_length-1]; + + kpu_run_dma_output(task->dma_ch, task->dst, last_layer->dma_parameter.data.dma_total_byte+1, kpu_run_all_done, task); + + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int=0, + .layer_cfg_almost_empty_int=0, + .layer_cfg_almost_full_int=1 + }; + kpu_continue(task); + return 0; +} + +static void kpu_run_dma_input(uint32_t dma_ch, const void* src, plic_irq_callback_t cb, void* _task) +{ + kpu_task_t* task = _task; + kpu_layer_argument_t* first_layer = &task->layers[0]; + uint64_t input_size = first_layer->kernel_calc_type_cfg.data.channel_switch_addr * 64 * (first_layer->image_channel_num.data.i_ch_num+1); + void *v_src = ((uintptr_t)src > 0x80000000 && (uintptr_t)src < 0x80600000) ? (void *)(src - 0x40000000) : (void *)src; + dmac_irq_register(dma_ch, cb, _task, 1); + dmac_set_single_mode(dma_ch, (void *)v_src, (void *)(AI_IO_BASE_ADDR), DMAC_ADDR_INCREMENT, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_16, DMAC_TRANS_WIDTH_64, input_size / 8); +} + +int kpu_run(kpu_task_t* v_task, dmac_channel_number_t dma_ch, const void *src, void* dest, plic_irq_callback_t callback) +{ + if(atomic_cas(&g_kpu_context.kpu_status, 0, 1)) + return -1; + + memcpy((void *)&g_kpu_context.kpu_task, v_task, sizeof(kpu_task_t)); + kpu_task_t *task = (kpu_task_t *)&g_kpu_context.kpu_task; + + kpu_layer_argument_t* last_layer = &task->layers[task->layers_length-1]; + + uint64_t output_size = last_layer->dma_parameter.data.dma_total_byte+1; + + last_layer->dma_parameter.data.send_data_out = 1; + last_layer->interrupt_enabe.data.int_en = 1; + + task->dma_ch = dma_ch; + task->dst = dest; + task->dst_length = output_size; + task->callback = callback; + task->remain_layers_length = task->layers_length; + task->remain_layers = task->layers; + + plic_irq_enable(IRQN_AI_INTERRUPT); + plic_set_priority(IRQN_AI_INTERRUPT, 1); + plic_irq_register(IRQN_AI_INTERRUPT, kpu_continue, task); + + kpu_run_dma_input(dma_ch, src, kpu_run_dma_input_done_push_layers, task); + + return 0; +} + +uint8_t *kpu_get_output_buf(kpu_task_t* task) +{ + kpu_layer_argument_t* last_layer = &task->layers[task->layers_length-1]; + size_t output_size = ((last_layer->dma_parameter.data.dma_total_byte+1) + 7) / 8 * 8; + return malloc(output_size); +} + +void kpu_release_output_buf(uint8_t *output_buf) +{ + if(output_buf != NULL) + free(output_buf); +} + +static int kpu_done(void *ctx) +{ + atomic_swap(&kpu_status, 0); + kpu_task_t *task = (kpu_task_t *)ctx; + task->callback(task->ctx); + return 0; +} + +static int kpu_config_input(void *ctx) +{ + kpu_task_t *task = (kpu_task_t *)ctx; + kpu->interrupt_clear.reg = 7; + if (task->remain_layers_length <= LAYER_BURST_SIZE) + { + for (uint32_t i = 0; i < task->remain_layers_length; i++) + { + kpu->layer_argument_fifo = task->remain_layers[i].interrupt_enabe.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_addr.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_channel_num.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_size.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_pool_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_load_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_offset.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_calc_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].write_back_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value2.reg; + kpu->layer_argument_fifo = task->remain_layers[i].dma_parameter.reg; + } + task->remain_layers_length = 0; + kpu->interrupt_mask.reg = 7; + } + else + { + for (uint32_t i = 0; i < LAYER_BURST_SIZE; i++) + { + kpu->layer_argument_fifo = task->remain_layers[i].interrupt_enabe.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_addr.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_channel_num.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_size.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_pool_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_load_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_offset.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_calc_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].write_back_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value2.reg; + kpu->layer_argument_fifo = task->remain_layers[i].dma_parameter.reg; + } + task->remain_layers += LAYER_BURST_SIZE; + task->remain_layers_length -= LAYER_BURST_SIZE; + } + return 0; +} + +static void kpu_data_output(kpu_task_t *task) +{ + sysctl_dma_select(task->dma_ch, SYSCTL_DMA_SELECT_AI_RX_REQ); + dmac_irq_register(task->dma_ch, kpu_done, task, 1); + dmac_set_single_mode(task->dma_ch, (void *)(&kpu->fifo_data_out), (void *)(task->dst), DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, task->dst_length); +} + +static int kpu_data_ready(void *ctx) +{ + kpu_task_t *task = (kpu_task_t *)ctx; + + dmac->channel[task->dma_ch].intclear = 0xFFFFFFFF; + kpu_data_output(task); + + kpu->eight_bit_mode.reg = task->eight_bit_mode; + kpu->interrupt_mask.reg = 7; + kpu->interrupt_clear.reg = 7; + kpu->fifo_threshold.data = (kpu_config_fifo_threshold_t) + { + .fifo_full_threshold = 12, .fifo_empty_threshold = 1 + }; + plic_irq_enable(IRQN_AI_INTERRUPT); + plic_set_priority(IRQN_AI_INTERRUPT, 2); + plic_irq_register(IRQN_AI_INTERRUPT, kpu_config_input, task); + kpu_config_input(task); + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 0, + .layer_cfg_almost_full_int = 1 + }; + return 0; +} + +static void kpu_data_input(kpu_task_t *task) +{ + if (task->src == NULL) + { + kpu_data_ready(task); + return; + } + void *v_src = ((uintptr_t)task->src > 0x80000000 && (uintptr_t)task->src < 0x80600000) ? (void *)((void *)task->src - 0x40000000) : (void *)task->src; + dmac_irq_register(task->dma_ch, kpu_data_ready, task, 1); + kpu_layer_argument_t *layer = &task->layers[0]; + dmac_set_single_mode(task->dma_ch, v_src, (void *)(uintptr_t)(AI_IO_BASE_ADDR + layer->image_addr.data.image_src_addr * 64), DMAC_ADDR_INCREMENT, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_16, DMAC_TRANS_WIDTH_64, task->src_length); +} + +int kpu_single_task_init(kpu_task_t *task) +{ + sysctl_clock_enable(SYSCTL_CLOCK_AI); + kpu_layer_argument_t *first_layer = &task->layers[0]; + kpu_layer_argument_t *last_layer = &task->layers[task->layers_length - 1]; + + last_layer->dma_parameter.data.send_data_out = 1; + last_layer->interrupt_enabe.data.int_en = 1; + task->src_length = first_layer->kernel_calc_type_cfg.data.channel_switch_addr * 64 * (first_layer->image_channel_num.data.i_ch_num + 1) / 8; + task->dst_length = ((last_layer->dma_parameter.data.dma_total_byte + 1) + 7) / 8; + task->dst = (uint64_t *)malloc(task->dst_length * 8); + memset(task->dst, 0, task->dst_length * 8); + if (task->dst == NULL) + return 1; + return 0; +} + +int kpu_single_task_deinit(kpu_task_t *task) +{ + free(task->dst); + return 0; +} + +int kpu_model_load_from_buffer(kpu_task_t *task, uint8_t *buffer, kpu_model_layer_metadata_t **meta) +{ + uintptr_t base_addr = (uintptr_t)buffer; + kpu_model_header_t *header = (kpu_model_header_t *)buffer; + kpu_model_layer_metadata_t *layer_meta = (kpu_model_layer_metadata_t *)(base_addr + sizeof(kpu_model_header_t)); + kpu_layer_argument_t *layers = (kpu_layer_argument_t *)(base_addr + header->layers_argument_start); + + if (header->version != 1) + return -1; + uint32_t layers_length = header->layers_length; + task->layers_length = layers_length; + task->eight_bit_mode = header->flags & 1; + task->layers = layers; + task->output_scale = layer_meta[layers_length - 1].output_scale; + task->output_bias = layer_meta[layers_length - 1].output_bias; + size_t i; + for (i = 0; i < layers_length; i++) + { + layers[i].kernel_load_cfg.data.para_start_addr = (uint64_t)(base_addr + layer_meta[i].weigths_offset); + layers[i].kernel_pool_type_cfg.data.bwsx_base_addr = (uint64_t)(base_addr + layer_meta[i].bn_offset); + layers[i].kernel_calc_type_cfg.data.active_addr = (uint64_t)(base_addr + layer_meta[i].act_offset); + } + + if (meta) + *meta = layer_meta; + return 0; +} + +int kpu_start(kpu_task_t *task) +{ + if (atomic_cas(&kpu_status, 0, 1)) + return -1; + + task->remain_layers_length = task->layers_length; + task->remain_layers = task->layers; + kpu_data_input(task); + return 0; +} + +static void kpu_send_layer(const kpu_layer_argument_t *layer) +{ + kpu->layer_argument_fifo = layer->interrupt_enabe.reg; + kpu->layer_argument_fifo = layer->image_addr.reg; + kpu->layer_argument_fifo = layer->image_channel_num.reg; + kpu->layer_argument_fifo = layer->image_size.reg; + kpu->layer_argument_fifo = layer->kernel_pool_type_cfg.reg; + kpu->layer_argument_fifo = layer->kernel_load_cfg.reg; + kpu->layer_argument_fifo = layer->kernel_offset.reg; + kpu->layer_argument_fifo = layer->kernel_calc_type_cfg.reg; + kpu->layer_argument_fifo = layer->write_back_cfg.reg; + kpu->layer_argument_fifo = layer->conv_value.reg; + kpu->layer_argument_fifo = layer->conv_value2.reg; + kpu->layer_argument_fifo = layer->dma_parameter.reg; +} + +void kpu_init(int eight_bit_mode, plic_irq_callback_t callback, void *userdata) +{ + kpu->interrupt_clear.reg = 7; + kpu->fifo_threshold.data = (kpu_config_fifo_threshold_t) + { + .fifo_full_threshold = 10, .fifo_empty_threshold = 1 + }; + kpu->eight_bit_mode.data = (kpu_config_eight_bit_mode_t) + { + .eight_bit_mode = eight_bit_mode + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 0, + .layer_cfg_almost_full_int = 1 + }; + + plic_irq_enable(IRQN_AI_INTERRUPT); + plic_set_priority(IRQN_AI_INTERRUPT, 1); + plic_irq_register(IRQN_AI_INTERRUPT, callback, userdata); +} + +#if 0 +void kpu_input_dma(kpu_layer_argument_t *layer, const uint8_t *src, dmac_channel_number_t dma_ch, plic_irq_callback_t callback, void *userdata) +{ + uint64_t input_size = layer->kernel_calc_type_cfg.data.channel_switch_addr * 64 * (layer->image_channel_num.data.i_ch_num + 1); + dmac_set_irq(dma_ch, callback, userdata, 1); + dmac_set_single_mode(dma_ch, (void *)src, (void *)(AI_IO_BASE_ADDR + layer->image_addr.data.image_src_addr * 64), DMAC_ADDR_INCREMENT, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_16, DMAC_TRANS_WIDTH_64, input_size / 8); +} +#endif + +void kpu_input_dma(const kpu_layer_argument_t *layer, const uint8_t *src, dmac_channel_number_t dma_ch, plic_irq_callback_t callback, void *userdata) +{ + uint64_t input_size = layer->kernel_calc_type_cfg.data.channel_switch_addr * 64 * (layer->image_channel_num.data.i_ch_num + 1); + void *v_src = ((uintptr_t)src > 0x80000000 && (uintptr_t)src < 0x80600000) ? (void *)(src - 0x40000000) : (void *)src; + dmac_set_irq(dma_ch, callback, userdata, 1); + dmac_set_single_mode(dma_ch, (void *)v_src, (void *)(uintptr_t)(AI_IO_BASE_ADDR + layer->image_addr.data.image_src_addr * 64), DMAC_ADDR_INCREMENT, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_16, DMAC_TRANS_WIDTH_64, input_size / 8); +} + +static void kpu_conv2d_core(kpu_layer_argument_t *layer) +{ + kpu_send_layer(layer); +} + +void kpu_conv2d(kpu_layer_argument_t *layer) +{ + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 0, + .layer_cfg_almost_full_int = 1 + }; + kpu_conv2d_core(layer); +} + +void kpu_conv2d_output(kpu_layer_argument_t *layer, dmac_channel_number_t dma_ch, uint8_t *dest, plic_irq_callback_t callback, void *userdata) +{ + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + layer->dma_parameter.data.send_data_out = 1; + sysctl_dma_select(dma_ch, SYSCTL_DMA_SELECT_AI_RX_REQ); + dmac_set_irq(dma_ch, callback, userdata, 1); + dmac_set_single_mode(dma_ch, (void *)(&kpu->fifo_data_out), dest, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, (layer->dma_parameter.data.dma_total_byte + 8) / 8); + kpu_conv2d_core(layer); +} + +void kpu_conv2d_output_full_add(kpu_layer_argument_t *layer, dmac_channel_number_t dma_ch, uint64_t *dest, plic_irq_callback_t callback, void *userdata) +{ + uint32_t channels = layer->image_channel_num.data.o_ch_num + 1; + layer->interrupt_enabe.data.full_add = 1; + + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + layer->dma_parameter.data.send_data_out = 1; + sysctl_dma_select(dma_ch, SYSCTL_DMA_SELECT_AI_RX_REQ); + dmac_set_irq(dma_ch, callback, userdata, 1); + dmac_set_single_mode(dma_ch, (void *)(&kpu->fifo_data_out), dest, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, channels); + kpu_conv2d_core(layer); +} + +void kpu_add(const uint8_t *src1, const quantize_param_t *src1_param, const uint8_t *src2, const quantize_param_t *src2_param, size_t count, uint8_t *dest, const quantize_param_t *dest_param) +{ + quantize_param_t q1 = *src1_param, q2 = *src2_param, q3 = *dest_param; + + size_t i; + for (i = 0; i < count; i++) + { + int value = ((*src1++ * q1.scale + q1.bias + *src2++ * q2.scale + q2.bias) - q3.bias) / q3.scale; + if (value < 0) value = 0; + if (value > 0xFF) value = 0xFF; + *dest++ = value; + } +} + +void kpu_global_average_pool(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, uint8_t *dest, const quantize_param_t *dest_param) +{ + quantize_param_t q1 = *src_param, q2 = *dest_param; + size_t oc, y, x; + + if (((uintptr_t)dest) >= AI_IO_BASE_ADDR && ((uintptr_t)dest) < AI_IO_BASE_ADDR + 2 * 1024 * 1024) + { + uint32_t row_padding = 16; + uint32_t row_group = 4; + uint32_t row_length = 1; + uint32_t height = 4; + + for (oc = 0; oc < channels; oc++) + { + uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding; + for (y = 0; y < 1; y++) + { + uint8_t *y_origin = channel_origin + y * row_length * 64; + for (x = 0; x < 1; x++) + { + int64_t sum = 0; + size_t i; + for (i = 0; i < kernel_size; i++) + sum += *src++; + + int value = ((sum * q1.scale + q1.bias) / kernel_size - q2.bias) / q2.scale; + if (value < 0) value = 0; + if (value > 0xFF) value = 0xFF; + y_origin[x] = value; + } + } + } + } + else + { + for (oc = 0; oc < channels; oc++) + { + int64_t sum = 0; + size_t i; + for (i = 0; i < kernel_size; i++) + sum += *src++; + + int value = ((sum * q1.scale + q1.bias) / kernel_size - q2.bias) / q2.scale; + if (value < 0) value = 0; + if (value > 0xFF) value = 0xFF; + dest[oc] = value; + } + } +} + +void kpu_global_average_pool_float(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, float *dest) +{ + quantize_param_t q = *src_param; + size_t oc; + + for (oc = 0; oc < channels; oc++) + { + int64_t sum = 0; + size_t i; + for (i = 0; i < kernel_size; i++) + sum += *src++; + + float value = (sum * q.scale + q.bias) / kernel_size; + dest[oc] = value; + } +} + +void kpu_matmul_end(const uint8_t *src, int channels, float *dest, const quantize_param_t *dest_param) +{ + quantize_param_t q1 = *dest_param; + size_t i = 0; + for (i = 0; i < channels; i++) + *dest++ = src[i * 16] * q1.scale + q1.bias; +} + +void kpu_fully_connected(const float *src, const float *weights, const float *biases, float *dest, int input_channels, int output_channels) +{ + int ic, oc; + for (oc = 0; oc < output_channels; oc++) + { + const float *c_weights = weights + oc * input_channels; + + float sum = 0.0f; + for (ic = 0; ic < input_channels; ic++) + sum += src[ic] * c_weights[ic]; + dest[oc] = sum + biases[oc]; + } +} + +void kpu_dequantize(const uint8_t *src, const quantize_param_t *src_param, size_t count, float *dest) +{ + quantize_param_t q1 = *src_param; + size_t i = 0; + for (i = 0; i < count; i++) + *dest++ = src[i] * q1.scale + q1.bias; +} + + +void kpu_input_with_padding(kpu_layer_argument_t *layer, const uint8_t *src, int width, int height, int channels) +{ + uint8_t *dest = (uint8_t *)(uintptr_t)(AI_IO_BASE_ADDR + layer->image_addr.data.image_src_addr * 64); + size_t oc, y, x; + + uint32_t row_padding; + uint32_t row_group; + uint32_t row_length; + + if (width <= 16) + { + row_padding = 16; + row_group = 4; + row_length = 1; + } + else if (width <= 32) + { + row_padding = 32; + row_group = 2; + row_length = 1; + } + else + { + row_padding = 64; + row_group = 1; + row_length = (width + 63) / 64; + } + + for (oc = 0; oc < channels; oc++) + { + uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding; + for (y = 0; y < height; y++) + { + uint8_t *y_origin = channel_origin + y * row_length * 64; + for (x = 0; x < width; x++) + y_origin[x] = *src++; + } + } +} +#if USE_CACHED_AI_RAM +static void kpu_flush_cache(uint32_t addr, size_t lines) +{ + size_t line; + for (line = 0; line < lines; line++) + { + const uint64_t *src = (const uint64_t *)(AI_RAM_BASE_ADDR + (addr + line) * 64); + uint64_t *dest = (uint64_t *)(AI_IO_BASE_ADDR + (addr + line) * 64); + size_t i; + for (i = 0; i < 8; i++) + dest[i] = src[i]; + } +} +#endif +static int64_t kpu_carry_shift(int64_t value, uint32_t shift) +{ + if (shift > 0) + { + value >>= shift - 1; + if (value & 0x1) + { + if (value < 0) + value = (value >> 1) - 1; + else + value = (value >> 1) + 1; + } + else + { + value >>= 1; + } + } + + return value; +} +static void kpu_upload_core(size_t width, size_t height, size_t channels, const uint8_t *src, uint32_t kpu_addr) +{ + uint8_t *dest = (uint8_t *)(uintptr_t)(AI_IO_BASE_ADDR + kpu_addr * 64); + size_t oc, y, x; + uint32_t row_padding; + uint32_t row_group; + uint32_t row_length; + if (width <= 16) + { + row_padding = 16; + row_group = 4; + row_length = 1; + } + else if (width <= 32) + { + row_padding = 32; + row_group = 2; + row_length = 1; + } + else + { + row_padding = 64; + row_group = 1; + row_length = (width + 63) / 64; + } + + if ((uintptr_t)src % 8 == 0 && width % 8 == 0) + { +#define UPLOAD_BEGIN() \ + for (oc = 0; oc < channels; oc++) \ + { \ + uint8_t* channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding; \ + for (y = 0; y < height; y++) \ + { \ + uint64_t* y_origin = (uint64_t*)(channel_origin + y * row_length * 64); \ + +#define UPLOAD_END() \ + } \ + } + + width /= 8; + const uint64_t *u64_src = (const uint64_t *)src; + if (width == 1) + { + UPLOAD_BEGIN() + y_origin[0] = *u64_src++; + UPLOAD_END() + } + else if (width == 2) + { + UPLOAD_BEGIN() + { + y_origin[0] = *u64_src++; + y_origin[1] = *u64_src++; + } + UPLOAD_END() + } + else if (width == 4) + { + UPLOAD_BEGIN() + { + y_origin[0] = *u64_src++; + y_origin[1] = *u64_src++; + y_origin[2] = *u64_src++; + y_origin[3] = *u64_src++; + } + UPLOAD_END() + } + else + { + UPLOAD_BEGIN() + for (x = 0; x < width; x++) + y_origin[x] = *u64_src++; + UPLOAD_END() + } + } + else + { + for (oc = 0; oc < channels; oc++) + { + uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding; + for (y = 0; y < height; y++) + { + uint8_t *y_origin = channel_origin + y * row_length * 64; + for (x = 0; x < width; x++) + y_origin[x] = *src++; + } + } + } +} +static void kpu_kmodel_input_with_padding(const kpu_layer_argument_t *layer, const uint8_t *src) +{ + size_t width = layer->image_size.data.i_row_wid + 1; + size_t height = layer->image_size.data.i_col_high + 1; + size_t channels = layer->image_channel_num.data.i_ch_num + 1; + + kpu_upload_core(width, height, channels, src, layer->image_addr.data.image_src_addr); +} + +static void kpu_kmodel_add(const kpu_model_add_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src_a = (const float *)(ctx->main_buffer + arg->main_mem_in_a_address); + const float *src_b = (const float *)(ctx->main_buffer + arg->main_mem_in_b_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + size_t i, count = arg->count; + + for (i = 0; i < count; i++) + dest[i] = src_a[i] + src_b[i]; +} + +static void kpu_quantized_add(const kpu_model_quant_add_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src_a = (const uint8_t*)(ctx->main_buffer + arg->main_mem_in_a_address); + const uint8_t *src_b = (const uint8_t*)(ctx->main_buffer + arg->main_mem_in_b_address); + size_t count = ALIGN_UP(arg->count, 8) / 8; + int64_t off_a = arg->in_a_offset, mul_a = arg->in_a_mul, sh_a = arg->in_a_shift; + int64_t off_b = arg->in_b_offset, mul_b = arg->in_b_mul, sh_b = arg->in_b_shift; + int64_t off_o = arg->out_offset, mul_o = arg->out_mul, sh_o = arg->out_shift; + + uint8_t* dest = (uint8_t*)(ctx->main_buffer + arg->main_mem_out_address); + size_t i; + + if (sh_a == sh_b) + { +#define QADD_UNROLL_1(x) \ + int64_t a##x = *src_a++; \ + int64_t b##x = *src_b++; + +#define QADD_UNROLL_2(x) \ + a##x += off_a; \ + b##x += off_b; + +#define QADD_UNROLL_3(x) \ + a##x *= mul_a; \ + b##x *= mul_b; + +#define QADD_UNROLL_4(x) \ + int64_t v##x = a##x + b##x; + +#define QADD_UNROLL_5(x) \ + v##x >>= sh_a; + +#define QADD_UNROLL_6(x) \ + v##x *= mul_o; + +#define QADD_UNROLL_7(x) \ + v##x = kpu_carry_shift(v##x, sh_o); + +#define QADD_UNROLL_8(x) \ + v##x += off_o; + +#define QADD_UNROLL_9(x) \ + v##x = min(0xFF, max(0, v##x)); + +#define QADD_UNROLL_10(x) \ + *dest++ = v##x; + +#define QADD_UNROLL_S(x) \ + QADD_UNROLL_##x(0) \ + QADD_UNROLL_##x(1) \ + QADD_UNROLL_##x(2) \ + QADD_UNROLL_##x(3) \ + QADD_UNROLL_##x(4) \ + QADD_UNROLL_##x(5) \ + QADD_UNROLL_##x(6) \ + QADD_UNROLL_##x(7) + + for (i = 0; i < count; i++) + { + QADD_UNROLL_S(1); + QADD_UNROLL_S(2); + QADD_UNROLL_S(3); + QADD_UNROLL_S(4); + QADD_UNROLL_S(5); + QADD_UNROLL_S(6); + QADD_UNROLL_S(7); + QADD_UNROLL_S(8); + QADD_UNROLL_S(9); + QADD_UNROLL_S(10); + } + } + else + { +#undef QADD_UNROLL_1 +#define QADD_UNROLL_1(x) \ + int64_t a##x = *src_a++; \ + int64_t b##x = *src_b++; + +#undef QADD_UNROLL_2 +#define QADD_UNROLL_2(x) \ + a##x += off_a; \ + b##x += off_b; + +#undef QADD_UNROLL_3 +#define QADD_UNROLL_3(x) \ + a##x *= mul_a; \ + b##x *= mul_b; + +#undef QADD_UNROLL_4 +#define QADD_UNROLL_4(x) \ + a##x >>= sh_a; \ + b##x >>= sh_b; + +#undef QADD_UNROLL_5 +#define QADD_UNROLL_5(x) \ + int64_t v##x = a##x + b##x; + +#undef QADD_UNROLL_6 +#define QADD_UNROLL_6(x) \ + v##x *= mul_o; + +#undef QADD_UNROLL_7 +#define QADD_UNROLL_7(x) \ + v##x >>= sh_o; + +#undef QADD_UNROLL_8 +#define QADD_UNROLL_8(x) \ + v##x += off_o; + +#undef QADD_UNROLL_9 +#define QADD_UNROLL_9(x) \ + v##x = min(0xFF, max(0, v##x)); + +#undef QADD_UNROLL_10 +#define QADD_UNROLL_10(x) \ + *dest++ = v##x; + +#undef QADD_UNROLL_S +#define QADD_UNROLL_S(x) \ + QADD_UNROLL_##x(0) \ + QADD_UNROLL_##x(1) \ + QADD_UNROLL_##x(2) \ + QADD_UNROLL_##x(3) \ + QADD_UNROLL_##x(4) \ + QADD_UNROLL_##x(5) \ + QADD_UNROLL_##x(6) \ + QADD_UNROLL_##x(7) + + for (i = 0; i < count; i++) + { + QADD_UNROLL_S(1); + QADD_UNROLL_S(2); + QADD_UNROLL_S(3); + QADD_UNROLL_S(4); + QADD_UNROLL_S(5); + QADD_UNROLL_S(6); + QADD_UNROLL_S(7); + QADD_UNROLL_S(8); + QADD_UNROLL_S(9); + QADD_UNROLL_S(10); + } + } +} + +static void kpu_global_average_pool2d(const kpu_model_gap2d_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + size_t oc, channels = arg->channels, kernel_size = arg->kernel_size; + + for (oc = 0; oc < channels; oc++) + { + float sum = 0.f; + size_t i; + for (i = 0; i < kernel_size; i++) + sum += *src++; + + dest[oc] = sum / kernel_size; + } +} + +static void kpu_quantized_max_pool2d(const kpu_model_quant_max_pool2d_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address); + uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address); + kpu_model_shape_t in_shape = arg->in_shape, out_shape = arg->out_shape; + uint32_t kernel_width = arg->kernel_width, kernel_height = arg->kernel_height; + uint32_t stride_width = arg->stride_width, stride_height = arg->stride_height; + uint32_t padding_width = arg->padding_width, padding_height = arg->padding_height; + + uint32_t out_y, out_x, oc; + + for (oc = 0; oc < out_shape.channels; oc++) + { + const uint8_t *channel_src = src + in_shape.width * in_shape.height * oc; + for (out_y = 0; out_y < out_shape.height; out_y++) + { + for (out_x = 0; out_x < out_shape.width; out_x++) + { + int32_t in_x_origin = (int32_t)(out_x * stride_width) - padding_width; + int32_t in_y_origin = (int32_t)(out_y * stride_height) - padding_height; + int32_t kernel_x_start = max(0, -in_x_origin); + int32_t kernel_x_end = min(kernel_width, in_shape.width - in_x_origin); + int32_t kernel_y_start = max(0, -in_y_origin); + int32_t kernel_y_end = min(kernel_height, in_shape.height - in_y_origin); + uint8_t value = 0; + + int32_t kernel_y, kernel_x; + for (kernel_y = kernel_y_start; kernel_y < kernel_y_end; kernel_y++) + { + for (kernel_x = kernel_x_start; kernel_x < kernel_x_end; kernel_x++) + { + int32_t in_x = in_x_origin + kernel_x; + int32_t in_y = in_y_origin + kernel_y; + value = max(value, channel_src[in_y * in_shape.width + in_x]); + } + } + + *dest++ = value; + } + } + } +} + +static void kpu_average_pool2d(const kpu_model_ave_pool2d_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + kpu_model_shape_t in_shape = arg->in_shape, out_shape = arg->out_shape; + uint32_t kernel_width = arg->kernel_width, kernel_height = arg->kernel_height; + uint32_t stride_width = arg->stride_width, stride_height = arg->stride_height; + uint32_t padding_width = arg->padding_width, padding_height = arg->padding_height; + + uint32_t out_y, out_x, oc; + + for (oc = 0; oc < out_shape.channels; oc++) + { + const float *channel_src = src + in_shape.width * in_shape.height * oc; + for (out_y = 0; out_y < out_shape.height; out_y++) + { + for (out_x = 0; out_x < out_shape.width; out_x++) + { + int32_t in_x_origin = (int32_t)(out_x * stride_width) - padding_width; + int32_t in_y_origin = (int32_t)(out_y * stride_height) - padding_height; + int32_t kernel_x_start = max(0, -in_x_origin); + int32_t kernel_x_end = min(kernel_width, in_shape.width - in_x_origin); + int32_t kernel_y_start = max(0, -in_y_origin); + int32_t kernel_y_end = min(kernel_height, in_shape.height - in_y_origin); + float value = 0; + float kernel_count = 0; + + int32_t kernel_y, kernel_x; + for (kernel_y = kernel_y_start; kernel_y < kernel_y_end; kernel_y++) + { + for (kernel_x = kernel_x_start; kernel_x < kernel_x_end; kernel_x++) + { + int32_t in_x = in_x_origin + kernel_x; + int32_t in_y = in_y_origin + kernel_y; + value += channel_src[in_y * in_shape.width + in_x]; + kernel_count++; + } + } + + *dest++ = value / kernel_count; + } + } + } +} + +static void kpu_quantize(const kpu_model_quantize_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + size_t count = arg->count; + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address);; + const kpu_model_quant_param_t q = arg->quant_param; + float scale = 1.f / q.scale; + + uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->mem_out_address); + size_t i; + for (i = 0; i < count; i++) + { + int value = (*src++ - q.bias) * scale; + if (value < 0) value = 0; + if (value > 0xFF) value = 0xFF; + *dest++ = (uint8_t)value; + } +} + +static void kpu_kmodel_dequantize(const kpu_model_dequantize_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + size_t oc, count = arg->count; + const kpu_model_quant_param_t q = arg->quant_param; + + for (oc = 0; oc < count; oc++) + dest[oc] = *src++ * q.scale + q.bias; +} + +static void kpu_kmodel_channelwise_dequantize(const kpu_model_channelwise_dequant_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + size_t oc, i, channels = arg->channels, count = arg->channel_size; + + for (oc = 0; oc < channels; oc++) + { + const kpu_model_quant_param_t q = arg->quant_params[oc]; + + for (i = 0; i < count; i++) + *dest++ = *src++ * q.scale + q.bias; + } +} + +static void kpu_requantize(const kpu_model_requantize_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address); + uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address); + size_t oc, count = ALIGN_UP(arg->count, 8) / 8; + const uint8_t *table = arg->table; + + for (oc = 0; oc < count;) + { + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + } +} + +static void kpu_l2_normalization(const kpu_model_l2_norm_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + size_t oc, channels = arg->channels; + + float sum = 0.f; + const float epsilon = 1e-10f; + for (oc = 0; oc < channels; oc++) + sum += src[oc] * src[oc]; + if (sum < epsilon) + sum = epsilon; + sum = 1.f / sqrtf(sum); + for (oc = 0; oc < channels; oc++) + dest[oc] = src[oc] * sum; +} + +static void kpu_softmax(const kpu_model_softmax_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + size_t oc, channels = arg->channels; + + float max = FLT_MIN; + for (oc = 0; oc < channels; oc++) + max = fmaxf(max, src[oc]); + + float sum = 0.f; + for (oc = 0; oc < channels; oc++) + { + float value = expf(src[oc] - max); + sum += value; + dest[oc] = value; + } + + for (oc = 0; oc < channels; oc++) + dest[oc] /= sum; +} + +static void kpu_concat(const kpu_model_concat_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address); + uint32_t count = arg->input_count, i; + + for (i = 0; i < count; i++) + { + kpu_model_memory_range_t input = arg->inputs_mem[i]; + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + input.start); + memcpy(dest, src, input.size); + dest += input.size; + } +} + +static void kpu_kmodel_fully_connected(const kpu_model_fully_connected_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + uint32_t in_channels = arg->in_channels, out_channels = arg->out_channels, ic, oc; + const float *weights = arg->weights, *bias = arg->weights + in_channels * out_channels; + + if (in_channels % 8 == 0) + { +#define FC_UNROLL_1(x) \ + float i##x = *c_src++; \ + float w##x = *c_weights++; + +#define FC_UNROLL_2(x) \ + sum += i##x * w##x; + +#define FC_UNROLL_S(x) \ + FC_UNROLL_##x(0) \ + FC_UNROLL_##x(1) \ + FC_UNROLL_##x(2) \ + FC_UNROLL_##x(3) \ + FC_UNROLL_##x(4) \ + FC_UNROLL_##x(5) \ + FC_UNROLL_##x(6) \ + FC_UNROLL_##x(7) + + for (oc = 0; oc < out_channels; oc++) + { + const float *c_src = src; + const float *c_weights = weights + oc * in_channels; + + float sum = 0.0f; + for (ic = 0; ic < in_channels / 8; ic++) + { + FC_UNROLL_S(1); + FC_UNROLL_S(2); + } + + dest[oc] = sum + bias[oc]; + } + } + else + { + for (oc = 0; oc < out_channels; oc++) + { + const float *c_weights = weights + oc * in_channels; + + float sum = 0.0f; + for (ic = 0; ic < in_channels; ic++) + sum += src[ic] * c_weights[ic]; + dest[oc] = sum + bias[oc]; + } + } +} + +static void kpu_tf_flatten(const kpu_model_tf_flatten_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + kpu_model_shape_t in_shape = arg->shape; + uint32_t oc, oy, ox; + + for (oy = 0; oy < in_shape.height; oy++) + for (ox = 0; ox < in_shape.width; ox++) + for (oc = 0; oc < in_shape.channels; oc++) + *dest++ = src[(oc * in_shape.height + oy) * in_shape.width + ox]; +} + +static void kpu_resize_nearest_neighbor(const kpu_model_resize_nearest_neighbor_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + kpu_model_shape_t in_shape = arg->in_shape; + uint32_t out_width = arg->out_width, out_height = arg->out_height; + uint32_t oc, oy, ox; + + float height_scale = (float)in_shape.height / out_height; + float width_scale = (float)in_shape.width / out_width; + + for (oc = 0; oc < in_shape.channels; oc++) + { + const float *channel_src = src + in_shape.width * in_shape.height * oc; + for (oy = 0; oy model_buffer + arg->layer_offset); + layer.kernel_load_cfg.data.para_start_addr = (uintptr_t)(ctx->model_buffer + arg->weights_offset); + layer.kernel_pool_type_cfg.data.bwsx_base_addr = (uintptr_t)(ctx->model_buffer + arg->bn_offset); + layer.kernel_calc_type_cfg.data.active_addr = (uintptr_t)(ctx->model_buffer + arg->act_offset); + + if (arg->flags & KLF_MAIN_MEM_OUT) + { + dmac_channel_number_t dma_ch = ctx->dma_ch; + uint8_t *dest = ctx->main_buffer + arg->main_mem_out_address; + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + layer.dma_parameter.data.send_data_out = 1; + sysctl_dma_select(dma_ch, SYSCTL_DMA_SELECT_AI_RX_REQ); + if (ctx->current_layer != ctx->layers_length) + dmac_set_irq(dma_ch, ai_step, ctx, 1); + else + dmac_set_irq(dma_ch, (plic_irq_callback_t)kpu_kmodel_done, ctx, 1); + dmac_set_single_mode(dma_ch, (void *)(&kpu->fifo_data_out), dest, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, (layer.dma_parameter.data.dma_total_byte + 8) / 8); + } + else + { + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 0, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + layer.interrupt_enabe.data.int_en = 1; + } + + kpu_send_layer((const kpu_layer_argument_t *)&layer); +} + +static void kpu_add_padding(const kpu_model_add_padding_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address); +#if USE_CACHED_AI_RAM + uint8_t *dest = (uint8_t *)(uintptr_t)(AI_RAM_BASE_ADDR + arg->kpu_mem_out_address * 64); +#else + uint8_t *dest = (uint8_t *)(uintptr_t)(AI_IO_BASE_ADDR + arg->kpu_mem_out_address * 64); +#endif + + uint32_t row_padding = 16; + uint32_t row_group = 4; + uint32_t row_length = 1; + uint32_t height = 4; + uint32_t oc, x, y, channels = arg->channels; + + for (oc = 0; oc < channels; oc++) + { + uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding; + for (y = 0; y < 1; y++) + { + uint8_t *y_origin = channel_origin + y * row_length * 64; + for (x = 0; x < 1; x++) + y_origin[x] = *src++; + } + } + +#if USE_CACHED_AI_RAM + uint32_t lines = row_length * height * channels / row_group; + kpu_flush_cache(arg->kpu_mem_out_address, lines); +#endif +} + +static void kpu_remove_padding(const kpu_model_remove_padding_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address); + uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address); + uint32_t oc, channels = arg->channels; + + for (oc = 0; oc < channels; oc++) + *dest++ = src[oc * 16]; +} + +static void kpu_upload(const kpu_model_upload_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + size_t width = arg->width; + size_t height = arg->height; + size_t channels = arg->channels; + + kpu_upload_core(width, height, channels, ctx->main_buffer + arg->main_mem_in_address, arg->kpu_mem_out_address); +} + +int kpu_load_kmodel(kpu_model_context_t *ctx, const uint8_t *buffer) +{ + uintptr_t base_addr = (uintptr_t)buffer; + const kpu_kmodel_header_t *header = (const kpu_kmodel_header_t *)buffer; + printf("\nheader->version:%d,header->arch:%d\n",header->version,header->arch); + if (header->version == 3 && header->arch == 0) + { + ctx->model_buffer = buffer; + ctx->output_count = header->output_count; + ctx->outputs = (const kpu_model_output_t *)(base_addr + sizeof(kpu_kmodel_header_t)); + ctx->layer_headers = (const kpu_model_layer_header_t *)((uintptr_t)ctx->outputs + sizeof(kpu_model_output_t) * ctx->output_count); + ctx->layers_length = header->layers_length; + ctx->body_start = (const uint8_t *)((uintptr_t)ctx->layer_headers + sizeof(kpu_model_layer_header_t) * header->layers_length); + ctx->main_buffer = (uint8_t *)malloc(header->main_mem_usage); + if (!ctx->main_buffer) + return -1; + } + else + { + return -1; + } + + return 0; +} + +int kpu_get_output(kpu_model_context_t *ctx, uint32_t index, uint8_t **data, size_t *size) +{ + if (index >= ctx->output_count) + return -1; + + const kpu_model_output_t * output = ctx->outputs + index; + *data = ctx->main_buffer + output->address; + *size = output->size; + return 0; +} + +void kpu_model_free(kpu_model_context_t *ctx) +{ + free(ctx->main_buffer); + ctx->main_buffer = NULL; +} + +#if KPU_DEBUG +static uint64_t last_time; +static uint64_t total_time; +static uint64_t kpu_time; +static uint32_t last_layer_type; + +static const char *str_layer_type(uint32_t type) +{ + switch (type) + { + case KL_ADD: + return "Add"; + case KL_QUANTIZED_ADD: + return "QuantAdd"; + case KL_GLOBAL_AVERAGE_POOL2D: + return "GAP"; + case KL_QUANTIZED_MAX_POOL2D: + return "QuantMaxPool2d"; + case KL_AVERAGE_POOL2D: + return "AveragePool2d"; + case KL_QUANTIZE: + return "Quantize"; + case KL_DEQUANTIZE: + return "Dequantize"; + case KL_REQUANTIZE: + return "Requantize"; + case KL_L2_NORMALIZATION: + return "L2Norm"; + case KL_SOFTMAX: + return "Softmax"; + case KL_CONCAT: + return "Concat"; + case KL_QUANTIZED_CONCAT: + return "QuantConcat"; + case KL_FULLY_CONNECTED: + return "FullyConnected"; + case KL_TENSORFLOW_FLATTEN: + return "TFFlatten"; + case KL_RESIZE_NEAREST_NEIGHBOR: + return "ResizeNearestNeighbor"; + case KL_CHANNELWISE_DEQUANTIZE: + return "ChannelwiseDequantize"; + case KL_K210_CONV: + return "K210Conv"; + case KL_K210_ADD_PADDING: + return "K210AddPad"; + case KL_K210_REMOVE_PADDING: + return "K210RemovePad"; + case KL_K210_UPLOAD: + return "K210Upload"; + default: + return "Unknown"; + } +} +#endif + +static int kpu_kmodel_done(kpu_model_context_t *ctx) +{ + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; +#if KPU_DEBUG + uint32_t cnt_layer_id = ctx->current_layer - 1; + uint64_t time = sysctl_get_time_us(); + if (last_time != 0) + { + uint64_t layer_time = time - last_time; + printf("layer %d [%s]: %f ms\n", cnt_layer_id, str_layer_type(last_layer_type), layer_time / 1000.0); + total_time += layer_time; + if (last_layer_type == KL_K210_CONV) + kpu_time += layer_time; + } + + printf("KPU: %f ms\n", kpu_time / 1000.0); + printf("CPU: %f ms\n", (total_time - kpu_time) / 1000.0); + printf("Model: %f ms\n", total_time / 1000.0); +#endif + ctx->done_callback(ctx->userdata); + return 0; +} + +static int ai_step(void *userdata) +{ + kpu_model_context_t *ctx = (kpu_model_context_t *)userdata; + + uint32_t cnt_layer_id = ctx->current_layer++; + const uint8_t *layer_body = ctx->current_body; + const kpu_model_layer_header_t *cnt_layer_header = ctx->layer_headers + cnt_layer_id; + ctx->current_body += cnt_layer_header->body_size; + +#if KPU_DEBUG + uint64_t time = sysctl_get_time_us(); + if (last_time != 0) + { + uint64_t layer_time = time - last_time; + printf("layer %d [%s]: %f ms\n", cnt_layer_id - 1, str_layer_type(last_layer_type), layer_time / 1000.0); + total_time += layer_time; + if (last_layer_type == KL_K210_CONV) + kpu_time += layer_time; + } + + last_layer_type = cnt_layer_header->type; + last_time = sysctl_get_time_us(); +#endif + + switch (cnt_layer_header->type) + { + case KL_ADD: + kpu_kmodel_add((const kpu_model_add_layer_argument_t *)layer_body, ctx); + break; + case KL_QUANTIZED_ADD: + kpu_quantized_add((const kpu_model_quant_add_layer_argument_t *)layer_body, ctx); + break; + case KL_GLOBAL_AVERAGE_POOL2D: + kpu_global_average_pool2d((const kpu_model_gap2d_layer_argument_t *)layer_body, ctx); + break; + case KL_QUANTIZED_MAX_POOL2D: + kpu_quantized_max_pool2d((const kpu_model_quant_max_pool2d_layer_argument_t *)layer_body, ctx); + break; + case KL_AVERAGE_POOL2D: + kpu_average_pool2d((const kpu_model_ave_pool2d_layer_argument_t *)layer_body, ctx); + break; + case KL_QUANTIZE: + kpu_quantize((const kpu_model_quantize_layer_argument_t *)layer_body, ctx); + break; + case KL_DEQUANTIZE: + kpu_kmodel_dequantize((const kpu_model_dequantize_layer_argument_t *)layer_body, ctx); + break; + case KL_REQUANTIZE: + kpu_requantize((const kpu_model_requantize_layer_argument_t *)layer_body, ctx); + break; + case KL_L2_NORMALIZATION: + kpu_l2_normalization((const kpu_model_l2_norm_layer_argument_t *)layer_body, ctx); + break; + case KL_SOFTMAX: + kpu_softmax((const kpu_model_softmax_layer_argument_t *)layer_body, ctx); + break; + case KL_CONCAT: + case KL_QUANTIZED_CONCAT: + kpu_concat((const kpu_model_concat_layer_argument_t *)layer_body, ctx); + break; + case KL_FULLY_CONNECTED: + kpu_kmodel_fully_connected((const kpu_model_fully_connected_layer_argument_t *)layer_body, ctx); + break; + case KL_TENSORFLOW_FLATTEN: + kpu_tf_flatten((const kpu_model_tf_flatten_layer_argument_t *)layer_body, ctx); + break; + case KL_RESIZE_NEAREST_NEIGHBOR: + kpu_resize_nearest_neighbor((const kpu_model_resize_nearest_neighbor_layer_argument_t *)layer_body, ctx); + break; + case KL_CHANNELWISE_DEQUANTIZE: + kpu_kmodel_channelwise_dequantize((const kpu_model_channelwise_dequant_argument_t *)layer_body, ctx); + break; + case KL_K210_CONV: + kpu_conv((const kpu_model_conv_layer_argument_t *)layer_body, ctx); + return 0; + case KL_K210_ADD_PADDING: + kpu_add_padding((const kpu_model_add_padding_layer_argument_t *)layer_body, ctx); + break; + case KL_K210_REMOVE_PADDING: + kpu_remove_padding((const kpu_model_remove_padding_layer_argument_t *)layer_body, ctx); + break; + case KL_K210_UPLOAD: + kpu_upload((const kpu_model_upload_layer_argument_t *)layer_body, ctx); + break; + default: + assert(!"Layer is not supported."); + } + + if (cnt_layer_id != (ctx->layers_length - 1)) + ai_step(userdata); + else + kpu_kmodel_done(ctx); + return 0; +} + +static void ai_step_not_isr(void *userdata) +{ + sysctl_disable_irq(); + ai_step(userdata); + sysctl_enable_irq(); +} + +int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_number_t dma_ch, kpu_done_callback_t done_callback, void *userdata) +{ + ctx->dma_ch = dma_ch; + ctx->done_callback = done_callback; + ctx->userdata = userdata; + ctx->current_layer = 0; + ctx->current_body = ctx->body_start; +#if KPU_DEBUG + last_time = 0; + total_time = 0; + kpu_time = 0; +#endif + + kpu_kmodel_header_t *header = (kpu_kmodel_header_t *)ctx->model_buffer; + kpu->interrupt_clear.reg = 7; + kpu->fifo_threshold.data = (kpu_config_fifo_threshold_t) + { + .fifo_full_threshold = 10, .fifo_empty_threshold = 1 + }; + kpu->eight_bit_mode.data = (kpu_config_eight_bit_mode_t) + { + .eight_bit_mode = header->flags & 1 + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 0, + .layer_cfg_almost_full_int = 1 + }; + + plic_irq_enable(IRQN_AI_INTERRUPT); + plic_set_priority(IRQN_AI_INTERRUPT, 1); + plic_irq_register(IRQN_AI_INTERRUPT, ai_step, ctx); + + const kpu_model_layer_header_t *first_layer_header = ctx->layer_headers; + if (first_layer_header->type != KL_K210_CONV) + return -1; + const kpu_model_conv_layer_argument_t *first_layer = (const kpu_model_conv_layer_argument_t *)ctx->body_start; + kpu_layer_argument_t layer_arg = *(volatile kpu_layer_argument_t *)(ctx->model_buffer + first_layer->layer_offset); + + if ((layer_arg.image_size.data.i_row_wid + 1) % 64 != 0) + { + kpu_kmodel_input_with_padding(&layer_arg, src); + ai_step_not_isr(ctx); + } + else + { + kpu_input_dma(&layer_arg, src, ctx->dma_ch, ai_step, ctx); + } + + return 0; +} + diff --git a/Ubiquitous/XiZi_IIoT/path_kernel.mk b/Ubiquitous/XiZi_IIoT/path_kernel.mk index 3731ae559..b9544200b 100755 --- a/Ubiquitous/XiZi_IIoT/path_kernel.mk +++ b/Ubiquitous/XiZi_IIoT/path_kernel.mk @@ -461,6 +461,9 @@ KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/tensorflow KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/tensorflow-lite/tensorflow-lite-for-mcu/source/third_party/gemmlowp # KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/tensorflow-lite/tensorflow-lite-for-mcu/source/third_party/flatbuffers/include # KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/tensorflow-lite/tensorflow-lite-for-mcu/source/third_party/ruy # +KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure # +KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/kpu/yolov2 # +KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/kpu/yolov2_json # endif ifeq ($(CONFIG_LIB_LV),y) @@ -479,6 +482,10 @@ KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protoc KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protocol/melsec # KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protocol/opcua # KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protocol/s7 # +endif + + +ifeq ($(CONFIG_LIB_USING_CJSON), y) KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/lib/cJSON endif diff --git a/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c b/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c index 6eba43464..e66e82166 100644 --- a/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c +++ b/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c @@ -850,7 +850,6 @@ static uint32 SdReadMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const uint do { - BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param); BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); SD_TIMEOUT(start_time, 10 * SPI_SD_TIMEOUT_NUM); From 04dc796f9582737efbbac89753d7aa69cb37c76a Mon Sep 17 00:00:00 2001 From: wuzheng Date: Mon, 12 Dec 2022 16:22:36 +0800 Subject: [PATCH 07/33] fix problems in client recv --- .../Applications/app_test/test_ethernet.c | 38 ++++++++++--------- .../ethernet/connect_w5500.c | 23 ++++++----- .../ethernet/connect_w5500.c | 23 ++++++----- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/APP_Framework/Applications/app_test/test_ethernet.c b/APP_Framework/Applications/app_test/test_ethernet.c index 5574d2fcb..6e551c004 100644 --- a/APP_Framework/Applications/app_test/test_ethernet.c +++ b/APP_Framework/Applications/app_test/test_ethernet.c @@ -9,7 +9,6 @@ #define TCP_PORT 12345 const static uint32_t sn = 0; -const static uint32_t socket_tcp = 0; #ifdef ETHERNET_AS_SERVER static int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, @@ -26,9 +25,9 @@ static int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, uint32_t sent_size = 0; memset(buf,0,buf_size); strcpy(buf,"The message has been recved"); - ret = wiz_sock_send(socket_tcp, buf, buf_size); + ret = wiz_sock_send(sn, buf, buf_size); if (ret < 0) { - wiz_sock_close(socket_tcp); + wiz_sock_close(sn); return ret; } } else if (opt == RECV_DATA) { @@ -87,27 +86,27 @@ static uint32_t wiz_client_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, enum TCP_OPTION opt) { // assert(buf_size <= g_wiznet_buf_size); int32_t ret; - switch (getSn_SR(socket_tcp)) { + switch (getSn_SR(sn)) { case SOCK_CLOSE_WAIT: - wiz_sock_disconnect(socket_tcp); + wiz_sock_disconnect(sn); break; case SOCK_CLOSED: - wiz_socket(socket_tcp, Sn_MR_TCP, 5000, 0x00); + wiz_socket(sn, Sn_MR_TCP, 5000, 0x00); break; case SOCK_INIT: KPrintf("[SOCKET CLIENT] sock init.\n"); - wiz_sock_connect(socket_tcp, dst_ip, dst_port); + wiz_sock_connect(sn, dst_ip, dst_port); break; case SOCK_ESTABLISHED: - if (getSn_IR(socket_tcp) & Sn_IR_CON) { - printf("[SOCKET CLIENT] %d:Connected\r\n", socket_tcp); - setSn_IR(socket_tcp, Sn_IR_CON); + if (getSn_IR(sn) & Sn_IR_CON) { + printf("[SOCKET CLIENT] %d:Connected\r\n", sn); + setSn_IR(sn, Sn_IR_CON); } if (opt == SEND_DATA) { uint32_t sent_size = 0; - ret = wiz_sock_send(socket_tcp, buf, buf_size); + ret = wiz_sock_send(sn, buf, buf_size); if (ret < 0) { - wiz_sock_close(socket_tcp); + wiz_sock_close(sn); return ret; } } else if (opt == RECV_DATA) { @@ -145,15 +144,18 @@ void TestSocketAsClient(int argc, char *argv[]) } while(1){ - ret = wiz_client_op(client_sock, argv[2], sizeof(argv[2]), destination_ip, port,SEND_DATA); - PrivTaskDelay(10); + ret = wiz_client_op(client_sock, argv[2], strlen(argv[2]), destination_ip, port,SEND_DATA); + printf("sizeof:%d\n",strlen(argv[2])); + PrivTaskDelay(1000); if (ret > 0) { ret=wiz_client_op(client_sock, buf, BUFF_SIZE, destination_ip, port, RECV_DATA); - printf("client recv msg successfully!\n"); - printf("%s\n",buf); - break; + printf("read ret is %d\n",ret); + if(ret>0){ + printf("client recv msg successfully!\n"); + printf("%s\n",buf); + } }; - PrivTaskDelay(100); + PrivTaskDelay(1000); } diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c index ba1e0b810..62ad935e7 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c @@ -22,7 +22,6 @@ extern void spi_select_cs(void); extern void spi_deselete_cs(void); // global configurations for w5500 tcp connection -const uint32_t socket_tcp = 0; const uint32_t g_wiznet_buf_size = 2048; static wiz_NetInfo g_wiz_netinfo = {.mac = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11}, @@ -269,27 +268,27 @@ uint32_t wiz_client_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, enum TCP_OPTION opt) { // assert(buf_size <= g_wiznet_buf_size); int32_t ret; - switch (getSn_SR(socket_tcp)) { + switch (getSn_SR(sn)) { case SOCK_CLOSE_WAIT: - wiz_sock_disconnect(socket_tcp); + wiz_sock_disconnect(sn); break; case SOCK_CLOSED: - wiz_socket(socket_tcp, Sn_MR_TCP, 5000, 0x00); + wiz_socket(sn, Sn_MR_TCP, 5000, 0x00); break; case SOCK_INIT: KPrintf("[SOCKET CLIENT] sock init.\n"); - wiz_sock_connect(socket_tcp, dst_ip, dst_port); + wiz_sock_connect(sn, dst_ip, dst_port); break; case SOCK_ESTABLISHED: - if (getSn_IR(socket_tcp) & Sn_IR_CON) { - printf("[SOCKET CLIENT] %d:Connected\r\n", socket_tcp); - setSn_IR(socket_tcp, Sn_IR_CON); + if (getSn_IR(sn) & Sn_IR_CON) { + printf("[SOCKET CLIENT] %d:Connected\r\n", sn); + setSn_IR(sn, Sn_IR_CON); } if (opt == SEND_DATA) { uint32_t sent_size = 0; - ret = wiz_sock_send(socket_tcp, buf, buf_size); + ret = wiz_sock_send(sn, buf, buf_size); if (ret < 0) { - wiz_sock_close(socket_tcp); + wiz_sock_close(sn); return ret; } } else if (opt == RECV_DATA) { @@ -348,9 +347,9 @@ int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, } if (opt == SEND_DATA) { uint32_t sent_size = 0; - ret = wiz_sock_send(socket_tcp, buf, buf_size); + ret = wiz_sock_send(sn, buf, buf_size); if (ret < 0) { - wiz_sock_close(socket_tcp); + wiz_sock_close(sn); return ret; } } else if (opt == RECV_DATA) { diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-riscv64/third_party_driver/ethernet/connect_w5500.c b/Ubiquitous/XiZi_IIoT/board/xidatong-riscv64/third_party_driver/ethernet/connect_w5500.c index 22803ee9e..93fcba38c 100644 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-riscv64/third_party_driver/ethernet/connect_w5500.c +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-riscv64/third_party_driver/ethernet/connect_w5500.c @@ -22,7 +22,6 @@ extern void spi_select_cs(void); extern void spi_deselete_cs(void); // global configurations for w5500 tcp connection -const uint32_t socket_tcp = 0; const uint32_t g_wiznet_buf_size = 2048; static wiz_NetInfo g_wiz_netinfo = {.mac = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11}, @@ -269,27 +268,27 @@ uint32_t wiz_client_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, enum TCP_OPTION opt) { // assert(buf_size <= g_wiznet_buf_size); int32_t ret; - switch (getSn_SR(socket_tcp)) { + switch (getSn_SR(sn)) { case SOCK_CLOSE_WAIT: - wiz_sock_disconnect(socket_tcp); + wiz_sock_disconnect(sn); break; case SOCK_CLOSED: - wiz_socket(socket_tcp, Sn_MR_TCP, 5000, 0x00); + wiz_socket(sn, Sn_MR_TCP, 5000, 0x00); break; case SOCK_INIT: KPrintf("[SOCKET CLIENT] sock init.\n"); - wiz_sock_connect(socket_tcp, dst_ip, dst_port); + wiz_sock_connect(sn, dst_ip, dst_port); break; case SOCK_ESTABLISHED: - if (getSn_IR(socket_tcp) & Sn_IR_CON) { - printf("[SOCKET CLIENT] %d:Connected\r\n", socket_tcp); - setSn_IR(socket_tcp, Sn_IR_CON); + if (getSn_IR(sn) & Sn_IR_CON) { + printf("[SOCKET CLIENT] %d:Connected\r\n", sn); + setSn_IR(sn, Sn_IR_CON); } if (opt == SEND_DATA) { uint32_t sent_size = 0; - ret = wiz_sock_send(socket_tcp, buf, buf_size); + ret = wiz_sock_send(sn, buf, buf_size); if (ret < 0) { - wiz_sock_close(socket_tcp); + wiz_sock_close(sn); return ret; } } else if (opt == RECV_DATA) { @@ -348,9 +347,9 @@ int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, } if (opt == SEND_DATA) { uint32_t sent_size = 0; - ret = wiz_sock_send(socket_tcp, buf, buf_size); + ret = wiz_sock_send(sn, buf, buf_size); if (ret < 0) { - wiz_sock_close(socket_tcp); + wiz_sock_close(sn); return ret; } } else if (opt == RECV_DATA) { From 6a89a12c492fd1123df3798b37ced2b08dd4a750 Mon Sep 17 00:00:00 2001 From: wuzheng Date: Mon, 12 Dec 2022 16:24:54 +0800 Subject: [PATCH 08/33] temporarily adapt kpu for XiZi --- .../Applications/app_test/test_camera.c | 9 - APP_Framework/Framework/knowing/Makefile | 2 +- APP_Framework/Framework/knowing/kpu/Makefile | 3 + .../kpu/k210_yolov2_detect_procedure/Kconfig | 5 +- .../k210_yolov2_detect.c | 218 ++++++++++-------- .../transform_layer/xizi/transform.c | 5 +- .../transform_layer/xizi/transform.h | 38 +++ .../xizi/user_api/posix_support/pthread.c | 1 + .../edu-riscv64/third_party_driver/dma/dmac.c | 18 +- .../third_party_driver/dvp/connect_dvp.c | 43 +++- .../third_party_driver/include/connect_dvp.h | 28 +++ .../edu-riscv64/third_party_driver/kpu/kpu.c | 32 +-- 12 files changed, 268 insertions(+), 134 deletions(-) create mode 100644 APP_Framework/Framework/knowing/kpu/Makefile diff --git a/APP_Framework/Applications/app_test/test_camera.c b/APP_Framework/Applications/app_test/test_camera.c index f414dd2ee..56f389ff1 100644 --- a/APP_Framework/Applications/app_test/test_camera.c +++ b/APP_Framework/Applications/app_test/test_camera.c @@ -2,15 +2,6 @@ #include #include -#define NULL_PARAMETER 0 - -#define DVP_INIT 0x00U -#define REG_SCCB_READ 0x12U -#define REG_SCCB_WRITE 0x13U -#define OUTPUT_CONFIG 0x20U -#define LCD_STRING_TYPE 0 -#define LCD_DOT_TYPE 1 -#define LCD_SIZE 320 static uint16_t image_buff[384000]; diff --git a/APP_Framework/Framework/knowing/Makefile b/APP_Framework/Framework/knowing/Makefile index d12b24374..62c998618 100644 --- a/APP_Framework/Framework/knowing/Makefile +++ b/APP_Framework/Framework/knowing/Makefile @@ -1,4 +1,4 @@ -SRC_DIR := tensorflow-lite +SRC_DIR := kpu tensorflow-lite include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/knowing/kpu/Makefile b/APP_Framework/Framework/knowing/kpu/Makefile new file mode 100644 index 000000000..ff538d7ef --- /dev/null +++ b/APP_Framework/Framework/knowing/kpu/Makefile @@ -0,0 +1,3 @@ +SRC_DIR := k210_yolov2_detect_procedure yolov2 yolov2_json + +include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig index 2d25a5710..a359ac926 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig @@ -4,8 +4,11 @@ menuconfig USING_K210_YOLOV2_DETECT default n config CAMERA_DEV_DRIVER - string "Set camera dev path" + string "Set camera dev path for kpu" default "/dev/ov2640" +config KPU_LCD_DEV_DRIVER + string "Set lcd dev path for kpu" + default "/dev/lcd_dev" diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c index 028784b2d..e2aa4d8ec 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c @@ -1,24 +1,26 @@ #include "k210_yolov2_detect.h" #include "cJSON.h" +#include "dvp.h" #ifdef USING_YOLOV2_JSONPARSER #include #endif #include "region_layer.h" #define STACK_SIZE (128 * 1024) -static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX; +static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX-1; +static _ioctl_shoot_para shoot_para_t = {0}; #define THREAD_PRIORITY_D (11) static pthread_t tid = 0; static void *thread_detect_entry(void *parameter); -static int g_fd = 0; +static int camera_fd = 0; static int kmodel_fd = 0; static int if_exit = 0; static unsigned char *showbuffer = NULL; static unsigned char *kpurgbbuffer = NULL; -static _ioctl_shoot_para shoot_para_t = {0}; + unsigned char *model_data = NULL; // kpu data load memory unsigned char *model_data_align = NULL; @@ -29,6 +31,8 @@ volatile uint32_t g_ai_done_flag; static void ai_done(void *ctx) { g_ai_done_flag = 1; } +#define ERROR_FLAG (1) + void k210_detect(char *json_file_path) { int ret = 0; @@ -36,50 +40,78 @@ void k210_detect(char *json_file_path) int size = 0; char kmodel_path[127] = {}; + // open and parse from json file yolov2_params_t detect_params = param_parse(json_file_path); if (!detect_params.is_valid) { return; } - - g_fd = open("/dev/ov2640", O_RDONLY); - if (g_fd < 0) { - printf("open ov2640 fail !!"); + printf("select camera device name:%s\n",CAMERA_DEV_DRIVER); + camera_fd = PrivOpen(CAMERA_DEV_DRIVER, O_RDONLY); + if (camera_fd < 0) { + printf("open %s fail !!",CAMERA_DEV_DRIVER); return; } + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = CAMERA_TYPE; + struct CameraCfg camera_init_cfg ={ + .gain_manu_enable = 0, + .gain = 0xFF, + .window_w = 800, + .window_h = 600, + .output_w = IMAGE_WIDTH, + .output_h = IMAGE_HEIGHT, + .window_xoffset = 0, + .window_yoffset = 0 + }; + ioctl_cfg.args = &camera_init_cfg; + if (0 != PrivIoctl(camera_fd, OPE_CFG, &ioctl_cfg)) + { + printf("camera pin fd error %d\n", camera_fd); + PrivClose(camera_fd); + } + + // configure the resolution of camera _ioctl_set_reso set_dvp_reso = {detect_params.sensor_output_size[1], detect_params.sensor_output_size[0]}; - ioctl(g_fd, IOCTRL_CAMERA_OUT_SIZE_RESO, &set_dvp_reso); - showbuffer = - (unsigned char *)rt_malloc_align(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2, 64); + struct PrivIoctlCfg camera_cfg; + camera_cfg.args = &set_dvp_reso; + camera_cfg.ioctl_driver_type = CAMERA_TYPE; + PrivIoctl(camera_fd, IOCTRL_CAMERA_OUT_SIZE_RESO, &camera_cfg); + + // alloc the memory for camera and kpu running + showbuffer = (unsigned char *)malloc(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); if (NULL == showbuffer) { - close(g_fd); + close(camera_fd); printf("showbuffer apply memory fail !!"); return; } - kpurgbbuffer = (unsigned char *)rt_malloc_align(detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3, 64); + kpurgbbuffer = (unsigned char *)malloc(detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3); if (NULL == kpurgbbuffer) { - close(g_fd); - rt_free_align(showbuffer); + close(camera_fd); + free(showbuffer); printf("kpurgbbuffer apply memory fail !!"); return; } model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); + printf("model address:%x->%x\n",model_data_align,model_data_align + detect_params.kmodel_size); if (NULL == model_data) { - rt_free_align(showbuffer); - rt_free_align(kpurgbbuffer); - close(g_fd); + free(showbuffer); + free(kpurgbbuffer); + close(camera_fd); printf("model_data apply memory fail !!"); return; } memset(model_data, 0, detect_params.kmodel_size + 255); memset(showbuffer, 0, detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); memset(kpurgbbuffer, 0, detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3); - shoot_para_t.pdata = (unsigned int *)(showbuffer); + shoot_para_t.pdata = (uintptr_t)(showbuffer); shoot_para_t.length = (size_t)(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); + /* load memory */ // kmodel path generate from json file path, *.json -> *.kmodel memcpy(kmodel_path, json_file_path, strlen(json_file_path)); + int idx_suffix_start = strlen(json_file_path) - 4; const char kmodel_suffix[7] = "kmodel"; int kmodel_suffix_len = 6; @@ -87,45 +119,56 @@ void k210_detect(char *json_file_path) kmodel_path[idx_suffix_start + 5 - kmodel_suffix_len] = kmodel_suffix[5 - kmodel_suffix_len]; } printf("kmodel path: %s\n", kmodel_path); - kmodel_fd = open(kmodel_path, O_RDONLY); + unsigned char *model_data_align = (unsigned char *)(((uintptr_t)model_data + 255) & (~255)); + kmodel_fd = PrivOpen(kmodel_path, O_RDONLY); + + memset(model_data,0,sizeof(model_data)); if (kmodel_fd < 0) { printf("open kmodel fail"); - close(g_fd); + close(camera_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); return; } else { - size = read(kmodel_fd, model_data, detect_params.kmodel_size); + size = read(kmodel_fd, model_data_align, detect_params.kmodel_size); if (size != detect_params.kmodel_size) { printf("read kmodel error size %d\n", size); - close(g_fd); + close(camera_fd); close(kmodel_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); return; - } else { + close(kmodel_fd); printf("read kmodel success \n"); } } - unsigned char *model_data_align = (unsigned char *)(((unsigned int)model_data + 255) & (~255)); - // dvp_set_ai_addr((uint32_t)kpurgbbuffer, - // (uint32_t)(kpurgbbuffer + detect_params.net_input_size[0] * detect_params.net_input_size[1]), - // (uint32_t)(kpurgbbuffer + detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2)); + +#ifdef ADD_RTTHREAD_FETURES dvp_set_ai_addr( - (uint32_t)(kpurgbbuffer + + (uintptr_t)(kpurgbbuffer + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0])), - (uint32_t)(kpurgbbuffer + + (uintptr_t)(kpurgbbuffer + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + detect_params.net_input_size[0] * detect_params.net_input_size[1]), - (uint32_t)(kpurgbbuffer + + (uintptr_t)(kpurgbbuffer + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2)); +#endif + // Set AI buff address of Camera + RgbAddress ai_address_preset; + ai_address_preset.r_addr = (uintptr_t)kpurgbbuffer + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]); + ai_address_preset.g_addr = ai_address_preset.r_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1]; + ai_address_preset.b_addr = ai_address_preset.g_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1]; + camera_cfg.args = &ai_address_preset; + PrivIoctl(camera_fd,SET_AI_ADDR,&camera_cfg); + + // Load kmodel into kpu task if (kpu_load_kmodel(&detect_task, model_data_align) != 0) { printf("\nmodel init error\n"); - close(g_fd); + close(camera_fd); close(kmodel_fd); free(showbuffer); free(kpurgbbuffer); @@ -137,8 +180,7 @@ void k210_detect(char *json_file_path) detect_rl.anchor = detect_params.anchor; detect_rl.nms_value = detect_params.nms_thresh; detect_rl.classes = detect_params.class_num; - result = - region_layer_init(&detect_rl, detect_params.net_output_shape[0], detect_params.net_output_shape[1], + result =region_layer_init(&detect_rl, detect_params.net_output_shape[0], detect_params.net_output_shape[1], detect_params.net_output_shape[2], detect_params.net_input_size[1], detect_params.net_input_size[0]); printf("region_layer_init result %d \n\r", result); for (int idx = 0; idx < detect_params.class_num; idx++) { @@ -159,7 +201,7 @@ void k210_detect(char *json_file_path) printf("thread_detect_entry successfully!\n"); } else { printf("thread_detect_entry failed! error code is %d\n", result); - close(g_fd); + close(camera_fd); } } // #ifdef __RT_THREAD_H__ @@ -168,22 +210,38 @@ void k210_detect(char *json_file_path) static void *thread_detect_entry(void *parameter) { +#ifdef BSP_USING_LCD + int lcd_fd = PrivOpen(KPU_LCD_DEV_DRIVER, O_RDWR); + if (lcd_fd < 0) + { + printf("open lcd fd error:%d\n", lcd_fd); + } + LcdWriteParam graph_param; + graph_param.type = LCD_DOT_TYPE; +#endif + yolov2_params_t detect_params = *(yolov2_params_t *)parameter; - extern void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t * ptr); + struct PrivIoctlCfg camera_cfg; + camera_cfg.ioctl_driver_type = CAMERA_TYPE; + printf("thread_detect_entry start!\n"); int ret = 0; - // sysctl_enable_irq(); while (1) { - // memset(showbuffer,0,320*240*2); g_ai_done_flag = 0; - ret = ioctl(g_fd, IOCTRL_CAMERA_START_SHOT, &shoot_para_t); - if (RT_ERROR == ret) { + + //get a graph map from camera + camera_cfg.args = &shoot_para_t; + ret = PrivIoctl(camera_fd, IOCTRL_CAMERA_START_SHOT, &camera_cfg); + if (ERROR_FLAG == ret) { printf("ov2640 can't wait event flag"); - rt_free(showbuffer); - close(g_fd); + free(showbuffer); + close(camera_fd); pthread_exit(NULL); return NULL; } + + +#ifdef ADD_RTTHREAD_FETURES if (dmalock_sync_take(&dma_ch, 2000)) { printf("Fail to take DMA channel"); } @@ -191,13 +249,19 @@ static void *thread_detect_entry(void *parameter) while (!g_ai_done_flag) ; dmalock_release(dma_ch); +#elif defined ADD_XIZI_FETURES + kpu_run_kmodel(&detect_task, kpurgbbuffer, dma_ch, ai_done, NULL); + while (!g_ai_done_flag) + ; +#endif + float *output; size_t output_size; kpu_get_output(&detect_task, 0, (uint8_t **)&output, &output_size); detect_rl.input = output; region_layer_run(&detect_rl, &detect_info); + printf("detect_info.obj_number:%d\n",detect_info.obj_number); /* display result */ - for (int cnt = 0; cnt < detect_info.obj_number; cnt++) { detect_info.obj[cnt].y1 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0])/2; detect_info.obj[cnt].y2 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0])/2; @@ -208,12 +272,27 @@ static void *thread_detect_entry(void *parameter) detect_info.obj[cnt].prob); } #ifdef BSP_USING_LCD - lcd_draw_picture(0, 0, (uint16_t)detect_params.sensor_output_size[1] - 1, - (uint16_t)detect_params.sensor_output_size[0] - 1, (uint32_t *)showbuffer); - // lcd_show_image(0, 0, (uint16_t)detect_params.sensor_output_size[1], (uint16_t)detect_params.sensor_output_size[0], - // (unsigned int *)showbuffer); + +#ifdef ADD_RTTHREAD_FETURES + extern void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t * ptr); + lcd_draw_picture(0, 0, (uint16_t)detect_params.sensor_output_size[1] - 1, + (uint16_t)detect_params.sensor_output_size[0] - 1, (uint32_t *)showbuffer); + // lcd_show_image(0, 0, (uint16_t)detect_params.sensor_output_size[1], (uint16_t)detect_params.sensor_output_size[0], + // (unsigned int *)showbuffer); +#else + //refresh the LCD using photo of camera + for (int i = 0; i < IMAGE_HEIGHT; i++) + { + graph_param.pixel_info.pixel_color = (uint16_t*)showbuffer + i * IMAGE_WIDTH; + graph_param.pixel_info.x_startpos = 0; + graph_param.pixel_info.y_startpos = i + (LCD_SIZE - IMAGE_HEIGHT) / 2; + graph_param.pixel_info.x_endpos = IMAGE_WIDTH - 1; + graph_param.pixel_info.y_endpos = i + (LCD_SIZE - IMAGE_HEIGHT) / 2; + PrivWrite(lcd_fd, &graph_param, NULL_PARAMETER); + } +#endif + #endif - usleep(500); if (1 == if_exit) { if_exit = 0; printf("thread_detect_entry exit"); @@ -226,7 +305,7 @@ void detect_delete() { if (showbuffer != NULL) { int ret = 0; - close(g_fd); + close(camera_fd); close(kmodel_fd); free(showbuffer); free(kpurgbbuffer); @@ -235,46 +314,3 @@ void detect_delete() if_exit = 1; } } -// #ifdef __RT_THREAD_H__ -// MSH_CMD_EXPORT(detect_delete, detect task delete); -// #endif - -// void kmodel_load(unsigned char *model_data) -// { -// int kmodel_fd = 0; -// int size = 0; -// char kmodel_path[127] = {}; -// // kmodel path generate from json file path, *.json -> *.kmodel -// memcpy(kmodel_path, json_file_path, strlen(json_file_path)); -// int idx_suffix_start = strlen(json_file_path) - 4; -// const char kmodel_suffix[5] = "kmodel"; -// int kmodel_suffix_len = 5; -// while (kmodel_suffix_len--) { -// kmodel_path[idx_suffix_start + 4 - kmodel_suffix_len] = kmodel_suffix[4 - kmodel_suffix_len]; -// } -// printf("Kmodel path: %s\n", kmodel_path); -// kmodel_fd = open(kmodel_path, O_RDONLY); - -// model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); -// if (NULL == model_data) { -// printf("model_data apply memory fail !!"); -// return; -// } -// memset(model_data, 0, detect_params.kmodel_size + 255); - -// if (kmodel_fd >= 0) { -// size = read(kmodel_fd, model_data, detect_params.kmodel_size); -// if (size != detect_params.kmodel_size) { -// printf("read kmodel error size %d\n", size); - -// } else { -// printf("read kmodel success"); -// } -// } else { -// free(model_data); -// printf("open kmodel fail"); -// } -// } -// #ifdef __RT_THREAD_H__ -// MSH_CMD_EXPORT(kmodel_load, kmodel load memory); -// #endif diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.c b/APP_Framework/Framework/transform_layer/xizi/transform.c index f2d53d155..3fb8c4ddc 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.c +++ b/APP_Framework/Framework/transform_layer/xizi/transform.c @@ -154,7 +154,6 @@ int PrivIoctl(int fd, int cmd, void *args) { int ret; struct PrivIoctlCfg *ioctl_cfg = (struct PrivIoctlCfg *)args; - switch (ioctl_cfg->ioctl_driver_type) { case SERIAL_TYPE: @@ -163,12 +162,10 @@ int PrivIoctl(int fd, int cmd, void *args) case PIN_TYPE: ret = PrivPinIoctl(fd, cmd, ioctl_cfg->args); break; - case I2C_TYPE: - ret = ioctl(fd, cmd, ioctl_cfg->args); - break; case LCD_TYPE: ret = PrivLcdIoctl(fd, cmd, ioctl_cfg->args); break; + case I2C_TYPE: case RTC_TYPE: case ADC_TYPE: case DAC_TYPE: diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.h b/APP_Framework/Framework/transform_layer/xizi/transform.h index 9cb3be855..54f2b6897 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.h +++ b/APP_Framework/Framework/transform_layer/xizi/transform.h @@ -227,6 +227,25 @@ struct RtcDrvConfigureParam time_t *time; }; +typedef struct +{ + uintptr_t pdata; + uint32_t length; +}_ioctl_shoot_para; + +typedef struct +{ + uint32_t width; // width The width of image + uint32_t height; // height The height of image +}_ioctl_set_reso; + +typedef struct +{ + uintptr_t r_addr; + uintptr_t g_addr; + uintptr_t b_addr; +}RgbAddress; + enum TCP_OPTION { SEND_DATA = 0, RECV_DATA, @@ -241,6 +260,25 @@ enum TCP_OPTION { #define MY_INDEV_X BSP_LCD_Y_MAX #define MY_INDEV_Y BSP_LCD_X_MAX +#define DVP_INIT 0x00U +#define REG_SCCB_READ 0x12U +#define REG_SCCB_WRITE 0x13U +#define OUTPUT_CONFIG 0x20U +#define LCD_STRING_TYPE 0 +#define LCD_DOT_TYPE 1 +#define LCD_SIZE 320 +#define IMAGE_HEIGHT 240 +#define IMAGE_WIDTH 320 +#define NULL_PARAMETER 0 + +#define REG_SCCB_READ 0x12U +#define REG_SCCB_WRITE 0x13U +#define SCCB_REG_LENGTH 0x08U +#define IOCTRL_CAMERA_START_SHOT (20) +#define SET_DISPLAY_ADDR (21) +#define SET_AI_ADDR (22) +#define IOCTRL_CAMERA_OUT_SIZE_RESO (23) + /*********************shell***********************/ //for int func(int argc, char *agrv[]) #define PRIV_SHELL_CMD_MAIN_ATTR (SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)) diff --git a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c index ce33b259a..b10b2d07f 100644 --- a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c +++ b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c @@ -77,6 +77,7 @@ int pthread_attr_setschedparam(pthread_attr_t *attr, int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size) { + attr->stacksize = stack_size; return 0; } diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dma/dmac.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dma/dmac.c index a899e44f2..3306e7524 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dma/dmac.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dma/dmac.c @@ -31,6 +31,7 @@ #include "utils.h" #include "plic.h" #include "stdlib.h" +#include volatile dmac_t *const dmac = (dmac_t *)DMAC_BASE_ADDR; @@ -172,6 +173,7 @@ void dmac_channel_disable(dmac_channel_number_t channel_num) } writeq(chen.data, &dmac->chen); + } int32_t dmac_check_channel_busy(dmac_channel_number_t channel_num) @@ -766,26 +768,30 @@ void dmac_set_src_dest_length(dmac_channel_number_t channel_num, const void *src dmac_channel_enable(channel_num); } -static int dmac_irq_callback(void *ctx) +static int dmac_irq_callback(int vector,void *ctx) { dmac_context_t *v_dmac_context = (dmac_context_t *)(ctx); dmac_channel_number_t v_dmac_channel = v_dmac_context->dmac_channel; dmac_chanel_interrupt_clear(v_dmac_channel); - if(v_dmac_context->callback != NULL) + if(v_dmac_context->callback != NULL){ v_dmac_context->callback(v_dmac_context->ctx); - + } return 0; } + + void dmac_irq_register(dmac_channel_number_t channel_num , plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority) { dmac_context[channel_num].dmac_channel = channel_num; dmac_context[channel_num].callback = dmac_callback; dmac_context[channel_num].ctx = ctx; dmac_enable_channel_interrupt(channel_num); - plic_set_priority(IRQN_DMA0_INTERRUPT + channel_num, priority); - plic_irq_enable(IRQN_DMA0_INTERRUPT + channel_num); - plic_irq_register(IRQN_DMA0_INTERRUPT + channel_num, dmac_irq_callback, &dmac_context[channel_num]); + // plic_set_priority(IRQN_DMA0_INTERRUPT + channel_num, priority); + // plic_irq_enable(IRQN_DMA0_INTERRUPT + channel_num); + // plic_irq_register(IRQN_DMA0_INTERRUPT + channel_num, dmac_irq_callback, &dmac_context[channel_num]); + isrManager.done->enableIrq(IRQN_DMA0_INTERRUPT + channel_num); + isrManager.done->registerIrq(IRQN_DMA0_INTERRUPT + channel_num, (IsrHandlerType)dmac_irq_callback, &dmac_context[channel_num]); } void __attribute__((weak, alias("dmac_irq_register"))) dmac_set_irq(dmac_channel_number_t channel_num , plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority); diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c index 04463832b..116c2bd07 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c @@ -6,9 +6,11 @@ #include "plic.h" #include -#define REG_SCCB_READ 0x12U -#define REG_SCCB_WRITE 0x13U -#define SCCB_REG_LENGTH 0x08U +#define CONTINOUS_SHOOTS 1 +#define ONLY_ONE_SHOOT 2 +#define STOP_SHOOT 0 + +static int shoot_flag = 0; // shoot will close when shoot_flag == 0 // irq interrupt function static int on_irq_dvp(int irq, void *arg) @@ -17,11 +19,16 @@ static int on_irq_dvp(int irq, void *arg) { dvp_clear_interrupt(DVP_STS_FRAME_FINISH); } - else - { - dvp_start_convert(); + else{ + if(shoot_flag>0){ + dvp_start_convert(); + if(ONLY_ONE_SHOOT==shoot_flag){ + shoot_flag=STOP_SHOOT; + } + } dvp_clear_interrupt(DVP_STS_FRAME_START); } + return 0; } @@ -64,14 +71,14 @@ static uint32 DvpDrvInit(void) #endif #ifdef DVP_AI_OUTPUT dvp_set_output_enable(DVP_OUTPUT_AI, 1); - dvp_set_ai_addr((uint32_t)DVP_AI_RED_ADRESS, (uint32_t)DVP_AI_GREEN_ADRESS, (uint32_t)DVP_AI_BLUE_ADRESS); + // dvp_set_ai_addr((uint32_t)DVP_AI_RED_ADRESS, (uint32_t)DVP_AI_GREEN_ADRESS, (uint32_t)DVP_AI_BLUE_ADRESS); #endif #ifdef DVP_INTERRUPT_ENABLE dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 0); isrManager.done->registerIrq(IRQN_DVP_INTERRUPT, (IsrHandlerType)on_irq_dvp, NULL); isrManager.done->enableIrq(IRQN_DVP_INTERRUPT); dvp_clear_interrupt(DVP_STS_FRAME_START | DVP_STS_FRAME_FINISH); - dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 1); + dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 0); KPrintf("camera interrupt has open!\n"); #endif return ret; @@ -125,15 +132,33 @@ static uint32 DvpDrvConfigure(void *drv, struct BusConfigureInfo *args) int cmd_type = args->configure_cmd; struct CameraCfg* tmp_cfg; + RgbAddress* kpu_rgb_address; + _ioctl_shoot_para* pixel_cfg; switch (cmd_type) { case OPE_INT: break; case OPE_CFG: tmp_cfg = (struct CameraCfg *)args->private_data; - SensorConfigure(tmp_cfg); + memcpy(&sensor_config,tmp_cfg,sizeof(struct CameraCfg)); + SensorConfigure(&sensor_config); dvp_set_image_size(tmp_cfg->output_w, tmp_cfg->output_h); break; + case IOCTRL_CAMERA_START_SHOT: + pixel_cfg = (_ioctl_shoot_para*)args->private_data; + dvp_set_display_addr(pixel_cfg->pdata); + dvp_set_output_enable(DVP_OUTPUT_DISPLAY, 1); + dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 1); + shoot_flag=ONLY_ONE_SHOOT; + break; + case SET_AI_ADDR: + kpu_rgb_address = (RgbAddress*)args->private_data; + dvp_set_output_enable(DVP_OUTPUT_AI, 1); + dvp_set_ai_addr(kpu_rgb_address->r_addr,kpu_rgb_address->g_addr,kpu_rgb_address->b_addr); + break; + case IOCTRL_CAMERA_OUT_SIZE_RESO: + dvp_set_image_size(((uint32_t*)args->private_data)[0], ((uint32_t*)args->private_data)[1]); + break; case REG_SCCB_READ: ReadDvpReg(drv, (struct DvpRegConfigureInfo *)args->private_data); break; diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h index 178fc5ddd..14695c659 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h @@ -25,6 +25,34 @@ extern "C" { #endif +#define REG_SCCB_READ 0x12U +#define REG_SCCB_WRITE 0x13U +#define SCCB_REG_LENGTH 0x08U +#define IOCTRL_CAMERA_START_SHOT (20) +#define SET_DISPLAY_ADDR (21) +#define SET_AI_ADDR (22) +#define IOCTRL_CAMERA_OUT_SIZE_RESO (23) + + +typedef struct +{ + uintptr_t r_addr; + uintptr_t g_addr; + uintptr_t b_addr; +}RgbAddress; + +typedef struct +{ + uintptr_t pdata; + uint32_t length; +}_ioctl_shoot_para; + +typedef struct +{ + uint32_t width; // width The width of image + uint32_t height; // height The height of image +}_ioctl_set_reso; + int HwDvpInit(void); #ifdef __cplusplus diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c index 4926c8d6a..01e2d21b5 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c @@ -10,6 +10,8 @@ #include "bsp.h" #include #include +#include "plic.h" +#include #define LAYER_BURST_SIZE 12 @@ -765,7 +767,6 @@ static void kpu_kmodel_input_with_padding(const kpu_layer_argument_t *layer, con size_t width = layer->image_size.data.i_row_wid + 1; size_t height = layer->image_size.data.i_col_high + 1; size_t channels = layer->image_channel_num.data.i_ch_num + 1; - kpu_upload_core(width, height, channels, src, layer->image_addr.data.image_src_addr); } @@ -1349,7 +1350,7 @@ int kpu_load_kmodel(kpu_model_context_t *ctx, const uint8_t *buffer) { uintptr_t base_addr = (uintptr_t)buffer; const kpu_kmodel_header_t *header = (const kpu_kmodel_header_t *)buffer; - printf("\nheader->version:%d,header->arch:%d\n",header->version,header->arch); + if (header->version == 3 && header->arch == 0) { ctx->model_buffer = buffer; @@ -1500,7 +1501,6 @@ static int ai_step(void *userdata) last_layer_type = cnt_layer_header->type; last_time = sysctl_get_time_us(); #endif - switch (cnt_layer_header->type) { case KL_ADD: @@ -1564,9 +1564,10 @@ static int ai_step(void *userdata) default: assert(!"Layer is not supported."); } - - if (cnt_layer_id != (ctx->layers_length - 1)) - ai_step(userdata); + if (cnt_layer_id != (ctx->layers_length - 1)){ + + ai_step(userdata); + } else kpu_kmodel_done(ctx); return 0; @@ -1579,6 +1580,11 @@ static void ai_step_not_isr(void *userdata) sysctl_enable_irq(); } +static void ai_my_step(int vector,void *userdata) +{ + ai_step(userdata); +} + int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_number_t dma_ch, kpu_done_callback_t done_callback, void *userdata) { ctx->dma_ch = dma_ch; @@ -1608,10 +1614,12 @@ int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_nu .layer_cfg_almost_empty_int = 0, .layer_cfg_almost_full_int = 1 }; - - plic_irq_enable(IRQN_AI_INTERRUPT); - plic_set_priority(IRQN_AI_INTERRUPT, 1); - plic_irq_register(IRQN_AI_INTERRUPT, ai_step, ctx); + isrManager.done->enableIrq(IRQN_AI_INTERRUPT); + isrManager.done->registerIrq(IRQN_AI_INTERRUPT, (IsrHandlerType)ai_my_step, ctx); + + // plic_irq_enable(IRQN_AI_INTERRUPT); + // plic_set_priority(IRQN_AI_INTERRUPT, 1); + // plic_irq_register(IRQN_AI_INTERRUPT, ai_step, ctx); const kpu_model_layer_header_t *first_layer_header = ctx->layer_headers; if (first_layer_header->type != KL_K210_CONV) @@ -1624,11 +1632,9 @@ int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_nu kpu_kmodel_input_with_padding(&layer_arg, src); ai_step_not_isr(ctx); } - else - { + else{ kpu_input_dma(&layer_arg, src, ctx->dma_ch, ai_step, ctx); } - return 0; } From 56a014fe98c017bbaa4a3cd4df775a2f83737b37 Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Tue, 13 Dec 2022 11:19:11 +0800 Subject: [PATCH 09/33] feat add modbus tcp protocol for control framework --- .../connection_app/4g_app/4g_app.c | 133 ++++++ .../connection_app/4g_app/Makefile | 3 + .../Applications/connection_app/Makefile | 4 + .../plc_demo/mitsubishi/mitsubishi_fx3u.c | 43 +- .../Framework/control/ipc_protocol/Kconfig | 7 +- .../control/ipc_protocol/include/modbus_tcp.h | 69 +++ .../ipc_protocol/modbus_tcp/modbus_tcp.c | 432 +++++++++++++++++- .../ipc_protocol/modbus_tcp/modbus_tcp.h | 26 -- .../modbus_tcp/test_recipe_modbus.json | 142 ++++++ .../control/plc_protocol/fins/fins.c | 10 +- .../control/plc_protocol/melsec/melsec.c | 12 +- .../Framework/control/shared/control_def.c | 7 + .../Framework/control/shared/control_def.h | 1 + 13 files changed, 855 insertions(+), 34 deletions(-) create mode 100644 APP_Framework/Applications/connection_app/4g_app/4g_app.c create mode 100644 APP_Framework/Applications/connection_app/4g_app/Makefile create mode 100755 APP_Framework/Framework/control/ipc_protocol/include/modbus_tcp.h delete mode 100755 APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.h create mode 100644 APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus.json diff --git a/APP_Framework/Applications/connection_app/4g_app/4g_app.c b/APP_Framework/Applications/connection_app/4g_app/4g_app.c new file mode 100644 index 000000000..fc7eb0213 --- /dev/null +++ b/APP_Framework/Applications/connection_app/4g_app/4g_app.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2022 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 4g_app.c + * @brief support get data from and send data to 4g server + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2022.12.12 + */ + +#include +#include +#include +#include + +static uint8_t adapter_4g_status = 0; +static pthread_t recv_4g_heart_task; +struct Adapter *adapter_4g; + +static const uint8_t server_addr[] = "xxx.xxx.xxx.xxx"; +static const uint8_t server_port[] = "xxx"; + +#define ADAPTER_4G_HEART "HEART" + +int Adapter4GConnectFunction(struct Adapter *adapter, uint8_t reconnect) +{ + int ret = 0; + int baud_rate = BAUD_RATE_115200; + + if (1 != reconnect) { + ret = AdapterDeviceOpen(adapter); + if (ret < 0) { + goto out; + } + + ret = AdapterDeviceControl(adapter, OPE_INT, &baud_rate); + if (ret < 0) { + goto out; + } + } + + ret = AdapterDeviceConnect(adapter, CLIENT, server_addr, server_port, IPV4); + if (ret < 0) { + goto out; + } + +out: + if (ret < 0) { + AdapterDeviceClose(adapter); + } + return ret; +} + +void Adapter4gSend(uint8_t *send_data, size_t length) +{ + if (adapter_4g_status) { + AdapterDeviceSend(adapter_4g, send_data, length); + } +} + +static void *Receive4gHeartTask(void* parameter) +{ + char recv_msg[16] = {0}; + ssize_t recv_length = 0; + uint8_t net_status_cnt = 0; + + while (1) { + + SetTaskStatus(0x01); + + if (net_status_cnt > 5) { + adapter_4g_status = 0; + + while (Adapter4GConnectFunction(adapter_4g, 1) < 0) { + PrivTaskDelay(10000); + } + + net_status_cnt = 0; + } + + adapter_4g_status = 1; + + recv_length = AdapterDeviceRecv(adapter_4g, recv_msg, 6); + if (recv_length > 0) { + //if (0 == strcmp(recv_msg, ADAPTER_4G_HEART)) { + net_status_cnt = 0; + //} + } else { + printf("4G recv heart error re-recv cnt %d\n", net_status_cnt); + net_status_cnt++; + } + memset(recv_msg, 0, sizeof(recv_msg)); + } +} + +int Adapter4GActive(void) +{ + int ret = 0; + adapter_4g = AdapterDeviceFindByName(ADAPTER_4G_NAME); + +#ifdef ADAPTER_EC200T + adapter_4g->socket.socket_id = 0; + + ret = Adapter4GConnectFunction(adapter_4g, 0); + if (ret < 0) { + printf("Adapter4GConnect failed %d\n", ret); + } + + adapter_4g_status = 1; + + pthread_attr_t attr; + attr.schedparam.sched_priority = 22; + attr.stacksize = 2048; + + PrivTaskCreate(&recv_4g_heart_task, &attr, &Receive4gHeartTask, NULL); + PrivTaskStartup(&recv_4g_heart_task); + +#endif + + return ret; +} + + diff --git a/APP_Framework/Applications/connection_app/4g_app/Makefile b/APP_Framework/Applications/connection_app/4g_app/Makefile new file mode 100644 index 000000000..68d972542 --- /dev/null +++ b/APP_Framework/Applications/connection_app/4g_app/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := 4g_app.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Applications/connection_app/Makefile b/APP_Framework/Applications/connection_app/Makefile index f50c4dbda..0cb8c9568 100755 --- a/APP_Framework/Applications/connection_app/Makefile +++ b/APP_Framework/Applications/connection_app/Makefile @@ -10,6 +10,10 @@ endif ifeq ($(CONFIG_ADD_XIZI_FETURES),y) + ifeq ($(CONFIG_CONNECTION_ADAPTER_4G),y) + SRC_DIR += 4g_app + endif + ifeq ($(CONFIG_RESOURCES_LWIP),y) SRC_DIR += socket_demo endif diff --git a/APP_Framework/Applications/control_app/plc_demo/mitsubishi/mitsubishi_fx3u.c b/APP_Framework/Applications/control_app/plc_demo/mitsubishi/mitsubishi_fx3u.c index 9567871c3..985a5fc61 100644 --- a/APP_Framework/Applications/control_app/plc_demo/mitsubishi/mitsubishi_fx3u.c +++ b/APP_Framework/Applications/control_app/plc_demo/mitsubishi/mitsubishi_fx3u.c @@ -18,6 +18,47 @@ * @date 2022.9.27 */ - +#include + +extern int Adapter4GActive(void); + +void ControlFx3uTest(void) +{ + int i, j = 0; + int read_data_length = 0; + uint8_t read_data[128] = {0}; + +#ifdef CONNECTION_ADAPTER_4G + Adapter4GActive(); +#endif + + 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(ControlFx3uTest, Mitsubishi fx3u Demo, PRIV_SHELL_CMD_MAIN_ATTR); diff --git a/APP_Framework/Framework/control/ipc_protocol/Kconfig b/APP_Framework/Framework/control/ipc_protocol/Kconfig index bc72c4672..3c586a36b 100755 --- a/APP_Framework/Framework/control/ipc_protocol/Kconfig +++ b/APP_Framework/Framework/control/ipc_protocol/Kconfig @@ -1,8 +1,13 @@ config CONTROL_PROTOCOL_MODBUS_TCP bool "Using modbus_tcp control protocol" default n +if CONTROL_PROTOCOL_MODBUS_TCP + source "$APP_DIR/Framework/control/ipc_protocol/modbus_tcp/Kconfig" +endif config CONTROL_PROTOCOL_MODBUS_UART bool "Using modbus_uart control protocol" default n - +if CONTROL_PROTOCOL_MODBUS_UART + source "$APP_DIR/Framework/control/ipc_protocol/modbus_uart/Kconfig" +endif diff --git a/APP_Framework/Framework/control/ipc_protocol/include/modbus_tcp.h b/APP_Framework/Framework/control/ipc_protocol/include/modbus_tcp.h new file mode 100755 index 000000000..4eb8210b8 --- /dev/null +++ b/APP_Framework/Framework/control/ipc_protocol/include/modbus_tcp.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2022 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 modbus_tcp.h + * @brief support modbus_tcp function + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2022.09.27 + */ + +#ifndef MODBUS_TCP_H +#define MODBUS_TCP_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MODBUS_TCP_UNIT_ID 0x00 +#define MODBUS_TCP_READ_CMD_LENGTH 0x0C +#define MODBUS_TCP_WRITE_SINGLE_CMD_LENGTH 0x0C + +#define MODBUS_TCP_WRITE_MULTI_HEAD 0x07 + +typedef enum +{ + READ_COIL_STATUS = 0x01, //read coil cmd + READ_INPUT_STATUS = 0x02, //read input colr cmd + READ_HOLDING_REGISTER = 0x03, //read register info cmd + READ_INPUT_REGISTER = 0x04, //read input register cmd + WRITE_SINGLE_COIL = 0x05, //write coil cmd + WRITE_SINGLE_REGISTER = 0x06, //write single register cmd + WRITE_MULTIPLE_COIL = 0x0F, //write multi coil cmd + WRITE_MULTIPLE_REGISTER = 0x10 //write multi register cmd +}ModbusTcpFunctionCode; + +typedef struct +{ + BasicPlcDataInfo base_data_info; + ModbusTcpFunctionCode function_code; +}ModbusTcpDataInfo; + +typedef struct +{ + ModbusTcpDataInfo data_info; + + UniformValueType value_type; + char value_name[20]; + + uint16_t start_address; + uint16_t quantity; +}ModbusTcpReadItem; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c index 9fc2d4c6a..45734f2ca 100755 --- a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c @@ -15,6 +15,436 @@ * @brief support modbus_tcp function * @version 3.0 * @author AIIT XUOS Lab - * @date 2022.09.27 + * @date 2022.12.09 */ +#include + +/*using cirtular area to receive write-data*/ +#define CA_DATA_LENGTH 512 +struct CircularAreaApp *g_write_data; + +static BasicSocketPlc plc_socket = {0}; +static uint8_t recv_buff[1024] = {0}; + +/** + * @description: Modbus Tcp Data Transform from Receive Buffer To Control-Data + * @param p_read_item - read item pointer + * @param recv_buff - receive buff + * @return success : 0 error : -1 + */ +static int ModbusTcpTransformRecvBuffToData(ModbusTcpReadItem *p_read_item, uint8_t *recv_buff) +{ + uint8_t *data_buffer; + ModbusTcpDataInfo *p_modbus_tcp_data_info = &(p_read_item->data_info); + uint16_t quantity = p_read_item->quantity; + + ModbusTcpFunctionCode function_code = p_modbus_tcp_data_info->function_code; + uint8_t *p_data = p_modbus_tcp_data_info->base_data_info.p_data; + + printf("Receive data is "); + + uint8_t bytes_count = recv_buff[8]; + data_buffer = recv_buff + 9;//remove head data + + if (READ_COIL_STATUS == function_code || READ_INPUT_STATUS == function_code) { + for (int i = 0;i < bytes_count;i ++) { + for (int j = 0;j < 8;j ++) { + if ((i * 8 + j) < p_read_item->quantity) { + *(uint8_t *)(p_data + i * 8 + j) = ((data_buffer[i] >> j) & 0x01) ? 1 : 0; + printf("0x%x", *(uint8_t *)(p_data + i * 8 + j)); + } + } + } + } else { + for (uint16_t i = 0; i < quantity; i ++) { + ((int16_t *)p_data)[i] = ((int16_t *)data_buffer)[quantity - i - 1]; + printf("0x%x 0x%x ", p_data[2 * i], p_data[2 * i + 1]); + } + } + printf("\n"); +} + +/** + * @description: Modbus Tcp Get Data From Socket + * @param socket - socket + * @param p_read_item - read item pointer + * @return success : 0 error : -1 -2 + */ +static int ModbusTcpGetData(int32_t socket, ModbusTcpReadItem *p_read_item) +{ + uint8_t try_count = 0; + int32_t write_error = 0; + + ModbusTcpDataInfo *p_modbus_tcp_data_info = &(p_read_item->data_info); + BasicPlcDataInfo *p_base_data_info = &(p_modbus_tcp_data_info->base_data_info); + + if (!p_base_data_info->command_ready) { + //command not ready, just return + return 1; + } + + memset(recv_buff, 0, sizeof(recv_buff)); + + while (try_count < 10) { + ControlPrintfList("SEND", p_base_data_info->p_command, p_base_data_info->command_length); + try_count++; + + write_error = socket_write(socket, p_base_data_info->p_command, p_base_data_info->command_length); + if (write_error < 0) { + printf("Write socket error, errno is %d!", errno); + } else { + PrivTaskDelay(20); + + int32_t recv_length = socket_read(socket, recv_buff, sizeof(recv_buff)); + if (recv_length < 0) { + printf("Read socket error, errno is %d!", errno); + } else { + ControlPrintfList("RECV", recv_buff, recv_length); + return ModbusTcpTransformRecvBuffToData(p_read_item, recv_buff); + } + } + + if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) { + printf("Send command failed, errno is %d!", errno); + continue; + } else { + return -1; + } + } + return -2; +} + +/** + * @description: Modbus Tcp Data Info Init + * @param p_read_item - read item pointer + * @param index - read item index + * @param p_data - control-data pointer + * @return success : 0 error : -1 + */ +static int ModbusTcpInitialDataInfo(ModbusTcpReadItem *p_read_item, uint16_t index, uint8_t *p_data) +{ + uint16_t command_index = 0; + uint8_t function_code = p_read_item->data_info.function_code; + uint16_t start_address = p_read_item->start_address; + uint16_t quantity = p_read_item->quantity; + + BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info); + + switch (function_code) + { + case READ_COIL_STATUS: + case READ_INPUT_STATUS: + case READ_HOLDING_REGISTER: + case READ_INPUT_REGISTER: + p_base_data_info->command_length = MODBUS_TCP_READ_CMD_LENGTH; + p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length); + p_base_data_info->p_data = p_data; + p_base_data_info->command_ready = 1; + break; + case WRITE_SINGLE_COIL: + case WRITE_SINGLE_REGISTER: + if (p_data == NULL) { + return -1; + } else { + p_base_data_info->command_length = MODBUS_TCP_WRITE_SINGLE_CMD_LENGTH; + p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length); + p_base_data_info->p_data = p_data; + p_base_data_info->data_size = 2; + p_base_data_info->command_ready = 0; + } + break; + case WRITE_MULTIPLE_COIL: + if (p_data == NULL) { + return -1; + } else { + //"quantity" define how many coil need to be written,"n_byte" define the bytes of write-data(counted by bit) + uint16_t n_byte = (quantity - 1) / 8 + 1; + p_base_data_info->command_length = n_byte + MODBUS_TCP_WRITE_MULTI_HEAD + 6; + p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length); + + //13th command define the bytes of write-data + p_base_data_info->p_command[12] = ((quantity - 1) / 8 + 1); + p_base_data_info->p_data = p_data; + p_base_data_info->data_size = n_byte; + p_base_data_info->command_ready = 0; + } + break; + case WRITE_MULTIPLE_REGISTER: + if (p_data == NULL) { + return -1; + } else { + //"quantity" define how many register need to be written + p_base_data_info->command_length = quantity * 2 + MODBUS_TCP_WRITE_MULTI_HEAD + 6; + p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length); + + //13th command define the bytes of write-data + p_base_data_info->p_command[12] = 2 * quantity; + p_base_data_info->p_data = p_data; + p_base_data_info->data_size = quantity * 2; + p_base_data_info->command_ready = 0; + } + break; + default: + return -2; + break; + } + + command_index = 0; + p_base_data_info->p_command[command_index++] = index >> 8; + p_base_data_info->p_command[command_index++] = index; + p_base_data_info->p_command[command_index++] = 0x00; + p_base_data_info->p_command[command_index++] = 0x00; + p_base_data_info->p_command[command_index++] = 0x00; + + if (function_code < 5) { + p_base_data_info->p_command[command_index++] = 0x06; + } else { + p_base_data_info->p_command[command_index++] = 0x09; + } + + p_base_data_info->p_command[command_index++] = MODBUS_TCP_UNIT_ID; + p_base_data_info->p_command[command_index++] = function_code; + p_base_data_info->p_command[command_index++] = start_address >> 8; + p_base_data_info->p_command[command_index++] = start_address; + + if (function_code != WRITE_SINGLE_COIL || function_code != WRITE_SINGLE_REGISTER) { + p_base_data_info->p_command[command_index++] = quantity >> 8; + p_base_data_info->p_command[command_index++] = quantity; + } + return 0; +} + +/** + * @description: Modbus Tcp Format write data from "g_write_data" + * @param p_read_item - read item pointer + * @return success : 0 error : -1 + */ +static int ModbusTcpForamatWriteData(ModbusTcpReadItem *p_read_item) +{ + int i = 0; + uint16_t command_index = 0; + int write_data_length = 0; + uint8_t write_data_buffer[32] = {0}; + + BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info); + uint8_t *p_command = p_base_data_info->p_command; + uint8_t function_code = p_read_item->data_info.function_code; + + if (function_code < WRITE_SINGLE_COIL) { + return 0; + } + + write_data_length = CircularAreaAppRead(g_write_data, write_data_buffer, p_base_data_info->data_size); + if (p_base_data_info->data_size != write_data_length) { + printf("%s get write data %d [should be %d]failed!", __func__, write_data_length, p_base_data_info->data_size); + return 0; + } + + switch (function_code) + { + case WRITE_SINGLE_COIL: + case WRITE_SINGLE_REGISTER: + command_index = 10; + case WRITE_MULTIPLE_COIL: + case WRITE_MULTIPLE_REGISTER: + command_index = 13; + break; + default: + return -2; + break; + } + + for (i = 0; i < write_data_length; i ++) { + p_base_data_info->p_command[command_index++] = write_data_buffer[i]; + } + + return write_data_length; +} + +/** + * @description: Modbus Tcp Receive Plc Data Task + * @param parameter - parameter pointer + * @return + */ +void *ReceivePlcDataTask(void *parameter) +{ + int i = 0; + uint8_t try_count = 0; + uint16_t data_length = 0; + uint8_t *modbus_tcp_data; + uint16_t read_item_size = sizeof(ModbusTcpReadItem); + + struct ControlProtocol *control_protocol = (struct ControlProtocol *)parameter; + struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args; + ModbusTcpReadItem *modbus_tcp_read_item = (ModbusTcpReadItem *)control_protocol->recipe->read_item; + modbus_tcp_data = control_protocol->recipe->protocol_data.data; + data_length = control_protocol->recipe->protocol_data.data_length; + + memset(&plc_socket, 0, sizeof(BasicSocketPlc)); + memcpy(plc_socket.ip, control_protocol->recipe->socket_config.plc_ip, 4); + plc_socket.port = control_protocol->recipe->socket_config.port; + plc_socket.socket = -1; + plc_socket.secondary_connect_flag = 0; + + while (1) { + for (i = 0; i < control_protocol->recipe->read_item_count; i ++) { + /*only connect socket when close socket or init*/ + while (ControlConnectSocket(&plc_socket) < 0) { + PrivTaskDelay(1000); + } + + ModbusTcpForamatWriteData((ModbusTcpReadItem *)modbus_tcp_read_item + i); + + ModbusTcpGetData(plc_socket.socket, (ModbusTcpReadItem *)modbus_tcp_read_item + i); + } + + /*read all variable item data, put them into circular_area*/ + if (i == control_protocol->recipe->read_item_count) { + printf("%s get %d item %d length modbus_tcp_data %p\n", __func__, i, data_length, modbus_tcp_data); + CircularAreaAppWrite(circular_area, modbus_tcp_data, data_length, 0); + } + + /*read data every single 'read_period' ms*/ + PrivTaskDelay(control_protocol->recipe->read_period); + } +} + +/** + * @description: Modbus Tcp Protocol Open + * @param control_protocol - control protocol pointer + * @return success : 0 error + */ +int ModbusTcpOpen(struct ControlProtocol *control_protocol) +{ + ControlProtocolOpenDef(control_protocol); + + g_write_data = CircularAreaAppInit(CA_DATA_LENGTH); + if (NULL == g_write_data) { + printf("%s CircularAreaInit error\n", __func__); + return -1; + } + + return 0; +} + +/** + * @description: Modbus Tcp Protocol Close + * @param control_protocol - control protocol pointer + * @return success : 0 error + */ +int ModbusTcpClose(struct ControlProtocol *control_protocol) +{ + CircularAreaAppRelease(g_write_data); + + ControlDisconnectSocket(&plc_socket); + + ControlProtocolCloseDef(); + + return 0; +} + +/** + * @description: Modbus Tcp Protocol Read Data + * @param control_protocol - control protocol pointer + * @param buf - read data buffer + * @param len - read data length + * @return success : data length error : 0 + */ +int ModbusTcpRead(struct ControlProtocol *control_protocol, void *buf, size_t len) +{ + struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args; + return CircularAreaAppRead(circular_area, buf, len); +} + +/** + * @description: Modbus Tcp Protocol Write Data + * @param control_protocol - control protocol pointer + * @param buf - write data buffer + * @param len - write data length + * @return success : data length error : 0 + */ +int ModbusTcpWrite(struct ControlProtocol *control_protocol, const void *buf, size_t len) +{ + CircularAreaAppWrite(g_write_data, (uint8_t *)buf, len, 0); + + return 0; +} + +/** + * @description: Modbus Tcp Protocol Ioctl + * @param control_protocol - control protocol pointer + * @param cmd - ioctl cmd + * @param args - ioctl args + * @return success : data length error : 0 + */ +int ModbusTcpIoctl(struct ControlProtocol *control_protocol, int cmd, void *args) +{ + //to do + return 0; +} + +static struct ControlDone modbustcp_protocol_done = +{ + ._open = ModbusTcpOpen, + ._close = ModbusTcpClose, + ._read = ModbusTcpRead, + ._write = ModbusTcpWrite, + ._ioctl = ModbusTcpIoctl, +}; + +/** + * @description: Modbus TCP Protocol Cmd Generate + * @param p_recipe - recipe pointer + * @param protocol_format_info - protocol format info pointer + * @return success : 0 error : -1 + */ +int ModbusTcpProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info) +{ + int ret = 0; + static uint8_t last_item_size = 0; + uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size; + + ModbusTcpReadItem *modbustcp_read_item = (ModbusTcpReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index; + + modbustcp_read_item->value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint; + strncpy(modbustcp_read_item->value_name, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_name")->valuestring, 20); + modbustcp_read_item->data_info.function_code = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "function_code")->valueint; + modbustcp_read_item->start_address = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "start_address")->valueint; + modbustcp_read_item->quantity = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "quantity")->valueint; + + ret = ModbusTcpInitialDataInfo(modbustcp_read_item, + protocol_format_info->read_item_index, + p_read_item_data); + + ControlPrintfList("CMD", modbustcp_read_item->data_info.base_data_info.p_command, modbustcp_read_item->data_info.base_data_info.command_length); + protocol_format_info->last_item_size = GetValueTypeMemorySize(modbustcp_read_item->value_type); + + last_item_size += protocol_format_info->last_item_size; + + return ret; + +} + +/** + * @description: Modbus TCP Protocol Init + * @param p_recipe - recipe pointer + * @return success : 0 error : -1 + */ +int ModbusTcpProtocolInit(struct ControlRecipe *p_recipe) +{ + p_recipe->read_item = PrivMalloc(sizeof(ModbusTcpReadItem) * p_recipe->read_item_count); + if (NULL == p_recipe->read_item) { + PrivFree(p_recipe->read_item); + return -1; + } + + memset(p_recipe->read_item, 0, sizeof(ModbusTcpReadItem)); + + p_recipe->ControlProtocolFormatCmd = ModbusTcpProtocolFormatCmd; + + p_recipe->done = &modbustcp_protocol_done; + + return 0; +} + diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.h b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.h deleted file mode 100755 index a2063e96f..000000000 --- a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2022 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 modbus_tcp.h - * @brief support modbus_tcp function - * @version 3.0 - * @author AIIT XUOS Lab - * @date 2022.09.27 - */ - -#ifndef MODBUS_TCP_H -#define MODBUS_TCP_H - - - -#endif diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus.json b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus.json new file mode 100644 index 000000000..b08980aaf --- /dev/null +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus.json @@ -0,0 +1,142 @@ +{ + "device_id": 4, + "device_name": "GJ2", + "communication_type": 0, + "socket_config": { + "plc_ip": "192.168.250.9", + "local_ip": "192.168.250.233", + "gateway": "192.168.250.1", + "netmask": "255.255.254.0", + "port": 502 + }, + "protocol_type": 2, + "read_period": 100, + "read_item_list": [ + { + "value_name": "M0", + "value_type": 1, + "function_code": 1, + "start_address": 8192, + "quantity": 1 + }, + { + "value_name": "M1", + "value_type": 1, + "function_code": 1, + "start_address":8193, + "quantity": 1 + }, + { + "value_name": "M102", + "value_type": 1, + "function_code": 1, + "start_address": 8294, + "quantity": 1 + }, + { + "value_name": "M200", + "value_type": 1, + "function_code": 1, + "start_address": 8392, + "quantity": 1 + }, + { + "value_name": "M201", + "value_type": 1, + "function_code": 1, + "start_address":8393, + "quantity": 1 + }, + { + "value_name": "M202", + "value_type": 1, + "function_code": 1, + "start_address": 8394, + "quantity": 1 + }, + { + "value_name": "M203", + "value_type": 1, + "function_code": 1, + "start_address": 8395, + "quantity": 1 + }, + { + "value_name": "M204", + "value_type": 1, + "function_code": 1, + "start_address": 8396, + "quantity": 1 + }, + { + "value_name": "M205", + "value_type": 1, + "function_code": 1, + "start_address": 8397, + "quantity": 1 + }, + { + "value_name": "M206", + "value_type": 1, + "function_code": 1, + "start_address": 8398, + "quantity": 1 + }, + { + "value_name": "D20", + "value_type": 3, + "function_code": 3, + "start_address": 20, + "quantity": 1 + }, + { + "value_name": "D21", + "value_type": 3, + "function_code": 3, + "start_address": 21, + "quantity": 1 + }, + { + "value_name": "D22", + "value_type": 3, + "function_code": 3, + "start_address": 22, + "quantity": 1 + }, + { + "value_name": "D23", + "value_type": 3, + "function_code": 3, + "start_address": 23, + "quantity": 1 + }, + { + "value_name": "D202", + "value_type": 9, + "function_code": 3, + "start_address": 202, + "quantity": 2 + }, + { + "value_name": "D204", + "value_type": 9, + "function_code": 3, + "start_address": 204, + "quantity": 2 + }, + { + "value_name": "D206", + "value_type": 9, + "function_code": 3, + "start_address": 206, + "quantity": 2 + }, + { + "value_name": "D208", + "value_type": 9, + "function_code": 3, + "start_address": 208, + "quantity": 2 + } + ] +} \ No newline at end of file diff --git a/APP_Framework/Framework/control/plc_protocol/fins/fins.c b/APP_Framework/Framework/control/plc_protocol/fins/fins.c index 1c20eba77..1b0419a88 100644 --- a/APP_Framework/Framework/control/plc_protocol/fins/fins.c +++ b/APP_Framework/Framework/control/plc_protocol/fins/fins.c @@ -328,7 +328,7 @@ void *ReceivePlcDataTask(void *parameter) CircularAreaAppWrite(circular_area, fins_data, data_length, 0); } - /*read data every single 200ms*/ + /*read data every single 'read_period' ms*/ PrivTaskDelay(control_protocol->recipe->read_period); } } @@ -390,6 +390,8 @@ static struct ControlDone fins_protocol_done = int FinsProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info) { int ret = 0; + static uint8_t last_item_size = 0; + uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size; FinsReadItem *fins_read_item = (FinsReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index; @@ -405,11 +407,13 @@ int FinsProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *pr ret = FinsInitialDataInfo(fins_read_item, p_recipe->socket_config.plc_ip[3], p_recipe->socket_config.local_ip[3], - protocol_format_info->p_read_item_data + protocol_format_info->last_item_size); + p_read_item_data); ControlPrintfList("CMD", fins_read_item->data_info.base_data_info.p_command, fins_read_item->data_info.base_data_info.command_length); protocol_format_info->last_item_size = GetValueTypeMemorySize(fins_read_item->value_type); + last_item_size += protocol_format_info->last_item_size; + return ret; } @@ -426,6 +430,8 @@ int FinsProtocolInit(struct ControlRecipe *p_recipe) return -1; } + memset(p_recipe->read_item, 0, sizeof(FinsReadItem)); + p_recipe->ControlProtocolFormatCmd = FinsProtocolFormatCmd; p_recipe->done = &fins_protocol_done; diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c index 9d95485eb..4a48288d8 100644 --- a/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c +++ b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c @@ -566,7 +566,7 @@ void *ReceivePlcDataTask(void *parameter) CircularAreaAppWrite(circular_area, melsec_data, data_length, 0); } - /*read data every single read_period*/ + /*read data every single 'read_period' ms*/ PrivTaskDelay(control_protocol->recipe->read_period); } } @@ -628,6 +628,9 @@ static struct ControlDone melsec_protocol_done = int MelsecProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info) { int ret = 0; + static uint8_t last_item_size = 0; + uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size; + MelsecReadItem *melsec_read_item = (MelsecReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index; melsec_read_item->value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint; @@ -639,12 +642,13 @@ int MelsecProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo * strncpy(melsec_read_item->head_device_number_string, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "head_device_number_string")->valuestring, 6); melsec_read_item->device_points_count = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "device_points_count")->valueint; - ret = MelsecInitialDataInfo(melsec_read_item, - protocol_format_info->p_read_item_data + protocol_format_info->last_item_size); + ret = MelsecInitialDataInfo(melsec_read_item, p_read_item_data); ControlPrintfList("CMD", melsec_read_item->data_info.base_data_info.p_command, melsec_read_item->data_info.base_data_info.command_length); protocol_format_info->last_item_size = GetValueTypeMemorySize(melsec_read_item->value_type); + last_item_size += protocol_format_info->last_item_size; + return ret; } @@ -661,6 +665,8 @@ int MelsecProtocolInit(struct ControlRecipe *p_recipe) return -1; } + memset(p_recipe->read_item, 0, sizeof(MelsecReadItem)); + p_recipe->ControlProtocolFormatCmd = MelsecProtocolFormatCmd; p_recipe->done = &melsec_protocol_done; diff --git a/APP_Framework/Framework/control/shared/control_def.c b/APP_Framework/Framework/control/shared/control_def.c index fbc33225c..33783456b 100644 --- a/APP_Framework/Framework/control/shared/control_def.c +++ b/APP_Framework/Framework/control/shared/control_def.c @@ -37,6 +37,10 @@ extern int FinsProtocolInit(struct ControlRecipe *p_recipe); extern int MelsecProtocolInit(struct ControlRecipe *p_recipe); #endif +#ifdef CONTROL_PROTOCOL_MODBUS_TCP +extern int ModbusTcpProtocolInit(struct ControlRecipe *p_recipe); +#endif + /* CONTROL FRAMEWORK READ DATA FORMAT: | HEAD |device_id|read data length|read item count| data | @@ -66,6 +70,9 @@ static struct ControlProtocolInitParam protocol_init[] = { PROTOCOL_MELSEC_1C, MelsecProtocolInit }, { PROTOCOL_MELSEC_3C, MelsecProtocolInit }, #endif +#ifdef CONTROL_PROTOCOL_MODBUS_TCP + { PROTOCOL_MODBUS_TCP, ModbusTcpProtocolInit }, +#endif { PROTOCOL_END, NULL }, }; diff --git a/APP_Framework/Framework/control/shared/control_def.h b/APP_Framework/Framework/control/shared/control_def.h index 9126c6c1d..fced6fd80 100644 --- a/APP_Framework/Framework/control/shared/control_def.h +++ b/APP_Framework/Framework/control/shared/control_def.h @@ -69,6 +69,7 @@ typedef struct { uint16_t command_length; uint16_t data_size; + uint8_t command_ready; uint8_t *p_command; uint8_t *p_data; }BasicPlcDataInfo; From 59fa5451ca6e6c79f190d2e4fda4f0cf857bc46e Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Tue, 13 Dec 2022 17:25:37 +0800 Subject: [PATCH 10/33] feat add modbus tcp write function and fix modbus tcp bug --- .../circular_area/circular_area_app.c | 4 +- .../control/ipc_protocol/include/modbus_tcp.h | 2 +- .../ipc_protocol/modbus_tcp/modbus_tcp.c | 52 ++++++++++++------- .../Framework/control/shared/control_def.c | 2 +- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/APP_Framework/Applications/general_functions/circular_area/circular_area_app.c b/APP_Framework/Applications/general_functions/circular_area/circular_area_app.c index 25e81c39c..9ac93bc65 100644 --- a/APP_Framework/Applications/general_functions/circular_area/circular_area_app.c +++ b/APP_Framework/Applications/general_functions/circular_area/circular_area_app.c @@ -48,7 +48,7 @@ int CircularAreaAppIsEmpty(CircularAreaAppType circular_area) CA_PARAM_CHECK(circular_area); if((circular_area->readidx == circular_area->writeidx) && (!circular_area->b_status)) { - printf("the circular area is empty\n"); + //printf("the circular area is empty\n"); return 1; } else { return 0; @@ -164,7 +164,7 @@ int CircularAreaAppRead(CircularAreaAppType circular_area, uint8_t *output_buffe return -1; } - uint32_t read_length = (data_length > CircularAreaAppGetDataLength(circular_area)) ? CircularAreaAppGetDataLength(circular_area) : data_length; + int read_length = (data_length > CircularAreaAppGetDataLength(circular_area)) ? CircularAreaAppGetDataLength(circular_area) : data_length; // if (data_length > CircularAreaAppGetDataLength(circular_area)) { // return -1; // } diff --git a/APP_Framework/Framework/control/ipc_protocol/include/modbus_tcp.h b/APP_Framework/Framework/control/ipc_protocol/include/modbus_tcp.h index 4eb8210b8..3d1532ace 100755 --- a/APP_Framework/Framework/control/ipc_protocol/include/modbus_tcp.h +++ b/APP_Framework/Framework/control/ipc_protocol/include/modbus_tcp.h @@ -27,7 +27,7 @@ extern "C" { #endif -#define MODBUS_TCP_UNIT_ID 0x00 +#define MODBUS_TCP_UNIT_ID 0x01 #define MODBUS_TCP_READ_CMD_LENGTH 0x0C #define MODBUS_TCP_WRITE_SINGLE_CMD_LENGTH 0x0C diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c index 45734f2ca..b9788a893 100755 --- a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c @@ -35,6 +35,7 @@ static uint8_t recv_buff[1024] = {0}; */ static int ModbusTcpTransformRecvBuffToData(ModbusTcpReadItem *p_read_item, uint8_t *recv_buff) { + uint8_t head_length = 9; uint8_t *data_buffer; ModbusTcpDataInfo *p_modbus_tcp_data_info = &(p_read_item->data_info); uint16_t quantity = p_read_item->quantity; @@ -45,7 +46,16 @@ static int ModbusTcpTransformRecvBuffToData(ModbusTcpReadItem *p_read_item, uint printf("Receive data is "); uint8_t bytes_count = recv_buff[8]; - data_buffer = recv_buff + 9;//remove head data + + if ((WRITE_SINGLE_COIL == function_code) || (WRITE_SINGLE_REGISTER == function_code) || + (WRITE_MULTIPLE_COIL == function_code) || (WRITE_MULTIPLE_REGISTER == function_code)) { + head_length = 10; + if (p_modbus_tcp_data_info->base_data_info.command_ready) { + p_modbus_tcp_data_info->base_data_info.command_ready = 0; + } + } + + data_buffer = recv_buff + head_length;//remove head data if (READ_COIL_STATUS == function_code || READ_INPUT_STATUS == function_code) { for (int i = 0;i < bytes_count;i ++) { @@ -190,27 +200,28 @@ static int ModbusTcpInitialDataInfo(ModbusTcpReadItem *p_read_item, uint16_t ind break; } - command_index = 0; - p_base_data_info->p_command[command_index++] = index >> 8; - p_base_data_info->p_command[command_index++] = index; - p_base_data_info->p_command[command_index++] = 0x00; - p_base_data_info->p_command[command_index++] = 0x00; - p_base_data_info->p_command[command_index++] = 0x00; + memset(p_base_data_info->p_command, 0, p_base_data_info->command_length); - if (function_code < 5) { - p_base_data_info->p_command[command_index++] = 0x06; + p_base_data_info->p_command[0] = index >> 8; + p_base_data_info->p_command[1] = index; + p_base_data_info->p_command[2] = 0x00; + p_base_data_info->p_command[3] = 0x00; + p_base_data_info->p_command[4] = 0x00; + + if (function_code < WRITE_MULTIPLE_COIL) { + p_base_data_info->p_command[5] = 0x06; } else { - p_base_data_info->p_command[command_index++] = 0x09; + p_base_data_info->p_command[5] = 0x09; } - p_base_data_info->p_command[command_index++] = MODBUS_TCP_UNIT_ID; - p_base_data_info->p_command[command_index++] = function_code; - p_base_data_info->p_command[command_index++] = start_address >> 8; - p_base_data_info->p_command[command_index++] = start_address; + p_base_data_info->p_command[6] = MODBUS_TCP_UNIT_ID; + p_base_data_info->p_command[7] = function_code; + p_base_data_info->p_command[8] = start_address >> 8; + p_base_data_info->p_command[9] = start_address; - if (function_code != WRITE_SINGLE_COIL || function_code != WRITE_SINGLE_REGISTER) { - p_base_data_info->p_command[command_index++] = quantity >> 8; - p_base_data_info->p_command[command_index++] = quantity; + if ((function_code != WRITE_SINGLE_COIL) && (function_code != WRITE_SINGLE_REGISTER)) { + p_base_data_info->p_command[10] = quantity >> 8; + p_base_data_info->p_command[11] = quantity; } return 0; } @@ -237,7 +248,7 @@ static int ModbusTcpForamatWriteData(ModbusTcpReadItem *p_read_item) write_data_length = CircularAreaAppRead(g_write_data, write_data_buffer, p_base_data_info->data_size); if (p_base_data_info->data_size != write_data_length) { - printf("%s get write data %d [should be %d]failed!", __func__, write_data_length, p_base_data_info->data_size); + //printf("%s get write data %d [should be %d]failed!\n", __func__, write_data_length, p_base_data_info->data_size); return 0; } @@ -246,6 +257,7 @@ static int ModbusTcpForamatWriteData(ModbusTcpReadItem *p_read_item) case WRITE_SINGLE_COIL: case WRITE_SINGLE_REGISTER: command_index = 10; + break; case WRITE_MULTIPLE_COIL: case WRITE_MULTIPLE_REGISTER: command_index = 13; @@ -256,9 +268,11 @@ static int ModbusTcpForamatWriteData(ModbusTcpReadItem *p_read_item) } for (i = 0; i < write_data_length; i ++) { - p_base_data_info->p_command[command_index++] = write_data_buffer[i]; + p_base_data_info->p_command[command_index + i] = write_data_buffer[i]; } + p_base_data_info->command_ready = 1; + return write_data_length; } diff --git a/APP_Framework/Framework/control/shared/control_def.c b/APP_Framework/Framework/control/shared/control_def.c index 33783456b..306b1b5f4 100644 --- a/APP_Framework/Framework/control/shared/control_def.c +++ b/APP_Framework/Framework/control/shared/control_def.c @@ -202,7 +202,7 @@ static void ControlBasicSocketConfig(struct ControlRecipe *p_recipe, cJSON *p_re */ void ControlPrintfList(char name[5], uint8_t *number_list, uint16_t length) { - printf("\n******************%5s****************\n", name); + printf("\n******************%s****************\n", name); for (int32_t i = 0;i < length;i ++) { printf("0x%x ", number_list[i]); } From 1864f39dd296a01e7098317b87616b3308c45eed Mon Sep 17 00:00:00 2001 From: WuZheng Date: Wed, 14 Dec 2022 17:35:10 +0800 Subject: [PATCH 11/33] fix bugs in multi-blocks read meeting '0xFE' CRCs --- .../resources/spi/sd_card_spi/sd_spi.c | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c b/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c index e66e82166..8c0854830 100644 --- a/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c +++ b/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c @@ -28,7 +28,7 @@ static uint32 SdReady(SpiSdDeviceType spi_sd_dev) NULL_PARAM_CHECK(spi_sd_dev); uint8 data = 0xFF; - uint8 read; + uint8 read = 0x00; uint32 start_time; struct BusBlockWriteParam write_param; @@ -42,7 +42,7 @@ static uint32 SdReady(SpiSdDeviceType spi_sd_dev) start_time = 0; do { - BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param); + // BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param); BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); @@ -690,7 +690,7 @@ static uint32 SdHwReadCSD(SpiSdDeviceType spi_sd_dev) if (0xFE != g_sd_cmd_param.sd_respone_data[1]) { /*Step2 : SPI write data 0xFF until read 0xFE*/ uint8 data = 0xFF; - uint8 read_spi=0x00; + uint8 read_spi = 0x00; uint32 start_time; write_param.buffer = (void *)&data; @@ -702,7 +702,7 @@ static uint32 SdHwReadCSD(SpiSdDeviceType spi_sd_dev) do { - BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param); + // BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param); BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); SD_TIMEOUT(start_time, 10 * SPI_SD_TIMEOUT_NUM); }while(0xFE != read_spi); @@ -768,7 +768,7 @@ static uint32 SdReadSingleBlock(SpiSdDeviceType spi_sd_dev, uint32 id, uint8 *re /*Step2 : SPI read until 0xFE*/ uint8 data = 0xFF; - uint8 read[2]; + uint8 read[2]={0}; uint32 start_time; write_param.buffer = (void *)&data; @@ -837,7 +837,7 @@ static uint32 SdReadMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const uint /*Step2 : SPI write data 0xFF until read 0xFE*/ uint32 i = 0; uint8 data = 0xFF; - uint8 read[2]; + uint8 read[2] = {0}; uint32 start_time; for (i = 0 ; i < block_num ; i ++) { @@ -847,7 +847,7 @@ static uint32 SdReadMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const uint read_param.size = 1; start_time = 0; - + read[0] = 0; do { BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); @@ -859,12 +859,12 @@ static uint32 SdReadMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const uint read_param.buffer = (void *)((uint8 *)read_buffer + i * spi_sd_dev->sd_param.block_param.block_size); read_param.size = spi_sd_dev->sd_param.block_param.block_size; BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); - } - /*Step4 : SPI read 2 bytes CRC*/ - read_param.buffer = (void *)read; - read_param.size = 2; - BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); + /*Step4 : SPI read 2 bytes CRC*/ + read_param.buffer = (void *)read; + read_param.size = 2; + BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); + } /*Step5 : CMD12 stop read*/ g_sd_cmd_param.sd_cmd_type = SD_CMD_12; @@ -921,7 +921,7 @@ static uint32 SdWriteSingleBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const ui /*Step2 : SPI write data 0xFE*/ uint8 data = 0xFE; - uint8 read; + uint8 read = 0x00; uint8 write[2] = {0xFF, 0xFF}; write_param.buffer = (void *)&data; @@ -1034,7 +1034,7 @@ static uint32 SdWriteMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const voi /*Step3 : SPI write data 0xFC*/ uint32 i; uint8 data = 0xFC; - uint8 read; + uint8 read = 0x00; uint8 write[2] = {0xFF, 0xFF}; for (i = 0 ; i < block_num; i ++) { @@ -1057,6 +1057,7 @@ static uint32 SdWriteMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const voi read_param.size = 1; start_time = 0; + read = 0xFF; do { BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); @@ -1232,7 +1233,6 @@ uint32 SdRead(void *dev, struct BusBlockReadParam *read_param) KMutexAbandon(spi_sd_dev->spi_dev->haldev.owner_bus->bus_lock); return ERROR; } - /*Step2 : read SD block*/ if (1 == block_num) { ret = SdReadSingleBlock(spi_sd_dev, id, read_buffer); From 186790f5ec29737b5d3dc0ead8571a40606c515e Mon Sep 17 00:00:00 2001 From: WuZheng Date: Thu, 15 Dec 2022 10:36:56 +0800 Subject: [PATCH 12/33] fix bugs camera buff unstable --- .../k210_yolov2_detect.c | 160 +++++++++++------- .../transform_layer/xizi/transform.h | 1 + .../third_party_driver/dvp/connect_dvp.c | 3 + .../third_party_driver/include/connect_dvp.h | 1 + 4 files changed, 103 insertions(+), 62 deletions(-) diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c index e2aa4d8ec..99c51f6dc 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c @@ -8,7 +8,7 @@ #include "region_layer.h" #define STACK_SIZE (128 * 1024) -static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX-1; +static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX - 1; static _ioctl_shoot_para shoot_para_t = {0}; #define THREAD_PRIORITY_D (11) @@ -19,9 +19,10 @@ static int kmodel_fd = 0; static int if_exit = 0; static unsigned char *showbuffer = NULL; static unsigned char *kpurgbbuffer = NULL; +static int image_width = IMAGE_WIDTH; +static int image_height = IMAGE_HEIGHT; - -unsigned char *model_data = NULL; // kpu data load memory +unsigned char *model_data = NULL; // kpu data load memory unsigned char *model_data_align = NULL; kpu_model_context_t detect_task; @@ -42,18 +43,20 @@ void k210_detect(char *json_file_path) // open and parse from json file yolov2_params_t detect_params = param_parse(json_file_path); - if (!detect_params.is_valid) { + if (!detect_params.is_valid) + { return; } - printf("select camera device name:%s\n",CAMERA_DEV_DRIVER); + printf("select camera device name:%s\n", CAMERA_DEV_DRIVER); camera_fd = PrivOpen(CAMERA_DEV_DRIVER, O_RDONLY); - if (camera_fd < 0) { - printf("open %s fail !!",CAMERA_DEV_DRIVER); + if (camera_fd < 0) + { + printf("open %s fail !!", CAMERA_DEV_DRIVER); return; } struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = CAMERA_TYPE; - struct CameraCfg camera_init_cfg ={ + struct CameraCfg camera_init_cfg = { .gain_manu_enable = 0, .gain = 0xFF, .window_w = 800, @@ -61,39 +64,43 @@ void k210_detect(char *json_file_path) .output_w = IMAGE_WIDTH, .output_h = IMAGE_HEIGHT, .window_xoffset = 0, - .window_yoffset = 0 - }; + .window_yoffset = 0}; ioctl_cfg.args = &camera_init_cfg; if (0 != PrivIoctl(camera_fd, OPE_CFG, &ioctl_cfg)) { printf("camera pin fd error %d\n", camera_fd); PrivClose(camera_fd); } - + // configure the resolution of camera _ioctl_set_reso set_dvp_reso = {detect_params.sensor_output_size[1], detect_params.sensor_output_size[0]}; struct PrivIoctlCfg camera_cfg; camera_cfg.args = &set_dvp_reso; camera_cfg.ioctl_driver_type = CAMERA_TYPE; PrivIoctl(camera_fd, IOCTRL_CAMERA_OUT_SIZE_RESO, &camera_cfg); + image_height = set_dvp_reso.height; + image_width = set_dvp_reso.width; + model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); // alloc the memory for camera and kpu running showbuffer = (unsigned char *)malloc(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); - if (NULL == showbuffer) { + if (NULL == showbuffer) + { close(camera_fd); printf("showbuffer apply memory fail !!"); return; } kpurgbbuffer = (unsigned char *)malloc(detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3); - if (NULL == kpurgbbuffer) { + if (NULL == kpurgbbuffer) + { close(camera_fd); free(showbuffer); printf("kpurgbbuffer apply memory fail !!"); return; } - model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); - printf("model address:%x->%x\n",model_data_align,model_data_align + detect_params.kmodel_size); - if (NULL == model_data) { + + if (NULL == model_data) + { free(showbuffer); free(kpurgbbuffer); close(camera_fd); @@ -115,24 +122,30 @@ void k210_detect(char *json_file_path) int idx_suffix_start = strlen(json_file_path) - 4; const char kmodel_suffix[7] = "kmodel"; int kmodel_suffix_len = 6; - while (kmodel_suffix_len--) { + while (kmodel_suffix_len--) + { kmodel_path[idx_suffix_start + 5 - kmodel_suffix_len] = kmodel_suffix[5 - kmodel_suffix_len]; } printf("kmodel path: %s\n", kmodel_path); unsigned char *model_data_align = (unsigned char *)(((uintptr_t)model_data + 255) & (~255)); + printf("model address:%x->%x\n", model_data_align, model_data_align + detect_params.kmodel_size); + kmodel_fd = PrivOpen(kmodel_path, O_RDONLY); - memset(model_data,0,sizeof(model_data)); - if (kmodel_fd < 0) { + if (kmodel_fd < 0) + { printf("open kmodel fail"); close(camera_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); return; - } else { + } + else + { size = read(kmodel_fd, model_data_align, detect_params.kmodel_size); - if (size != detect_params.kmodel_size) { + if (size != detect_params.kmodel_size) + { printf("read kmodel error size %d\n", size); close(camera_fd); close(kmodel_fd); @@ -140,7 +153,9 @@ void k210_detect(char *json_file_path) free(kpurgbbuffer); free(model_data); return; - } else { + } + else + { close(kmodel_fd); printf("read kmodel success \n"); } @@ -149,24 +164,25 @@ void k210_detect(char *json_file_path) #ifdef ADD_RTTHREAD_FETURES dvp_set_ai_addr( (uintptr_t)(kpurgbbuffer + - detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0])), + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0])), (uintptr_t)(kpurgbbuffer + - detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + - detect_params.net_input_size[0] * detect_params.net_input_size[1]), + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + + detect_params.net_input_size[0] * detect_params.net_input_size[1]), (uintptr_t)(kpurgbbuffer + - detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + - detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2)); + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + + detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2)); #endif // Set AI buff address of Camera RgbAddress ai_address_preset; - ai_address_preset.r_addr = (uintptr_t)kpurgbbuffer + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]); + ai_address_preset.r_addr = (uintptr_t)kpurgbbuffer + detect_params.net_input_size[1]; ai_address_preset.g_addr = ai_address_preset.r_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1]; - ai_address_preset.b_addr = ai_address_preset.g_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1]; + ai_address_preset.b_addr = ai_address_preset.g_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1]; camera_cfg.args = &ai_address_preset; - PrivIoctl(camera_fd,SET_AI_ADDR,&camera_cfg); + PrivIoctl(camera_fd, SET_AI_ADDR, &camera_cfg); // Load kmodel into kpu task - if (kpu_load_kmodel(&detect_task, model_data_align) != 0) { + if (kpu_load_kmodel(&detect_task, model_data_align) != 0) + { printf("\nmodel init error\n"); close(camera_fd); close(kmodel_fd); @@ -180,10 +196,11 @@ void k210_detect(char *json_file_path) detect_rl.anchor = detect_params.anchor; detect_rl.nms_value = detect_params.nms_thresh; detect_rl.classes = detect_params.class_num; - result =region_layer_init(&detect_rl, detect_params.net_output_shape[0], detect_params.net_output_shape[1], - detect_params.net_output_shape[2], detect_params.net_input_size[1], detect_params.net_input_size[0]); + result = region_layer_init(&detect_rl, detect_params.net_output_shape[0], detect_params.net_output_shape[1], + detect_params.net_output_shape[2], detect_params.net_input_size[1], detect_params.net_input_size[0]); printf("region_layer_init result %d \n\r", result); - for (int idx = 0; idx < detect_params.class_num; idx++) { + for (int idx = 0; idx < detect_params.class_num; idx++) + { detect_rl.threshold[idx] = detect_params.obj_thresh[idx]; } @@ -197,9 +214,12 @@ void k210_detect(char *json_file_path) /* 创建线程 1, 属性为 attr,入口函数是 thread_entry,入口函数参数是 1 */ result = pthread_create(&tid, &attr, thread_detect_entry, &detect_params); - if (0 == result) { + if (0 == result) + { printf("thread_detect_entry successfully!\n"); - } else { + } + else + { printf("thread_detect_entry failed! error code is %d\n", result); close(camera_fd); } @@ -226,13 +246,15 @@ static void *thread_detect_entry(void *parameter) printf("thread_detect_entry start!\n"); int ret = 0; - while (1) { + while (1) + { g_ai_done_flag = 0; - //get a graph map from camera + // get a graph map from camera camera_cfg.args = &shoot_para_t; ret = PrivIoctl(camera_fd, IOCTRL_CAMERA_START_SHOT, &camera_cfg); - if (ERROR_FLAG == ret) { + if (ERROR_FLAG == ret) + { printf("ov2640 can't wait event flag"); free(showbuffer); close(camera_fd); @@ -240,9 +262,15 @@ static void *thread_detect_entry(void *parameter) return NULL; } + int shoot_flag = 0; + camera_cfg.args = (int *)&shoot_flag; + PrivIoctl(camera_fd, FLAG_CHECK, &camera_cfg); + while (shoot_flag == 2) + PrivIoctl(camera_fd, FLAG_CHECK, &camera_cfg); #ifdef ADD_RTTHREAD_FETURES - if (dmalock_sync_take(&dma_ch, 2000)) { + if (dmalock_sync_take(&dma_ch, 2000)) + { printf("Fail to take DMA channel"); } kpu_run_kmodel(&detect_task, kpurgbbuffer, DMAC_CHANNEL5, ai_done, NULL); @@ -252,7 +280,7 @@ static void *thread_detect_entry(void *parameter) #elif defined ADD_XIZI_FETURES kpu_run_kmodel(&detect_task, kpurgbbuffer, dma_ch, ai_done, NULL); while (!g_ai_done_flag) - ; + ; #endif float *output; @@ -260,11 +288,12 @@ static void *thread_detect_entry(void *parameter) kpu_get_output(&detect_task, 0, (uint8_t **)&output, &output_size); detect_rl.input = output; region_layer_run(&detect_rl, &detect_info); - printf("detect_info.obj_number:%d\n",detect_info.obj_number); + printf("detect_info.obj_number:%d\n", detect_info.obj_number); /* display result */ - for (int cnt = 0; cnt < detect_info.obj_number; cnt++) { - detect_info.obj[cnt].y1 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0])/2; - detect_info.obj[cnt].y2 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0])/2; + for (int cnt = 0; cnt < detect_info.obj_number; cnt++) + { + detect_info.obj[cnt].y1 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0]) / 2; + detect_info.obj[cnt].y2 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0]) / 2; draw_edge((uint32_t *)showbuffer, &detect_info, cnt, 0xF800, (uint16_t)detect_params.sensor_output_size[1], (uint16_t)detect_params.sensor_output_size[0]); printf("%d: (%d, %d, %d, %d) cls: %s conf: %f\t", cnt, detect_info.obj[cnt].x1, detect_info.obj[cnt].y1, @@ -274,26 +303,32 @@ static void *thread_detect_entry(void *parameter) #ifdef BSP_USING_LCD #ifdef ADD_RTTHREAD_FETURES - extern void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t * ptr); - lcd_draw_picture(0, 0, (uint16_t)detect_params.sensor_output_size[1] - 1, - (uint16_t)detect_params.sensor_output_size[0] - 1, (uint32_t *)showbuffer); - // lcd_show_image(0, 0, (uint16_t)detect_params.sensor_output_size[1], (uint16_t)detect_params.sensor_output_size[0], - // (unsigned int *)showbuffer); + extern void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t * ptr); + lcd_draw_picture(0, 0, (uint16_t)detect_params.sensor_output_size[1] - 1, + (uint16_t)detect_params.sensor_output_size[0] - 1, (uint32_t *)showbuffer); + // lcd_show_image(0, 0, (uint16_t)detect_params.sensor_output_size[1], (uint16_t)detect_params.sensor_output_size[0], + // (unsigned int *)showbuffer); #else - //refresh the LCD using photo of camera - for (int i = 0; i < IMAGE_HEIGHT; i++) - { - graph_param.pixel_info.pixel_color = (uint16_t*)showbuffer + i * IMAGE_WIDTH; - graph_param.pixel_info.x_startpos = 0; - graph_param.pixel_info.y_startpos = i + (LCD_SIZE - IMAGE_HEIGHT) / 2; - graph_param.pixel_info.x_endpos = IMAGE_WIDTH - 1; - graph_param.pixel_info.y_endpos = i + (LCD_SIZE - IMAGE_HEIGHT) / 2; - PrivWrite(lcd_fd, &graph_param, NULL_PARAMETER); - } + // refresh the LCD using photo of camera + for (int i = 0; i < image_height; i++) + { + graph_param.pixel_info.pixel_color = (uint16_t *)showbuffer + i * image_width; + graph_param.pixel_info.x_startpos = (LCD_SIZE - image_width) / 2; + graph_param.pixel_info.y_startpos = i + (LCD_SIZE - image_height) / 2; + graph_param.pixel_info.x_endpos = LCD_SIZE - 1 - (LCD_SIZE - image_width) / 2; + graph_param.pixel_info.y_endpos = graph_param.pixel_info.y_startpos; + // printf("refreshing screen: address[%08X] at row in %d\n",graph_param.pixel_info.pixel_color, graph_param.pixel_info.y_startpos); + // for(int j=0;jprivate_data) = shoot_flag; + break; case SET_AI_ADDR: kpu_rgb_address = (RgbAddress*)args->private_data; dvp_set_output_enable(DVP_OUTPUT_AI, 1); diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h index 14695c659..9970920db 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h @@ -32,6 +32,7 @@ extern "C" { #define SET_DISPLAY_ADDR (21) #define SET_AI_ADDR (22) #define IOCTRL_CAMERA_OUT_SIZE_RESO (23) +#define FLAG_CHECK (24) typedef struct From 5761bd09162e2539e8354dfa31c920bdc68b6691 Mon Sep 17 00:00:00 2001 From: WuZheng Date: Thu, 15 Dec 2022 15:51:46 +0800 Subject: [PATCH 13/33] primarily unify dvp APIs with rt --- .../k210_yolov2_detect.c | 33 +- .../transform_layer/xizi/transform.h | 26 +- .../third_party_driver/dvp/connect_dvp.c | 30 +- .../third_party_driver/dvp/ov2640.c | 402 +++++++++++++++++- .../third_party_driver/include/connect_dvp.h | 21 +- .../third_party_driver/include/ov2640.h | 12 + 6 files changed, 488 insertions(+), 36 deletions(-) diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c index 99c51f6dc..1261ba685 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c @@ -7,11 +7,11 @@ #endif #include "region_layer.h" #define STACK_SIZE (128 * 1024) +#define THREAD_PRIORITY_D (11) static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX - 1; static _ioctl_shoot_para shoot_para_t = {0}; -#define THREAD_PRIORITY_D (11) static pthread_t tid = 0; static void *thread_detect_entry(void *parameter); static int camera_fd = 0; @@ -32,7 +32,6 @@ volatile uint32_t g_ai_done_flag; static void ai_done(void *ctx) { g_ai_done_flag = 1; } -#define ERROR_FLAG (1) void k210_detect(char *json_file_path) { @@ -47,6 +46,7 @@ void k210_detect(char *json_file_path) { return; } + printf("select camera device name:%s\n", CAMERA_DEV_DRIVER); camera_fd = PrivOpen(CAMERA_DEV_DRIVER, O_RDONLY); if (camera_fd < 0) @@ -54,6 +54,8 @@ void k210_detect(char *json_file_path) printf("open %s fail !!", CAMERA_DEV_DRIVER); return; } + +#ifdef ADD_XIZI_FETURES struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = CAMERA_TYPE; struct CameraCfg camera_init_cfg = { @@ -71,6 +73,7 @@ void k210_detect(char *json_file_path) printf("camera pin fd error %d\n", camera_fd); PrivClose(camera_fd); } +#endif // configure the resolution of camera _ioctl_set_reso set_dvp_reso = {detect_params.sensor_output_size[1], detect_params.sensor_output_size[0]}; @@ -81,8 +84,16 @@ void k210_detect(char *json_file_path) image_height = set_dvp_reso.height; image_width = set_dvp_reso.width; - model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); // alloc the memory for camera and kpu running + model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); + if (NULL == model_data) + { + free(showbuffer); + free(kpurgbbuffer); + close(camera_fd); + printf("model_data apply memory fail !!"); + return; + } showbuffer = (unsigned char *)malloc(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); if (NULL == showbuffer) { @@ -99,14 +110,7 @@ void k210_detect(char *json_file_path) return; } - if (NULL == model_data) - { - free(showbuffer); - free(kpurgbbuffer); - close(camera_fd); - printf("model_data apply memory fail !!"); - return; - } + memset(model_data, 0, detect_params.kmodel_size + 255); memset(showbuffer, 0, detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); memset(kpurgbbuffer, 0, detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3); @@ -171,7 +175,7 @@ void k210_detect(char *json_file_path) (uintptr_t)(kpurgbbuffer + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2)); -#endif +#else // Set AI buff address of Camera RgbAddress ai_address_preset; ai_address_preset.r_addr = (uintptr_t)kpurgbbuffer + detect_params.net_input_size[1]; @@ -179,6 +183,7 @@ void k210_detect(char *json_file_path) ai_address_preset.b_addr = ai_address_preset.g_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1]; camera_cfg.args = &ai_address_preset; PrivIoctl(camera_fd, SET_AI_ADDR, &camera_cfg); +#endif // Load kmodel into kpu task if (kpu_load_kmodel(&detect_task, model_data_align) != 0) @@ -207,7 +212,7 @@ void k210_detect(char *json_file_path) size_t stack_size = STACK_SIZE; pthread_attr_t attr; /* 线程属性 */ struct sched_param prio; /* 线程优先级 */ - prio.sched_priority = 8; /* 优先级设置为 8 */ + prio.sched_priority = THREAD_PRIORITY_D; /* 优先级设置为 11 */ pthread_attr_init(&attr); /* 先使用默认值初始化属性 */ pthread_attr_setschedparam(&attr, &prio); /* 修改属性对应的优先级 */ pthread_attr_setstacksize(&attr, stack_size); @@ -253,7 +258,7 @@ static void *thread_detect_entry(void *parameter) // get a graph map from camera camera_cfg.args = &shoot_para_t; ret = PrivIoctl(camera_fd, IOCTRL_CAMERA_START_SHOT, &camera_cfg); - if (ERROR_FLAG == ret) + if (EOF == ret) { printf("ov2640 can't wait event flag"); free(showbuffer); diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.h b/APP_Framework/Framework/transform_layer/xizi/transform.h index c35dc5c01..c989c58dd 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.h +++ b/APP_Framework/Framework/transform_layer/xizi/transform.h @@ -260,10 +260,6 @@ enum TCP_OPTION { #define MY_INDEV_X BSP_LCD_Y_MAX #define MY_INDEV_Y BSP_LCD_X_MAX -#define DVP_INIT 0x00U -#define REG_SCCB_READ 0x12U -#define REG_SCCB_WRITE 0x13U -#define OUTPUT_CONFIG 0x20U #define LCD_STRING_TYPE 0 #define LCD_DOT_TYPE 1 #define LCD_SIZE 320 @@ -271,15 +267,23 @@ enum TCP_OPTION { #define IMAGE_WIDTH 320 #define NULL_PARAMETER 0 -#define REG_SCCB_READ 0x12U -#define REG_SCCB_WRITE 0x13U +#define REG_SCCB_READ 0xA2U +#define REG_SCCB_WRITE 0xA3U #define SCCB_REG_LENGTH 0x08U -#define IOCTRL_CAMERA_START_SHOT (20) -#define SET_DISPLAY_ADDR (21) -#define SET_AI_ADDR (22) -#define IOCTRL_CAMERA_OUT_SIZE_RESO (23) -#define FLAG_CHECK (24) +#define SET_DISPLAY_ADDR (0xD1) +#define SET_AI_ADDR (0xD2) +#define FLAG_CHECK (0xD4) + +#define IOCTRL_CAMERA_START_SHOT (22) // start shoot +#define IOCTRL_CAMERA_OUT_SIZE_RESO (23) +#define IOCTRL_CAMERA_SET_WINDOWS_SIZE (21) // user set specific windows outsize +#define IOCTRL_CAMERA_SET_LIGHT (24) //set light mode +#define IOCTRL_CAMERA_SET_COLOR (25) //set color saturation +#define IOCTRL_CAMERA_SET_BRIGHTNESS (26) //set color brightness +#define IOCTRL_CAMERA_SET_CONTRAST (27) //set contrast +#define IOCTRL_CAMERA_SET_EFFECT (28) //set effect +#define IOCTRL_CAMERA_SET_EXPOSURE (29) //set auto exposure /*********************shell***********************/ //for int func(int argc, char *agrv[]) #define PRIV_SHELL_CMD_MAIN_ATTR (SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)) diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c index 50b8d5386..983719e61 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c @@ -126,6 +126,10 @@ static uint32 DvpRead(void *dev, struct BusBlockReadParam *read_param) return ret; } +/** + * @brief configure api for dvp device + * TODO: unified APIs to keep consistent with RT-thread + */ static uint32 DvpDrvConfigure(void *drv, struct BusConfigureInfo *args) { x_err_t ret = EOK; @@ -134,6 +138,7 @@ static uint32 DvpDrvConfigure(void *drv, struct BusConfigureInfo *args) struct CameraCfg* tmp_cfg; RgbAddress* kpu_rgb_address; _ioctl_shoot_para* pixel_cfg; + int value = ((int*)args->private_data)[0]; switch (cmd_type) { case OPE_INT: @@ -151,6 +156,9 @@ static uint32 DvpDrvConfigure(void *drv, struct BusConfigureInfo *args) dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 1); shoot_flag=ONLY_ONE_SHOOT; break; + case IOCTRL_CAMERA_OUT_SIZE_RESO: + dvp_set_image_size(((uint32_t*)args->private_data)[0], ((uint32_t*)args->private_data)[1]); + break; case FLAG_CHECK: *((int*)args->private_data) = shoot_flag; break; @@ -159,9 +167,27 @@ static uint32 DvpDrvConfigure(void *drv, struct BusConfigureInfo *args) dvp_set_output_enable(DVP_OUTPUT_AI, 1); dvp_set_ai_addr(kpu_rgb_address->r_addr,kpu_rgb_address->g_addr,kpu_rgb_address->b_addr); break; - case IOCTRL_CAMERA_OUT_SIZE_RESO: - dvp_set_image_size(((uint32_t*)args->private_data)[0], ((uint32_t*)args->private_data)[1]); + + // make compatible for rt-fusion xizi + case IOCTRL_CAMERA_SET_LIGHT: + ov2640_set_light_mode(value); break; + case IOCTRL_CAMERA_SET_COLOR: + ov2640_set_color_saturation(value); + break; + case IOCTRL_CAMERA_SET_BRIGHTNESS: + ov2640_set_brightness(value); + break; + case IOCTRL_CAMERA_SET_CONTRAST: + ov2640_set_contrast(value); + break; + case IOCTRL_CAMERA_SET_EFFECT: + ov2640_set_special_effects(value); + break; + case IOCTRL_CAMERA_SET_EXPOSURE: + ov2640_set_auto_exposure(value); + break; + case REG_SCCB_READ: ReadDvpReg(drv, (struct DvpRegConfigureInfo *)args->private_data); break; diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/ov2640.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/ov2640.c index 991a8982a..9f4e00859 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/ov2640.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/ov2640.c @@ -399,8 +399,8 @@ const uint8_t ov2640_config[][2]= #else const uint8_t ov2640_config[][2]= { - {0x00,x00} -} + {0x00,0x00} +}; #endif @@ -447,7 +447,7 @@ int SensorConfigure(struct CameraCfg *cfg_info) //set reg mode to dsp dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x01); - + //configure dsp gain if(cfg_info->gain_manu_enable){ reg_tmp = dvp_sccb_receive_data(OV2640_ADDR, 0x13); @@ -461,3 +461,399 @@ int SensorConfigure(struct CameraCfg *cfg_info) return 1; } + +const uint8_t OV2640_AUTOEXPOSURE_LEVEL[5][8]= +{ + { + 0xFF,0x01, + 0x24,0x20, + 0x25,0x18, + 0x26,0x60, + }, + { + 0xFF,0x01, + 0x24,0x34, + 0x25,0x1c, + 0x26,0x00, + }, + { + 0xFF,0x01, + 0x24,0x3e, + 0x25,0x38, + 0x26,0x81, + }, + { + 0xFF,0x01, + 0x24,0x48, + 0x25,0x40, + 0x26,0x81, + }, + { + 0xFF,0x01, + 0x24,0x58, + 0x25,0x50, + 0x26,0x92, + }, +}; + +const uint8_t ov2640_yuv422_reg_tbl[][2] = +{ + {0xFF, 0x00}, + {0xDA, 0x10}, + {0xD7, 0x03}, + {0xDF, 0x00}, + {0x33, 0x80}, + {0x3C, 0x40}, + {0xe1, 0x77}, + {0x00, 0x00}, +}; + +const uint8_t ov2640_jpeg_reg_tbl[][2]= +{ + {0xff, 0x01}, + {0xe0, 0x14}, + {0xe1, 0x77}, + {0xe5, 0x1f}, + {0xd7, 0x03}, + {0xda, 0x10}, + {0xe0, 0x00}, +}; + +const uint8_t ov2640_rgb565_reg_tbl[][2]= +{ + {0xFF, 0x00}, + {0xDA, 0x08}, + {0xD7, 0x03}, + {0xDF, 0x02}, + {0x33, 0xa0}, + {0x3C, 0x00}, + {0xe1, 0x67}, + + {0xff, 0x01}, + {0xe0, 0x00}, + {0xe1, 0x00}, + {0xe5, 0x00}, + {0xd7, 0x00}, + {0xda, 0x00}, + {0xe0, 0x00}, +}; + + +/* change ov2640 to jpeg mode */ +void ov2640_jpeg_mode(void) +{ + uint16_t i=0; + /* set yun422 mode */ + for (i = 0; i < (sizeof(ov2640_yuv422_reg_tbl) / 2); i++) + { + dvp_sccb_send_data(OV2640_ADDR, ov2640_yuv422_reg_tbl[i][0],ov2640_yuv422_reg_tbl[i][1]); + } + + /* set jpeg mode */ + for(i=0;i<(sizeof(ov2640_jpeg_reg_tbl)/2);i++) + { + dvp_sccb_send_data(OV2640_ADDR, ov2640_jpeg_reg_tbl[i][0],ov2640_jpeg_reg_tbl[i][1]); + } +} + +/* change ov2640 to rgb565 mode */ +void ov2640_rgb565_mode(void) +{ + uint16_t i=0; + for (i = 0; i < (sizeof(ov2640_rgb565_reg_tbl) / 2); i++) + { + dvp_sccb_send_data(OV2640_ADDR, ov2640_rgb565_reg_tbl[i][0],ov2640_rgb565_reg_tbl[i][1]); + } +} + + + +/* set auto exposure level value must be 0 ~4 */ +void ov2640_set_auto_exposure(uint8_t level) +{ + uint8_t i = 0; + uint8_t *p = (uint8_t*)OV2640_AUTOEXPOSURE_LEVEL[level]; + for (i = 0; i < 4; i++) + { + dvp_sccb_send_data(OV2640_ADDR, p[i*2],p[i*2+1]); + } +} + +/* set light mode + * 0: auto + * 1: sunny + * 2: cloudy + * 3: office + * 4: home + * */ +void ov2640_set_light_mode(uint8_t mode) +{ + uint8_t regccval, regcdval, regceval; + + switch(mode) + { + case 0: + dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0xC7, 0x10); + return; + + case 2: + regccval = 0x65; + regcdval = 0x41; + regceval = 0x4F; + break; + + case 3: + regccval = 0x52; + regcdval = 0x41; + regceval = 0x66; + break; + + case 4: + regccval = 0x42; + regcdval = 0x3F; + regceval = 0x71; + break; + + default: + regccval = 0x5E; + regcdval = 0x41; + regceval = 0x54; + break; + } + + dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0xC7, 0x40); + dvp_sccb_send_data(OV2640_ADDR, 0xCC, regccval); + dvp_sccb_send_data(OV2640_ADDR, 0xCD, regcdval); + dvp_sccb_send_data(OV2640_ADDR, 0xCE, regceval); +} + +/* set color saturation + * 0: -2 + * 1: -1 + * 2: 0 + * 3: +1 + * 4: +2 + * */ +void ov2640_set_color_saturation(uint8_t sat) +{ + uint8_t reg7dval = ((sat+2)<<4) | 0x08; + dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0X00); + dvp_sccb_send_data(OV2640_ADDR, 0x7C, 0X00); + dvp_sccb_send_data(OV2640_ADDR, 0x7D, 0X02); + dvp_sccb_send_data(OV2640_ADDR, 0x7C, 0X03); + dvp_sccb_send_data(OV2640_ADDR, 0x7D, reg7dval); + dvp_sccb_send_data(OV2640_ADDR, 0x7D, reg7dval); +} + +/* set brightness + * 0: -2 + * 1: -1 + * 2: 0 + * 3: 1 + * 4: 2 + * */ +void ov2640_set_brightness(uint8_t bright) +{ + dvp_sccb_send_data(OV2640_ADDR, 0xff, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0x7c, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, 0x04); + dvp_sccb_send_data(OV2640_ADDR, 0x7c, 0x09); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, bright << 4); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, 0x00); +} + +/* set contrast + * 0: -2 + * 1: -1 + * 2: 0 + * 3: 1 + * 4: 2 + * */ +void ov2640_set_contrast(uint8_t contrast) +{ + uint8_t reg7d0val, reg7d1val; + + switch(contrast) + { + case 0: + reg7d0val = 0x18; + reg7d1val = 0x34; + break; + + case 1: + reg7d0val = 0x1C; + reg7d1val = 0x2A; + break; + + case 3: + reg7d0val = 0x24; + reg7d1val = 0x16; + break; + + case 4: + reg7d0val = 0x28; + reg7d1val = 0x0C; + break; + + default: + reg7d0val = 0x20; + reg7d1val = 0x20; + break; + } + dvp_sccb_send_data(OV2640_ADDR, 0xff, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0x7c, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, 0x04); + dvp_sccb_send_data(OV2640_ADDR, 0x7c, 0x07); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, 0x20); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, reg7d0val); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, reg7d1val); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, 0x06); +} + +/* set special effects + * 0: noraml + * 1: negative film + * 2: black-and-white + * 3: the red + * 4: the green + * 5: the blue + * 6: Retro +*/ +void ov2640_set_special_effects(uint8_t eft) +{ + uint8_t reg7d0val, reg7d1val, reg7d2val; + + switch(eft) + { + case 1: + reg7d0val = 0x40; + break; + case 2: + reg7d0val = 0x18; + break; + case 3: + reg7d0val = 0x18; + reg7d1val = 0x40; + reg7d2val = 0xC0; + break; + case 4: + reg7d0val = 0x18; + reg7d1val = 0x40; + reg7d2val = 0x40; + break; + case 5: + reg7d0val = 0x18; + reg7d1val = 0xA0; + reg7d2val = 0x40; + break; + case 6: + reg7d0val = 0x18; + reg7d1val = 0x40; + reg7d2val = 0xA6; + break; + default: + reg7d0val = 0x00; + reg7d1val = 0x80; + reg7d2val = 0x80; + break; + } + dvp_sccb_send_data(OV2640_ADDR, 0xff, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0x7c, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, reg7d0val); + dvp_sccb_send_data(OV2640_ADDR, 0x7c, 0x05); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, reg7d1val); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, reg7d2val); +} + +/* set the image output window */ +void ov2640_set_window_size(uint16_t sx,uint16_t sy,uint16_t width,uint16_t height) +{ + uint16_t endx; + uint16_t endy; + uint8_t temp; + endx = sx + width / 2; + endy = sy + height / 2; + + dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x01); + temp = dvp_sccb_receive_data(OV2640_ADDR,0x03); + temp &= 0xF0; + temp |= ((endy & 0x03) << 2) | (sy & 0x03); + dvp_sccb_send_data(OV2640_ADDR, 0x03, temp); + dvp_sccb_send_data(OV2640_ADDR, 0x19, sy>>2); + dvp_sccb_send_data(OV2640_ADDR, 0x1A, endy>>2); + + temp = dvp_sccb_receive_data(OV2640_ADDR,0x32); + temp &= 0xC0; + temp |= ((endx & 0x07) << 3) | (sx & 0x07); + dvp_sccb_send_data(OV2640_ADDR, 0x32, temp); + dvp_sccb_send_data(OV2640_ADDR, 0x17, sx>>3); + dvp_sccb_send_data(OV2640_ADDR, 0x18, endx>>3); +} + +/* set the image output size */ +uint8_t ov2640_set_image_out_size(uint16_t width,uint16_t height) +{ + uint16_t outh, outw; + uint8_t temp; + + if(width%4)return 1; + if(height%4)return 2; + outw = width /4; + outh = height/4; + dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0xE0, 0x04); + dvp_sccb_send_data(OV2640_ADDR, 0x5A, outw & 0XFF); + dvp_sccb_send_data(OV2640_ADDR, 0x5B, outh & 0XFF); + temp = (outw >> 8) & 0x03; + temp |= (outh >> 6) & 0x04; + dvp_sccb_send_data(OV2640_ADDR, 0x5C, temp); + dvp_sccb_send_data(OV2640_ADDR, 0xE0, 0X00); + + return 1; +} + +/* set the image window size */ +uint8_t ov2640_set_image_window_size(uint16_t offx, uint16_t offy, uint16_t width, uint16_t height) +{ + uint16_t hsize, vsize; + uint8_t temp; + if ((width % 4) || (height%4)) + { + return EOF; + } + hsize = width /4; + vsize = height/4; + dvp_sccb_send_data(OV2640_ADDR, 0XFF,0X00); + dvp_sccb_send_data(OV2640_ADDR, 0XE0,0X04); + dvp_sccb_send_data(OV2640_ADDR, 0X51,hsize&0XFF); + dvp_sccb_send_data(OV2640_ADDR, 0X52,vsize&0XFF); + dvp_sccb_send_data(OV2640_ADDR, 0X53,offx&0XFF); + dvp_sccb_send_data(OV2640_ADDR, 0X54,offy&0XFF); + temp=(vsize>>1)&0X80; + temp|=(offy>>4)&0X70; + temp|=(hsize>>5)&0X08; + temp|=(offx>>8)&0X07; + dvp_sccb_send_data(OV2640_ADDR, 0X55,temp); // + dvp_sccb_send_data(OV2640_ADDR, 0X57,(hsize>>2)&0X80); // + dvp_sccb_send_data(OV2640_ADDR, 0XE0,0X00); + return 0; +} + +/* set output resolution */ +uint8_t ov2640_set_image_size(uint16_t width ,uint16_t height) +{ + uint8_t temp; + dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0xE0, 0x04); + dvp_sccb_send_data(OV2640_ADDR, 0xC0, (width >>3) & 0xFF); + dvp_sccb_send_data(OV2640_ADDR, 0xC1, (height >> 3) & 0xFF); + temp = (width & 0x07) << 3; + temp |= height & 0x07; + temp |= (width >> 4) & 0x80; + dvp_sccb_send_data(OV2640_ADDR, 0x8C, temp); + dvp_sccb_send_data(OV2640_ADDR, 0xE0, 0x00); + + return 1; +} diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h index 9970920db..7e31c9aff 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h @@ -25,14 +25,23 @@ extern "C" { #endif -#define REG_SCCB_READ 0x12U -#define REG_SCCB_WRITE 0x13U +#define REG_SCCB_READ 0xA2U +#define REG_SCCB_WRITE 0xA3U #define SCCB_REG_LENGTH 0x08U -#define IOCTRL_CAMERA_START_SHOT (20) -#define SET_DISPLAY_ADDR (21) -#define SET_AI_ADDR (22) + +#define SET_DISPLAY_ADDR (0xD1) +#define SET_AI_ADDR (0xD2) +#define FLAG_CHECK (0xD4) + +#define IOCTRL_CAMERA_START_SHOT (22) // start shoot #define IOCTRL_CAMERA_OUT_SIZE_RESO (23) -#define FLAG_CHECK (24) +#define IOCTRL_CAMERA_SET_WINDOWS_SIZE (21) // user set specific windows outsize +#define IOCTRL_CAMERA_SET_LIGHT (24) //set light mode +#define IOCTRL_CAMERA_SET_COLOR (25) //set color saturation +#define IOCTRL_CAMERA_SET_BRIGHTNESS (26) //set color brightness +#define IOCTRL_CAMERA_SET_CONTRAST (27) //set contrast +#define IOCTRL_CAMERA_SET_EFFECT (28) //set effect +#define IOCTRL_CAMERA_SET_EXPOSURE (29) //set auto exposure typedef struct diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/ov2640.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/ov2640.h index 4f1240b73..4451a8e33 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/ov2640.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/ov2640.h @@ -34,5 +34,17 @@ struct CameraCfg int ov2640_init(void); int ov2640_read_id(uint16_t *manuf_id, uint16_t *device_id); int SensorConfigure(struct CameraCfg* cfg_info); +void ov2640_jpeg_mode(void); +void ov2640_rgb565_mode(void); +void ov2640_set_auto_exposure(uint8_t level); +void ov2640_set_light_mode(uint8_t mode); +void ov2640_set_color_saturation(uint8_t sat); +void ov2640_set_brightness(uint8_t bright); +void ov2640_set_contrast(uint8_t contrast); +void ov2640_set_special_effects(uint8_t eft); +void ov2640_set_window_size(uint16_t sx,uint16_t sy,uint16_t width,uint16_t height); +uint8_t ov2640_set_image_out_size(uint16_t width,uint16_t height); +uint8_t ov2640_set_image_window_size(uint16_t offx, uint16_t offy, uint16_t width, uint16_t height); +uint8_t ov2640_set_image_size(uint16_t width ,uint16_t height); #endif /* _OV2640_H */ From 4e1bc3bf0422d7a80e68dec7a44e0563596e79cd Mon Sep 17 00:00:00 2001 From: WuZheng Date: Thu, 15 Dec 2022 16:17:31 +0800 Subject: [PATCH 14/33] add readme for yolo framework --- .../k210_yolov2_detect_procedure/Readme.md | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md new file mode 100644 index 000000000..7b04a9288 --- /dev/null +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md @@ -0,0 +1,34 @@ +# YOLO Framework for K210 KPU + +## Usage + +* Include all src and header there in menuconfig, and copy codes like below in *main.c* in folder *Application*. +* In board *edu-riscv64*, if all operations are right, the LCD should light and show the image from camera and YOLO inference. + +```C +#include +#include +// #include +#include + + +extern int FrameworkInit(); +extern void ApplicationOtaTaskInit(void); +extern void k210_detect(char *json_file_path); + +int main(void) +{ + printf("Hello, world! \n"); + FrameworkInit(); +#ifdef APPLICATION_OTA + ApplicationOtaTaskInit(); +#endif + k210_detect("instrusion.json"); + return 0; +} +``` + +## TODO + +* KPU drivers are still not completed, because it is undefined how to reisgter KPU's bus and device name in XIZI system. The framework is still directly using the SDK From Canaan Inc. But after the driver completed, it will be easy to adapt framework for the APIs. +* Camera and LCD drivers between RT and XIZI are not completely compatible. So there are some marcos like `ifdef` to make the framework compatible for both systems. From bc014769f5664474e5dac9227cf2c3a25bcfe0f1 Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Fri, 16 Dec 2022 10:58:26 +0800 Subject: [PATCH 15/33] =?UTF-8?q?1=E3=80=81fix=20modbus=5Ftcp=20socket=20b?= =?UTF-8?q?ug;2=E3=80=81fix=20ch438=20init=20error=20on=20xidatong-arm32?= =?UTF-8?q?=20board?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ipc_protocol/modbus_tcp/modbus_tcp.c | 25 +++++++++++++------ .../XiZi_IIoT/board/xidatong-arm32/board.c | 2 +- .../XiZi_IIoT/resources/include/bus_serial.h | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c index b9788a893..a731695b8 100755 --- a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c @@ -33,7 +33,7 @@ static uint8_t recv_buff[1024] = {0}; * @param recv_buff - receive buff * @return success : 0 error : -1 */ -static int ModbusTcpTransformRecvBuffToData(ModbusTcpReadItem *p_read_item, uint8_t *recv_buff) +static void ModbusTcpTransformRecvBuffToData(ModbusTcpReadItem *p_read_item, uint8_t *recv_buff) { uint8_t head_length = 9; uint8_t *data_buffer; @@ -43,8 +43,6 @@ static int ModbusTcpTransformRecvBuffToData(ModbusTcpReadItem *p_read_item, uint ModbusTcpFunctionCode function_code = p_modbus_tcp_data_info->function_code; uint8_t *p_data = p_modbus_tcp_data_info->base_data_info.p_data; - printf("Receive data is "); - uint8_t bytes_count = recv_buff[8]; if ((WRITE_SINGLE_COIL == function_code) || (WRITE_SINGLE_REGISTER == function_code) || @@ -58,6 +56,7 @@ static int ModbusTcpTransformRecvBuffToData(ModbusTcpReadItem *p_read_item, uint data_buffer = recv_buff + head_length;//remove head data if (READ_COIL_STATUS == function_code || READ_INPUT_STATUS == function_code) { + printf("Receive data is "); for (int i = 0;i < bytes_count;i ++) { for (int j = 0;j < 8;j ++) { if ((i * 8 + j) < p_read_item->quantity) { @@ -66,7 +65,8 @@ static int ModbusTcpTransformRecvBuffToData(ModbusTcpReadItem *p_read_item, uint } } } - } else { + } else if (READ_HOLDING_REGISTER == function_code || READ_INPUT_REGISTER == function_code) { + printf("Receive data is "); for (uint16_t i = 0; i < quantity; i ++) { ((int16_t *)p_data)[i] = ((int16_t *)data_buffer)[quantity - i - 1]; printf("0x%x 0x%x ", p_data[2 * i], p_data[2 * i + 1]); @@ -102,21 +102,30 @@ static int ModbusTcpGetData(int32_t socket, ModbusTcpReadItem *p_read_item) write_error = socket_write(socket, p_base_data_info->p_command, p_base_data_info->command_length); if (write_error < 0) { - printf("Write socket error, errno is %d!", errno); + printf("Write socket error, errno is %d!\n", errno); } else { PrivTaskDelay(20); int32_t recv_length = socket_read(socket, recv_buff, sizeof(recv_buff)); if (recv_length < 0) { - printf("Read socket error, errno is %d!", errno); + printf("Read socket error, errno is %d! read again\n", errno); + memset(recv_buff, 0, sizeof(recv_buff)); + recv_length = socket_read(socket, recv_buff, sizeof(recv_buff)); + if (recv_length > 0) { + ControlPrintfList("RECV", recv_buff, recv_length); + ModbusTcpTransformRecvBuffToData(p_read_item, recv_buff); + return 0; + } } else { ControlPrintfList("RECV", recv_buff, recv_length); - return ModbusTcpTransformRecvBuffToData(p_read_item, recv_buff); + ModbusTcpTransformRecvBuffToData(p_read_item, recv_buff); + + return 0; } } if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) { - printf("Send command failed, errno is %d!", errno); + printf("Send command failed, errno is %d!\n", errno); continue; } else { return -1; diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/board.c b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/board.c index 1a64fc4f2..2d9236270 100644 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/board.c +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/board.c @@ -300,7 +300,7 @@ struct InitSequenceDesc _board_init[] = #endif #ifdef BSP_USING_CH438 - {"ch438", Imxrt1052HwCh438Init()}, + {"ch438", Imxrt1052HwCh438Init }, #endif #ifdef BSP_USING_SDIO diff --git a/Ubiquitous/XiZi_IIoT/resources/include/bus_serial.h b/Ubiquitous/XiZi_IIoT/resources/include/bus_serial.h index 917acfc1e..96af36dc6 100644 --- a/Ubiquitous/XiZi_IIoT/resources/include/bus_serial.h +++ b/Ubiquitous/XiZi_IIoT/resources/include/bus_serial.h @@ -46,6 +46,7 @@ struct SerialDataCfg uint16 serial_buffer_size; int32 serial_timeout; + uint8 is_ext_uart; uint8 ext_uart_no; enum ExtSerialPortConfigure port_configure; }; From 38c4419ef911289f5b066a7998a75a5e18d256d7 Mon Sep 17 00:00:00 2001 From: WuZheng Date: Mon, 19 Dec 2022 14:13:54 +0800 Subject: [PATCH 16/33] add KPU driver and resource in XiZi for edu-riscv64 --- .../kpu/k210_yolov2_detect_procedure/Kconfig | 4 + .../k210_yolov2_detect.c | 113 ++++++---- .../transform_layer/xizi/transform.c | 1 + .../transform_layer/xizi/transform.h | 16 +- .../XiZi_IIoT/board/edu-riscv64/board.c | 5 + .../third_party_driver/include/connect_kpu.h | 41 ++++ .../third_party_driver/kpu/Kconfig | 14 ++ .../third_party_driver/kpu/Makefile | 2 +- .../third_party_driver/kpu/connect_kpu.c | 170 +++++++++++++++ Ubiquitous/XiZi_IIoT/resources/Kconfig | 6 + Ubiquitous/XiZi_IIoT/resources/Makefile | 4 + Ubiquitous/XiZi_IIoT/resources/include/bus.h | 3 + .../XiZi_IIoT/resources/include/bus_kpu.h | 69 ++++++ .../XiZi_IIoT/resources/include/dev_kpu.h | 69 ++++++ .../XiZi_IIoT/resources/include/device.h | 5 + Ubiquitous/XiZi_IIoT/resources/kpu/Makefile | 5 + Ubiquitous/XiZi_IIoT/resources/kpu/bus_kpu.c | 123 +++++++++++ Ubiquitous/XiZi_IIoT/resources/kpu/dev_kpu.c | 200 ++++++++++++++++++ Ubiquitous/XiZi_IIoT/resources/kpu/drv_kpu.c | 68 ++++++ 19 files changed, 870 insertions(+), 48 deletions(-) create mode 100644 Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_kpu.h create mode 100644 Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/connect_kpu.c create mode 100644 Ubiquitous/XiZi_IIoT/resources/include/bus_kpu.h create mode 100644 Ubiquitous/XiZi_IIoT/resources/include/dev_kpu.h create mode 100644 Ubiquitous/XiZi_IIoT/resources/kpu/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/resources/kpu/bus_kpu.c create mode 100644 Ubiquitous/XiZi_IIoT/resources/kpu/dev_kpu.c create mode 100644 Ubiquitous/XiZi_IIoT/resources/kpu/drv_kpu.c diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig index a359ac926..185b1f6cb 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig @@ -3,6 +3,10 @@ menuconfig USING_K210_YOLOV2_DETECT depends on USING_KPU_PROCESSING default n +config KPU_DEV_DRIVER + string "Set kpu dev path" + default "/dev/kpu_dev" + config CAMERA_DEV_DRIVER string "Set camera dev path for kpu" default "/dev/ov2640" diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c index 1261ba685..aea9b553f 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c @@ -16,6 +16,7 @@ static pthread_t tid = 0; static void *thread_detect_entry(void *parameter); static int camera_fd = 0; static int kmodel_fd = 0; +static int kpu_fd = 0; static int if_exit = 0; static unsigned char *showbuffer = NULL; static unsigned char *kpurgbbuffer = NULL; @@ -46,7 +47,16 @@ void k210_detect(char *json_file_path) { return; } - + +#ifdef ADD_XIZI_FETURES + kpu_fd = PrivOpen(KPU_DEV_DRIVER, O_RDONLY); + if (camera_fd < 0) + { + printf("open %s fail !!", KPU_DEV_DRIVER); + return; + } +#endif + printf("select camera device name:%s\n", CAMERA_DEV_DRIVER); camera_fd = PrivOpen(CAMERA_DEV_DRIVER, O_RDONLY); if (camera_fd < 0) @@ -55,26 +65,6 @@ void k210_detect(char *json_file_path) return; } -#ifdef ADD_XIZI_FETURES - struct PrivIoctlCfg ioctl_cfg; - ioctl_cfg.ioctl_driver_type = CAMERA_TYPE; - struct CameraCfg camera_init_cfg = { - .gain_manu_enable = 0, - .gain = 0xFF, - .window_w = 800, - .window_h = 600, - .output_w = IMAGE_WIDTH, - .output_h = IMAGE_HEIGHT, - .window_xoffset = 0, - .window_yoffset = 0}; - ioctl_cfg.args = &camera_init_cfg; - if (0 != PrivIoctl(camera_fd, OPE_CFG, &ioctl_cfg)) - { - printf("camera pin fd error %d\n", camera_fd); - PrivClose(camera_fd); - } -#endif - // configure the resolution of camera _ioctl_set_reso set_dvp_reso = {detect_params.sensor_output_size[1], detect_params.sensor_output_size[0]}; struct PrivIoctlCfg camera_cfg; @@ -90,21 +80,21 @@ void k210_detect(char *json_file_path) { free(showbuffer); free(kpurgbbuffer); - close(camera_fd); + PrivClose(camera_fd); printf("model_data apply memory fail !!"); return; } showbuffer = (unsigned char *)malloc(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); if (NULL == showbuffer) { - close(camera_fd); + PrivClose(camera_fd); printf("showbuffer apply memory fail !!"); return; } kpurgbbuffer = (unsigned char *)malloc(detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3); if (NULL == kpurgbbuffer) { - close(camera_fd); + PrivClose(camera_fd); free(showbuffer); printf("kpurgbbuffer apply memory fail !!"); return; @@ -122,7 +112,6 @@ void k210_detect(char *json_file_path) */ // kmodel path generate from json file path, *.json -> *.kmodel memcpy(kmodel_path, json_file_path, strlen(json_file_path)); - int idx_suffix_start = strlen(json_file_path) - 4; const char kmodel_suffix[7] = "kmodel"; int kmodel_suffix_len = 6; @@ -139,7 +128,7 @@ void k210_detect(char *json_file_path) if (kmodel_fd < 0) { printf("open kmodel fail"); - close(camera_fd); + PrivClose(camera_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); @@ -147,12 +136,12 @@ void k210_detect(char *json_file_path) } else { - size = read(kmodel_fd, model_data_align, detect_params.kmodel_size); + size = PrivRead(kmodel_fd, model_data_align, detect_params.kmodel_size); if (size != detect_params.kmodel_size) { printf("read kmodel error size %d\n", size); - close(camera_fd); - close(kmodel_fd); + PrivClose(camera_fd); + PrivClose(kmodel_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); @@ -160,7 +149,7 @@ void k210_detect(char *json_file_path) } else { - close(kmodel_fd); + PrivClose(kmodel_fd); printf("read kmodel success \n"); } } @@ -186,16 +175,32 @@ void k210_detect(char *json_file_path) #endif // Load kmodel into kpu task +#ifdef ADD_RTTHREAD_FETURES if (kpu_load_kmodel(&detect_task, model_data_align) != 0) { printf("\nmodel init error\n"); - close(camera_fd); - close(kmodel_fd); + PrivClose(camera_fd); + PrivClose(kmodel_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); return; } +#else + struct PrivIoctlCfg kpu_cfg; + kpu_cfg.args = model_data_align; + kpu_cfg.ioctl_driver_type = KPU_TYPE; + if (PrivIoctl(kpu_fd,LOAD_KMODEL,&kpu_cfg) != 0) + { + printf("\nmodel init error\n"); + PrivClose(camera_fd); + PrivClose(kmodel_fd); + free(showbuffer); + free(kpurgbbuffer); + free(model_data); + return; + } +#endif detect_rl.anchor_number = ANCHOR_NUM; detect_rl.anchor = detect_params.anchor; @@ -226,7 +231,7 @@ void k210_detect(char *json_file_path) else { printf("thread_detect_entry failed! error code is %d\n", result); - close(camera_fd); + PrivClose(camera_fd); } } // #ifdef __RT_THREAD_H__ @@ -243,6 +248,15 @@ static void *thread_detect_entry(void *parameter) } LcdWriteParam graph_param; graph_param.type = LCD_DOT_TYPE; + for (int i = 0; i < LCD_SIZE; i++) + { + graph_param.pixel_info.pixel_color = (uint16_t *)showbuffer; + graph_param.pixel_info.x_startpos = 0; + graph_param.pixel_info.y_startpos = i; + graph_param.pixel_info.x_endpos = LCD_SIZE - 1; + graph_param.pixel_info.y_endpos = graph_param.pixel_info.y_startpos; + PrivWrite(lcd_fd, &graph_param, NULL_PARAMETER); + } #endif yolov2_params_t detect_params = *(yolov2_params_t *)parameter; @@ -262,7 +276,7 @@ static void *thread_detect_entry(void *parameter) { printf("ov2640 can't wait event flag"); free(showbuffer); - close(camera_fd); + PrivClose(camera_fd); pthread_exit(NULL); return NULL; } @@ -283,15 +297,29 @@ static void *thread_detect_entry(void *parameter) ; dmalock_release(dma_ch); #elif defined ADD_XIZI_FETURES - kpu_run_kmodel(&detect_task, kpurgbbuffer, dma_ch, ai_done, NULL); - while (!g_ai_done_flag) - ; + struct PrivIoctlCfg kpu_cfg; + kpu_cfg.args = kpurgbbuffer; + kpu_cfg.ioctl_driver_type = KPU_TYPE; + PrivIoctl(kpu_fd,RUN_KMODEL,&kpu_cfg); + + int wait_flag=0; + kpu_cfg.args = &wait_flag; + while (0==wait_flag){ + PrivIoctl(kpu_fd,WAIT_FLAG,&kpu_cfg); + } #endif +#ifdef ADD_RTTHREAD_FETURES float *output; size_t output_size; kpu_get_output(&detect_task, 0, (uint8_t **)&output, &output_size); detect_rl.input = output; +#else + KpuOutputBuffer output_buffer; + kpu_cfg.args = &output_buffer; + PrivIoctl(kpu_fd,GET_OUTPUT,&kpu_cfg); + detect_rl.input = (float*)(output_buffer.buffer); +#endif region_layer_run(&detect_rl, &detect_info); printf("detect_info.obj_number:%d\n", detect_info.obj_number); /* display result */ @@ -317,16 +345,11 @@ static void *thread_detect_entry(void *parameter) // refresh the LCD using photo of camera for (int i = 0; i < image_height; i++) { - graph_param.pixel_info.pixel_color = (uint16_t *)showbuffer + i * image_width; + graph_param.pixel_info.pixel_color = (uint16_t *)showbuffer + (image_height-i-1) * image_width; graph_param.pixel_info.x_startpos = (LCD_SIZE - image_width) / 2; graph_param.pixel_info.y_startpos = i + (LCD_SIZE - image_height) / 2; graph_param.pixel_info.x_endpos = LCD_SIZE - 1 - (LCD_SIZE - image_width) / 2; graph_param.pixel_info.y_endpos = graph_param.pixel_info.y_startpos; - // printf("refreshing screen: address[%08X] at row in %d\n",graph_param.pixel_info.pixel_color, graph_param.pixel_info.y_startpos); - // for(int j=0;jargs); break; default: diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.h b/APP_Framework/Framework/transform_layer/xizi/transform.h index c989c58dd..692c8083b 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.h +++ b/APP_Framework/Framework/transform_layer/xizi/transform.h @@ -151,6 +151,7 @@ enum IoctlDriverType WDT_TYPE, RTC_TYPE, CAMERA_TYPE, + KPU_TYPE, DEFAULT_TYPE, }; @@ -247,10 +248,16 @@ typedef struct }RgbAddress; enum TCP_OPTION { - SEND_DATA = 0, - RECV_DATA, + SEND_DATA = 0, + RECV_DATA, }; +typedef struct +{ + uint8_t *buffer; + size_t length; +}KpuOutputBuffer; + #define PRIV_SYSTICK_GET (CurrentTicksGain()) #define PRIV_LCD_DEV "/dev/lcd_dev" #define MY_DISP_HOR_RES BSP_LCD_Y_MAX @@ -275,6 +282,11 @@ enum TCP_OPTION { #define SET_AI_ADDR (0xD2) #define FLAG_CHECK (0xD4) +#define LOAD_KMODEL 0xA0 +#define RUN_KMODEL 0xA1 +#define GET_OUTPUT 0xA2 +#define WAIT_FLAG 0xA3 + #define IOCTRL_CAMERA_START_SHOT (22) // start shoot #define IOCTRL_CAMERA_OUT_SIZE_RESO (23) #define IOCTRL_CAMERA_SET_WINDOWS_SIZE (21) // user set specific windows outsize diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c index 1a76f26c6..bfa49afc1 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c @@ -48,6 +48,7 @@ Modification: #include "connect_w5500.h" #include "connect_wdt.h" #include "connect_dvp.h" +#include "connect_kpu.h" #include "dmac.h" #include "encoding.h" #include "fpioa.h" @@ -71,6 +72,7 @@ extern int HwSpiInit(void); extern int HwSoftSPIInit(void); extern int HwWiznetInit(void); extern int HwDvpInit(void); +extern int HwKpuInit(void); #include #ifdef MOUNT_USB @@ -221,6 +223,9 @@ struct InitSequenceDesc _board_init[] = { #endif #ifdef BSP_USING_CAMERA {"hw_camera", HwDvpInit }, +#endif +#ifdef BSP_USING_KPU + {"hw_kpu", HwKpuInit }, #endif { " NONE ",NONE }, }; diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_kpu.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_kpu.h new file mode 100644 index 000000000..6b4e828b2 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_kpu.h @@ -0,0 +1,41 @@ +/* +* 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. +*/ + +/** +* @file connect_dvp.h +* @brief define edu-riscv64-board DVP init function +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-11-21 +*/ +#ifndef CONNECT_DVP_H +#define CONNECT_DVP_H +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + uint8_t *buffer; + size_t length; +}KpuOutputBuffer; + + +int HwKpuInit(void); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig index 8b1378917..279af3459 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig @@ -1 +1,15 @@ +if BSP_USING_KPU + config KPU_DMA_CH + int "KPU DMA channel number" + default 5 + config KPU_BUS_NAME + string "kpu bus name" + default "kpu" + config KPU_DRV_NAME + string "kpu driver name" + default "kpu_drv" + config KPU_DEVICE_NAME + string "kpu device name" + default "kpu_dev" +endif diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile index cedabd673..3d79cd367 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile @@ -1,4 +1,4 @@ -SRC_FILES := kpu.c +SRC_FILES := kpu.c connect_kpu.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/connect_kpu.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/connect_kpu.c new file mode 100644 index 000000000..dc3366059 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/connect_kpu.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include "bsp.h" + +#define LOAD_KMODEL 0xA0 +#define RUN_KMODEL 0xA1 +#define GET_OUTPUT 0xA2 +#define WAIT_FLAG 0xA3 + +static kpu_model_context_t kpu_task; +static int g_ai_done_flag = 0; + +// irq interrupt function +static void ai_done(void *ctx) +{ + g_ai_done_flag = 1; +} + +struct KpuRegConfigureInfo +{ + uint8_t device_addr; + uint16_t reg_addr; + uint8_t reg_value; +}; + +static uint32 KpuDrvInit(void) +{ + x_err_t ret = EOK; + return ret; +} + +static uint32 KpuOpen(void *dev) +{ + x_err_t ret = EOK; + KpuDrvInit(); + return ret; +} + +static uint32 KpuClose(void *dev) +{ + x_err_t ret = EOK; + return ret; +} + +static uint32 KpuDrvConfigure(void *drv, struct BusConfigureInfo *args) +{ + x_err_t ret = EOK; + int cmd_type = args->configure_cmd; + KpuOutputBuffer* output_data; + switch (cmd_type) + { + case OPE_INT: + break; + case OPE_CFG: + break; + case LOAD_KMODEL: + kpu_load_kmodel(&kpu_task, args->private_data); + break; + case RUN_KMODEL: + g_ai_done_flag=0; + kpu_run_kmodel(&kpu_task, args->private_data, KPU_DMA_CH, ai_done, NULL); + break; + case GET_OUTPUT: + output_data = (KpuOutputBuffer*)args->private_data; + kpu_get_output(&kpu_task, 0, (uint8_t **)&(output_data->buffer), &(output_data->length)); + break; + case WAIT_FLAG: + *((uint8_t*)(args->private_data)) = g_ai_done_flag; + break; + default: + break; + } + return ret; +} + +/*manage the kpu device operations*/ +static const struct KpuDevDone kpu_dev_done = +{ + .dev_open = KpuOpen, + .dev_close = KpuClose, + .dev_write = NONE, + .dev_read = NONE, +}; + +/*Init kpu bus*/ +static int BoardKpuBusInit(struct KpuBus *kpu_bus, struct KpuDriver *kpu_driver) +{ + x_err_t ret = EOK; + + /*Init the kpu bus */ + kpu_bus->private_data = (void *)&kpu_dev_done; + ret = KpuBusInit(kpu_bus, KPU_BUS_NAME); + if (EOK != ret) + { + KPrintf("board_kpu_init KpuBusInit error %d\n", ret); + return ERROR; + } + + /*Init the kpu driver*/ + kpu_driver->private_data = (void *)&kpu_dev_done; + ret = KpuDriverInit(kpu_driver, KPU_DRV_NAME); + if (EOK != ret) + { + KPrintf("board_kpu_init KpuDriverInit error %d\n", ret); + return ERROR; + } + + /*Attach the kpu driver to the kpu bus*/ + ret = KpuDriverAttachToBus(KPU_DRV_NAME, KPU_BUS_NAME); + if (EOK != ret) + { + KPrintf("board_kpu_init KpuDriverAttachToBus error %d\n", ret); + return ERROR; + } + + return ret; +} + +/*Attach the kpu device to the kpu bus*/ +static int BoardKpuDevBend(void) +{ + x_err_t ret = EOK; + static struct KpuHardwareDevice kpu_device; + memset(&kpu_device, 0, sizeof(struct KpuHardwareDevice)); + + kpu_device.kpu_dev_done = &kpu_dev_done; + + ret = KpuDeviceRegister(&kpu_device, NONE, KPU_DEVICE_NAME); + if (EOK != ret) + { + KPrintf("board_kpu_init KpuDeviceInit device %s error %d\n", KPU_DEVICE_NAME, ret); + return ERROR; + } + + ret = KpuDeviceAttachToBus(KPU_DEVICE_NAME, KPU_BUS_NAME); + if (EOK != ret) + { + KPrintf("board_kpu_init KpuDeviceAttachToBus device %s error %d\n", KPU_DEVICE_NAME, ret); + return ERROR; + } + + return ret; +} + +int HwKpuInit(void) +{ + x_err_t ret = EOK; + static struct KpuBus kpu_bus; + memset(&kpu_bus, 0, sizeof(struct KpuBus)); + + static struct KpuDriver kpu_driver; + memset(&kpu_driver, 0, sizeof(struct KpuDriver)); + + kpu_driver.configure = KpuDrvConfigure; + ret = BoardKpuBusInit(&kpu_bus, &kpu_driver); + if (EOK != ret) + { + KPrintf("board_kpu_Init error ret %u\n", ret); + return ERROR; + } + + ret = BoardKpuDevBend(); + if (EOK != ret) + { + KPrintf("board_kpu_Init error ret %u\n", ret); + return ERROR; + } + return ret; +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/resources/Kconfig b/Ubiquitous/XiZi_IIoT/resources/Kconfig index c8119869a..4e143e847 100644 --- a/Ubiquitous/XiZi_IIoT/resources/Kconfig +++ b/Ubiquitous/XiZi_IIoT/resources/Kconfig @@ -169,3 +169,9 @@ if BSP_USING_CAMERA bool "Using Camera bus drivers" default n endif + +if BSP_USING_KPU + config RESOURCES_KPU + bool "Using Kpu bus drivers" + default n +endif diff --git a/Ubiquitous/XiZi_IIoT/resources/Makefile b/Ubiquitous/XiZi_IIoT/resources/Makefile index 833c982f2..3ac83f7d5 100644 --- a/Ubiquitous/XiZi_IIoT/resources/Makefile +++ b/Ubiquitous/XiZi_IIoT/resources/Makefile @@ -69,4 +69,8 @@ ifeq ($(CONFIG_RESOURCES_CAMERA),y) SRC_DIR += camera endif +ifeq ($(CONFIG_RESOURCES_KPU),y) + SRC_DIR += kpu +endif + include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/resources/include/bus.h b/Ubiquitous/XiZi_IIoT/resources/include/bus.h index c0f65c4a7..557fb977c 100644 --- a/Ubiquitous/XiZi_IIoT/resources/include/bus.h +++ b/Ubiquitous/XiZi_IIoT/resources/include/bus.h @@ -55,6 +55,7 @@ enum BusType_e TYPE_ADC_BUS, TYPE_DAC_BUS, TYPE_CAMERA_BUS, + TYPE_KPU_BUS, TYPE_BUS_END, }; @@ -82,6 +83,7 @@ enum DevType TYPE_ADC_DEV, TYPE_DAC_DEV, TYPE_CAMERA_DEV, + TYPE_KPU_DEV, TYPE_DEV_END, }; @@ -109,6 +111,7 @@ enum DriverType_e TYPE_ADC_DRV, TYPE_DAC_DRV, TYPE_CAMERA_DRV, + TYPE_KPU_DRV, TYPE_DRV_END, }; diff --git a/Ubiquitous/XiZi_IIoT/resources/include/bus_kpu.h b/Ubiquitous/XiZi_IIoT/resources/include/bus_kpu.h new file mode 100644 index 000000000..1ce2e21e5 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/include/bus_kpu.h @@ -0,0 +1,69 @@ +/* +* 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. +*/ + +/** +* @file bus_kpu.h +* @brief define kpu bus and drv function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-12-19 +*/ + +#ifndef BUS_KPU_H +#define BUS_KPU_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +struct KpuDriver +{ + struct Driver driver; + + uint32 (*configure) (void *drv, struct BusConfigureInfo *configure_info); + + void *private_data; +}; + +struct KpuBus +{ + struct Bus bus; + + void *private_data; +}; + +/*Register the KPU bus*/ +int KpuBusInit(struct KpuBus *kpu_bus, const char *bus_name); + +/*Register the KPU driver*/ +int KpuDriverInit(struct KpuDriver *kpu_driver, const char *driver_name); + +/*Release the KPU device*/ +int KpuReleaseBus(struct KpuBus *kpu_bus); + +/*Register the KPU driver to the KPU bus*/ +int KpuDriverAttachToBus(const char *drv_name, const char *bus_name); + +/*Register the driver, manage with the double linklist*/ +int KpuDriverRegister(struct Driver *driver); + +/*Find the register driver*/ +DriverType KpuDriverFind(const char *drv_name, enum DriverType_e drv_type); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/resources/include/dev_kpu.h b/Ubiquitous/XiZi_IIoT/resources/include/dev_kpu.h new file mode 100644 index 000000000..b6a4a895e --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/include/dev_kpu.h @@ -0,0 +1,69 @@ +/* +* 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. +*/ + +/** +* @file dev_kpu.h +* @brief define kpu dev function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-12-19 +*/ + +#ifndef DEV_KPU_H +#define DEV_KPU_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +struct KpuDataStandard +{ + uint16 addr; + uint16 flags; + uint16 len; + uint16 retries; + uint8 *buf; + + struct KpuDataStandard *next; +}; + +struct KpuDevDone +{ + uint32 (*dev_open) (void *kpu_device); + uint32 (*dev_close) (void *kpu_device); + uint32 (*dev_write) (void *kpu_device, struct BusBlockWriteParam *msg); + uint32 (*dev_read) (void *kpu_device, struct BusBlockReadParam *msg); +}; + +struct KpuHardwareDevice +{ + struct HardwareDev haldev; + const struct KpuDevDone *kpu_dev_done; +}; + +/*Register the KPU device*/ +int KpuDeviceRegister(struct KpuHardwareDevice *kpu_device, void *kpu_param, const char *device_name); + +/*Register the KPU device to the KPU bus*/ +int KpuDeviceAttachToBus(const char *dev_name, const char *bus_name); + +/*Find the register KPU device*/ +HardwareDevType KpuDeviceFind(const char *dev_name, enum DevType dev_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/resources/include/device.h b/Ubiquitous/XiZi_IIoT/resources/include/device.h index fc4540f75..a73e64bb4 100644 --- a/Ubiquitous/XiZi_IIoT/resources/include/device.h +++ b/Ubiquitous/XiZi_IIoT/resources/include/device.h @@ -111,4 +111,9 @@ HardwareDevType ObtainConsole(void); #include #endif +#ifdef RESOURCES_KPU +#include +#include +#endif + #endif diff --git a/Ubiquitous/XiZi_IIoT/resources/kpu/Makefile b/Ubiquitous/XiZi_IIoT/resources/kpu/Makefile new file mode 100644 index 000000000..a0905642c --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/kpu/Makefile @@ -0,0 +1,5 @@ +SRC_FILES += dev_kpu.c drv_kpu.c bus_kpu.c + + + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/resources/kpu/bus_kpu.c b/Ubiquitous/XiZi_IIoT/resources/kpu/bus_kpu.c new file mode 100644 index 000000000..58f2bef0e --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/kpu/bus_kpu.c @@ -0,0 +1,123 @@ +/* +* 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. +*/ + +/** +* @file bus_kpu.c +* @brief register kpu bus function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-12-19 +*/ + +#include +#include + +/*Register the KPU BUS*/ +int KpuBusInit(struct KpuBus *kpu_bus, const char *bus_name) +{ + NULL_PARAM_CHECK(kpu_bus); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + if (BUS_INSTALL != kpu_bus->bus.bus_state) { + strncpy(kpu_bus->bus.bus_name, bus_name, NAME_NUM_MAX); + + kpu_bus->bus.bus_type = TYPE_KPU_BUS; + kpu_bus->bus.bus_state = BUS_INSTALL; + kpu_bus->bus.private_data = kpu_bus->private_data; + + ret = BusRegister(&kpu_bus->bus); + if (EOK != ret) { + KPrintf("KpuBusInit BusRegister error %u\n", ret); + return ret; + } + } else { + KPrintf("KpuBusInit BusRegister bus has been register state%u\n", kpu_bus->bus.bus_state); + } + + return ret; +} + +/*Register the KPU Driver*/ +int KpuDriverInit(struct KpuDriver *kpu_driver, const char *driver_name) +{ + NULL_PARAM_CHECK(kpu_driver); + NULL_PARAM_CHECK(driver_name); + + x_err_t ret = EOK; + + if (DRV_INSTALL != kpu_driver->driver.driver_state) { + kpu_driver->driver.driver_type = TYPE_KPU_DRV; + kpu_driver->driver.driver_state = DRV_INSTALL; + + strncpy(kpu_driver->driver.drv_name, driver_name, NAME_NUM_MAX); + + kpu_driver->driver.private_data = kpu_driver->private_data; + + kpu_driver->driver.configure = kpu_driver->configure; + + ret = KpuDriverRegister(&kpu_driver->driver); + if (EOK != ret) { + KPrintf("KpuDriverInit DriverRegister error %u\n", ret); + return ret; + } + } else { + KPrintf("KpuDriverInit DriverRegister driver has been register state%u\n", kpu_driver->driver.driver_state); + } + + return ret; +} + +/*Release the KPU device*/ +int KpuReleaseBus(struct KpuBus *kpu_bus) +{ + NULL_PARAM_CHECK(kpu_bus); + + return BusRelease(&kpu_bus->bus); +} + +/*Register the KPU Driver to the KPU BUS*/ +int KpuDriverAttachToBus(const char *drv_name, const char *bus_name) +{ + NULL_PARAM_CHECK(drv_name); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + struct Bus *bus; + struct Driver *driver; + + bus = BusFind(bus_name); + if (NONE == bus) { + KPrintf("KpuDriverAttachToBus find kpu bus error!name %s\n", bus_name); + return ERROR; + } + + if (TYPE_KPU_BUS == bus->bus_type) { + driver = KpuDriverFind(drv_name, TYPE_KPU_DRV); + if (NONE == driver) { + KPrintf("KpuDriverAttachToBus find kpu driver error!name %s\n", drv_name); + return ERROR; + } + + if (TYPE_KPU_DRV == driver->driver_type) { + ret = DriverRegisterToBus(bus, driver); + if (EOK != ret) { + KPrintf("KpuDriverAttachToBus DriverRegisterToBus error %u\n", ret); + return ERROR; + } + } + } + + return ret; +} diff --git a/Ubiquitous/XiZi_IIoT/resources/kpu/dev_kpu.c b/Ubiquitous/XiZi_IIoT/resources/kpu/dev_kpu.c new file mode 100644 index 000000000..acbe17909 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/kpu/dev_kpu.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2006-03-13 bernard first version + * 2012-05-15 lgnq modified according bernard's implementation. + * 2012-05-28 bernard code cleanup + * 2012-11-23 bernard fix compiler warning. + * 2013-02-20 bernard use RT_KPU_RB_BUFSZ to define + * the size of ring buffer. + * 2014-07-10 bernard rewrite kpu framework + * 2014-12-31 bernard use open_flag for poll_tx stream mode. + * 2015-05-19 Quintin fix DMA tx mod tx_dma->activated flag !=RT_FALSE BUG + * in open function. + * 2015-11-10 bernard fix the poll rx issue when there is no data. + * 2016-05-10 armink add fifo mode to DMA rx when kpu->config.bufsz != 0. + * 2017-01-19 aubr.cool prevent change kpu rx bufsz when kpu is opened. + * 2017-11-07 JasonJia fix data bits error issue when using tcsetattr. + * 2017-11-15 JasonJia fix poll rx issue when data is full. + * add TCFLSH and FIONREAD support. + * 2018-12-08 Ernest Chen add DMA choice + * 2020-09-14 WillianChan add a line feed to the carriage return character + * when using interrupt tx + */ + +/** +* @file dev_kpu.c +* @brief register kpu dev function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-12-19 +*/ + +/************************************************* +File name: dev_kpu.c +Description: support kpu dev INT and DMA configure、transfer data +Others: take RT-Thread v4.0.2/components/driver/kpu/kpu.c for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2021-04-24 +Author: AIIT XUOS Lab +Modification: +1. support kpu dev register, configure, write and read +2. add bus driver framework support, include INT and DMA mode +*************************************************/ + +#include +#include + +static DoubleLinklistType kpudev_linklist; + +static uint32 KpuDevOpen(void *dev) +{ + NULL_PARAM_CHECK(dev); + + x_err_t ret = EOK; + struct KpuHardwareDevice *kpu_dev = (struct KpuHardwareDevice *)dev; + + ret = kpu_dev->kpu_dev_done->dev_open(dev); + + return EOK; +} + +static uint32 KpuDevClose(void *dev) +{ + NULL_PARAM_CHECK(dev); + + x_err_t ret = EOK; + struct KpuHardwareDevice *kpu_dev = (struct KpuHardwareDevice *)dev; + + ret = kpu_dev->kpu_dev_done->dev_close(dev); + return EOK; +} + +static uint32 KpuDevWrite(void *dev, struct BusBlockWriteParam *write_param) +{ + NULL_PARAM_CHECK(dev); + NULL_PARAM_CHECK(write_param); + + x_err_t ret = EOK; + + struct KpuHardwareDevice *kpu_dev = (struct KpuHardwareDevice *)dev; + ret = kpu_dev->kpu_dev_done->dev_write(dev,write_param); + + return ret; +} + +static uint32 KpuDevRead(void *dev, struct BusBlockReadParam *read_param) +{ + NULL_PARAM_CHECK(dev); + NULL_PARAM_CHECK(read_param); + + x_err_t ret = EOK; + + struct KpuHardwareDevice *kpu_dev = (struct KpuHardwareDevice *)dev; + ret = kpu_dev->kpu_dev_done->dev_read(dev,read_param); + + return EOK; +} + + +static const struct HalDevDone dev_done = +{ + .open = KpuDevOpen, + .close = KpuDevClose, + .write = KpuDevWrite, + .read = KpuDevRead, +}; + +/*Create the kpu device linklist*/ +static void KpuDeviceLinkInit() +{ + InitDoubleLinkList(&kpudev_linklist); +} + +HardwareDevType KpuDeviceFind(const char *dev_name, enum DevType dev_type) +{ + NULL_PARAM_CHECK(dev_name); + + struct HardwareDev *device = NONE; + + DoubleLinklistType *node = NONE; + DoubleLinklistType *head = &kpudev_linklist; + + for (node = head->node_next; node != head; node = node->node_next) { + device = SYS_DOUBLE_LINKLIST_ENTRY(node, struct HardwareDev, dev_link); + if ((!strcmp(device->dev_name, dev_name)) && (dev_type == device->dev_type)) { + return device; + } + } + + KPrintf("KpuDeviceFind cannot find the %s device.return NULL\n", dev_name); + return NONE; +} + +int KpuDeviceRegister(struct KpuHardwareDevice *kpu_device, void *kpu_param, const char *device_name) +{ + NULL_PARAM_CHECK(kpu_device); + NULL_PARAM_CHECK(device_name); + + x_err_t ret = EOK; + static x_bool dev_link_flag = RET_FALSE; + + if (!dev_link_flag) { + KpuDeviceLinkInit(); + dev_link_flag = RET_TRUE; + } + + if (DEV_INSTALL != kpu_device->haldev.dev_state) { + strncpy(kpu_device->haldev.dev_name, device_name, NAME_NUM_MAX); + kpu_device->haldev.dev_type = TYPE_KPU_DEV; + kpu_device->haldev.dev_state = DEV_INSTALL; + kpu_device->haldev.dev_done = (struct HalDevDone *)&dev_done; + + + DoubleLinkListInsertNodeAfter(&kpudev_linklist, &(kpu_device->haldev.dev_link)); + } else { + KPrintf("KpuDeviceRegister device has been register state%u\n", kpu_device->haldev.dev_state); + } + + return ret; +} + +int KpuDeviceAttachToBus(const char *dev_name, const char *bus_name) +{ + NULL_PARAM_CHECK(dev_name); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + struct Bus *bus; + struct HardwareDev *device; + + bus = BusFind(bus_name); + if (NONE == bus) { + KPrintf("KpuDeviceAttachToBus find kpu bus error!name %s\n", bus_name); + return ERROR; + } + + if (TYPE_KPU_BUS == bus->bus_type) { + device = KpuDeviceFind(dev_name, TYPE_KPU_DEV); + if (NONE == device) { + KPrintf("KpuDeviceAttachToBus find kpu device error!name %s\n", dev_name); + return ERROR; + } + + if (TYPE_KPU_DEV == device->dev_type) { + ret = DeviceRegisterToBus(bus, device); + if (EOK != ret) { + KPrintf("KpuDeviceAttachToBus DeviceRegisterToBus error %u\n", ret); + return ERROR; + } + } + } + + return EOK; +} diff --git a/Ubiquitous/XiZi_IIoT/resources/kpu/drv_kpu.c b/Ubiquitous/XiZi_IIoT/resources/kpu/drv_kpu.c new file mode 100644 index 000000000..6ed1f0738 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/kpu/drv_kpu.c @@ -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. +*/ + +/** +* @file drv_kpu.c +* @brief register kpu drv function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-12-19 +*/ + +#include +#include + +static DoubleLinklistType kpu_drv_linklist; + +/*Create the driver linklist*/ +static void KpuDrvLinkInit() +{ + InitDoubleLinkList(&kpu_drv_linklist); +} + +DriverType KpuDriverFind(const char *drv_name, enum DriverType_e drv_type) +{ + NULL_PARAM_CHECK(drv_name); + + struct Driver *driver = NONE; + + DoubleLinklistType *node = NONE; + DoubleLinklistType *head = &kpu_drv_linklist; + + for (node = head->node_next; node != head; node = node->node_next) { + driver = SYS_DOUBLE_LINKLIST_ENTRY(node, struct Driver, driver_link); + + if ((!strcmp(driver->drv_name, drv_name)) && (drv_type == driver->driver_type)) { + return driver; + } + } + + KPrintf("KpuDriverFind cannot find the %s driver.return NULL\n", drv_name); + return NONE; +} + +int KpuDriverRegister(struct Driver *driver) +{ + NULL_PARAM_CHECK(driver); + + x_err_t ret = EOK; + static x_bool driver_link_flag = RET_FALSE; + + if (!driver_link_flag) { + KpuDrvLinkInit(); + driver_link_flag = RET_TRUE; + } + + DoubleLinkListInsertNodeAfter(&kpu_drv_linklist, &(driver->driver_link)); + + return ret; +} From 27cc89bcef34678f72874d6400b34079aa14bdb4 Mon Sep 17 00:00:00 2001 From: WuZheng Date: Mon, 19 Dec 2022 14:24:35 +0800 Subject: [PATCH 17/33] update readme.md for know framwork --- .../knowing/kpu/k210_yolov2_detect_procedure/Readme.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md index 7b04a9288..3ca0ceec6 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md @@ -30,5 +30,6 @@ int main(void) ## TODO -* KPU drivers are still not completed, because it is undefined how to reisgter KPU's bus and device name in XIZI system. The framework is still directly using the SDK From Canaan Inc. But after the driver completed, it will be easy to adapt framework for the APIs. -* Camera and LCD drivers between RT and XIZI are not completely compatible. So there are some marcos like `ifdef` to make the framework compatible for both systems. +* KPU drivers and frameworks are still not completed, because it is undefined how to reisgter KPU's bus and device name in rt-fusion system. The framework is still directly using the SDK with *ifdef* From Canaan Inc. But after the driver completed, it will be easy to adapt framework for the APIs. +* Camera and LCD drivers between RT and XIZI are not completely compatible. So there are some marcos like *ifdef* to make the framework compatible for both systems. +* After completed, all codes from kernel in knowing framework should be posix interfaces,like *PrivOpen*、*PrivIoctrl*、*PrivRead*. From 4f7f98b0e9dfac43b7fa638f020bce4c66966b5f Mon Sep 17 00:00:00 2001 From: Wang_Weigen Date: Mon, 19 Dec 2022 16:33:25 +0800 Subject: [PATCH 18/33] add armv7-a start file --- .../hardkernel/abstraction/interrupt.c | 45 ++++ .../arch/arm/armv7-a/cortex-a7/boot.S | 87 +++++++ .../arch/arm/armv7-a/cortex-a7/exception.S | 66 +++++ .../arch/arm/armv7-a/cortex-a9/boot.S | 89 +++++++ .../arch/arm/armv7-a/cortex-a9/exception.S | 66 +++++ .../arch/arm/armv7-a/cortex-a9/gic.c | 243 ++++++++++++++++++ .../arm/armv7-a/cortex-a9/gic_registers.h | 140 ++++++++++ .../XiZi_IIoT/board/imxrt1176-sbc/link.lds | 2 +- 8 files changed, 737 insertions(+), 1 deletion(-) create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic.c create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic_registers.h diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/interrupt.c b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/interrupt.c index e69de29bb..2d44ea94b 100755 --- a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/interrupt.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/interrupt.c @@ -0,0 +1,45 @@ +extern void _svcall(uintptr_t* contex); + +x_base __attribute__((naked)) DisableLocalInterrupt() +{ + +} + +void __attribute__((naked)) EnableLocalInterrupt(x_base level) +{ + +} + +int32 ArchEnableHwIrq(uint32_t irq_num) +{ + + return EOK; +} + +int32 ArchDisableHwIrq(uint32_t irq_num) +{ + return EOK; +} + +extern void KTaskOsAssignAfterIrq(void *context); + +void IsrEntry() +{ + uint32_t ipsr; + + // __asm__ volatile("MRS %0, IPSR" : "=r"(ipsr)); + + isrManager.done->incCounter(); + isrManager.done->handleIrq(ipsr); + KTaskOsAssignAfterIrq(NONE); + isrManager.done->decCounter(); + +} + +uintptr_t *Svcall(unsigned int ipsr, uintptr_t* contex ) +{ +#ifdef TASK_ISOLATION + _svcall(contex); +#endif + return contex; +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a7/boot.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a7/boot.S index e69de29bb..95fdb6a2a 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a7/boot.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a7/boot.S @@ -0,0 +1,87 @@ + +.equ Mode_USR, 0x10 +.equ Mode_FIQ, 0x11 +.equ Mode_IRQ, 0x12 +.equ Mode_SVC, 0x13 +.equ Mode_ABT, 0x17 +.equ Mode_UND, 0x1B +.equ Mode_SYS, 0x1F + +.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled +.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled + +.equ STACK_SIZE, 0x00000100 + +.globl _start + +_start: + /* set the cpu to SVC32 mode and disable interrupt */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0x13 + msr cpsr_c, r0 + + mrc p15, 0, r0, c1, c0, 0 + bic r0, #(1 << 12) /* i cache */ + bic r0, #(1 << 2) /* d cache */ + bic r0, #(1 << 0) /* mmu */ + mcr p15, 0, r0, c1, c0, 0 + + ldr r0, =stack_top + + @ Set the startup stack for svc + mov sp, r0 + + @ Enter Undefined Instruction Mode and set its Stack Pointer + msr cpsr_c, #Mode_UND|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #STACK_SIZE + + @ Enter Abort Mode and set its Stack Pointer + msr cpsr_c, #Mode_ABT|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #STACK_SIZE + + @ Enter FIQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #STACK_SIZE + + @ Enter IRQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #STACK_SIZE + + /* come back to SVC mode */ + msr cpsr_c, #Mode_SVC|I_Bit|F_Bit + + /* clear .bss */ + mov r0, #0 /* get a zero */ + ldr r1,=BSS_START /* bss start */ + ldr r2,=BSS_END /* bss end */ + +bss_loop: + cmp r1,r2 /* check if data to clear */ + strlo r0,[r1],#4 /* clear 4 bytes */ + blo bss_loop /* loop until done */ + + /* call C++ constructors of global objects */ + ldr r0, =__ctors_start__ + ldr r1, =__ctors_end__ +bss_end: + +ctor_loop: + cmp r0, r1 + beq ctor_end + ldr r2, [r0], #4 + stmfd sp!, {r0-r1} + mov lr, pc + bx r2 + ldmfd sp!, {r0-r1} + b ctor_loop +ctor_end: + + bl start_kernel + +_loop_here: + b _loop_here \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a7/exception.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a7/exception.S index e69de29bb..c1c7f5a90 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a7/exception.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a7/exception.S @@ -0,0 +1,66 @@ +.section .vectors, "ax" +.code 32 + +.globl ExceptionVectors +ExceptionVectors: + ldr pc, _ResetException + ldr pc, _UndefInstrException + ldr pc, _SwiException + ldr pc, _PrefetchAbortException + ldr pc, _DataAbortAbortException + ldr pc, _ResvException + ldr pc, _IrqException + ldr pc, _FiqException + +.globl Reset_Handler +.globl UndefInstrExceptionHandle +.globl SwiExceptionHandle +.globl PrefetchAbortExceptionHandle +.globl DataAbortExceptionHandle +.globl ResvExceptionHandle +.globl ExceptionIsrEntry +.globl FiqExceptionHandle + +_ResetException: + .word Reset_Handler +_UndefInstrException: + .word UndefInstrExceptionHandle +_SwiException: + .word SwiExceptionHandle +_PrefetchAbortException: + .word PrefetchAbortExceptionHandle +_DataAbortAbortException: + .word DataAbortExceptionHandle +_ResvException: + .word ResvExceptionHandle +_IrqException: + .word ExceptionIsrEntry +_FiqException: + .word FiqExceptionHandle + +.globl _start +Reset_Handler: + b _start + +UndefInstrExceptionHandle: + b UndefInstrIsrEntry + +SwiExceptionHandle: + b SvcIsrEntry + +PrefetchAbortExceptionHandle: + b PrefetchAbortIsrEntry + +DataAbortExceptionHandle: + b UndefInstrIsrEntry + +ResvExceptionHandle: + b DataAbortIsrEntry + +ExceptionIsrEntry: + stmfd sp!, {r0-r12,lr} + + bl IsrEntry + +FiqExceptionHandle: + b FiqIsrEntry diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S index e69de29bb..7d4d0da8d 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S @@ -0,0 +1,89 @@ + +.equ Mode_USR, 0x10 +.equ Mode_FIQ, 0x11 +.equ Mode_IRQ, 0x12 +.equ Mode_SVC, 0x13 +.equ Mode_ABT, 0x17 +.equ Mode_UND, 0x1B +.equ Mode_SYS, 0x1F + +.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled +.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled + +.equ STACK_SIZE, 0x00000100 + +.globl _start + +_start: + + /* set the cpu to SVC32 mode and disable interrupt */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0x13 + msr cpsr_c, r0 + + /* disable i/d cache mmu*/ + mrc p15, 0, r0, c1, c0, 0 + bic r0, #(1 << 12) /* i cache */ + bic r0, #(1 << 2) /* d cache */ + bic r0, #(1 << 0) /* mmu */ + mcr p15, 0, r0, c1, c0, 0 + + ldr r0, =stack_top + + @ Set the startup stack for svc + mov sp, r0 + + @ Enter Undefined Instruction Mode and set its Stack Pointer + msr cpsr_c, #Mode_UND|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #STACK_SIZE + + @ Enter Abort Mode and set its Stack Pointer + msr cpsr_c, #Mode_ABT|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #STACK_SIZE + + @ Enter FIQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #STACK_SIZE + + @ Enter IRQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #STACK_SIZE + + /* come back to SVC mode */ + msr cpsr_c, #Mode_SVC|I_Bit|F_Bit + + /* clear .bss */ + mov r0, #0 /* get a zero */ + ldr r1,=BSS_START /* bss start */ + ldr r2,=BSS_END /* bss end */ + +bss_loop: + cmp r1,r2 /* check if data to clear */ + strlo r0,[r1],#4 /* clear 4 bytes */ + blo bss_loop /* loop until done */ + + /* call C++ constructors of global objects */ + ldr r0, =__ctors_start__ + ldr r1, =__ctors_end__ +bss_end: + +ctor_loop: + cmp r0, r1 + beq ctor_end + ldr r2, [r0], #4 + stmfd sp!, {r0-r1} + mov lr, pc + bx r2 + ldmfd sp!, {r0-r1} + b ctor_loop +ctor_end: + + bl start_kernel + +_loop_here: + b _loop_here \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S new file mode 100644 index 000000000..7f52ee1ee --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S @@ -0,0 +1,66 @@ +.section .vectors, "ax" +.code 32 + +.globl ExceptionVectors +ExceptionVectors: + ldr pc, _ResetException + ldr pc, _UndefInstrException + ldr pc, _SwiException + ldr pc, _PrefetchAbortException + ldr pc, _DataAbortAbortException + ldr pc, _ResvException + ldr pc, _IrqException + ldr pc, _FiqException + +.globl Reset_Handler +.globl UndefInstrExceptionHandle +.globl SwiExceptionHandle +.globl PrefetchAbortExceptionHandle +.globl DataAbortExceptionHandle +.globl ResvExceptionHandle +.globl ExceptionIsrEntry +.globl FiqExceptionHandle + +_ResetException: + .word Reset_Handler +_UndefInstrException: + .word UndefInstrExceptionHandle +_SwiException: + .word SwiExceptionHandle +_PrefetchAbortException: + .word PrefetchAbortExceptionHandle +_DataAbortAbortException: + .word DataAbortExceptionHandle +_ResvException: + .word ResvExceptionHandle +_IrqException: + .word ExceptionIsrEntry +_FiqException: + .word FiqExceptionHandle + +.globl _start +Reset_Handler: + b _start + +UndefInstrExceptionHandle: + b UndefInstrIsrEntry + +SwiExceptionHandle: + b SvcIsrEntry + +PrefetchAbortExceptionHandle: + b PrefetchAbortIsrEntry + +DataAbortExceptionHandle: + b DataAbortIsrEntry + +ResvExceptionHandle: + b ResvIsrEntry + +ExceptionIsrEntry: + stmfd sp!, {r0-r12,lr} + + b IsrEntry + +FiqExceptionHandle: + b FiqIsrEntry diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic.c b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic.c new file mode 100644 index 000000000..5249d76e4 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include "core/gic.h" +#include "gic_registers.h" +#include "core/cortex_a9.h" + +//////////////////////////////////////////////////////////////////////////////// +// Prototypes +//////////////////////////////////////////////////////////////////////////////// + +static inline gicd_t * gic_get_gicd(void); +static inline gicc_t * gic_get_gicc(void); +static inline uint32_t irq_get_register_offset(uint32_t irqID); +static inline uint32_t irq_get_bit_offset(uint32_t irqID); +static inline uint32_t irq_get_bit_mask(uint32_t irqID); + +//////////////////////////////////////////////////////////////////////////////// +// Code +//////////////////////////////////////////////////////////////////////////////// + +static inline gicd_t * gic_get_gicd(void) +{ + uint32_t base = get_arm_private_peripheral_base() + kGICDBaseOffset; + return (gicd_t *)base; +} + +static inline gicc_t * gic_get_gicc(void) +{ + uint32_t base = get_arm_private_peripheral_base() + kGICCBaseOffset; + return (gicc_t *)base; +} + +static inline uint32_t irq_get_register_offset(uint32_t irqID) +{ + return irqID / 32; +} + +static inline uint32_t irq_get_bit_offset(uint32_t irqID) +{ + return irqID & 0x1f; +} + +static inline uint32_t irq_get_bit_mask(uint32_t irqID) +{ + return 1 << irq_get_bit_offset(irqID); +} + +void gic_enable(bool enableIt) +{ + gicd_t * gicd = gic_get_gicd(); + + if (enableIt) + { + // Enable both secure and non-secure. + gicd->CTLR |= kBM_GICD_CTLR_EnableGrp0 | kBM_GICD_CTLR_EnableGrp1; + } + else + { + // Clear the enable bits. + gicd->CTLR &= ~(kBM_GICD_CTLR_EnableGrp0 | kBM_GICD_CTLR_EnableGrp1); + } +} + +void gic_set_irq_security(uint32_t irqID, bool isSecure) +{ + gicd_t * gicd = gic_get_gicd(); + + uint32_t reg = irq_get_register_offset(irqID); + uint32_t mask = irq_get_bit_mask(irqID); + + uint32_t value = gicd->IGROUPRn[reg]; + if (!isSecure) + { + value &= ~mask; + } + else + { + value |= mask; + } + gicd->IGROUPRn[reg] = value; +} + +void gic_enable_irq(uint32_t irqID, bool isEnabled) +{ + gicd_t * gicd = gic_get_gicd(); + + uint32_t reg = irq_get_register_offset(irqID); + uint32_t mask = irq_get_bit_mask(irqID); + + // Select set-enable or clear-enable register based on enable flag. + if (isEnabled) + { + gicd->ISENABLERn[reg] = mask; + } + else + { + gicd->ICENABLERn[reg] = mask; + } +} + +void gic_set_irq_priority(uint32_t ID, uint32_t priority) +{ + gicd_t * gicd = gic_get_gicd(); + + // Update the priority register. The priority registers are byte accessible, and the register + // struct has the priority registers as a byte array, so we can just index directly by the + // interrupt ID. + gicd->IPRIORITYRn[ID] = priority & 0xff; +} + +void gic_set_cpu_target(uint32_t irqID, unsigned cpuNumber, bool enableIt) +{ + // Make sure the CPU number is valid. + assert(cpuNumber <= 7); + + gicd_t * gicd = gic_get_gicd(); + uint8_t cpuMask = 1 << cpuNumber; + + // Like the priority registers, the target registers are byte accessible, and the register + // struct has the them as a byte array, so we can just index directly by the + // interrupt ID. + if (enableIt) + { + gicd->ITARGETSRn[irqID] |= (cpuMask & 0xff); + } + else + { + gicd->ITARGETSRn[irqID] &= ~(cpuMask & 0xff); + } +} + +void gic_send_sgi(uint32_t irqID, uint32_t target_list, uint32_t filter_list) +{ + gicd_t * gicd = gic_get_gicd(); + + gicd->SGIR = (filter_list << kBP_GICD_SGIR_TargetListFilter) + | (target_list << kBP_GICD_SGIR_CPUTargetList) + | (irqID & 0xf); +} + +void gic_cpu_enable(bool enableIt) +{ + gicc_t * gicc = gic_get_gicc(); + + if (enableIt) + { + gicc->CTLR |= kBM_GICC_CTLR_EnableS | kBM_GICC_CTLR_EnableNS; + } + else + { + gicc->CTLR &= ~(kBM_GICC_CTLR_EnableS | kBM_GICC_CTLR_EnableNS); + } +} + +void gic_set_cpu_priority_mask(uint32_t priority) +{ + gicc_t * gicc = gic_get_gicc(); + gicc->PMR = priority & 0xff; +} + +uint32_t gic_read_irq_ack(void) +{ + gicc_t * gicc = gic_get_gicc(); + return gicc->IAR; +} + +void gic_write_end_of_irq(uint32_t irqID) +{ + gicc_t * gicc = gic_get_gicc(); + gicc->EOIR = irqID; +} + +void gic_init(void) +{ + gicd_t * gicd = gic_get_gicd(); + + // First disable the distributor. + gic_enable(false); + + // Clear all pending interrupts. + int i; + for (i = 0; i < 32; ++i) + { + gicd->ICPENDRn[i] = 0xffffffff; + } + + // Set all interrupts to secure. + for (i = 0; i < 8; ++i) + { + gicd->IGROUPRn[i] = 0; + } + + // Init the GIC CPU interface. + gic_init_cpu(); + + // Now enable the distributor. + gic_enable(true); +} + +void gic_init_cpu(void) +{ + // Init the GIC CPU interface. + gic_set_cpu_priority_mask(0xff); + + // Disable preemption. + gicc_t * gicc = gic_get_gicc(); + gicc->BPR = 7; + + // Enable signaling the CPU. + gic_cpu_enable(true); +} + +//////////////////////////////////////////////////////////////////////////////// +// EOF +//////////////////////////////////////////////////////////////////////////////// diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic_registers.h b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic_registers.h new file mode 100644 index 000000000..bf9a11851 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic_registers.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "sdk_types.h" + +//////////////////////////////////////////////////////////////////////////////// +// Definitions +//////////////////////////////////////////////////////////////////////////////// + +//! @brief Offsets to the GIC registers. +enum _gic_base_offsets +{ + kGICDBaseOffset = 0x1000, //!< GIC distributor offset. + kGICCBaseOffset = 0x100 //!< GIC CPU interface offset. +}; + +//! @brief GIC distributor registers. +//! +//! Uses the GICv2 register names, but does not include GICv2 registers. +//! +//! The IPRIORITYRn and ITARGETSRn registers are byte accessible, so their types are uint8_t +//! instead of uint32_t to reflect this. These members are indexed directly with the interrupt +//! number. +struct _gicd_registers +{ + uint32_t CTLR; //!< Distributor Control Register. + uint32_t TYPER; //!< Interrupt Controller Type Register. + uint32_t IIDR; //!< Distributor Implementer Identification Register. + uint32_t _reserved0[29]; + uint32_t IGROUPRn[8]; //!< Interrupt Group Registers. + uint32_t _reserved1[24]; + uint32_t ISENABLERn[32]; //!< Interrupt Set-Enable Registers. + uint32_t ICENABLERn[32]; //!< Interrupt Clear-Enable Registers. + uint32_t ISPENDRn[32]; //!< Interrupt Set-Pending Registers. + uint32_t ICPENDRn[32]; //!< Interrupt Clear-Pending Registers. + uint32_t ICDABRn[32]; //!< Active Bit Registers. + uint32_t _reserved2[32]; + uint8_t IPRIORITYRn[255 * sizeof(uint32_t)]; //!< Interrupt Priority Registers. (Byte accessible) + uint32_t _reserved3; + uint8_t ITARGETSRn[255 * sizeof(uint32_t)]; //!< Interrupt Processor Targets Registers. (Byte accessible) + uint32_t _reserved4; + uint32_t ICFGRn[64]; //!< Interrupt Configuration Registers. + uint32_t _reserved5[128]; + uint32_t SGIR; //!< Software Generated Interrupt Register +}; + +//! @brief Bitfields constants for the GICD_CTLR register. +enum _gicd_ctlr_fields +{ + kBM_GICD_CTLR_EnableGrp1 = (1 << 1), + kBM_GICD_CTLR_EnableGrp0 = (1 << 0) +}; + +//! @brief Bitfields constants for the GICD_SGIR register. +enum _gicd_sgir_fields +{ + kBP_GICD_SGIR_TargetListFilter = 24, + kBM_GICD_SGIR_TargetListFilter = (0x3 << kBP_GICD_SGIR_TargetListFilter), + + kBP_GICD_SGIR_CPUTargetList = 16, + kBM_GICD_SGIR_CPUTargetList = (0xff << kBP_GICD_SGIR_CPUTargetList), + + kBP_GICD_SGIR_NSATT = 15, + kBM_GICD_SGIR_NSATT = (1 << kBP_GICD_SGIR_NSATT), + + kBP_GICD_SGIR_SGIINTID = 0, + kBM_GICD_SGIR_SGIINTID = 0xf +}; + +//! @brief GIC CPU interface registers. +//! +//! Uses the GICv2 register names. Does not include GICv2 registers. +struct _gicc_registers +{ + uint32_t CTLR; //!< CPU Interface Control Register. + uint32_t PMR; //!< Interrupt Priority Mask Register. + uint32_t BPR; //!< Binary Point Register. + uint32_t IAR; //!< Interrupt Acknowledge Register. + uint32_t EOIR; //!< End of Interrupt Register. + uint32_t RPR; //!< Running Priority Register. + uint32_t HPPIR; //!< Highest Priority Pending Interrupt Register. + uint32_t ABPR; //!< Aliased Binary Point Register. (only visible with a secure access) + uint32_t _reserved[56]; + uint32_t IIDR; //!< CPU Interface Identification Register. +}; + +//! @brief Bitfields constants for the GICC_CTLR register. +enum _gicc_ctlr_fields +{ + kBP_GICC_CTLR_EnableS = 0, + kBM_GICC_CTLR_EnableS = (1 << 0), + + kBP_GICC_CTLR_EnableNS = 1, + kBM_GICC_CTLR_EnableNS = (1 << 1), + + kBP_GICC_CTLR_AckCtl = 2, + kBM_GICC_CTLR_AckCtl = (1 << 2), + + kBP_GICC_CTLR_FIQEn = 3, + kBM_GICC_CTLR_FIQEn = (1 << 3), + + kBP_GICC_CTLR_SBPR = 4, + kBM_GICC_CTLR_SBPR = (1 << 4) +}; + +//! @brier Type for the GIC distributor registers. +typedef volatile struct _gicd_registers gicd_t; + +//! @brier Type for the GIC CPU interface registers. +typedef volatile struct _gicc_registers gicc_t; + +//////////////////////////////////////////////////////////////////////////////// +// EOF +//////////////////////////////////////////////////////////////////////////////// diff --git a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/link.lds b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/link.lds index 5b0d78cbb..ce211a026 100644 --- a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/link.lds +++ b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/link.lds @@ -79,7 +79,7 @@ MEMORY sram_oc_ecc2 (rwx) : ORIGIN = 0x20350000, LENGTH = 0x10000 /* 64K bytes (alias RAM7) */ /* define extern sdram 32MB*/ - board_sdram (rwx) : ORIGIN = 0x80000000, LENGTH = 0x2000000 /* 64M bytes (alias RAM8) */ + board_sdram (rwx) : ORIGIN = 0x80000000, LENGTH = 0x2000000 /* 32M bytes (alias RAM8) */ } From 0b5c6b0f9fbb2274f10e14d259d2cbf433d51e2d Mon Sep 17 00:00:00 2001 From: WuZheng Date: Tue, 20 Dec 2022 15:15:35 +0800 Subject: [PATCH 19/33] fix bugs that e220 initialize death --- APP_Framework/Framework/connection/lora/e220/e220.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/APP_Framework/Framework/connection/lora/e220/e220.c b/APP_Framework/Framework/connection/lora/e220/e220.c index 7f3c4638c..201e9417f 100644 --- a/APP_Framework/Framework/connection/lora/e220/e220.c +++ b/APP_Framework/Framework/connection/lora/e220/e220.c @@ -263,7 +263,7 @@ static int E220SetRegisterParam(struct Adapter *adapter, uint16 address, uint8 c uint8 baud_rate_bit = E220BaudRateSwitch(baud_rate); E220LoraModeConfig(CONFIGURE_MODE_MODE); - PrivTaskDelay(30); + PrivTaskDelay(2000); buffer[0] = 0xC0; //write register order buffer[1] = 0x00; //register start-address @@ -286,6 +286,7 @@ static int E220SetRegisterParam(struct Adapter *adapter, uint16 address, uint8 c printf("E220SetRegisterParam send failed %d!\n", ret); } + PrivTaskDelay(2000); PrivRead(adapter->fd, buffer, 11); E220LoraModeConfig(DATA_TRANSFER_MODE); From b933e0decb03cb8a498169408bb40c428d9e0108 Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Wed, 21 Dec 2022 12:07:47 +0800 Subject: [PATCH 20/33] fix spi6 io define error on hc32f4a0 board --- .../third_party_driver/spi/connect_spi.c | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/spi/connect_spi.c b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/spi/connect_spi.c index f74767f13..8cfae2660 100644 --- a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/spi/connect_spi.c +++ b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/spi/connect_spi.c @@ -61,21 +61,21 @@ Modification: #define SPI6_UNIT (CM_SPI6) #define SPI6_CLK (FCG1_PERIPH_SPI6) -/* SS = PI01 */ -#define SPI6_SS_PORT (GPIO_PORT_I) -#define SPI6_SS_PIN (GPIO_PIN_01) -/* SCK = PH14 */ -#define SPI6_SCK_PORT (GPIO_PORT_H) -#define SPI6_SCK_PIN (GPIO_PIN_14) -#define SPI6_SCK_FUNC (GPIO_FUNC_40) -/* MOSI = PI00 */ -#define SPI6_MOSI_PORT (GPIO_PORT_I) -#define SPI6_MOSI_PIN (GPIO_PIN_00) -#define SPI6_MOSI_FUNC (GPIO_FUNC_41) -/* MISO = PH15 */ -#define SPI6_MISO_PORT (GPIO_PORT_H) -#define SPI6_MISO_PIN (GPIO_PIN_15) -#define SPI6_MISO_FUNC (GPIO_FUNC_42) +/* SS = PE02 */ +#define SPI6_SS_PORT (GPIO_PORT_E) +#define SPI6_SS_PIN (GPIO_PIN_02) +/* SCK = PE03 */ +#define SPI6_SCK_PORT (GPIO_PORT_E) +#define SPI6_SCK_PIN (GPIO_PIN_03) +#define SPI6_SCK_FUNC (GPIO_FUNC_46) +/* MOSI = PE04 */ +#define SPI6_MOSI_PORT (GPIO_PORT_E) +#define SPI6_MOSI_PIN (GPIO_PIN_04) +#define SPI6_MOSI_FUNC (GPIO_FUNC_47) +/* MISO = PE05 */ +#define SPI6_MISO_PORT (GPIO_PORT_E) +#define SPI6_MISO_PIN (GPIO_PIN_05) +#define SPI6_MISO_FUNC (GPIO_FUNC_48) #define SPI6_DEVICE_SLAVE_ID_0 0 From 4edf73254e8566dad72dc05ca52d632300b6907a Mon Sep 17 00:00:00 2001 From: wlyu Date: Wed, 21 Dec 2022 18:25:35 +0800 Subject: [PATCH 21/33] support i2c and fixed no shell bug --- .../aiit_board/hc32f4a0/src/hc32_bringup.c | 1 - .../nuttx/arch/arm/include/hc32/irq.h | 4 +- .../nuttx/arch/arm/src/hc32/Kconfig | 19 +- .../nuttx/arch/arm/src/hc32/Make.defs | 4 +- .../nuttx/arch/arm/src/hc32/hc32_console.c | 37 +- .../nuttx/arch/arm/src/hc32/hc32_gpio.h | 2 + .../nuttx/arch/arm/src/hc32/hc32_i2c.c | 844 ++++++++++++ .../nuttx/arch/arm/src/hc32/hc32_idle.c | 5 - .../nuttx/arch/arm/src/hc32/hc32_irq.c | 1208 +---------------- .../nuttx/arch/arm/src/hc32/hc32_serial.c | 332 ++--- .../nuttx/arch/arm/src/hc32/hc32_timerisr.c | 5 + .../nuttx/arch/arm/src/hc32/hc32_vectors.c | 173 --- .../arch/arm/src/hc32/hc32f4a0_interrupts.h | 2 + 13 files changed, 1084 insertions(+), 1552 deletions(-) create mode 100755 Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_i2c.c diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/hc32f4a0/src/hc32_bringup.c b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/hc32f4a0/src/hc32_bringup.c index 9ea9d7fde..62ca6b4be 100755 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/hc32f4a0/src/hc32_bringup.c +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/hc32f4a0/src/hc32_bringup.c @@ -71,6 +71,5 @@ int hc32_bringup(void) } #endif - printf("start %s\n", __func__); return ret; } diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/include/hc32/irq.h b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/include/hc32/irq.h index f88f1e4f5..8030320fe 100755 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/include/hc32/irq.h +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/include/hc32/irq.h @@ -86,8 +86,8 @@ extern "C" #define NR_IRQS (144 + 15) -#define NVIC_SYSH_PRIORITY_MIN 0xf0 -#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 +#define NVIC_SYSH_PRIORITY_MIN 0U// 0xf0 +#define NVIC_SYSH_PRIORITY_DEFAULT 0U //0x80 #define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_PRIORITY_DEFAULT #define ARMV7M_PERIPHERAL_INTERRUPTS NR_IRQS diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/Kconfig b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/Kconfig index c1c3ebc02..ee027beaf 100755 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/Kconfig +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/Kconfig @@ -181,10 +181,27 @@ config HC32_SPI1 config HC32_SPI2 bool "SPI2" default n - depends on HC32_HAVE_SPI2 select SPI select HC32_SPI +config HC32_I2C1 + bool "I2C1" + default n + select I2C + select HC32_I2C + +config HC32_I2C2 + bool "I2C2" + default n + select I2C + select HC32_I2C + +config HC32_I2C3 + bool "I2C3" + default n + select I2C + select HC32_I2C + config HC32_SPI bool diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/Make.defs b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/Make.defs index b85737cb1..3bd6007a1 100755 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/Make.defs +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/Make.defs @@ -86,9 +86,11 @@ CHIP_CSRCS += hc32_console.c CHIP_CSRCS += hc32f4a0_clk.c hc32f4a0_efm.c hc32f4a0_gpio.c CHIP_CSRCS += hc32f4a0_interrupts.c hc32f4a0_usart.c hc32f4a0_utility.c -CHIP_CSRCS += hc32f4a0_sram.c hc32f4a0_pwc.c +CHIP_CSRCS += hc32f4a0_sram.c hc32f4a0_pwc.c hc32f4a0_i2c.c CHIP_CSRCS += hc32f4a0_spi.c CHIP_CSRCS += hc32_spiflash.c hc32_spi.c +CHIP_CSRCS += hc32_i2c.c + diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_console.c b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_console.c index e6fd16e9a..e07a325b8 100755 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_console.c +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_console.c @@ -18,6 +18,9 @@ #include "hc32_uart.h" #include "hc32_spi.h" +#define CMP_STR(_tar, _str) (strncmp(_tar, _str, strlen(_str)) == 0) +extern int hc32_i2c_test(void); + void hc32_test_console(void) { char *dev_str = "/dev/console"; @@ -31,16 +34,44 @@ void hc32_test_console(void) close(fd); } +void hc32_bmp180_test(void) +{ + char *bmp_dev = "/dev/bmp180"; + char write_arr[] = {0xF4, 0x2E}; + int fd = 0, ret; + + fd = open(bmp_dev, 0x6); + ret = write(fd, write_arr, 2); + hc32_print("%s: write attr ret %x\n", __func__, ret); + close(fd); +} + void hc32_console_handle(char *buf) { - if(strncmp(buf, "console", 7) == 0) + if(CMP_STR(buf, "console")) { hc32_test_console(); } - else if(strncmp(buf, "spi", 7) == 0) + else if(CMP_STR(buf, "spi")) { - hc32_print("start flash test ...\n"); + hc32_print("start flash test %d ...\n", g_system_timer); hc32_spiflash_test(); } + else if(CMP_STR(buf, "i2c")) + { + hc32_print("start i2c test %d ...\n", g_system_timer); + hc32_i2c_test(); + } + else if(CMP_STR(buf, "bmp")) + { + hc32_print("start bmp180 test ...\n"); + hc32_bmp180_test(); + } + else if(CMP_STR(buf, "pr")) + { + printf("z\n"); + hc32_print("start pr test %d ...\n", g_system_timer); + printf("b\n"); + } } diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_gpio.h b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_gpio.h index aeaf436fc..a54ab40e1 100755 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_gpio.h +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_gpio.h @@ -39,6 +39,8 @@ /**************************************************************************** * Pre-Processor Declarations ****************************************************************************/ +typedef uint32_t gpio_pinset_t; + #define GPIO_OUTPUT_SET (1 << 25) /* Bit 8: If output, initial value of output */ #define GPIO_OUTPUT_CLEAR (0) diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_i2c.c b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_i2c.c new file mode 100755 index 000000000..9c1a2498d --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_i2c.c @@ -0,0 +1,844 @@ +/** + ******************************************************************************* + * @file i2c/i2c_master_polling/source/main.c + * @brief Main program of I2C master polling for the Device Driver Library. + @verbatim + Change Logs: + Date Author Notes + 2020-06-12 Hexiao First version + 2020-08-31 Hexiao Modify I2C init flow + 2020-09-04 Hexiao Modify compile warning + 2021-01-21 Hexiao Replace PWC_FCG1_IIC1 with PWC_FCG1_I2C1 + @endverbatim + ******************************************************************************* + * Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved. + * + * This software component is licensed by HDSC under BSD 3-Clause license + * (the "License"); You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ******************************************************************************* + */ + +/******************************************************************************* + * Include files + ******************************************************************************/ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "hc32_ddl.h" +#include "hc32_gpio.h" +#include "hc32_uart.h" + +/** + * @addtogroup HC32F4A0_DDL_Examples + * @{ + */ + +/** + * @addtogroup I2C_Master_Polling + * @{ + */ + +/******************************************************************************* + * Local type definitions ('typedef') + ******************************************************************************/ + +/******************************************************************************* + * Local pre-processor symbols/macros ('#define') + ******************************************************************************/ +/* Define slave device address for example */ +#define DEVICE_ADDRESS (0x77U) //bmp180 +/* Define port and pin for SDA and SCL */ +#define I2C_SCL_PORT (GPIO_PORT_D) +#define I2C_SCL_PIN (GPIO_PIN_03) +#define I2C_SDA_PORT (GPIO_PORT_F) +#define I2C_SDA_PIN (GPIO_PIN_10) + +#define I2C_RET_OK (0U) +#define I2C_RET_ERROR (1U) + +#define GENERATE_START (0x00U) +#define GENERATE_RESTART (0x01U) + +#define ADDRESS_W (0x00U) +#define ADDRESS_R (0x01U) + +/* Define Write and read data length for the example */ +#define TEST_DATA_LEN (1U) +/* Define i2c baudrate */ +#define I2C_BAUDRATE (400000UL) + +//#define LED_GREEN_PORT (GPIO_PORT_I) +//#define LED_GREEN_PIN (GPIO_PIN_03) + +#define I2C_MASTER 1 +#define I2C_SLAVE 2 + +/******************************************************************************* + * Global variable definitions (declared in header file with 'extern') + ******************************************************************************/ + +/* I2C Device hardware configuration */ + +struct hc32_i2c_config_s +{ + M4_I2C_TypeDef *base; /* I2C base address */ + gpio_pinset_t scl_pin; /* GPIO configuration for SCL as SCL */ + gpio_pinset_t sda_pin; /* GPIO configuration for SDA as SDA */ + uint8_t mode; /* Master or Slave mode */ +#ifndef CONFIG_I2C_POLLED + uint32_t irq; /* Event IRQ */ +#endif +}; + +/* I2C Device Private Data */ + +struct hc32_i2c_priv_s +{ + /* Standard I2C operations */ + + const struct i2c_ops_s *ops; + + /* Port configuration */ + + const struct hc32_i2c_config_s *config; + + int refs; /* Reference count */ + sem_t sem_excl; /* Mutual exclusion semaphore */ +#ifndef CONFIG_I2C_POLLED + sem_t sem_isr; /* Interrupt wait semaphore */ +#endif + volatile uint8_t intstate; /* Interrupt handshake (see enum hc32_intstate_e) */ + + uint8_t msgc; /* Message count */ + struct i2c_msg_s *msgv; /* Message list */ + uint8_t *ptr; /* Current message buffer */ + uint32_t frequency; /* Current I2C frequency */ + int dcnt; /* Current message length */ + uint16_t flags; /* Current message flags */ + + uint32_t status; /* End of transfer SR2|SR1 status */ +}; + +static int hc32_i2c_init(FAR struct hc32_i2c_priv_s *priv); +static int hc32_i2c_deinit(FAR struct hc32_i2c_priv_s *priv); +static int hc32_i2c_transfer(FAR struct i2c_master_s *dev, + FAR struct i2c_msg_s *msgs, int count); +#ifdef CONFIG_I2C_RESET +static int hc32_i2c_reset(FAR struct i2c_master_s *dev); +#endif + +/* I2C interface */ + +static const struct i2c_ops_s hc32_i2c_ops = +{ + .transfer = hc32_i2c_transfer +#ifdef CONFIG_I2C_RESET + , .reset = hc32_i2c_reset +#endif +}; + +/* I2C device structures */ + +#ifdef CONFIG_HC32_I2C1 +static const struct hc32_i2c_config_s hc32_i2c1_config = +{ + .base = M4_I2C1, + .scl_pin = GPIO_PINSET(I2C_SCL_PORT, I2C_SCL_PIN), + .sda_pin = GPIO_PINSET(I2C_SDA_PORT, I2C_SDA_PIN), +#ifndef CONFIG_I2C_SLAVE + .mode = I2C_MASTER, +#else + .mode = I2C_SLAVE, +#endif +#ifndef CONFIG_I2C_POLLED + .irq = EVT_I2C1_RXI, +#endif +}; + +static struct hc32_i2c_priv_s hc32_i2c1_priv = +{ + .ops = &hc32_i2c_ops, + .config = &hc32_i2c1_config, + .refs = 0, + .intstate = INTSTATE_IDLE, + .msgc = 0, + .msgv = NULL, + .ptr = NULL, + .dcnt = 0, + .flags = 0, + .status = 0 +}; +#endif + +#ifdef CONFIG_HC32_I2C2 +static const struct hc32_i2c_config_s hc32_i2c2_config = +{ + .base = M4_I2C2, + .scl_pin = GPIO_PINSET(I2C_SCL_PORT, I2C_SCL_PIN), + .sda_pin = GPIO_PINSET(I2C_SDA_PORT, I2C_SDA_PIN), +#ifndef CONFIG_I2C_SLAVE + .mode = I2C_MASTER, +#else + .mode = I2C_SLAVE, +#endif +#ifndef CONFIG_I2C_POLLED + .irq = EVT_I2C2_RXI, +#endif +}; + +static struct hc32_i2c_priv_s hc32_i2c2_priv = +{ + .ops = &hc32_i2c_ops, + .config = &hc32_i2c2_config, + .refs = 0, + .intstate = INTSTATE_IDLE, + .msgc = 0, + .msgv = NULL, + .ptr = NULL, + .dcnt = 0, + .flags = 0, + .status = 0 +}; +#endif + +#ifdef CONFIG_HC32_I2C3 +static const struct hc32_i2c_config_s hc32_i2c3_config = +{ + .base = M4_I2C3, + .scl_pin = GPIO_PINSET(I2C_SCL_PORT, I2C_SCL_PIN), + .sda_pin = GPIO_PINSET(I2C_SDA_PORT, I2C_SDA_PIN), +#ifndef CONFIG_I2C_SLAVE + .mode = I2C_MASTER, +#else + .mode = I2C_SLAVE, +#endif +#ifndef CONFIG_I2C_POLLED + .irq = EVT_I2C3_RXI, +#endif +}; + +static struct hc32_i2c_priv_s hc32_i2c3_priv = +{ + .ops = &hc32_i2c_ops, + .config = &hc32_i2c3_config, + .refs = 0, + .intstate = INTSTATE_IDLE, + .msgc = 0, + .msgv = NULL, + .ptr = NULL, + .dcnt = 0, + .flags = 0, + .status = 0 +}; +#endif + +/******************************************************************************* + * Local function prototypes ('static') + ******************************************************************************/ + +/******************************************************************************* + * Local variable definitions ('static') + ******************************************************************************/ +#define I2C_TIMEOUT (0x24000U) + +/******************************************************************************* + * Function implementation - global ('extern') and local ('static') + ******************************************************************************/ + +/** + * @brief MCU Peripheral registers write unprotected. + * @param None + * @retval None + * @note Comment/uncomment each API depending on APP requires. + */ +static void Peripheral_WE(void) +{ + /* Unlock GPIO register: PSPCR, PCCR, PINAER, PCRxy, PFSRxy */ + GPIO_Unlock(); + /* Unlock PWC register: FCG0 */ + PWC_FCG0_Unlock(); + /* Unlock PWC, CLK, PVD registers, @ref PWC_REG_Write_Unlock_Code for details */ + PWC_Unlock(PWC_UNLOCK_CODE_0 | PWC_UNLOCK_CODE_1 | PWC_UNLOCK_CODE_2); + /* Unlock SRAM register: WTCR */ + SRAM_WTCR_Unlock(); + /* Unlock SRAM register: CKCR */ + SRAM_CKCR_Unlock(); + /* Unlock all EFM registers */ + EFM_Unlock(); + /* Unlock EFM register: FWMC */ + //EFM_FWMC_Unlock(); + /* Unlock EFM OTP write protect registers */ + //EFM_OTP_WP_Unlock(); + /* Unlock all MPU registers */ + // MPU_Unlock(); +} + +/** + * @brief MCU Peripheral registers write protected. + * @param None + * @retval None + * @note Comment/uncomment each API depending on APP requires. + */ +static __attribute__((unused)) void Peripheral_WP(void) +{ + /* Lock GPIO register: PSPCR, PCCR, PINAER, PCRxy, PFSRxy */ + GPIO_Lock(); + /* Lock PWC register: FCG0 */ + PWC_FCG0_Lock(); + /* Lock PWC, CLK, PVD registers, @ref PWC_REG_Write_Unlock_Code for details */ + PWC_Lock(PWC_UNLOCK_CODE_0 | PWC_UNLOCK_CODE_1 | PWC_UNLOCK_CODE_2); + /* Lock SRAM register: WTCR */ + SRAM_WTCR_Lock(); + /* Lock SRAM register: CKCR */ + SRAM_CKCR_Lock(); + /* Lock EFM OTP write protect registers */ + //EFM_OTP_WP_Lock(); + /* Lock EFM register: FWMC */ + //EFM_FWMC_Lock(); + /* Lock all EFM registers */ + EFM_Lock(); + /* Lock all MPU registers */ + // MPU_Lock(); +} + +//static void Master_LedInit(void) +//{ +// stc_gpio_init_t stcGpioInit; +// +// /* RGB LED initialize */ +// (void)GPIO_StructInit(&stcGpioInit); +// (void)GPIO_Init(LED_GREEN_PORT, LED_GREEN_PIN, &stcGpioInit); +// +// /* "Turn off" LED before set to output */ +// GPIO_ResetPins(LED_GREEN_PORT, LED_GREEN_PIN); +// +// /* Output enable */ +// GPIO_OE(LED_GREEN_PORT, LED_GREEN_PIN, Enable); +//} + +//static void Master_LedOn(void) +//{ +// GPIO_SetPins(LED_GREEN_PORT, LED_GREEN_PIN); +//} + +/** + * @brief Send start or restart condition + * @param [in] u8Start Indicate the start mode, start or restart + * @retval Process result + * - I2C_RET_ERROR Send start or restart failed + * - I2C_RET_OK Send start or restart success + */ +static en_result_t Master_StartOrRestart(uint8_t u8Start) +{ + en_result_t enRet; + + /* generate start or restart signal */ + if(GENERATE_START == u8Start) + { + enRet = I2C_Start(M4_I2C1,I2C_TIMEOUT); + } + else + { + /* Clear start status flag */ + enRet = I2C_Restart(M4_I2C1,I2C_TIMEOUT); + } + + return enRet; +} + +/** + * @brief Send slave address + * @param [in] u8Adr The slave address + * @param [in] u8Dir The transfer direction @ref I2C_Transfer_Direction + * @retval Process result + * - I2C_RET_ERROR Send failed + * - I2C_RET_OK Send success + */ +static en_result_t Master_SendAdr(uint8_t u8Adr, uint8_t u8Dir) +{ + return I2C_TransAddr(M4_I2C1,u8Adr,u8Dir,I2C_TIMEOUT); +} + +/** + * @brief Send data to slave + * @param [in] pTxData Pointer to the data buffer + * @param [in] u32Size Data size + * @retval Process result + * - I2C_RET_ERROR Send failed + * - I2C_RET_OK Send success + */ +static en_result_t Master_WriteData(uint8_t const pTxData[], uint32_t u32Size) +{ + return I2C_TransData(M4_I2C1, pTxData, u32Size,I2C_TIMEOUT); +} + +/** + * @brief Write address and receive data from slave + * @param [in] pRxData Pointer to the data buffer + * @param [in] u32Size Data size + * @retval Process result + * - I2C_RET_ERROR Process failed + * - I2C_RET_OK Process success + */ +static en_result_t Master_ReceiveAndStop(uint8_t pRxData[], uint32_t u32Size) +{ + return I2C_MasterReceiveAndStop(M4_I2C1,pRxData, u32Size,I2C_TIMEOUT); +} + +/** + * @brief General stop condition to slave + * @param None + * @retval Process result + * - I2C_RET_ERROR Process failed + * - I2C_RET_OK Process success + */ +static en_result_t Master_Stop(void) +{ + return I2C_Stop(M4_I2C1,I2C_TIMEOUT); +} + +/** + * @brief Initialize the I2C peripheral for master + * @param None + * @retval Process result + * - I2C_RET_ERROR Process failed + * - I2C_RET_OK Process success + */ +static en_result_t Master_Initialize(void) +{ + stc_i2c_init_t stcI2cInit; + float32_t fErr; + + I2C_DeInit(M4_I2C1); + + (void)I2C_StructInit(&stcI2cInit); + stcI2cInit.u32Baudrate = I2C_BAUDRATE; + stcI2cInit.u32SclTime = 5U; + stcI2cInit.u32ClkDiv = I2C_CLK_DIV4; + en_result_t enRet = I2C_Init(M4_I2C1, &stcI2cInit, &fErr); + I2C_BusWaitCmd(M4_I2C1, Enable); + + if(enRet == Ok) + { + I2C_Cmd(M4_I2C1, Enable); + } + + return enRet; +} + +/** + * @brief Judge the result. LED0 toggle when result is error status. + * @param [in] enRet Result to be judged + * @retval None + */ +static void JudgeResult(en_result_t enRet) +{ + if(Ok != enRet) + { + for(;;) + { + DDL_DelayMS(500U); + } + } +} + +static int hc32_i2c_init(FAR struct hc32_i2c_priv_s *priv) +{ + return OK; +} + +static int hc32_i2c_deinit(FAR struct hc32_i2c_priv_s *priv) +{ + return OK; +} + +static inline void hc32_i2c_sem_init(FAR struct hc32_i2c_priv_s *priv) +{ + nxsem_init(&priv->sem_excl, 0, 1); + +#ifndef CONFIG_I2C_POLLED + /* This semaphore is used for signaling and, hence, should not have + * priority inheritance enabled. + */ + + nxsem_init(&priv->sem_isr, 0, 0); + nxsem_set_protocol(&priv->sem_isr, SEM_PRIO_NONE); +#endif +} + + +static inline void hc32_i2c_sem_destroy(FAR struct hc32_i2c_priv_s *priv) +{ + nxsem_destroy(&priv->sem_excl); +#ifndef CONFIG_I2C_POLLED + nxsem_destroy(&priv->sem_isr); +#endif +} + +/**************************************************************************** + * Name: hc32_i2c_sem_post + * + * Description: + * Release the mutual exclusion semaphore + * + ****************************************************************************/ + +static inline void hc32_i2c_sem_post(struct hc32_i2c_priv_s *priv) +{ + nxsem_post(&priv->sem_excl); +} + +#if 0 +static int hc32_i2c_transfer1(FAR struct i2c_master_s *dev, + FAR struct i2c_msg_s *msgs, int count) +{ + FAR struct hc32_i2c_priv_s *priv = (struct hc32_i2c_priv_s *)dev; + uint32_t status = 0; +#ifdef I2C1_FSMC_CONFLICT + uint32_t ahbenr; +#endif + int ret; + + DEBUGASSERT(count); + + /* Ensure that address or flags don't change meanwhile */ + + ret = nxsem_wait(&priv->sem_excl); + if (ret < 0) + { + return ret; + } +// +// + + /* Ensure that any ISR happening after we finish can't overwrite any user + * data + */ + + priv->dcnt = 0; + priv->ptr = NULL; + + hc32_i2c_sem_post(priv); + return ret; +} +#endif + +static int hc32_i2c_transfer(FAR struct i2c_master_s *dev, + FAR struct i2c_msg_s *msgs, int count) +{ + en_result_t ret; + FAR struct hc32_i2c_priv_s *priv = (struct hc32_i2c_priv_s *)dev; + + /* Initialize I2C peripheral and enable function*/ + ret = Master_Initialize(); + JudgeResult(ret); + + /* I2C master data write*/ + ret = Master_StartOrRestart(GENERATE_START); + JudgeResult(ret); + ret = Master_SendAdr(msgs->addr, I2C_DIR_TX); + JudgeResult(ret); + ret = Master_WriteData(msgs->buffer, msgs->length); + JudgeResult(ret); + ret = Master_Stop(); + JudgeResult(ret); + + /* 5mS delay for device*/ + DDL_DelayMS(5U); + + /* I2C master data read*/ + ret = Master_StartOrRestart(GENERATE_START); + if(1UL == msgs->length) + { + I2C_AckConfig(priv->config->base, I2C_NACK); + } + JudgeResult(ret); + ret = Master_SendAdr(msgs->addr, I2C_DIR_RX); + JudgeResult(ret); + ret = Master_ReceiveAndStop(msgs->buffer, msgs->length); + JudgeResult(ret); + + return ret; +} + +int hc32_i2c_config(void) +{ + /* Initialize I2C port*/ + stc_gpio_init_t stcGpioInit; + + Peripheral_WE(); + + (void)GPIO_StructInit(&stcGpioInit); + (void)GPIO_Init(I2C_SCL_PORT, I2C_SCL_PIN, &stcGpioInit); + (void)GPIO_Init(I2C_SDA_PORT, I2C_SDA_PIN, &stcGpioInit); + GPIO_SetFunc(I2C_SCL_PORT, I2C_SCL_PIN, GPIO_FUNC_49_I2C1_SCL, PIN_SUBFUNC_DISABLE); + GPIO_SetFunc(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_FUNC_48_I2C1_SDA, PIN_SUBFUNC_DISABLE); + + /* Enable peripheral clock */ + PWC_Fcg1PeriphClockCmd(PWC_FCG1_I2C1, Enable); + return OK; +} + + +/** + * @brief BSP clock initialize. + * Set board system clock to PLLH@240MHz + * Flash: 5 wait + * SRAM_HS: 1 wait + * SRAM1_2_3_4_B: 2 wait + * PCLK0: 240MHz + * PCLK1: 120MHz + * PCLK2: 60MHz + * PCLK3: 60MHz + * PCLK4: 120MHz + * EXCLK: 120MHz + * HCLK: 240MHz + * @param None + * @retval None + */ +void BSP_CLK_Init(void) +{ + stc_clk_xtal_init_t stcXtalInit; + stc_clk_pllh_init_t stcPLLHInit; + + /* PCLK0, HCLK Max 240MHz */ + /* PCLK1, PCLK4 Max 120MHz */ + /* PCLK2, PCLK3 Max 60MHz */ + /* EX BUS Max 120MHz */ + CLK_ClkDiv(CLK_CATE_ALL, \ + (CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 | \ + CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2 | CLK_EXCLK_DIV2 | \ + CLK_HCLK_DIV1)); + + CLK_XtalStructInit(&stcXtalInit); + /* Config Xtal and enable Xtal */ + stcXtalInit.u8XtalMode = CLK_XTALMODE_OSC; + stcXtalInit.u8XtalDrv = CLK_XTALDRV_LOW; + stcXtalInit.u8XtalState = CLK_XTAL_ON; + stcXtalInit.u8XtalStb = CLK_XTALSTB_2MS; + CLK_XtalInit(&stcXtalInit); + + (void)CLK_PLLHStructInit(&stcPLLHInit); + /* VCO = (8/1)*120 = 960MHz*/ + stcPLLHInit.u8PLLState = CLK_PLLH_ON; + stcPLLHInit.PLLCFGR = 0UL; + stcPLLHInit.PLLCFGR_f.PLLM = 1UL - 1UL; + stcPLLHInit.PLLCFGR_f.PLLN = 120UL - 1UL; + stcPLLHInit.PLLCFGR_f.PLLP = 4UL - 1UL; + stcPLLHInit.PLLCFGR_f.PLLQ = 4UL - 1UL; + stcPLLHInit.PLLCFGR_f.PLLR = 4UL - 1UL; + stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLLSRC_XTAL; + (void)CLK_PLLHInit(&stcPLLHInit); + + /* Highspeed SRAM set to 1 Read/Write wait cycle */ + SRAM_SetWaitCycle(SRAM_SRAMH, SRAM_WAIT_CYCLE_1, SRAM_WAIT_CYCLE_1); + + /* SRAM1_2_3_4_backup set to 2 Read/Write wait cycle */ + SRAM_SetWaitCycle((SRAM_SRAM123 | SRAM_SRAM4 | SRAM_SRAMB), SRAM_WAIT_CYCLE_2, SRAM_WAIT_CYCLE_2); + + /* 0-wait @ 40MHz */ + EFM_SetWaitCycle(EFM_WAIT_CYCLE_5); + + /* 4 cycles for 200 ~ 250MHz */ + GPIO_SetReadWaitCycle(GPIO_READ_WAIT_4); + + CLK_SetSysClkSrc(CLK_SYSCLKSOURCE_PLLH); +} + + +/** + * @brief Main function of i2c_master_polling project + * @param None + * @retval int32_t return value, if needed + */ +int hc32_i2c_test(void) +{ + en_result_t enRet; + uint8_t u8TxBuf[TEST_DATA_LEN] = {0xD0}; + uint8_t u8RxBuf[TEST_DATA_LEN] = {0U}; + + hc32_i2c_config(); + + hc32_print("%s: %d start ...\n", __func__, __LINE__); + + /* Initialize I2C peripheral and enable function*/ + enRet = Master_Initialize(); + JudgeResult(enRet); + + hc32_print("%s: %d ret %d\n", __func__, __LINE__, enRet); + + /* I2C master data write*/ + enRet = Master_StartOrRestart(GENERATE_START); + JudgeResult(enRet); + enRet = Master_SendAdr(DEVICE_ADDRESS, I2C_DIR_TX); + JudgeResult(enRet); + enRet = Master_WriteData(u8TxBuf, TEST_DATA_LEN); + JudgeResult(enRet); + enRet = Master_Stop(); + JudgeResult(enRet); + + /* 5mS delay for device*/ + DDL_DelayMS(5U); + + /* I2C master data read*/ + enRet = Master_StartOrRestart(GENERATE_START); + if(1UL == TEST_DATA_LEN) + { + I2C_AckConfig(M4_I2C1, I2C_NACK); + } + + JudgeResult(enRet); + enRet = Master_SendAdr(DEVICE_ADDRESS,I2C_DIR_RX); + JudgeResult(enRet); + enRet = Master_ReceiveAndStop(u8RxBuf, TEST_DATA_LEN); + JudgeResult(enRet); + + hc32_print("%s: i2c device id = %x\n", __func__, u8RxBuf[0]); + return OK; +} + + +/**************************************************************************** + * Name: hc32_i2cbus_initialize + * + * Description: + * Initialize one I2C bus + * + ****************************************************************************/ + +FAR struct i2c_master_s *hc32_i2cbus_initialize(int port) +{ + struct hc32_i2c_priv_s * priv = NULL; + irqstate_t flags; + + /* Get I2C private structure */ + + switch (port) + { +#ifdef CONFIG_HC32_I2C1 + case 0: + priv = (struct hc32_i2c_priv_s *)&hc32_i2c1_priv; + break; +#endif +#ifdef CONFIG_HC32_I2C2 + case 1: + priv = (struct hc32_i2c_priv_s *)&hc32_i2c2_priv; + break; +#endif +#ifdef CONFIG_HC32_I2C3 + case 2: + priv = (struct hc32_i2c_priv_s *)&hc32_i2c3_priv; + break; +#endif + default: + return NULL; + } + + /* Initialize private data for the first time, increment reference count, + * power-up hardware and configure GPIOs. + */ + + flags = enter_critical_section(); + + if ((volatile int)priv->refs++ == 0) + { + hc32_i2c_sem_init(priv); + hc32_i2c_init(priv); + } + + leave_critical_section(flags); + + return (struct i2c_master_s *)priv; +} + +/**************************************************************************** + * Name: hc32_i2cbus_uninitialize + * + * Description: + * Uninitialize an I2C bus + * + ****************************************************************************/ + +int hc32_i2cbus_uninitialize(FAR struct i2c_master_s *dev) +{ + FAR struct hc32_i2c_priv_s *priv = (struct hc32_i2c_priv_s *)dev; + irqstate_t flags; + + DEBUGASSERT(dev); + + /* Decrement reference count and check for underflow */ + + if (priv->refs == 0) + { + return ERROR; + } + + flags = enter_critical_section(); + + if (--priv->refs > 0) + { + leave_critical_section(flags); + return OK; + } + + leave_critical_section(flags); + + /* Disable power and other HW resource (GPIO's) */ + + hc32_i2c_deinit(priv); + + /* Release unused resources */ + + hc32_i2c_sem_destroy(priv); + return OK; +} + + +static void hc32_i2c_register(int bus) +{ + FAR struct i2c_master_s *i2c; + int ret; + + i2c = hc32_i2cbus_initialize(bus); + if (i2c == NULL) + { + syslog(LOG_ERR, "Failed to get I2C%d interface\n", bus); + } + else + { + ret = i2c_register(i2c, bus); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to register I2C%d driver: %d\n", bus, ret); + hc32_i2cbus_uninitialize(i2c); + } + } +} + +/** + * @} + */ + +/** + * @} + */ + +/******************************************************************************* + * EOF (not truncated) + ******************************************************************************/ diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_idle.c b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_idle.c index fb8deaacd..81f2d32c9 100755 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_idle.c +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_idle.c @@ -153,11 +153,6 @@ static void up_idlepm(void) void up_idle(void) { -#if defined (CONFIG_HC32F4A0_BOARD) - extern void hc32_uart_handle(void); - hc32_uart_handle(); -#endif - #if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) /* If the system is idle and there are no timer interrupts, then process * "fake" timer interrupts. Hopefully, something will wake up. diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_irq.c b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_irq.c index 91d6a86c7..e5e743c34 100755 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_irq.c +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_irq.c @@ -163,29 +163,6 @@ static void hc32_dumpnvic(const char *msg, int irq) * ****************************************************************************/ - -static int hc32_svc(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); -#ifdef CONFIG_DEBUG_FEATURES - _err("PANIC!!! SVC received\n"); - PANIC(); -#endif - SVC_Handler(); - return 0; -} - -static int hc32_hardfault(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); -#ifdef CONFIG_DEBUG_FEATURES - _err("PANIC!!! HardFault received\n"); - PANIC(); -#endif - HardFault_Handler(); - return 0; -} - #ifdef CONFIG_DEBUG_FEATURES static int hc32_nmi(int irq, FAR void *context, FAR void *arg) { @@ -268,1013 +245,6 @@ static int hc32_reserved(int irq, FAR void *context, FAR void *arg) } #endif #endif -static int hc32_irq000(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ000_Handler(); - return 0; -} - -static int hc32_irq001(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ001_Handler(); - return 0; -} - -static int hc32_irq002(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ002_Handler(); - return 0; -} - -static int hc32_irq003(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ003_Handler(); - return 0; -} - -static int hc32_irq004(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ004_Handler(); - return 0; -} - -static int hc32_irq005(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ005_Handler(); - return 0; -} - -static int hc32_irq006(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ006_Handler(); - return 0; -} - -static int hc32_irq007(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ007_Handler(); - return 0; -} - -static int hc32_irq008(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ008_Handler(); - return 0; -} - -static int hc32_irq009(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ009_Handler(); - return 0; -} - -static int hc32_irq010(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ010_Handler(); - return 0; -} - -static int hc32_irq011(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ011_Handler(); - return 0; -} - -static int hc32_irq012(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ012_Handler(); - return 0; -} - -static int hc32_irq013(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ013_Handler(); - return 0; -} - -static int hc32_irq014(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ014_Handler(); - return 0; -} - -static int hc32_irq015(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ015_Handler(); - return 0; -} - -static int hc32_irq016(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ016_Handler(); - return 0; -} - -static int hc32_irq017(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ017_Handler(); - return 0; -} - -static int hc32_irq018(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ018_Handler(); - return 0; -} - -static int hc32_irq019(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ019_Handler(); - return 0; -} - -static int hc32_irq020(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ020_Handler(); - return 0; -} - -static int hc32_irq021(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ021_Handler(); - return 0; -} - -static int hc32_irq022(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ022_Handler(); - return 0; -} - -static int hc32_irq023(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ023_Handler(); - return 0; -} - -static int hc32_irq024(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ024_Handler(); - return 0; -} - -static int hc32_irq025(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ025_Handler(); - return 0; -} - -static int hc32_irq026(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ026_Handler(); - return 0; -} - -static int hc32_irq027(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ027_Handler(); - return 0; -} - -static int hc32_irq028(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ028_Handler(); - return 0; -} - -static int hc32_irq029(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ029_Handler(); - return 0; -} - -static int hc32_irq030(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ030_Handler(); - return 0; -} - -static int hc32_irq031(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ031_Handler(); - return 0; -} - -static int hc32_irq032(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ032_Handler(); - return 0; -} - -static int hc32_irq033(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ033_Handler(); - return 0; -} - -static int hc32_irq034(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ034_Handler(); - return 0; -} - -static int hc32_irq035(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ035_Handler(); - return 0; -} - -static int hc32_irq036(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ036_Handler(); - return 0; -} - -static int hc32_irq037(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ037_Handler(); - return 0; -} - -static int hc32_irq038(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ038_Handler(); - return 0; -} - -static int hc32_irq039(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ039_Handler(); - return 0; -} - -static int hc32_irq040(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ040_Handler(); - return 0; -} - -static int hc32_irq041(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ041_Handler(); - return 0; -} - -static int hc32_irq042(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ042_Handler(); - return 0; -} - -static int hc32_irq043(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ043_Handler(); - return 0; -} - -static int hc32_irq044(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ044_Handler(); - return 0; -} - -static int hc32_irq045(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ045_Handler(); - return 0; -} - -static int hc32_irq046(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ046_Handler(); - return 0; -} - -static int hc32_irq047(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ047_Handler(); - return 0; -} - -static int hc32_irq048(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ048_Handler(); - return 0; -} - -static int hc32_irq049(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ049_Handler(); - return 0; -} - -static int hc32_irq050(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ050_Handler(); - return 0; -} - -static int hc32_irq051(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ051_Handler(); - return 0; -} - -static int hc32_irq052(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ052_Handler(); - return 0; -} - -static int hc32_irq053(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ053_Handler(); - return 0; -} - -static int hc32_irq054(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ054_Handler(); - return 0; -} - -static int hc32_irq055(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ055_Handler(); - return 0; -} - -static int hc32_irq056(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ056_Handler(); - return 0; -} - -static int hc32_irq057(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ057_Handler(); - return 0; -} - -static int hc32_irq058(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ058_Handler(); - return 0; -} - -static int hc32_irq059(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ059_Handler(); - return 0; -} - -static int hc32_irq060(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ060_Handler(); - return 0; -} - -static int hc32_irq061(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ061_Handler(); - return 0; -} - -static int hc32_irq062(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ062_Handler(); - return 0; -} - -static int hc32_irq063(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ063_Handler(); - return 0; -} - -static int hc32_irq064(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ064_Handler(); - return 0; -} - -static int hc32_irq065(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ065_Handler(); - return 0; -} - -static int hc32_irq066(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ066_Handler(); - return 0; -} - -static int hc32_irq067(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ067_Handler(); - return 0; -} - -static int hc32_irq068(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ068_Handler(); - return 0; -} - -static int hc32_irq069(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ069_Handler(); - return 0; -} - -static int hc32_irq070(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ070_Handler(); - return 0; -} - -static int hc32_irq071(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ071_Handler(); - return 0; -} - -static int hc32_irq072(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ072_Handler(); - return 0; -} - -static int hc32_irq073(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ073_Handler(); - return 0; -} - -static int hc32_irq074(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ074_Handler(); - return 0; -} - -static int hc32_irq075(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ075_Handler(); - return 0; -} - -static int hc32_irq076(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ076_Handler(); - return 0; -} - -static int hc32_irq077(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ077_Handler(); - return 0; -} - -static int hc32_irq078(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ078_Handler(); - return 0; -} - -static int hc32_irq079(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ079_Handler(); - return 0; -} - -static int hc32_irq080(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ080_Handler(); - return 0; -} - -static int hc32_irq081(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ081_Handler(); - return 0; -} - -static int hc32_irq082(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ082_Handler(); - return 0; -} - -static int hc32_irq083(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ083_Handler(); - return 0; -} - -static int hc32_irq084(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ084_Handler(); - return 0; -} - -static int hc32_irq085(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ085_Handler(); - return 0; -} - -static int hc32_irq086(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ086_Handler(); - return 0; -} - -static int hc32_irq087(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ087_Handler(); - return 0; -} - -static int hc32_irq088(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ088_Handler(); - return 0; -} - -static int hc32_irq089(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ089_Handler(); - return 0; -} - -static int hc32_irq090(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ090_Handler(); - return 0; -} - -static int hc32_irq091(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ091_Handler(); - return 0; -} - -static int hc32_irq092(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ092_Handler(); - return 0; -} - -static int hc32_irq093(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ093_Handler(); - return 0; -} - -static int hc32_irq094(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ094_Handler(); - return 0; -} - -static int hc32_irq095(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ095_Handler(); - return 0; -} - -static int hc32_irq096(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ096_Handler(); - return 0; -} - -static int hc32_irq097(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ097_Handler(); - return 0; -} - -static int hc32_irq098(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ098_Handler(); - return 0; -} - -static int hc32_irq099(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ099_Handler(); - return 0; -} - -static int hc32_irq100(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ100_Handler(); - return 0; -} - -static int hc32_irq101(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ101_Handler(); - return 0; -} - -static int hc32_irq102(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ102_Handler(); - return 0; -} - -static int hc32_irq103(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ103_Handler(); - return 0; -} - -static int hc32_irq104(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ104_Handler(); - return 0; -} - -static int hc32_irq105(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ105_Handler(); - return 0; -} - -static int hc32_irq106(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ106_Handler(); - return 0; -} - -static int hc32_irq107(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ107_Handler(); - return 0; -} - -static int hc32_irq108(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ108_Handler(); - return 0; -} - -static int hc32_irq109(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ109_Handler(); - return 0; -} - -static int hc32_irq110(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ110_Handler(); - return 0; -} - -static int hc32_irq111(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ111_Handler(); - return 0; -} - -static int hc32_irq112(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ112_Handler(); - return 0; -} - -static int hc32_irq113(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ113_Handler(); - return 0; -} - -static int hc32_irq114(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ114_Handler(); - return 0; -} - -static int hc32_irq115(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ115_Handler(); - return 0; -} - -static int hc32_irq116(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ116_Handler(); - return 0; -} - -static int hc32_irq117(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ117_Handler(); - return 0; -} - -static int hc32_irq118(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ118_Handler(); - return 0; -} - -static int hc32_irq119(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ119_Handler(); - return 0; -} - -static int hc32_irq120(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ120_Handler(); - return 0; -} - -static int hc32_irq121(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ121_Handler(); - return 0; -} - -static int hc32_irq122(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ122_Handler(); - return 0; -} - -static int hc32_irq123(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ123_Handler(); - return 0; -} - -static int hc32_irq124(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ124_Handler(); - return 0; -} - -static int hc32_irq125(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ125_Handler(); - return 0; -} - -static int hc32_irq126(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ126_Handler(); - return 0; -} - -static int hc32_irq127(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ127_Handler(); - return 0; -} - -static int hc32_irq128(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ128_Handler(); - return 0; -} - -static int hc32_irq129(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ129_Handler(); - return 0; -} - -static int hc32_irq130(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ130_Handler(); - return 0; -} - -static int hc32_irq131(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ131_Handler(); - return 0; -} - -static int hc32_irq132(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ132_Handler(); - return 0; -} - -static int hc32_irq133(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ133_Handler(); - return 0; -} - -static int hc32_irq134(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ134_Handler(); - return 0; -} - -static int hc32_irq135(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ135_Handler(); - return 0; -} - -static int hc32_irq136(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ136_Handler(); - return 0; -} - -static int hc32_irq137(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ137_Handler(); - return 0; -} - -static int hc32_irq138(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ138_Handler(); - return 0; -} - -static int hc32_irq139(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ139_Handler(); - return 0; -} - -static int hc32_irq140(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ140_Handler(); - return 0; -} - -static int hc32_irq141(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ141_Handler(); - return 0; -} - -static int hc32_irq142(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ142_Handler(); - return 0; -} - -static int hc32_irq143(int irq, FAR void *context, FAR void *arg) -{ - up_irq_save(); - IRQ143_Handler(); - return 0; -} /**************************************************************************** @@ -1360,169 +330,6 @@ static int hc32_irqinfo(int irq, uintptr_t *regaddr, uint32_t *bit, * Public Functions ****************************************************************************/ -void hc32_attach_irqs(void) -{ - irq_attach(HC32_IRQ_FIRST + Int000_IRQn, hc32_irq000, NULL); - irq_attach(HC32_IRQ_FIRST + Int001_IRQn, hc32_irq001, NULL); - irq_attach(HC32_IRQ_FIRST + Int002_IRQn, hc32_irq002, NULL); - irq_attach(HC32_IRQ_FIRST + Int003_IRQn, hc32_irq003, NULL); - irq_attach(HC32_IRQ_FIRST + Int004_IRQn, hc32_irq004, NULL); - irq_attach(HC32_IRQ_FIRST + Int005_IRQn, hc32_irq005, NULL); - irq_attach(HC32_IRQ_FIRST + Int006_IRQn, hc32_irq006, NULL); - irq_attach(HC32_IRQ_FIRST + Int007_IRQn, hc32_irq007, NULL); - irq_attach(HC32_IRQ_FIRST + Int008_IRQn, hc32_irq008, NULL); - irq_attach(HC32_IRQ_FIRST + Int009_IRQn, hc32_irq009, NULL); - - irq_attach(HC32_IRQ_FIRST + Int010_IRQn, hc32_irq010, NULL); - irq_attach(HC32_IRQ_FIRST + Int011_IRQn, hc32_irq011, NULL); - irq_attach(HC32_IRQ_FIRST + Int012_IRQn, hc32_irq012, NULL); - irq_attach(HC32_IRQ_FIRST + Int013_IRQn, hc32_irq013, NULL); - irq_attach(HC32_IRQ_FIRST + Int014_IRQn, hc32_irq014, NULL); - irq_attach(HC32_IRQ_FIRST + Int015_IRQn, hc32_irq015, NULL); - irq_attach(HC32_IRQ_FIRST + Int016_IRQn, hc32_irq016, NULL); - irq_attach(HC32_IRQ_FIRST + Int017_IRQn, hc32_irq017, NULL); - irq_attach(HC32_IRQ_FIRST + Int018_IRQn, hc32_irq018, NULL); - irq_attach(HC32_IRQ_FIRST + Int019_IRQn, hc32_irq019, NULL); - - irq_attach(HC32_IRQ_FIRST + Int020_IRQn, hc32_irq020, NULL); - irq_attach(HC32_IRQ_FIRST + Int021_IRQn, hc32_irq021, NULL); - irq_attach(HC32_IRQ_FIRST + Int022_IRQn, hc32_irq022, NULL); - irq_attach(HC32_IRQ_FIRST + Int023_IRQn, hc32_irq023, NULL); - irq_attach(HC32_IRQ_FIRST + Int024_IRQn, hc32_irq024, NULL); - irq_attach(HC32_IRQ_FIRST + Int025_IRQn, hc32_irq025, NULL); - irq_attach(HC32_IRQ_FIRST + Int026_IRQn, hc32_irq026, NULL); - irq_attach(HC32_IRQ_FIRST + Int027_IRQn, hc32_irq027, NULL); - irq_attach(HC32_IRQ_FIRST + Int028_IRQn, hc32_irq028, NULL); - irq_attach(HC32_IRQ_FIRST + Int029_IRQn, hc32_irq029, NULL); - - irq_attach(HC32_IRQ_FIRST + Int030_IRQn, hc32_irq030, NULL); - irq_attach(HC32_IRQ_FIRST + Int031_IRQn, hc32_irq031, NULL); - irq_attach(HC32_IRQ_FIRST + Int032_IRQn, hc32_irq032, NULL); - irq_attach(HC32_IRQ_FIRST + Int033_IRQn, hc32_irq033, NULL); - irq_attach(HC32_IRQ_FIRST + Int034_IRQn, hc32_irq034, NULL); - irq_attach(HC32_IRQ_FIRST + Int035_IRQn, hc32_irq035, NULL); - irq_attach(HC32_IRQ_FIRST + Int036_IRQn, hc32_irq036, NULL); - irq_attach(HC32_IRQ_FIRST + Int037_IRQn, hc32_irq037, NULL); - irq_attach(HC32_IRQ_FIRST + Int038_IRQn, hc32_irq038, NULL); - irq_attach(HC32_IRQ_FIRST + Int039_IRQn, hc32_irq039, NULL); - - irq_attach(HC32_IRQ_FIRST + Int040_IRQn, hc32_irq040, NULL); - irq_attach(HC32_IRQ_FIRST + Int041_IRQn, hc32_irq041, NULL); - irq_attach(HC32_IRQ_FIRST + Int042_IRQn, hc32_irq042, NULL); - irq_attach(HC32_IRQ_FIRST + Int043_IRQn, hc32_irq043, NULL); - irq_attach(HC32_IRQ_FIRST + Int044_IRQn, hc32_irq044, NULL); - irq_attach(HC32_IRQ_FIRST + Int045_IRQn, hc32_irq045, NULL); - irq_attach(HC32_IRQ_FIRST + Int046_IRQn, hc32_irq046, NULL); - irq_attach(HC32_IRQ_FIRST + Int047_IRQn, hc32_irq047, NULL); - irq_attach(HC32_IRQ_FIRST + Int048_IRQn, hc32_irq048, NULL); - irq_attach(HC32_IRQ_FIRST + Int049_IRQn, hc32_irq049, NULL); - - irq_attach(HC32_IRQ_FIRST + Int050_IRQn, hc32_irq050, NULL); - irq_attach(HC32_IRQ_FIRST + Int051_IRQn, hc32_irq051, NULL); - irq_attach(HC32_IRQ_FIRST + Int052_IRQn, hc32_irq052, NULL); - irq_attach(HC32_IRQ_FIRST + Int053_IRQn, hc32_irq053, NULL); - irq_attach(HC32_IRQ_FIRST + Int054_IRQn, hc32_irq054, NULL); - irq_attach(HC32_IRQ_FIRST + Int055_IRQn, hc32_irq055, NULL); - irq_attach(HC32_IRQ_FIRST + Int056_IRQn, hc32_irq056, NULL); - irq_attach(HC32_IRQ_FIRST + Int057_IRQn, hc32_irq057, NULL); - irq_attach(HC32_IRQ_FIRST + Int058_IRQn, hc32_irq058, NULL); - irq_attach(HC32_IRQ_FIRST + Int059_IRQn, hc32_irq059, NULL); - - irq_attach(HC32_IRQ_FIRST + Int060_IRQn, hc32_irq060, NULL); - irq_attach(HC32_IRQ_FIRST + Int061_IRQn, hc32_irq061, NULL); - irq_attach(HC32_IRQ_FIRST + Int062_IRQn, hc32_irq062, NULL); - irq_attach(HC32_IRQ_FIRST + Int063_IRQn, hc32_irq063, NULL); - irq_attach(HC32_IRQ_FIRST + Int064_IRQn, hc32_irq064, NULL); - irq_attach(HC32_IRQ_FIRST + Int065_IRQn, hc32_irq065, NULL); - irq_attach(HC32_IRQ_FIRST + Int066_IRQn, hc32_irq066, NULL); - irq_attach(HC32_IRQ_FIRST + Int067_IRQn, hc32_irq067, NULL); - irq_attach(HC32_IRQ_FIRST + Int068_IRQn, hc32_irq068, NULL); - irq_attach(HC32_IRQ_FIRST + Int069_IRQn, hc32_irq069, NULL); - - irq_attach(HC32_IRQ_FIRST + Int070_IRQn, hc32_irq070, NULL); - irq_attach(HC32_IRQ_FIRST + Int071_IRQn, hc32_irq071, NULL); - irq_attach(HC32_IRQ_FIRST + Int072_IRQn, hc32_irq072, NULL); - irq_attach(HC32_IRQ_FIRST + Int073_IRQn, hc32_irq073, NULL); - irq_attach(HC32_IRQ_FIRST + Int074_IRQn, hc32_irq074, NULL); - irq_attach(HC32_IRQ_FIRST + Int075_IRQn, hc32_irq075, NULL); - irq_attach(HC32_IRQ_FIRST + Int076_IRQn, hc32_irq076, NULL); - irq_attach(HC32_IRQ_FIRST + Int077_IRQn, hc32_irq077, NULL); - irq_attach(HC32_IRQ_FIRST + Int078_IRQn, hc32_irq078, NULL); - irq_attach(HC32_IRQ_FIRST + Int079_IRQn, hc32_irq079, NULL); - - irq_attach(HC32_IRQ_FIRST + Int080_IRQn, hc32_irq080, NULL); - irq_attach(HC32_IRQ_FIRST + Int081_IRQn, hc32_irq081, NULL); - irq_attach(HC32_IRQ_FIRST + Int082_IRQn, hc32_irq082, NULL); - irq_attach(HC32_IRQ_FIRST + Int083_IRQn, hc32_irq083, NULL); - irq_attach(HC32_IRQ_FIRST + Int084_IRQn, hc32_irq084, NULL); - irq_attach(HC32_IRQ_FIRST + Int085_IRQn, hc32_irq085, NULL); - irq_attach(HC32_IRQ_FIRST + Int086_IRQn, hc32_irq086, NULL); - irq_attach(HC32_IRQ_FIRST + Int087_IRQn, hc32_irq087, NULL); - irq_attach(HC32_IRQ_FIRST + Int088_IRQn, hc32_irq088, NULL); - irq_attach(HC32_IRQ_FIRST + Int089_IRQn, hc32_irq089, NULL); - - irq_attach(HC32_IRQ_FIRST + Int090_IRQn, hc32_irq090, NULL); - irq_attach(HC32_IRQ_FIRST + Int091_IRQn, hc32_irq091, NULL); - irq_attach(HC32_IRQ_FIRST + Int092_IRQn, hc32_irq092, NULL); - irq_attach(HC32_IRQ_FIRST + Int093_IRQn, hc32_irq093, NULL); - irq_attach(HC32_IRQ_FIRST + Int094_IRQn, hc32_irq094, NULL); - irq_attach(HC32_IRQ_FIRST + Int095_IRQn, hc32_irq095, NULL); - irq_attach(HC32_IRQ_FIRST + Int096_IRQn, hc32_irq096, NULL); - irq_attach(HC32_IRQ_FIRST + Int097_IRQn, hc32_irq097, NULL); - irq_attach(HC32_IRQ_FIRST + Int098_IRQn, hc32_irq098, NULL); - irq_attach(HC32_IRQ_FIRST + Int099_IRQn, hc32_irq099, NULL); - - irq_attach(HC32_IRQ_FIRST + Int100_IRQn, hc32_irq100, NULL); - irq_attach(HC32_IRQ_FIRST + Int101_IRQn, hc32_irq101, NULL); - irq_attach(HC32_IRQ_FIRST + Int102_IRQn, hc32_irq102, NULL); - irq_attach(HC32_IRQ_FIRST + Int103_IRQn, hc32_irq103, NULL); - irq_attach(HC32_IRQ_FIRST + Int104_IRQn, hc32_irq104, NULL); - irq_attach(HC32_IRQ_FIRST + Int105_IRQn, hc32_irq105, NULL); - irq_attach(HC32_IRQ_FIRST + Int106_IRQn, hc32_irq106, NULL); - irq_attach(HC32_IRQ_FIRST + Int107_IRQn, hc32_irq107, NULL); - irq_attach(HC32_IRQ_FIRST + Int108_IRQn, hc32_irq108, NULL); - irq_attach(HC32_IRQ_FIRST + Int109_IRQn, hc32_irq109, NULL); - - irq_attach(HC32_IRQ_FIRST + Int110_IRQn, hc32_irq110, NULL); - irq_attach(HC32_IRQ_FIRST + Int111_IRQn, hc32_irq111, NULL); - irq_attach(HC32_IRQ_FIRST + Int112_IRQn, hc32_irq112, NULL); - irq_attach(HC32_IRQ_FIRST + Int113_IRQn, hc32_irq113, NULL); - irq_attach(HC32_IRQ_FIRST + Int114_IRQn, hc32_irq114, NULL); - irq_attach(HC32_IRQ_FIRST + Int115_IRQn, hc32_irq115, NULL); - irq_attach(HC32_IRQ_FIRST + Int116_IRQn, hc32_irq116, NULL); - irq_attach(HC32_IRQ_FIRST + Int117_IRQn, hc32_irq117, NULL); - irq_attach(HC32_IRQ_FIRST + Int118_IRQn, hc32_irq118, NULL); - irq_attach(HC32_IRQ_FIRST + Int119_IRQn, hc32_irq119, NULL); - - irq_attach(HC32_IRQ_FIRST + Int120_IRQn, hc32_irq120, NULL); - irq_attach(HC32_IRQ_FIRST + Int121_IRQn, hc32_irq121, NULL); - irq_attach(HC32_IRQ_FIRST + Int122_IRQn, hc32_irq122, NULL); - irq_attach(HC32_IRQ_FIRST + Int123_IRQn, hc32_irq123, NULL); - irq_attach(HC32_IRQ_FIRST + Int124_IRQn, hc32_irq124, NULL); - irq_attach(HC32_IRQ_FIRST + Int125_IRQn, hc32_irq125, NULL); - irq_attach(HC32_IRQ_FIRST + Int126_IRQn, hc32_irq126, NULL); - irq_attach(HC32_IRQ_FIRST + Int127_IRQn, hc32_irq127, NULL); - irq_attach(HC32_IRQ_FIRST + Int128_IRQn, hc32_irq128, NULL); - irq_attach(HC32_IRQ_FIRST + Int129_IRQn, hc32_irq129, NULL); - - irq_attach(HC32_IRQ_FIRST + Int130_IRQn, hc32_irq130, NULL); - irq_attach(HC32_IRQ_FIRST + Int131_IRQn, hc32_irq131, NULL); - irq_attach(HC32_IRQ_FIRST + Int132_IRQn, hc32_irq132, NULL); - irq_attach(HC32_IRQ_FIRST + Int133_IRQn, hc32_irq133, NULL); - irq_attach(HC32_IRQ_FIRST + Int134_IRQn, hc32_irq134, NULL); - irq_attach(HC32_IRQ_FIRST + Int135_IRQn, hc32_irq135, NULL); - irq_attach(HC32_IRQ_FIRST + Int136_IRQn, hc32_irq136, NULL); - irq_attach(HC32_IRQ_FIRST + Int137_IRQn, hc32_irq137, NULL); - irq_attach(HC32_IRQ_FIRST + Int138_IRQn, hc32_irq138, NULL); - irq_attach(HC32_IRQ_FIRST + Int139_IRQn, hc32_irq139, NULL); - - irq_attach(HC32_IRQ_FIRST + Int140_IRQn, hc32_irq140, NULL); - irq_attach(HC32_IRQ_FIRST + Int141_IRQn, hc32_irq141, NULL); - irq_attach(HC32_IRQ_FIRST + Int142_IRQn, hc32_irq142, NULL); - irq_attach(HC32_IRQ_FIRST + Int143_IRQn, hc32_irq143, NULL); -} - - /**************************************************************************** * Name: up_irqinitialize ****************************************************************************/ @@ -1597,8 +404,8 @@ void up_irqinitialize(void) * under certain conditions. */ - irq_attach(HC32_IRQ_SVCALL, hc32_svc, NULL); - irq_attach(HC32_IRQ_HARDFAULT, hc32_hardfault, NULL); + irq_attach(HC32_IRQ_SVCALL, arm_svcall, NULL); + irq_attach(HC32_IRQ_HARDFAULT, arm_hardfault, NULL); /* Set the priority of the SVCall interrupt */ @@ -1638,8 +445,6 @@ void up_irqinitialize(void) irq_attach(HC32_IRQ_RESERVED, hc32_reserved, NULL); #endif - hc32_attach_irqs(); - hc32_dumpnvic("initial", NR_IRQS); #ifndef CONFIG_SUPPRESS_INTERRUPTS @@ -1674,8 +479,7 @@ void up_disable_irq(int irq) if (irq >= HC32_IRQ_FIRST) { - uint32_t act_irq = irq - HC32_IRQ_FIRST; - NVIC_DisableIRQ(act_irq); + putreg32(bit, regaddr); } else { @@ -1710,10 +514,7 @@ void up_enable_irq(int irq) if (irq >= HC32_IRQ_FIRST) { - uint32_t act_irq = irq - HC32_IRQ_FIRST; - NVIC_ClearPendingIRQ(act_irq); - NVIC_SetPriority(act_irq, DDL_IRQ_PRIORITY_00); - NVIC_EnableIRQ(act_irq); + putreg32(bit, regaddr); } else { @@ -1734,6 +535,7 @@ void up_enable_irq(int irq) void arm_ack_irq(int irq) { + NVIC_ClearPendingIRQ(irq); } /**************************************************************************** diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_serial.c b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_serial.c index 5c4e9f861..eb14a8281 100755 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_serial.c +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_serial.c @@ -64,49 +64,7 @@ * Pre-processor Definitions ****************************************************************************/ -#define USART_CR1_USED_INTS (USART_CR1_RIE | USART_CR1_TXEIE | USART_CR1_PCE | USART_CR1_TCIE) - - -/* Some sanity checks *******************************************************/ - -/* DMA configuration */ - -/* If DMA is enabled on any USART, then very that other pre-requisites - * have also been selected. - */ - -/* Power management definitions */ - -#if defined(CONFIG_PM) && !defined(CONFIG_HC32_PM_SERIAL_ACTIVITY) -# define CONFIG_HC32_PM_SERIAL_ACTIVITY 10 -#endif -#if defined(CONFIG_PM) -# define PM_IDLE_DOMAIN 0 /* Revisit */ -#endif - -/* Since RX DMA or TX DMA or both may be enabled for a given U[S]ART. - * We need runtime detection in up_dma_setup and up_dma_shutdown - * We use the default struct default init value of 0 which maps to - * HC32_DMA_MAP(DMA1,DMA_STREAM0,DMA_CHAN0) which is not a U[S]ART. - */ - -#define INVALID_SERIAL_DMA_CHANNEL 0 - -/* Keep track if a Break was set - * - * Note: - * - * 1) This value is set in the priv->ie but never written to the control - * register. It must not collide with USART_CR1_USED_INTS or USART_CR3_EIE - * 2) USART_CR3_EIE is also carried in the up_dev_s ie member. - * - * See up_restoreusartint where the masking is done. - */ - -#ifdef CONFIG_HC32_SERIALBRK_BSDCOMPAT -# define USART_CR1_IE_BREAK_INPROGRESS_SHFTS 15 -# define USART_CR1_IE_BREAK_INPROGRESS (1 << USART_CR1_IE_BREAK_INPROGRESS_SHFTS) -#endif +#define USART_CR1_USED_INTS (USART_CR1_RIE | USART_CR1_RTOIE | USART_CR1_TXEIE | USART_CR1_PCE | USART_CR1_TCIE) #ifdef USE_SERIALDRIVER #ifdef HAVE_SERIALDRIVER @@ -705,6 +663,10 @@ static struct up_dev_s * const g_uart_devs[HC32_NUSART] = static inline uint32_t up_serialin(struct up_dev_s *priv, int offset); +/**************************************************************************** + * Private Functions + ****************************************************************************/ + void hc32_rx_irq_cb(void) { up_interrupt(g_uart_rx_dev->rx_irq, NULL, g_uart_rx_dev); @@ -725,54 +687,34 @@ void hc32_err_irq_cb(void) up_interrupt(g_uart_rx_dev->err_irq, NULL, g_uart_rx_dev); } -void hc32_handle_recv_buf(void) -{ - struct up_dev_s *priv = g_uart_rx_dev; - struct uart_buffer_s *recv = &priv->dev.recv; - char recv_buf[255] = {0}; - int i, j = 0; - static int cnt = 0; - static int last_tail = 0; - if((recv->head != recv->tail) && (cnt ++ > 30)) - { - last_tail = recv->tail; - for(i = recv->tail; i < recv->head; i ++) - { - recv_buf[j++] = recv->buffer[last_tail++]; - } - hc32_console_handle(recv_buf); - hc32_print("nsh>%s\n", recv_buf); - recv->tail = recv->head; - cnt = 0; - last_tail = 0; - } +static int hc32_err_irq_handler(int irq, FAR void *context, FAR void *arg) +{ + up_irq_save(); + IRQ011_Handler(); + return 0; } -void hc32_handle_xmit_buf(void) +static int hc32_rx_irq_handler(int irq, FAR void *context, FAR void *arg) { - struct up_dev_s *priv = g_uart_rx_dev; - int i, j = 0; - char xmit_buf[255] = {0}; - - if(priv->dev.xmit.tail != priv->dev.xmit.head) - { - for(i = priv->dev.xmit.tail; i < priv->dev.xmit.head; i ++) - { - xmit_buf[j++] = priv->dev.xmit.buffer[i++]; - } - hc32_print("nsh>%s", xmit_buf); - } + up_irq_save(); + IRQ012_Handler(); + return 0; } -void hc32_uart_handle(void) +static int hc32_tx_irq_handler(int irq, FAR void *context, FAR void *arg) { - hc32_handle_recv_buf(); + up_irq_save(); + IRQ013_Handler(); + return 0; } -/**************************************************************************** - * Private Functions - ****************************************************************************/ +static int hc32_tci_irq_handler(int irq, FAR void *context, FAR void *arg) +{ + up_irq_save(); + IRQ014_Handler(); + return 0; +} int hc32_print(const char *fmt, ...) { @@ -802,7 +744,7 @@ int hc32_print(const char *fmt, ...) * @param [in] u32Priority Interrupt priority * @retval None */ -static void hc32_enable_irq(const stc_irq_signin_config_t *pstcConfig, +static void hc32_serial_enableirq(const stc_irq_signin_config_t *pstcConfig, uint32_t u32Priority) { if (NULL != pstcConfig) @@ -919,45 +861,6 @@ static void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) leave_critical_section(flags); } -static int hc32_enable_serialirq(struct uart_dev_s *dev) -{ - struct up_dev_s *priv = (struct up_dev_s *)dev->priv; - stc_irq_signin_config_t cfg; - - { - memset(&cfg, 0, sizeof(cfg)); - cfg.enIRQn = priv->rx_irq - HC32_IRQ_FIRST; - cfg.enIntSrc = priv->rxint_src; - cfg.pfnCallback = &hc32_rx_irq_cb; - hc32_enable_irq(&cfg, DDL_IRQ_PRIORITY_DEFAULT); - } - - { - memset(&cfg, 0, sizeof(cfg)); - cfg.enIRQn = priv->tx_irq - HC32_IRQ_FIRST; - cfg.enIntSrc = priv->txint_src; - cfg.pfnCallback = &hc32_tx_irq_cb; - hc32_enable_irq(&cfg, DDL_IRQ_PRIORITY_DEFAULT); - } - - { - memset(&cfg, 0, sizeof(cfg)); - cfg.enIRQn = priv->txc_irq - HC32_IRQ_FIRST; - cfg.enIntSrc = priv->txcint_src; - cfg.pfnCallback = &hc32_txc_irq_cb; - hc32_enable_irq(&cfg, DDL_IRQ_PRIORITY_DEFAULT); - } - - { - memset(&cfg, 0, sizeof(cfg)); - cfg.enIRQn = priv->err_irq - HC32_IRQ_FIRST; - cfg.enIntSrc = priv->errint_src; - cfg.pfnCallback = &hc32_err_irq_cb; - hc32_enable_irq(&cfg, DDL_IRQ_PRIORITY_DEFAULT); - } - - return OK; -} /**************************************************************************** * Name: up_setup @@ -971,6 +874,102 @@ static int up_setup(struct uart_dev_s *dev) { struct up_dev_s *priv = (struct up_dev_s *)dev->priv; +#ifndef CONFIG_SUPPRESS_UART_CONFIG + uint32_t regval; + + /* Note: The logic here depends on the fact that that the USART module + * was enabled in stm32_lowsetup(). + */ + + /* Enable USART APB1/2 clock */ + +// up_set_apb_clock(dev, true); + + /* Configure pins for USART use */ + + hc32_configgpio(priv->tx_gpio); + hc32_configgpio(priv->rx_gpio); + +#ifdef CONFIG_SERIAL_OFLOWCONTROL + if (priv->cts_gpio != 0) + { + hc32_configgpio(priv->cts_gpio); + } +#endif + +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->rts_gpio != 0) + { + uint32_t config = priv->rts_gpio; + +#ifdef CONFIG_STM32_FLOWCONTROL_BROKEN + /* Instead of letting hw manage this pin, we will bitbang */ + + config = (config & ~GPIO_MODE_MASK) | GPIO_OUTPUT; +#endif + hc32_configgpio(config); + } +#endif + +#ifdef HAVE_RS485 + if (priv->rs485_dir_gpio != 0) + { + hc32_configgpio(priv->rs485_dir_gpio); + hc32_gpiowrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity); + } +#endif + + /* Configure CR2 + * Clear STOP, CLKEN, CPOL, CPHA, LBCL, and interrupt enable bits + */ + + regval = up_serialin(priv, offsetof(M4_USART_TypeDef, _CR2)); + regval &= ~(USART_CR2_STOP | USART_CR2_CLKC | USART_CR2_WKUPIE | + USART_CR2_BEIE | USART_CR2_LBDIE | USART_CR2_LBDIE); + + /* Configure STOP bits */ + + if (priv->stopbits2) + { + regval |= USART_CR2_STOP; + } + + up_serialout(priv, offsetof(M4_USART_TypeDef, _CR2), regval); + + /* Configure CR1 + * Clear TE, REm and all interrupt enable bits + */ + + regval = up_serialin(priv, offsetof(M4_USART_TypeDef, _CR1)); + regval &= ~(USART_CR1_TE | USART_CR1_RE | USART_CR1_RTOE); + + up_serialout(priv, offsetof(M4_USART_TypeDef, _CR1), regval); + + /* Configure CR3 + * Clear CTSE, RTSE, and all interrupt enable bits + */ + + regval = up_serialin(priv, offsetof(M4_USART_TypeDef, _CR3)); + regval &= ~(USART_CR3_CTSE | USART_CR3_RTSE ); + + up_serialout(priv, offsetof(M4_USART_TypeDef, _CR3), regval); + + /* Configure the USART line format and speed. */ + +// up_set_format(dev); + + /* Enable Rx, Tx, and the USART */ + + regval = up_serialin(priv, offsetof(M4_USART_TypeDef, _CR1)); + + regval |= (USART_CR1_RTOE | USART_CR1_RTOIE | USART_CR1_TE | + USART_CR1_RE | USART_CR1_RIE | USART_CR1_TXEIE | USART_CR1_TCIE); + + up_serialout(priv, offsetof(M4_USART_TypeDef, _CR1), regval); + +#endif /* CONFIG_SUPPRESS_UART_CONFIG */ + + /* Set up the cached interrupt enables value */ priv->ie = 0; @@ -1062,13 +1061,39 @@ static void up_shutdown(struct uart_dev_s *dev) static int up_attach(struct uart_dev_s *dev) { struct up_dev_s *priv = (struct up_dev_s *)dev->priv; - int ret = 0; + stc_irq_signin_config_t cfg; - hc32_print("%s: attach irq rx %d %d tx %d %d\n", __func__, priv->rx_irq, priv->rxint_src, - priv->tx_irq, priv->txint_src); + memset(&cfg, 0, sizeof(cfg)); + cfg.enIRQn = priv->rx_irq - HC32_IRQ_FIRST; + cfg.enIntSrc = priv->rxint_src; + cfg.pfnCallback = &hc32_rx_irq_cb; + hc32_serial_enableirq(&cfg, DDL_IRQ_PRIORITY_DEFAULT); - ret = hc32_enable_serialirq(dev); - return ret; + memset(&cfg, 0, sizeof(cfg)); + cfg.enIRQn = priv->tx_irq - HC32_IRQ_FIRST; + cfg.enIntSrc = priv->txint_src; + cfg.pfnCallback = &hc32_tx_irq_cb; + hc32_serial_enableirq(&cfg, DDL_IRQ_PRIORITY_DEFAULT); + + memset(&cfg, 0, sizeof(cfg)); + cfg.enIRQn = priv->txc_irq - HC32_IRQ_FIRST; + cfg.enIntSrc = priv->txcint_src; + cfg.pfnCallback = &hc32_txc_irq_cb; + hc32_serial_enableirq(&cfg, DDL_IRQ_PRIORITY_DEFAULT); + + memset(&cfg, 0, sizeof(cfg)); + cfg.enIRQn = priv->err_irq - HC32_IRQ_FIRST; + cfg.enIntSrc = priv->errint_src; + cfg.pfnCallback = &hc32_err_irq_cb; + hc32_serial_enableirq(&cfg, DDL_IRQ_PRIORITY_DEFAULT); + + irq_attach(HC32_IRQ_SVCALL, arm_svcall, NULL); + irq_attach(HC32_IRQ_HARDFAULT, arm_hardfault, NULL); + irq_attach(USART_UNIT_ERR_INT_IRQn, hc32_err_irq_handler, NULL); + irq_attach(USART_UNIT_RX_INT_IRQn, hc32_rx_irq_handler, NULL); + irq_attach(USART_UNIT_TX_INT_IRQn, hc32_tx_irq_handler, NULL); + irq_attach(USART_UNIT_TCI_INT_IRQn, hc32_tci_irq_handler, NULL); + return OK; } /**************************************************************************** @@ -1084,10 +1109,14 @@ static int up_attach(struct uart_dev_s *dev) static void up_detach(struct uart_dev_s *dev) { struct up_dev_s *priv = (struct up_dev_s *)dev->priv; - up_disable_irq(priv->irq); - irq_detach(priv->irq); - - hc32_print("check %s line %d irq %d\n", __func__, __LINE__, priv->irq); + up_disable_irq(priv->rx_irq); + irq_detach(priv->rx_irq); + up_disable_irq(priv->tx_irq); + irq_detach(priv->tx_irq); + up_disable_irq(priv->txc_irq); + irq_detach(priv->txc_irq); + up_disable_irq(priv->err_irq); + irq_detach(priv->err_irq); } /**************************************************************************** @@ -1535,24 +1564,14 @@ static void up_rxint(struct uart_dev_s *dev, bool enable) * (or an Rx timeout occurs). */ - ie |= USART_CR1_RIE; + ie |= USART_CR1_RIE | USART_CR1_RTOIE | USART_CR1_RTOE | USART_CR1_TE | USART_CR1_RE; up_enable_irq(priv->irq); - - /* Enable TX && RX && RX interrupt function */ - USART_FuncCmd((M4_USART_TypeDef *)priv->usartbase, - (USART_RX | USART_INT_RX | USART_TX | \ - USART_RTO | USART_INT_RTO), Enable); - } else { - ie &= ~(USART_CR1_RIE); + ie &= ~(USART_CR1_RIE | USART_CR1_RTOIE | USART_CR1_RTOE); up_disable_irq(priv->irq); - - USART_FuncCmd((M4_USART_TypeDef *)priv->usartbase, - (USART_RX | USART_INT_RX | USART_TX | \ - USART_RTO | USART_INT_RTO), Disable); } /* Then set the new interrupt state */ @@ -1560,8 +1579,6 @@ static void up_rxint(struct uart_dev_s *dev, bool enable) up_restoreusartint(priv, ie); leave_critical_section(flags); - hc32_print("%s: opened %d irq %d %s ie %x\n", __func__, dev->open_count, priv->irq, - enable ? "enable" : "disable", ie); } /**************************************************************************** @@ -1740,11 +1757,11 @@ static void up_txint(struct uart_dev_s *dev, bool enable) static bool up_txready(struct uart_dev_s *dev) { - struct up_dev_s *priv = (struct up_dev_s *)dev->priv; - M4_USART_TypeDef *base = (M4_USART_TypeDef *)priv->usartbase; - - return((Set == USART_GetStatus(base, USART_FLAG_TXE)) - || (Set == USART_GetStatus(base, USART_FLAG_TC))); +// struct up_dev_s *priv = (struct up_dev_s *)dev->priv; +// M4_USART_TypeDef *base = (M4_USART_TypeDef *)priv->usartbase; +// return((Set == USART_GetStatus(base, USART_FLAG_TXE)) +// || (Set == USART_GetStatus(base, USART_FLAG_TC))); + return Set; } #endif /* HAVE_SERIALDRIVER */ @@ -1834,30 +1851,19 @@ void arm_serialinit(void) char devname[16]; unsigned i; unsigned minor = 0; - int ret; - - /* Register to receive power management callbacks */ - -#ifdef CONFIG_PM - ret = pm_register(&g_serialcb); - DEBUGASSERT(ret == OK); - UNUSED(ret); -#endif /* Register the console */ #if CONSOLE_UART > 0 - ret = uart_register("/dev/console", &g_uart_devs[CONSOLE_UART - 1]->dev); + uart_register("/dev/console", &g_uart_devs[CONSOLE_UART - 1]->dev); #ifndef CONFIG_HC32_SERIAL_DISABLE_REORDERING /* If not disabled, register the console UART to ttyS0 and exclude * it from initializing it further down */ - ret = uart_register("/dev/ttyS0", &g_uart_devs[CONSOLE_UART - 1]->dev); + uart_register("/dev/ttyS0", &g_uart_devs[CONSOLE_UART - 1]->dev); minor = 1; - - hc32_print("register /dev/ttyS0 %d = %d\n", CONSOLE_UART - 1, ret); #endif #endif /* CONSOLE_UART > 0 */ diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_timerisr.c b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_timerisr.c index be200c4a4..bca71488e 100755 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_timerisr.c +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_timerisr.c @@ -95,6 +95,11 @@ static int hc32_timerisr(int irq, uint32_t *regs, void *arg) } #endif +void SysTick_IrqHandler(void) +{ + nxsched_process_timer(); +} + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_vectors.c b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_vectors.c index d0c264e17..4c1032f3f 100755 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_vectors.c +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32_vectors.c @@ -77,7 +77,6 @@ extern void exception_common(void); * Note that the [ ... ] designated initializer is a GCC extension. */ -#if 0 unsigned _vectors[] locate_data(".vectors") = { /* Initial stack */ @@ -92,175 +91,3 @@ unsigned _vectors[] locate_data(".vectors") = [2 ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)] = (unsigned)&exception_common }; -#else -unsigned _vectors[] locate_data(".vectors") = -{ - /* Initial stack */ - - IDLE_STACK, - - /* Reset exception handler */ - - (unsigned)&__start, - (unsigned)&NMI_Handler, - (unsigned)&HardFault_Handler, - (unsigned)&MemManage_Handler, - (unsigned)&BusFault_Handler, - (unsigned)&UsageFault_Handler, - (unsigned)&exception_common, - (unsigned)&exception_common, - (unsigned)&exception_common, - (unsigned)&exception_common, - (unsigned)&SVC_Handler, /* SVC */ - (unsigned)&DebugMon_Handler, /* DebugMon */ - (unsigned)&exception_common, - (unsigned)&PendSV_Handler, - (unsigned)&SysTick_Handler, /* SysTick */ - (unsigned)&IRQ000_Handler, - (unsigned)&IRQ001_Handler, - (unsigned)&IRQ002_Handler, - (unsigned)&IRQ003_Handler, - (unsigned)&IRQ004_Handler, - (unsigned)&IRQ005_Handler, - (unsigned)&IRQ006_Handler, - (unsigned)&IRQ007_Handler, - (unsigned)&IRQ008_Handler, - (unsigned)&IRQ009_Handler, - (unsigned)&IRQ010_Handler, - (unsigned)&IRQ011_Handler, - (unsigned)&IRQ012_Handler, - (unsigned)&IRQ013_Handler, - (unsigned)&IRQ014_Handler, - (unsigned)&IRQ015_Handler, - (unsigned)&IRQ016_Handler, - (unsigned)&IRQ017_Handler, - (unsigned)&IRQ018_Handler, - (unsigned)&IRQ019_Handler, - (unsigned)&IRQ020_Handler, - (unsigned)&IRQ021_Handler, - (unsigned)&IRQ022_Handler, - (unsigned)&IRQ023_Handler, - (unsigned)&IRQ024_Handler, - (unsigned)&IRQ025_Handler, - (unsigned)&IRQ026_Handler, - (unsigned)&IRQ027_Handler, - (unsigned)&IRQ028_Handler, - (unsigned)&IRQ029_Handler, - (unsigned)&IRQ030_Handler, - (unsigned)&IRQ031_Handler, - (unsigned)&IRQ032_Handler, - (unsigned)&IRQ033_Handler, - (unsigned)&IRQ034_Handler, - (unsigned)&IRQ035_Handler, - (unsigned)&IRQ036_Handler, - (unsigned)&IRQ037_Handler, - (unsigned)&IRQ038_Handler, - (unsigned)&IRQ039_Handler, - (unsigned)&IRQ040_Handler, - (unsigned)&IRQ041_Handler, - (unsigned)&IRQ042_Handler, - (unsigned)&IRQ043_Handler, - (unsigned)&IRQ044_Handler, - (unsigned)&IRQ045_Handler, - (unsigned)&IRQ046_Handler, - (unsigned)&IRQ047_Handler, - (unsigned)&IRQ048_Handler, - (unsigned)&IRQ049_Handler, - (unsigned)&IRQ050_Handler, - (unsigned)&IRQ051_Handler, - (unsigned)&IRQ052_Handler, - (unsigned)&IRQ053_Handler, - (unsigned)&IRQ054_Handler, - (unsigned)&IRQ055_Handler, - (unsigned)&IRQ056_Handler, - (unsigned)&IRQ057_Handler, - (unsigned)&IRQ058_Handler, - (unsigned)&IRQ059_Handler, - (unsigned)&IRQ060_Handler, - (unsigned)&IRQ061_Handler, - (unsigned)&IRQ062_Handler, - (unsigned)&IRQ063_Handler, - (unsigned)&IRQ064_Handler, - (unsigned)&IRQ065_Handler, - (unsigned)&IRQ066_Handler, - (unsigned)&IRQ067_Handler, - (unsigned)&IRQ068_Handler, - (unsigned)&IRQ069_Handler, - (unsigned)&IRQ070_Handler, - (unsigned)&IRQ071_Handler, - (unsigned)&IRQ072_Handler, - (unsigned)&IRQ073_Handler, - (unsigned)&IRQ074_Handler, - (unsigned)&IRQ075_Handler, - (unsigned)&IRQ076_Handler, - (unsigned)&IRQ077_Handler, - (unsigned)&IRQ078_Handler, - (unsigned)&IRQ079_Handler, - (unsigned)&IRQ080_Handler, - (unsigned)&IRQ081_Handler, - (unsigned)&IRQ082_Handler, - (unsigned)&IRQ083_Handler, - (unsigned)&IRQ084_Handler, - (unsigned)&IRQ085_Handler, - (unsigned)&IRQ086_Handler, - (unsigned)&IRQ087_Handler, - (unsigned)&IRQ088_Handler, - (unsigned)&IRQ089_Handler, - (unsigned)&IRQ090_Handler, - (unsigned)&IRQ091_Handler, - (unsigned)&IRQ092_Handler, - (unsigned)&IRQ093_Handler, - (unsigned)&IRQ094_Handler, - (unsigned)&IRQ095_Handler, - (unsigned)&IRQ096_Handler, - (unsigned)&IRQ097_Handler, - (unsigned)&IRQ098_Handler, - (unsigned)&IRQ099_Handler, - (unsigned)&IRQ100_Handler, - (unsigned)&IRQ101_Handler, - (unsigned)&IRQ102_Handler, - (unsigned)&IRQ103_Handler, - (unsigned)&IRQ104_Handler, - (unsigned)&IRQ105_Handler, - (unsigned)&IRQ106_Handler, - (unsigned)&IRQ107_Handler, - (unsigned)&IRQ108_Handler, - (unsigned)&IRQ109_Handler, - (unsigned)&IRQ110_Handler, - (unsigned)&IRQ111_Handler, - (unsigned)&IRQ112_Handler, - (unsigned)&IRQ113_Handler, - (unsigned)&IRQ114_Handler, - (unsigned)&IRQ115_Handler, - (unsigned)&IRQ116_Handler, - (unsigned)&IRQ117_Handler, - (unsigned)&IRQ118_Handler, - (unsigned)&IRQ119_Handler, - (unsigned)&IRQ120_Handler, - (unsigned)&IRQ121_Handler, - (unsigned)&IRQ122_Handler, - (unsigned)&IRQ123_Handler, - (unsigned)&IRQ124_Handler, - (unsigned)&IRQ125_Handler, - (unsigned)&IRQ126_Handler, - (unsigned)&IRQ127_Handler, - (unsigned)&IRQ128_Handler, - (unsigned)&IRQ129_Handler, - (unsigned)&IRQ130_Handler, - (unsigned)&IRQ131_Handler, - (unsigned)&IRQ132_Handler, - (unsigned)&IRQ133_Handler, - (unsigned)&IRQ134_Handler, - (unsigned)&IRQ135_Handler, - (unsigned)&IRQ136_Handler, - (unsigned)&IRQ137_Handler, - (unsigned)&IRQ138_Handler, - (unsigned)&IRQ139_Handler, - (unsigned)&IRQ140_Handler, - (unsigned)&IRQ141_Handler, - (unsigned)&IRQ142_Handler, - (unsigned)&IRQ143_Handler - -// [2 ... (15 + ARMV7M_PERIPHERAL_INTERRUPTS)] = (unsigned)&exception_common -}; -#endif diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32f4a0_interrupts.h b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32f4a0_interrupts.h index 5e1eacec4..c44e53dfc 100755 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32f4a0_interrupts.h +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/arm/src/hc32/hc32f4a0_interrupts.h @@ -33,6 +33,8 @@ extern "C" ******************************************************************************/ #include "hc32_common.h" #include "ddl_config.h" +#include +#include /** * @addtogroup HC32F4A0_DDL_Driver From 9f6419e5f63139d4aa23474d3f4795a36f35eb78 Mon Sep 17 00:00:00 2001 From: WuZheng Date: Fri, 23 Dec 2022 09:09:54 +0800 Subject: [PATCH 22/33] fix dvp-read problem caused by driver adaptation --- .../board/edu-riscv64/third_party_driver/dvp/connect_dvp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c index 983719e61..8bf2ab67e 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c @@ -122,6 +122,8 @@ static uint32 DvpRead(void *dev, struct BusBlockReadParam *read_param) dvp_set_output_enable(DVP_OUTPUT_DISPLAY, 0); dvp_set_display_addr((uintptr_t)read_param->buffer); dvp_set_output_enable(DVP_OUTPUT_DISPLAY, 1); + shoot_flag=CONTINOUS_SHOOTS; + dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 1); return ret; } From ce60710fe615623ba91714396fec1f02f144d44f Mon Sep 17 00:00:00 2001 From: wagweigen Date: Fri, 23 Dec 2022 16:28:39 +0800 Subject: [PATCH 23/33] add exception.c and irq entry function --- .../arch/arm/armv7-a/cortex-a9/boot.S | 1 + .../arch/arm/armv7-a/cortex-a9/exception.S | 105 ++++++++++++++++-- .../arch/arm/armv7-a/cortex-a9/exception.c | 75 +++++++++++++ 3 files changed, 169 insertions(+), 12 deletions(-) create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.c diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S index 7d4d0da8d..3731ef6b8 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S @@ -28,6 +28,7 @@ _start: bic r0, #(1 << 2) /* d cache */ bic r0, #(1 << 0) /* mmu */ mcr p15, 0, r0, c1, c0, 0 + ldr r0, =stack_top diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S index 7f52ee1ee..dc3eb6e2d 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S @@ -12,7 +12,7 @@ ExceptionVectors: ldr pc, _IrqException ldr pc, _FiqException -.globl Reset_Handler +.globl _start .globl UndefInstrExceptionHandle .globl SwiExceptionHandle .globl PrefetchAbortExceptionHandle @@ -22,7 +22,7 @@ ExceptionVectors: .globl FiqExceptionHandle _ResetException: - .word Reset_Handler + .word _start _UndefInstrException: .word UndefInstrExceptionHandle _SwiException: @@ -38,29 +38,110 @@ _IrqException: _FiqException: .word FiqExceptionHandle -.globl _start -Reset_Handler: - b _start + .word 0 // extra word in RAM vectors + +.macro push_svc_reg + sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */ + stmia sp, {r0 - r12} @/* Calling r0-r12 */ + mov r0, sp + mrs r6, spsr @/* Save CPSR */ + str lr, [r0, #15*4] @/* Push PC */ + str r6, [r0, #16*4] @/* Push CPSR */ + cps #Mode_SVC + str sp, [r0, #13*4] @/* Save calling SP */ + str lr, [r0, #14*4] @/* Save calling PC */ +.endm + +.align 5 +.globl UndefInstrExceptionHandle UndefInstrExceptionHandle: - b UndefInstrIsrEntry +1: + b 1b +.align 5 +.globl SwiExceptionHandle SwiExceptionHandle: - b SvcIsrEntry + push_svc_reg + bl rt_hw_trap_swi + b . +.align 5 +.globl PrefetchAbortExceptionHandle PrefetchAbortExceptionHandle: - b PrefetchAbortIsrEntry +1: + b 1b +.align 5 +.globl DataAbortExceptionHandle DataAbortExceptionHandle: - b DataAbortIsrEntry +1: + b 1b +.align 5 +.globl ResvExceptionHandle ResvExceptionHandle: - b ResvIsrEntry +1: + b 1b +.section .text.isr, "ax" +.align 5 +.globl ExceptionIsrEntry ExceptionIsrEntry: + stmfd sp!, {r0-r12,lr} - b IsrEntry + bl rt_interrupt_enter + bl rt_hw_trap_irq + bl rt_interrupt_leave + @ if rt_thread_switch_interrupt_flag set, jump to + @ rt_hw_context_switch_interrupt_do and don't return + ldr r0, =rt_thread_switch_interrupt_flag + ldr r1, [r0] + cmp r1, #1 + beq rt_hw_context_switch_interrupt_do + + ldmfd sp!, {r0-r12,lr} + subs pc, lr, #4 + +rt_hw_context_switch_interrupt_do: + mov r1, #0 @ clear flag + str r1, [r0] + + mov r1, sp @ r1 point to {r0-r3} in stack + add sp, sp, #4*4 + ldmfd sp!, {r4-r12,lr}@ reload saved registers + mrs r0, spsr @ get cpsr of interrupt thread + sub r2, lr, #4 @ save old task's pc to r2 + + @ Switch to SVC mode with no interrupt. If the usr mode guest is + @ interrupted, this will just switch to the stack of kernel space. + @ save the registers in kernel space won't trigger data abort. + msr cpsr_c, #I_Bit|F_Bit|Mode_SVC + + stmfd sp!, {r2} @ push old task's pc + stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4 + ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread + stmfd sp!, {r1-r4} @ push old task's r0-r3 + stmfd sp!, {r0} @ push old task's cpsr + + ldr r4, =rt_interrupt_from_thread + ldr r5, [r4] + str sp, [r5] @ store sp in preempted tasks's TCB + + ldr r6, =rt_interrupt_to_thread + ldr r6, [r6] + ldr sp, [r6] @ get new task's stack pointer + + ldmfd sp!, {r4} @ pop new task's cpsr to spsr + msr spsr_cxsf, r4 + + ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr + + +.align 5 +.globl FiqExceptionHandle FiqExceptionHandle: - b FiqIsrEntry +1: + b 1b diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.c b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.c new file mode 100644 index 000000000..de9a52e32 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.c @@ -0,0 +1,75 @@ + +/** + * this function will show registers of CPU + * + * @param regs the registers point + */ +void PrintStackFrame(struct rt_hw_exp_stack *regs) +{ + rt_kprintf("Execption:\n"); + rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3); + rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7); + rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10); + rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip); + rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc); + rt_kprintf("cpsr:0x%08x\n", regs->cpsr); +} + + +/** + * The software interrupt instruction (SWI) is used for entering + * Supervisor mode, usually to request a particular supervisor + * function. + * + * @param regs system registers + * + * @note never invoke this function in application + */ +void rt_hw_trap_swi(struct rt_hw_exp_stack *regs) +{ + +} + +void rt_hw_trap_irq(void) +{ + void *param; + rt_isr_handler_t isr_func; + extern struct rt_irq_desc isr_table[]; + + // vectNum = RESERVED[31:13] | CPUID[12:10] | INTERRUPT_ID[9:0] + // send ack and get ID source + uint32_t vectNum = gic_read_irq_ack(); + + // Check that INT_ID isn't 1023 or 1022 (spurious interrupt) + if (vectNum & 0x0200) + { + gic_write_end_of_irq(vectNum); // send end of irq + } + else + { + // copy the local value to the global image of CPUID + unsigned cpu = (vectNum >> 10) & 0x7; + unsigned irq = vectNum & 0x1FF; + + /* skip warning */ + cpu = cpu; + + // Call the service routine stored in the handlers array. If there isn't + // one for this IRQ, then call the default handler. + /* get interrupt service routine */ + isr_func = isr_table[irq].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[irq].counter++; +#endif + if (isr_func) + { + /* Interrupt for myself. */ + param = isr_table[irq].param; + /* turn to interrupt service routine */ + isr_func(irq, param); + } + + // Signal the end of the irq. + gic_write_end_of_irq(vectNum); + } +} From 6010fe56545b375d011058bdd09e4b2d3db3f0e6 Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Thu, 29 Dec 2022 16:35:23 +0800 Subject: [PATCH 24/33] feat add melsec tcp protocol for control framework, compile OK --- .../control/plc_protocol/melsec/melsec.c | 136 +++++++++++++++++- .../melsec/test_recipe_melsec_1c.json | 33 +++++ .../melsec/test_recipe_melsec_1e.json | 34 +++++ .../melsec/test_recipe_melsec_3c.json | 33 +++++ .../melsec/test_recipe_melsec_3e_iq_r.json | 34 +++++ .../melsec/test_recipe_melsec_3e_q_l.json | 34 +++++ .../Framework/control/shared/control_io.c | 22 +++ .../Framework/control/shared/control_io.h | 6 + 8 files changed, 325 insertions(+), 7 deletions(-) create mode 100644 APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1c.json create mode 100644 APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1e.json create mode 100644 APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3c.json create mode 100644 APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3e_iq_r.json create mode 100644 APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3e_q_l.json diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c index 4a48288d8..465d2b532 100644 --- a/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c +++ b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c @@ -258,7 +258,7 @@ static uint16_t Melsec3eqlGenerateCommand(uint8_t *p_command, uint32_t command_c p_command[index++] = (uint8_t)QEQUEST_DESTINSTION_MODULE_IO_NUMBER; p_command[index++] = (uint8_t)(QEQUEST_DESTINSTION_MODULE_IO_NUMBER >> 8); p_command[index++] = QEQUEST_DESTINSTION_MODULE_STATION_NUMBER; - p_command[index++] = 0x0c; + p_command[index++] = 0x0C; p_command[index++] = 0x00; p_command[index++] = p_read_item->monitoring_timer; p_command[index++] = p_read_item->monitoring_timer >> 8; @@ -502,7 +502,77 @@ int MelsecInitialDataInfo(MelsecReadItem *p_read_item, uint8_t *p_data) */ static int MelsecTransformRecvBuffToData(MelsecReadItem *p_read_item, uint8_t *recv_buff) { + MelsecDataInfo *p_melsec_data_info = &(p_read_item->data_info); + MelsecFrameType frame_type = p_melsec_data_info->frame_type; + MelsecCommandType command_type = p_melsec_data_info->command_type; + uint8_t *p_data = p_melsec_data_info->base_data_info.p_data; + uint16_t device_points_count = p_read_item->device_points_count; + uint8_t is_ascii = ((MELSEC_1E_FRAME == frame_type) || (MELSEC_3E_Q_L_FRAME == frame_type) || (MELSEC_3E_IQ_R_FRAME == frame_type)) ? 0 : 1; + uint16_t abnormal_code = 0; + + switch (frame_type) { + case MELSEC_3E_IQ_R_FRAME: + case MELSEC_3E_Q_L_FRAME: + if (recv_buff[9] != 0 || recv_buff[10] != 0) + abnormal_code = recv_buff[10] * 256 + recv_buff[9]; + else + recv_buff += 11; + break; + case MELSEC_1E_FRAME: + if (recv_buff[1] != 0) + abnormal_code = recv_buff[2]; + else + recv_buff += 2; + break; + case MELSEC_1C_FRAME: + if (MELSEC_NAK == recv_buff[0]) + abnormal_code = recv_buff[5] * 256 + recv_buff[6]; + else + recv_buff += 5; + break; + case MELSEC_3C_FRAME: + if (MELSEC_NAK == recv_buff[0]) + abnormal_code = ((uint16_t)TransformAsciiToHex(recv_buff[11])) << 12 + ((uint16_t)TransformAsciiToHex(recv_buff[12])) << 8 + + ((uint16_t)TransformAsciiToHex(recv_buff[13])) << 4 + ((uint16_t)TransformAsciiToHex(recv_buff[14])); + else + recv_buff += 11; + break; + default: + return -1; + } + + if (abnormal_code != 0) { + printf("Data abnormal, abnormal code is %0x!", abnormal_code); + return -1; + } + + ControlPrintfList("DATA", recv_buff, (uint16_t)(device_points_count * (READ_IN_BITS == command_type ? 0.5 : 2) * (frame_type >= MELSEC_1C_FRAME ? 2 : 1) + 0.6)); + printf("Receive data is "); + for (uint16_t i = 0; i < device_points_count; i++) { + if (READ_IN_BITS == command_type) { + if (!is_ascii) { + p_data[i] = (recv_buff[i / 2] & (i % 2 == 0 ? 0x10 : 0x01)) || 0; + } else { + p_data[i] = TransformAsciiToHex(recv_buff[i]); + } + printf("0x%x", p_data[i]); + } else if (READ_IN_WORD == command_type) { + if (!is_ascii) { + uint16_t recv_buff_index = 2 * (device_points_count - 1 - i); + p_data[2 * i] = recv_buff[recv_buff_index + 1]; + p_data[2 * i + 1] = recv_buff[recv_buff_index]; + } else { + uint16_t recv_buff_index = 4 * (device_points_count - 1 - i); + p_data[2 * i] = TransformAsciiToHex(recv_buff[recv_buff_index]) * 16 + TransformAsciiToHex(recv_buff[recv_buff_index + 1]); + p_data[2 * i + 1] = TransformAsciiToHex(recv_buff[recv_buff_index + 2]) * 16 + TransformAsciiToHex(recv_buff[recv_buff_index + 3]); + } + printf("0x%x 0x%x", p_data[2 * i], p_data[2 * i + 1]); + } + } + printf("\n"); + + return 0; } /** @@ -513,7 +583,41 @@ static int MelsecTransformRecvBuffToData(MelsecReadItem *p_read_item, uint8_t *r */ static int MelsecGetDataBySocket(int32_t socket, MelsecReadItem *p_read_item) { + uint8_t try_count = 0; + int32_t write_error = 0; + MelsecDataInfo *p_melsec_data_info = &(p_read_item->data_info); + BasicPlcDataInfo *p_base_data_info = &(p_melsec_data_info->base_data_info); + + memset(recv_buff, 0, sizeof(recv_buff)); + + while (try_count < 10) { + ControlPrintfList("SEND", p_base_data_info->p_command, p_base_data_info->command_length); + try_count++; + + write_error = socket_write(socket, p_base_data_info->p_command, p_base_data_info->command_length); + if (write_error < 0) { + printf("Write socket error, errno is %d!", errno); + } else { + PrivTaskDelay(20); + + int32_t recv_length = socket_read(socket, recv_buff, sizeof(recv_buff)); + if (recv_length < 0) { + printf("Read socket error, errno is %d!", errno); + } else { + ControlPrintfList("RECV", recv_buff, recv_length); + return MelsecTransformRecvBuffToData(p_read_item, recv_buff); + } + } + + if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) { + printf("Send plc command failed, errno is %d!", errno); + continue; + } else { + return -1; + } + } + return -2; } /** @@ -523,7 +627,20 @@ static int MelsecGetDataBySocket(int32_t socket, MelsecReadItem *p_read_item) */ static int MelsecGetDataBySerial(MelsecReadItem *p_read_item) { + uint32_t read_length = 0; + memset(recv_buff, 0, sizeof(recv_buff)); + MelsecDataInfo *p_melsec_data_info = &(p_read_item->data_info); + BasicPlcDataInfo *p_base_data_info = &(p_melsec_data_info->base_data_info); + + ControlPrintfList("SEND", p_base_data_info->p_command, p_base_data_info->command_length); + SerialWrite(p_base_data_info->p_command, p_base_data_info->command_length); + + read_length = SerialRead(recv_buff, sizeof(recv_buff)); + if (read_length) { + ControlPrintfList("RECV", recv_buff, read_length); + return MelsecTransformRecvBuffToData(p_read_item, recv_buff); + } } /** @@ -552,12 +669,17 @@ void *ReceivePlcDataTask(void *parameter) while (1) { for (i = 0; i < control_protocol->recipe->read_item_count; i ++) { - /*only connect socket when close socket or init*/ - while (ControlConnectSocket(&plc_socket) < 0) { - PrivTaskDelay(1000); - } - MelsecGetDataBySocket(plc_socket.socket, (MelsecReadItem *)melsec_read_item + i); + if ((PROTOCOL_MELSEC_1C == control_protocol->protocol_type) || (PROTOCOL_MELSEC_3C == control_protocol->protocol_type)) { + MelsecGetDataBySerial((MelsecReadItem *)melsec_read_item + i); + } else { + /*only connect socket when close socket or init*/ + while (ControlConnectSocket(&plc_socket) < 0) { + PrivTaskDelay(1000); + } + + MelsecGetDataBySocket(plc_socket.socket, (MelsecReadItem *)melsec_read_item + i); + } } /*read all variable item data, put them into circular_area*/ @@ -638,7 +760,7 @@ int MelsecProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo * melsec_read_item->data_info.command_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "command_type")->valueint; melsec_read_item->data_info.frame_type = p_recipe->protocol_type - PROTOCOL_MELSEC_1E; melsec_read_item->monitoring_timer = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "monitoring_timer")->valueint; - melsec_read_item->device_code = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "device_code")->valuestring; + melsec_read_item->device_code = MelsecGetDeviceCode(melsec_read_item->data_info.frame_type, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "device_code")->valuestring); strncpy(melsec_read_item->head_device_number_string, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "head_device_number_string")->valuestring, 6); melsec_read_item->device_points_count = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "device_points_count")->valueint; diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1c.json b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1c.json new file mode 100644 index 000000000..ee43fe00c --- /dev/null +++ b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1c.json @@ -0,0 +1,33 @@ +{ + "device_id": 769, + "device_name": "S01", + "communication_type": 1, + "serial_config": { + "baud_rate": 19200, + "data_bits": 7, + "stop_bits": 1, + "check_mode": 3 + }, + "protocol_type": 9, + "read_period": 100, + "read_item_list": [ + { + "value_name": "启动", + "value_type": 1, + "device_code": "M", + "head_device_number_string": "0", + "device_points_count": 1, + "command_type": 0, + "monitoring_timer": 100 + }, + { + "value_name": "停止", + "value_type": 1, + "device_code": "M", + "head_device_number_string": "1", + "device_points_count": 1, + "command_type": 0, + "monitoring_timer": 100 + } + ] +} \ No newline at end of file diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1e.json b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1e.json new file mode 100644 index 000000000..964495ef0 --- /dev/null +++ b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1e.json @@ -0,0 +1,34 @@ +{ + "device_id": 771, + "device_name": "S03", + "communication_type": 0, + "socket_config": { + "plc_ip": "192.168.250.20", + "local_ip": "192.168.250.233", + "gateway": "192.168.250.1", + "netmask": "255.255.254.0", + "port": 2000 + }, + "protocol_type": 6, + "read_period": 100, + "read_item_list": [ + { + "value_name": "启动", + "value_type": 1, + "device_code": "M", + "head_device_number_string": "0", + "device_points_count": 1, + "command_type": 0, + "monitoring_timer": 100 + }, + { + "value_name": "停止", + "value_type": 1, + "device_code": "M", + "head_device_number_string": "1", + "device_points_count": 1, + "command_type": 0, + "monitoring_timer": 100 + } + ] +} diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3c.json b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3c.json new file mode 100644 index 000000000..097acbdbd --- /dev/null +++ b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3c.json @@ -0,0 +1,33 @@ +{ + "device_id": 770, + "device_name": "S02", + "communication_type": 1, + "serial_config": { + "baud_rate": 19200, + "data_bits": 7, + "stop_bits": 1, + "check_mode": 3 + }, + "protocol_type": 10, + "read_period": 100, + "read_item_list": [ + { + "value_name": "启动", + "value_type": 1, + "device_code": "M", + "head_device_number_string": "0", + "device_points_count": 1, + "command_type": 0, + "monitoring_timer": 100 + }, + { + "value_name": "停止", + "value_type": 1, + "device_code": "M", + "head_device_number_string": "1", + "device_points_count": 1, + "command_type": 0, + "monitoring_timer": 100 + } + ] +} \ No newline at end of file diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3e_iq_r.json b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3e_iq_r.json new file mode 100644 index 000000000..aa62a5299 --- /dev/null +++ b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3e_iq_r.json @@ -0,0 +1,34 @@ +{ + "device_id": 773, + "device_name": "S05", + "communication_type": 0, + "socket_config": { + "plc_ip": "192.168.250.20", + "local_ip": "192.168.250.233", + "gateway": "192.168.250.1", + "netmask": "255.255.254.0", + "port": 2000 + }, + "protocol_type": 8, + "read_period": 100, + "read_item_list": [ + { + "value_name": "启动", + "value_type": 1, + "device_code": "M", + "head_device_number_string": "0", + "device_points_count": 1, + "command_type": 0, + "monitoring_timer": 100 + }, + { + "value_name": "停止", + "value_type": 1, + "device_code": "M", + "head_device_number_string": "1", + "device_points_count": 1, + "command_type": 0, + "monitoring_timer": 100 + } + ] +} diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3e_q_l.json b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3e_q_l.json new file mode 100644 index 000000000..59c143e0d --- /dev/null +++ b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3e_q_l.json @@ -0,0 +1,34 @@ +{ + "device_id": 772, + "device_name": "S04", + "communication_type": 0, + "socket_config": { + "plc_ip": "192.168.250.20", + "local_ip": "192.168.250.233", + "gateway": "192.168.250.1", + "netmask": "255.255.254.0", + "port": 2000 + }, + "protocol_type": 7, + "read_period": 100, + "read_item_list": [ + { + "value_name": "启动", + "value_type": 1, + "device_code": "M", + "head_device_number_string": "0", + "device_points_count": 1, + "command_type": 0, + "monitoring_timer": 100 + }, + { + "value_name": "停止", + "value_type": 1, + "device_code": "M", + "head_device_number_string": "1", + "device_points_count": 1, + "command_type": 0, + "monitoring_timer": 100 + } + ] +} diff --git a/APP_Framework/Framework/control/shared/control_io.c b/APP_Framework/Framework/control/shared/control_io.c index eb7172883..b1a8ae1c8 100644 --- a/APP_Framework/Framework/control/shared/control_io.c +++ b/APP_Framework/Framework/control/shared/control_io.c @@ -50,3 +50,25 @@ void SerialInit(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_ { // Uart485Init(baud_rate, data_bits, stop_bits, check_mode); } + +/** + * @description: Control Framework Serial Write + * @param write_data - write data + * @param length - length + * @return + */ +void SerialWrite(uint8_t *write_data, int length) +{ + //to do +} + +/** + * @description: Control Framework Serial Read + * @param read_data - read data + * @param length - length + * @return + */ +int SerialRead(uint8_t *read_data, int length) +{ + //to do +} diff --git a/APP_Framework/Framework/control/shared/control_io.h b/APP_Framework/Framework/control/shared/control_io.h index 52c501486..ada560ae2 100644 --- a/APP_Framework/Framework/control/shared/control_io.h +++ b/APP_Framework/Framework/control/shared/control_io.h @@ -44,6 +44,12 @@ void SocketInit(char *ip, char *mask, char *gw); /*Control Framework Serial Init*/ void SerialInit(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_t check_mode); +/*Control Framework Serial Write*/ +void SerialWrite(uint8_t *write_data, int length); + +/*Control Framework Serial Read*/ +int SerialRead(uint8_t *read_data, int length); + #ifdef __cplusplus } #endif From 6b091797aee0369f7aa51918d33fb0a2572f32e3 Mon Sep 17 00:00:00 2001 From: Wang_Weigen Date: Fri, 30 Dec 2022 17:59:41 +0800 Subject: [PATCH 25/33] =?UTF-8?q?1=E3=80=81add=20'menuconfig'=20function?= =?UTF-8?q?=20for=20XiZi=5FAIoT=20with=20imx6q-sabrelite=20board;2?= =?UTF-8?q?=E3=80=81add=20compilation=20function=20for=20AIoT=20system=20w?= =?UTF-8?q?ith=20imx6q-sabrelite=20board;3=E3=80=81add=20newlib=20base=20f?= =?UTF-8?q?iles;4=E3=80=81add=20startup=20files=20and=20irq=20function=20f?= =?UTF-8?q?or=20imx6q-sabrelite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ubiquitous/XiZi_AIoT/Kconfig | 6 + Ubiquitous/XiZi_AIoT/Makefile | 144 ++++++++ Ubiquitous/XiZi_AIoT/compiler.mk | 127 +++++++ Ubiquitous/XiZi_AIoT/hardkernel/Makefile | 3 + .../XiZi_AIoT/hardkernel/abstraction/Makefile | 3 + .../hardkernel/abstraction/interrupt.c | 45 --- .../XiZi_AIoT/hardkernel/abstraction/isr.c | 215 ++++++++++++ .../XiZi_AIoT/hardkernel/abstraction/isr.h | 98 ++++++ Ubiquitous/XiZi_AIoT/hardkernel/arch/Kconfig | 13 + Ubiquitous/XiZi_AIoT/hardkernel/arch/Makefile | 3 + .../XiZi_AIoT/hardkernel/arch/arm/Makefile | 4 + .../hardkernel/arch/arm/armv7-a/Makefile | 8 + .../arch/arm/armv7-a/cortex-a9/Makefile | 3 + .../arm/armv7-a/cortex-a9/arch_interrupt.h | 46 +++ .../arch/arm/armv7-a/cortex-a9/boot.S | 37 +- .../arch/arm/armv7-a/cortex-a9/cortexA9.S | 327 ++++++++++++++++++ .../arch/arm/armv7-a/cortex-a9/cortex_a9.h | 230 ++++++++++++ .../arch/arm/armv7-a/cortex-a9/exception.S | 82 +++-- .../arch/arm/armv7-a/cortex-a9/exception.c | 75 ---- .../arch/arm/armv7-a/cortex-a9/gic.c | 4 +- .../arch/arm/armv7-a/cortex-a9/gic.h | 183 ++++++++++ .../arch/arm/armv7-a/cortex-a9/interrupt.c | 92 +++++ Ubiquitous/XiZi_AIoT/link.mk | 10 + Ubiquitous/XiZi_AIoT/path_kernel.mk | 51 +++ Ubiquitous/XiZi_AIoT/services/Kconfig | 4 + Ubiquitous/XiZi_AIoT/services/Makefile | 6 + Ubiquitous/XiZi_AIoT/services/boards/Makefile | 4 + .../services/boards/imx6q-sabrelite/.config | 18 + .../services/boards/imx6q-sabrelite/Kconfig | 26 ++ .../services/boards/imx6q-sabrelite/Makefile | 8 + .../services/boards/imx6q-sabrelite/board.c | 4 + .../services/boards/imx6q-sabrelite/board.h | 6 + .../services/boards/imx6q-sabrelite/config.mk | 23 ++ .../imx6q-sabrelite/include/asm_defines.h | 94 +++++ .../imx6q-sabrelite/include/sdk_types.h | 125 +++++++ .../services/boards/imx6q-sabrelite/link.lds | 96 +++++ .../third_party_driver/Kconfig} | 0 .../third_party_driver/Makefile | 4 + .../boards/imx6q-sabrelite/xsconfig.h | 18 + Ubiquitous/XiZi_AIoT/services/drivers/Kconfig | 0 .../XiZi_AIoT/services/drivers/Makefile | 4 + Ubiquitous/XiZi_AIoT/services/fs/Kconfig | 0 Ubiquitous/XiZi_AIoT/services/lib/Kconfig | 23 ++ Ubiquitous/XiZi_AIoT/services/lib/Makefile | 14 + .../XiZi_AIoT/services/lib/newlib/Kconfig | 6 + .../XiZi_AIoT/services/lib/newlib/Makefile | 5 + .../services/lib/newlib/fs_syscalls.c | 156 +++++++++ .../services/lib/newlib/include/libc.h | 29 ++ .../services/lib/newlib/mem_syscalls.c | 78 +++++ .../XiZi_AIoT/services/lib/newlib/stdio.c | 156 +++++++++ .../services/lib/newlib/task_syscalls.c | 44 +++ .../services/lib/newlib/time_syscalls.c | 42 +++ .../services/tools/hosttools/xsconfig.sh | 91 +++++ Ubiquitous/XiZi_AIoT/softkernel/Kconfig | 0 Ubiquitous/XiZi_AIoT/softkernel/Makefile | 4 + Ubiquitous/XiZi_AIoT/softkernel/task/Makefile | 3 + Ubiquitous/XiZi_AIoT/support/Kconfig | 0 Ubiquitous/XiZi_AIoT/support/Makefile | 4 + Ubiquitous/XiZi_AIoT/testing/Kconfig | 0 Ubiquitous/XiZi_AIoT/testing/Makefile | 4 + 60 files changed, 2726 insertions(+), 182 deletions(-) create mode 100644 Ubiquitous/XiZi_AIoT/compiler.mk create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/abstraction/Makefile delete mode 100755 Ubiquitous/XiZi_AIoT/hardkernel/abstraction/interrupt.c create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/abstraction/isr.c create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/abstraction/isr.h create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/arch/Kconfig create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/arch/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/arch_interrupt.h create mode 100755 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/cortexA9.S create mode 100755 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/cortex_a9.h delete mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.c create mode 100644 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic.h create mode 100755 Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/interrupt.c create mode 100644 Ubiquitous/XiZi_AIoT/link.mk create mode 100755 Ubiquitous/XiZi_AIoT/path_kernel.mk create mode 100644 Ubiquitous/XiZi_AIoT/services/Kconfig create mode 100644 Ubiquitous/XiZi_AIoT/services/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/.config create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Kconfig create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/board.c create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/board.h create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/config.mk create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/include/asm_defines.h create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/include/sdk_types.h create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/link.lds rename Ubiquitous/XiZi_AIoT/services/{lib/xxx.c => boards/imx6q-sabrelite/third_party_driver/Kconfig} (100%) create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/third_party_driver/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/xsconfig.h create mode 100644 Ubiquitous/XiZi_AIoT/services/drivers/Kconfig create mode 100644 Ubiquitous/XiZi_AIoT/services/drivers/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/services/fs/Kconfig create mode 100644 Ubiquitous/XiZi_AIoT/services/lib/Kconfig create mode 100644 Ubiquitous/XiZi_AIoT/services/lib/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/services/lib/newlib/Kconfig create mode 100644 Ubiquitous/XiZi_AIoT/services/lib/newlib/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/services/lib/newlib/fs_syscalls.c create mode 100644 Ubiquitous/XiZi_AIoT/services/lib/newlib/include/libc.h create mode 100644 Ubiquitous/XiZi_AIoT/services/lib/newlib/mem_syscalls.c create mode 100644 Ubiquitous/XiZi_AIoT/services/lib/newlib/stdio.c create mode 100644 Ubiquitous/XiZi_AIoT/services/lib/newlib/task_syscalls.c create mode 100644 Ubiquitous/XiZi_AIoT/services/lib/newlib/time_syscalls.c create mode 100755 Ubiquitous/XiZi_AIoT/services/tools/hosttools/xsconfig.sh create mode 100644 Ubiquitous/XiZi_AIoT/softkernel/Kconfig create mode 100644 Ubiquitous/XiZi_AIoT/softkernel/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/softkernel/task/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/support/Kconfig create mode 100644 Ubiquitous/XiZi_AIoT/support/Makefile create mode 100644 Ubiquitous/XiZi_AIoT/testing/Kconfig create mode 100644 Ubiquitous/XiZi_AIoT/testing/Makefile diff --git a/Ubiquitous/XiZi_AIoT/Kconfig b/Ubiquitous/XiZi_AIoT/Kconfig index e69de29bb..41ca9e96c 100644 --- a/Ubiquitous/XiZi_AIoT/Kconfig +++ b/Ubiquitous/XiZi_AIoT/Kconfig @@ -0,0 +1,6 @@ + +source "$KERNEL_DIR/services/Kconfig" +source "$KERNEL_DIR/softkernel/Kconfig" +source "$KERNEL_DIR/support/Kconfig" +source "$KERNEL_DIR/testing/Kconfig" + diff --git a/Ubiquitous/XiZi_AIoT/Makefile b/Ubiquitous/XiZi_AIoT/Makefile index e69de29bb..dfe98fe0d 100755 --- a/Ubiquitous/XiZi_AIoT/Makefile +++ b/Ubiquitous/XiZi_AIoT/Makefile @@ -0,0 +1,144 @@ +MAKEFLAGS += --no-print-directory + +.PHONY:all clean distclean show_info menuconfig +.PHONY:COMPILE_APP COMPILE_KERNEL + +riscv_support := +arm_support += imx6q-sabrelite +emulator_support += +support := $(riscv_support) $(arm_support) $(emulator_support) +SRC_DIR := + +export BOARD ?=imx6q-sabrelite +# This is the environment variable for kconfig-mconf +export KCONFIG_CONFIG ?= .config + +ifeq ($(filter $(BOARD),$(support)),) +$(warning "You should choose board like this: make BOARD=imx6q-sabrelite") +$(warning "This is what we support:") +$(warning "RISCV EVB: $(riscv_support)") +$(warning "ARM EVB: $(arm_support)") +$(warning "EMULATORS: $(emulator_support)") +# $(warning "$(support)") +$(error "break" ) +endif + +export TARGET +export COMPILE_TYPE +export KERNEL_ROOT ?=$(strip $(shell pwd)) + +MAKEFILES =$(KERNEL_ROOT)/.config +-include $(KERNEL_ROOT)/.config + +export BSP_ROOT ?= $(KERNEL_ROOT)/services/boards/$(BOARD) +export UBIQUITOUS_ROOT ?= .. +include services/boards/$(BOARD)/config.mk +export BSP_BUILD_DIR := boards/$(BOARD) +export HOSTTOOLS_DIR ?= $(KERNEL_ROOT)/services/tools/hosttools +export CONFIG2H_EXE ?= $(HOSTTOOLS_DIR)/xsconfig.sh + +export CPPPATHS +export SRC_APP_DIR := ../../APP_Framework +export SRC_KERNEL_DIR := hardkernel services softkernel support testing +# export SRC_DIR:= $(SRC_APP_DIR) $(SRC_KERNEL_DIR) +export SRC_DIR:= $(SRC_KERNEL_DIR) +export LIBCC +export MUSL_DIR := $(KERNEL_ROOT)/services/lib/musllib + +PART:= + +all: +ifeq ($(CONFIG_COMPILER_APP)_$(CONFIG_COMPILER_KERNEL),y_) +PART += COMPILE_APP + +else ifeq ($(CONFIG_COMPILER_APP)_$(CONFIG_COMPILER_KERNEL),_y) +PART += COMPILE_KERNEL + +else ifeq ($(CONFIG_COMPILER_APP)_$(CONFIG_COMPILER_KERNEL),y_y) +PART := COMPILE_APP COMPILE_KERNEL + +else + +ifeq ($(CONFIG_LIB_MUSLLIB), y) +PART += COMPILE_MUSL +endif + +PART += COMPILE_ALL +endif + + +all: $(PART) + + +COMPILE_ALL: + @for dir in $(SRC_DIR);do \ + $(MAKE) -C $$dir; \ + done + @cp link.mk build/Makefile + @$(MAKE) -C build TARGET=XiZi-$(BOARD).elf LINK_FLAGS=LFLAGS + @rm build/Makefile build/make.obj + +COMPILE_MUSL: + @for dir in $(MUSL_DIR);do \ + $(MAKE) -C $$dir COMPILE_TYPE=$@ CONFIG_RESOURCES_LWIP=n; \ + done + @cp link_libc.mk build/Makefile + @$(MAKE) -C build TARGET=libmusl.a LINK_FLAGS=LFLAGS + @cp build/libmusl.a $(KERNEL_ROOT)/lib/musllib/libmusl.a + @rm build/Makefile build/make.obj + +COMPILE_KERNEL: + @for dir in $(SRC_KERNEL_DIR);do \ + $(MAKE) -C $$dir; \ + done + @cp link.mk build/Makefile + @$(MAKE) -C build COMPILE_TYPE="_kernel" TARGET=XiZi-$(BOARD)_kernel.elf LINK_FLAGS=LFLAGS + @rm build/Makefile build/make.obj + +COMPILE_APP: + @echo $(SRC_APP_DIR) + @for dir in $(SRC_APP_DIR);do \ + $(MAKE) -C $$dir USE_APP_INCLUDEPATH=y; \ + done + @cp link.mk build/Makefile + @$(MAKE) -C build COMPILE_TYPE="_app" TARGET=XiZi-$(BOARD)_app.elf LINK_FLAGS=APPLFLAGS + @rm build/Makefile build/make.obj + +show_info: + @echo "CONFIG_COMPILER_APP is :" $(CONFIG_COMPILER_APP) + @echo "CONFIG_COMPILER_KERNEL is :" $(CONFIG_COMPILER_KERNEL) + @echo "KERNELPATHS is :" $(KERNELPATHS) + @echo "TARGET is :" $(TARGET) + @echo "VPATH is :" $(VPATH) + @echo "BSP_ROOT is :" $(BSP_ROOT) + @echo "KERNEL_ROOT is :" $(KERNEL_ROOT) + @echo "CPPPATHS is :" $(CPPPATHS) + @echo "SRC_DIR is :" $(SRC_DIR) + @echo "BUILD_DIR is :" $(BUILD_DIR) + @echo "BSP_BUILD_DIR is :" $(BSP_BUILD_DIR) + @echo "OBJS is :" $(OBJS) + @for f in $(CPPPATHS); do \ + echo $$f; \ + done + +menuconfig: + @if [ -f "$(BSP_ROOT)/.config" ]; then \ + cp $(BSP_ROOT)/.config $(KERNEL_ROOT)/.config; \ + else if [ -f "$(BSP_ROOT)/.defconfig" ]; then \ + cp $(BSP_ROOT)/.defconfig $(KERNEL_ROOT)/.config ;\ + fi ;fi + @kconfig-mconf $(BSP_ROOT)/Kconfig + @$(CONFIG2H_EXE) .config + @cp $(KERNEL_ROOT)/.config $(BSP_ROOT)/.config + +clean: + @echo Clean target and build_dir + @rm -rf build + @rm -rf temp.txt + +distclean: + @echo Clean all configuration + @make clean + @rm -f .config* + @rm -f $(KERNEL_ROOT)/lib/musllib/libmusl.a + @rm -f $(KERNEL_ROOT)/board/*/.config diff --git a/Ubiquitous/XiZi_AIoT/compiler.mk b/Ubiquitous/XiZi_AIoT/compiler.mk new file mode 100644 index 000000000..f217a06b0 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/compiler.mk @@ -0,0 +1,127 @@ +ifeq ($(COMPILE_TYPE), COMPILE_MUSL) +SRC_DIR_TEMP := $(MUSL_DIR) +else ifeq ($(COMPILE_TYPE), COMPILE_LWIP) +SRC_DIR_TEMP := $(LWIP_DIR) +else +SRC_DIR_TEMP := $(SRC_DIR) +endif + +SRC_DIR := +MUSL_DIR := +LWIP_DIR := + +ifeq ($(USE_APP_INCLUDEPATH), y) + include $(KERNEL_ROOT)/path_app.mk +else + include $(KERNEL_ROOT)/path_kernel.mk +endif +export CPPPATHS := $(KERNELPATHS) + +CUR_DIR :=$(shell pwd) + +CFLAGS += $(CPPPATHS) +AFLAGS += $(CPPPATHS) +CXXFLAGS += $(CPPPATHS) + +CFLAGS += $(DEFINES) +AFLAGS += $(DEFINES) +CXXFLAGS += $(DEFINES) +BUILD_DIR := $(KERNEL_ROOT)/build +APP_DIR := Ubiquitous/XiZi + + +.PHONY:COMPILER +COMPILER: + @if [ "${SRC_DIR_TEMP}" != "" ]; then \ + for dir in $(SRC_DIR_TEMP);do \ + $(MAKE) -C $$dir; \ + done; \ + fi + @/bin/echo -n $(OBJS) " " >> $(KERNEL_ROOT)/build/make.obj + + +################################################ +define add_c_file +$(eval COBJ := $(1:%.c=%.o)) \ +$(eval COBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(COBJ))) \ +$(eval LOCALC := $(addprefix $(BUILD_DIR)/,$(COBJ))) \ +$(eval OBJS += $(LOCALC)) \ +$(if $(strip $(LOCALC)),$(eval $(LOCALC): $(1) + @if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi + @echo cc $$< + @/bin/echo -n $(dir $(LOCALC)) >>$(KERNEL_ROOT)/build/make.dep + @($(CROSS_COMPILE)gcc -MM $$(CFLAGS) -c $$<) >>$(KERNEL_ROOT)/build/make.dep + @$(CROSS_COMPILE)gcc $$(CFLAGS) -c $$< -o $$@)) +endef + +define add_cpp_file +$(eval COBJ := $(1:%.cpp=%.o)) \ +$(eval COBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(COBJ))) \ +$(eval LOCALCPP := $(addprefix $(BUILD_DIR)/,$(COBJ))) \ +$(eval OBJS += $(LOCALCPP)) \ +$(if $(strip $(LOCALCPP)),$(eval $(LOCALCPP): $(1) + @if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi + @echo cc $$< + @/bin/echo -n $(dir $(LOCALCPP)) >>$(KERNEL_ROOT)/build/make.dep + @$(CROSS_COMPILE)g++ -MM $$(CXXFLAGS) -c $$< >>$(KERNEL_ROOT)/build/make.dep + @$(CROSS_COMPILE)g++ $$(CXXFLAGS) -c $$< -o $$@)) +endef + +define add_cc_file +$(eval COBJ := $(1:%.cc=%.o)) \ +$(eval COBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(COBJ))) \ +$(eval LOCALCPP := $(addprefix $(BUILD_DIR)/,$(COBJ))) \ +$(eval OBJS += $(LOCALCPP)) \ +$(if $(strip $(LOCALCPP)),$(eval $(LOCALCPP): $(1) + @if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi + @echo cc $$< + @/bin/echo -n $(dir $(LOCALCPP)) >>$(KERNEL_ROOT)/build/make.dep + @$(CROSS_COMPILE)g++ -MM $$(CXXFLAGS) -c $$< >>$(KERNEL_ROOT)/build/make.dep + @$(CROSS_COMPILE)g++ $$(CXXFLAGS) -c $$< -o $$@)) +endef + +define add_S_file +$(eval SOBJ := $(1:%.S=%.o)) \ +$(eval SOBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(SOBJ))) \ +$(eval LOCALS := $(addprefix $(BUILD_DIR)/,$(SOBJ))) \ +$(eval OBJS += $(LOCALS)) \ +$(if $(strip $(LOCALS)),$(eval $(LOCALS): $(1) + @if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi + @echo cc $$< + @/bin/echo -n $(dir $(LOCALC)) >>$(KERNEL_ROOT)/build/make.dep + @$(CROSS_COMPILE)gcc -MM $$(CFLAGS) -c $$< >>$(KERNEL_ROOT)/build/make.dep + @$(CROSS_COMPILE)gcc $$(AFLAGS) -c $$< -o $$@)) +endef + +define add_a_file +$(eval SOBJ := $(1:%.a=%.a)) \ +$(eval SOBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(SOBJ))) \ +$(eval LOCALA := $(addprefix $(BUILD_DIR)/,$(SOBJ))) \ +$(eval OBJS += $(LOCALA)) \ +$(if $(strip $(LOCALA)),$(eval $(LOCALA): $(1) + @if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi + @echo cp $$< + @cp $$< $$@)) +endef + + +SRCS := $(strip $(filter %.c,$(SRC_FILES))) +$(if $(SRCS),$(foreach f,$(SRCS),$(call add_c_file,$(addprefix $(CUR_DIR)/,$(f))))) + +SRCS := $(strip $(filter %.cpp,$(SRC_FILES))) +$(if $(SRCS),$(foreach f,$(SRCS),$(call add_cpp_file,$(addprefix $(CUR_DIR)/,$(f))))) + +SRCS := $(strip $(filter %.cc,$(SRC_FILES))) +$(if $(SRCS),$(foreach f,$(SRCS),$(call add_cc_file,$(addprefix $(CUR_DIR)/,$(f))))) + +SRCS := $(strip $(filter %.S,$(SRC_FILES))) +$(if $(SRCS),$(foreach f,$(SRCS),$(call add_S_file,$(addprefix $(CUR_DIR)/,$(f))))) + +SRCS := $(strip $(filter %.a,$(SRC_FILES))) +$(if $(SRCS),$(foreach f,$(SRCS),$(call add_a_file,$(addprefix $(CUR_DIR)/,$(f))))) + +COMPILER:$(OBJS) + + + +-include $(KERNEL_ROOT)/build/make.dep diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/Makefile b/Ubiquitous/XiZi_AIoT/hardkernel/Makefile new file mode 100644 index 000000000..f4c927675 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/Makefile @@ -0,0 +1,3 @@ +SRC_DIR := arch abstraction + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/Makefile b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/Makefile new file mode 100644 index 000000000..262587f99 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := cache.c isr.c mmu.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/interrupt.c b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/interrupt.c deleted file mode 100755 index 2d44ea94b..000000000 --- a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/interrupt.c +++ /dev/null @@ -1,45 +0,0 @@ -extern void _svcall(uintptr_t* contex); - -x_base __attribute__((naked)) DisableLocalInterrupt() -{ - -} - -void __attribute__((naked)) EnableLocalInterrupt(x_base level) -{ - -} - -int32 ArchEnableHwIrq(uint32_t irq_num) -{ - - return EOK; -} - -int32 ArchDisableHwIrq(uint32_t irq_num) -{ - return EOK; -} - -extern void KTaskOsAssignAfterIrq(void *context); - -void IsrEntry() -{ - uint32_t ipsr; - - // __asm__ volatile("MRS %0, IPSR" : "=r"(ipsr)); - - isrManager.done->incCounter(); - isrManager.done->handleIrq(ipsr); - KTaskOsAssignAfterIrq(NONE); - isrManager.done->decCounter(); - -} - -uintptr_t *Svcall(unsigned int ipsr, uintptr_t* contex ) -{ -#ifdef TASK_ISOLATION - _svcall(contex); -#endif - return contex; -} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/isr.c b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/isr.c new file mode 100644 index 000000000..54804bfac --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/isr.c @@ -0,0 +1,215 @@ +/* +* 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. +*/ + +/** +* @file: isr.c +* @brief: the general management of system isr +* @version: 1.0 +* @author: AIIT XUOS Lab +* @date: 2020/3/15 +* +*/ +#include +#include "isr.h" + +struct InterruptServiceRoutines isrManager = {0} ; + +#ifdef ARCH_SMP +extern int GetCpuId(void); +#endif +/** + * This functionwill get the isr nest level. + * + * @return isr nest level + */ +static uint16_t GetIsrCounter() +{ + uint16_t ret = 0; + +#ifdef ARCH_SMP + ret = isrManager.isr_count[GetCpuId()]; +#else + ret = isrManager.isr_count; +#endif + return ret; +} + +static void IncIsrCounter() +{ +#ifdef ARCH_SMP + isrManager.isr_count[GetCpuId()] ++ ; +#else + isrManager.isr_count ++; +#endif + return ; +} + +static void DecIsrCounter() +{ + +#ifdef ARCH_SMP + isrManager.isr_count[GetCpuId()] -- ; +#else + isrManager.isr_count --; +#endif + return ; +} + +bool IsInIsr() +{ +#ifdef ARCH_SMP + return ( isrManager.isr_count[GetCpuId()] != 0 ? TRUE : FALSE ) ; +#else + return ( isrManager.isr_count != 0 ? TRUE : FALSE ) ; +#endif + +} +/** + * This function will register a new irq. + * + * @param irq_num the number of the irq + * @param handler the callback of the interrupt + * @param arg param of thge callback + * + * @return 0 on success; -1 on failure + */ +static int32_t RegisterHwIrq(uint32_t irq_num, IsrHandlerType handler, void *arg) +{ + if (irq_num >= ARCH_MAX_IRQ_NUM ) + return -1; + + struct IrqDesc *desc = &isrManager.irq_table[irq_num]; + + desc->handler = handler; + desc->param = arg; + + return 0; +} +/** + * This function will free a irq. + * + * @param irq_num the number of the irq + * + * @return 0 on success; -1 on failure + */ +static int32_t FreeHwIrq(uint32_t irq_num) +{ + if (irq_num >= ARCH_MAX_IRQ_NUM ) + return -1; + + memset(&isrManager.irq_table[irq_num], 0, sizeof(struct IrqDesc)); + + return 0; +} + +/** + * This function will enable a irq. + * + * @param irq_num the number of the irq + * + * @return 0 on success; -1 on failure + */ +static int32_t EnableHwIrq(uint32_t irq_num) +{ + if (irq_num >= ARCH_MAX_IRQ_NUM ) + return -1; + + return ArchEnableHwIrq(irq_num); +} +/** + * This function will disable a irq. + * + * @param irq_num the number of the irq + * + * @return 0 on success; -1 on failure + */ + +static int32_t DisableHwIrq(uint32_t irq_num) +{ + if (irq_num >= ARCH_MAX_IRQ_NUM ) + return -1; + + return ArchDisableHwIrq(irq_num); +} + +/* called from arch-specific ISR wrapper */ +static void IsrCommon(uint32_t irq_num) +{ + struct IrqDesc *desc = &isrManager.irq_table[irq_num]; + + if (desc->handler == NULL) { + // SYS_KDEBUG_LOG(KDBG_IRQ, ("Spurious interrupt: IRQ No. %d\n", irq_num)); + while (1) {} + } + desc->handler(irq_num, desc->param); + +} + +static void SetIsrSwitchTrigerFlag() +{ + +#ifdef ARCH_SMP + isrManager.isr_switch_trigger_flag[GetCpuId()] = 1; +#else + isrManager.isr_switch_trigger_flag = 1; +#endif +} + +static void ClearIsrSwitchTrigerFlag() +{ + +#ifdef ARCH_SMP + isrManager.isr_switch_trigger_flag[GetCpuId()] = 0; +#else + isrManager.isr_switch_trigger_flag = 0; +#endif +} + +static uint8_t GetIsrSwitchTrigerFlag() +{ + +#ifdef ARCH_SMP + return isrManager.isr_switch_trigger_flag[GetCpuId()]; +#else + return isrManager.isr_switch_trigger_flag ; +#endif +} + +struct IsrDone isrDone = { + IsInIsr, + RegisterHwIrq , + FreeHwIrq, + EnableHwIrq, + DisableHwIrq, + IsrCommon, + GetIsrCounter, + IncIsrCounter, + DecIsrCounter, + GetIsrSwitchTrigerFlag, + SetIsrSwitchTrigerFlag, + ClearIsrSwitchTrigerFlag +}; + +void SysInitIsrManager() +{ + extern int __isrtbl_idx_start; + extern int __isrtbl_start; + extern int __isrtbl_end; + memset(&isrManager,0,sizeof(struct InterruptServiceRoutines)); + isrManager.done = &isrDone; + + uint32_t *index = (uint32_t *)&__isrtbl_idx_start; + struct IrqDesc *desc = (struct IrqDesc *)&__isrtbl_start; + + while (desc != (struct IrqDesc *)&__isrtbl_end) + isrManager.irq_table[*index++] = *desc++; +} diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/isr.h b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/isr.h new file mode 100644 index 000000000..edd939952 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/isr.h @@ -0,0 +1,98 @@ +/* +* 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. +*/ + +/** +* @file: isr.h +* @brief: function declaration and structure defintion of isr +* @version: 1.0 +* @author: AIIT XUOS Lab +* @date: 2020/3/10 +* +*/ + +#ifndef __ISR_H__ +#define __ISR_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define DECLARE_HW_IRQ(_irq_num, _handler, _arg) \ + const uint32_t __irq_desc_idx_##_handler SECTION(".isrtbl.idx") = _irq_num + ARCH_IRQ_NUM_OFFSET ; \ + const struct IrqDesc __irq_desc_##_handler SECTION(".isrtbl") = { \ + .handler = _handler, \ + .param = _arg, \ + } + +typedef void (*IsrHandlerType)(int vector, void *param); + +struct IrqDesc +{ + IsrHandlerType handler; + void *param; + +#ifdef CONFIG_INTERRUPT_INFO + char name[NAME_NUM_MAX]; + uint32_t counter; +#endif +}; + +struct IsrDone +{ + bool (*isInIsr)(); + int32_t (*registerIrq)(uint32_t irq_num, IsrHandlerType handler, void *arg); + int32_t (*freeIrq)(uint32_t irq_num); + int32_t (*enableIrq)(uint32_t irq_num); + int32_t (*disableIrq)(uint32_t irq_num); + void (*handleIrq)(uint32_t irq_num); + uint16_t (*getCounter)() ; + void (*incCounter)(); + void (*decCounter)(); + uint8_t (*getSwitchTrigerFlag)(); + void (*setSwitchTrigerFlag)(); + void (*clearSwitchTrigerFlag)(); +}; + +struct InterruptServiceRoutines { + +#ifdef ARCH_SMP + volatile uint16_t isr_count[CPU_NUMBERS]; + volatile uint8_t isr_switch_trigger_flag[CPU_NUMBERS]; +#else + volatile uint16_t isr_count ; + volatile uint8_t isr_switch_trigger_flag; +#endif + struct IrqDesc irq_table[ARCH_MAX_IRQ_NUM]; + struct IsrDone *done; +}; + +extern struct InterruptServiceRoutines isrManager ; + +unsigned long DisableLocalInterrupt(); +void EnableLocalInterrupt(unsigned long level); + +#define DISABLE_INTERRUPT DisableLocalInterrupt +#define ENABLE_INTERRUPT EnableLocalInterrupt + +void SysInitIsrManager(); +void InitHwinterrupt(void); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/Kconfig b/Ubiquitous/XiZi_AIoT/hardkernel/arch/Kconfig new file mode 100644 index 000000000..42e27ec53 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/Kconfig @@ -0,0 +1,13 @@ +config ARCH_CPU_64BIT + bool + +config ARCH_RISCV + bool + +config ARCH_ARM + bool + +config ARCH_RISCV64 + select ARCH_RISCV + select ARCH_CPU_64BIT + bool \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/Makefile b/Ubiquitous/XiZi_AIoT/hardkernel/arch/Makefile new file mode 100644 index 000000000..f629b85ec --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/Makefile @@ -0,0 +1,3 @@ +SRC_DIR := $(ARCH) + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/Makefile b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/Makefile new file mode 100644 index 000000000..c064ef38b --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/Makefile @@ -0,0 +1,4 @@ +# The following three platforms support compatiable instructions. +SRC_DIR := $(ARCH_ARMV) + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/Makefile b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/Makefile new file mode 100644 index 000000000..ed2a80a34 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/Makefile @@ -0,0 +1,8 @@ +# The following three platforms support compatiable instructions. + +ifeq ($(CONFIG_BOARD_IMX6Q_SABRELITE_EVB),y) +SRC_DIR := cortex-a9 +endif + + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/Makefile b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/Makefile new file mode 100644 index 000000000..7fc4ffac4 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := boot.S cache.S exception.S cortexA9.S gic.c interrupt.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/arch_interrupt.h b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/arch_interrupt.h new file mode 100644 index 000000000..95233993c --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/arch_interrupt.h @@ -0,0 +1,46 @@ +/* +* 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 ARCH_INTERRUPT_H__ +#define ARCH_INTERRUPT_H__ + +#include +#include +#include "gic.h" + +#define ARCH_MAX_IRQ_NUM PLATFORM_MAX_IRQ_NR + +int32_t ArchEnableHwIrq(uint32_t irq_num); +int32_t ArchDisableHwIrq(uint32_t irq_num); + +struct ExceptionStackRegister +{ + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + uint32_t r13_sp; + uint32_t r14_lr; + uint32_t r15_pc; + uint32_t cpsr; +}; + +#endif diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S index 3731ef6b8..a10b5ef7a 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S @@ -1,20 +1,21 @@ -.equ Mode_USR, 0x10 -.equ Mode_FIQ, 0x11 -.equ Mode_IRQ, 0x12 -.equ Mode_SVC, 0x13 -.equ Mode_ABT, 0x17 -.equ Mode_UND, 0x1B -.equ Mode_SYS, 0x1F +@ .equ Mode_USR, 0x10 +@ .equ Mode_FIQ, 0x11 +@ .equ Mode_IRQ, 0x12 +@ .equ Mode_SVC, 0x13 +@ .equ Mode_ABT, 0x17 +@ .equ Mode_UND, 0x1B +@ .equ Mode_SYS, 0x1F +#include -.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled -.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled +@ .equ I_BIT, 0x80 @ when I bit is set, IRQ is disabled +@ .equ F_BIT, 0x40 @ when F bit is set, FIQ is disabled .equ STACK_SIZE, 0x00000100 -.globl _start +.globl _reset -_start: +_reset: /* set the cpu to SVC32 mode and disable interrupt */ mrs r0, cpsr @@ -36,32 +37,32 @@ _start: mov sp, r0 @ Enter Undefined Instruction Mode and set its Stack Pointer - msr cpsr_c, #Mode_UND|I_Bit|F_Bit + msr cpsr_c, #MODE_UND|I_BIT|F_BIT mov sp, r0 sub r0, r0, #STACK_SIZE @ Enter Abort Mode and set its Stack Pointer - msr cpsr_c, #Mode_ABT|I_Bit|F_Bit + msr cpsr_c, #MODE_ABT|I_BIT|F_BIT mov sp, r0 sub r0, r0, #STACK_SIZE @ Enter FIQ Mode and set its Stack Pointer - msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit + msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT mov sp, r0 sub r0, r0, #STACK_SIZE @ Enter IRQ Mode and set its Stack Pointer - msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit + msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT mov sp, r0 sub r0, r0, #STACK_SIZE /* come back to SVC mode */ - msr cpsr_c, #Mode_SVC|I_Bit|F_Bit + msr cpsr_c, #MODE_SVC|I_BIT|F_BIT /* clear .bss */ mov r0, #0 /* get a zero */ - ldr r1,=BSS_START /* bss start */ - ldr r2,=BSS_END /* bss end */ + ldr r1,=__bss_start /* bss start */ + ldr r2,=__bss_end /* bss end */ bss_loop: cmp r1,r2 /* check if data to clear */ diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/cortexA9.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/cortexA9.S new file mode 100755 index 000000000..ce34242fc --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/cortexA9.S @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2010-2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*! + * @file cortexA9.s + * @brief This file contains cortexA9 functions + * + */ + + .code 32 + .section ".text","ax" + +/* + * bool arm_set_interrupt_state(bool enable) + */ + .global arm_set_interrupt_state + .func arm_set_interrupt_state +arm_set_interrupt_state: + mrs r2,CPSR @ read CPSR (Current Program Status Register) + teq r0,#0 + bicne r1,r2,#0xc0 @ disable IRQ and FIQ + orreq r1,r2,#0xc0 @ enable IRQ and FIQ + msr CPSR_c,r1 + tst r2,#0x80 + movne r0,#0 + moveq r0,#1 + bx lr + .endfunc + + .global cpu_get_current + @ int cpu_get_current(void)@ + @ get current CPU ID + .func cpu_get_current +cpu_get_current: + mrc p15, 0, r0, c0, c0, 5 + and r0, r0, #3 + BX lr + .endfunc @cpu_get_current()@ + + .global enable_neon_fpu + .func enable_neon_fpu +enable_neon_fpu: + /* set NSACR, both Secure and Non-secure access are allowed to NEON */ + MRC p15, 0, r0, c1, c1, 2 + ORR r0, r0, #(0x3<<10) @ enable fpu/neon + MCR p15, 0, r0, c1, c1, 2 + /* Set the CPACR for access to CP10 and CP11*/ + LDR r0, =0xF00000 + MCR p15, 0, r0, c1, c0, 2 + /* Set the FPEXC EN bit to enable the FPU */ + MOV r3, #0x40000000 + @VMSR FPEXC, r3 + MCR p10, 7, r3, c8, c0, 0 + .endfunc + + .global disable_strict_align_check + .func disable_strict_align_check +disable_strict_align_check: + /*Ray's note: disable strict alignment fault checking. + without disabling this, data abort will happen when accessing + the BPB structure of file system since it is packed.*/ + + push {r0, lr} + + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(0x1<<1) @clear A bit of SCTLR + mcr p15, 0, r0, c1, c0, 0 + + pop {r0, pc} + .endfunc + + .global disable_L1_cache + .func disable_L1_cache +disable_L1_cache: + push {r0-r6, lr} + + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(0x1<<12) + bic r0, r0, #(0x1<<11) + bic r0, r0, #(0x1<<2) + bic r0, r0, #(0x1<<0) + mcr p15, 0, r0, c1, c0, 0 + + pop {r0-r6, pc} + + .endfunc + + .global get_arm_private_peripheral_base + @ uint32_t get_arm_private_peripheral_base(void)@ + .func get_arm_private_peripheral_base +get_arm_private_peripheral_base: + + @ Get base address of private perpherial space + mrc p15, 4, r0, c15, c0, 0 @ Read periph base address + bx lr + + .endfunc @get_arm_private_peripheral_base()@ + +@ ------------------------------------------------------------ +@ TLB +@ ------------------------------------------------------------ + + .global arm_unified_tlb_invalidate + @ void arm_unified_tlb_invalidate(void)@ + .func arm_unified_tlb_invalidate +arm_unified_tlb_invalidate: + mov r0, #1 + mcr p15, 0, r0, c8, c7, 0 @ TLBIALL - Invalidate entire unified TLB + dsb + bx lr + .endfunc + + .global arm_unified_tlb_invalidate_is + @ void arm_unified_tlb_invalidate_is(void)@ + .func arm_unified_tlb_invalidate_is +arm_unified_tlb_invalidate_is: + mov r0, #1 + mcr p15, 0, r0, c8, c3, 0 @ TLBIALLIS - Invalidate entire unified TLB Inner Shareable + dsb + bx lr + .endfunc + +@ ------------------------------------------------------------ +@ Branch Prediction +@ ------------------------------------------------------------ + + .global arm_branch_prediction_enable + @ void arm_branch_prediction_enable(void) + .func arm_branch_prediction_enable +arm_branch_prediction_enable: + mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR + orr r0, r0, #(1 << 11) @ Set the Z bit (bit 11) + mcr p15, 0,r0, c1, c0, 0 @ Write SCTLR + bx lr + .endfunc + + .global arm_branch_prediction_disable + @ void arm_branch_prediction_disable(void) + .func arm_branch_prediction_disable +arm_branch_prediction_disable: + mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR + bic r0, r0, #(1 << 11) @ Clear the Z bit (bit 11) + mcr p15, 0,r0, c1, c0, 0 @ Write SCTLR + bx lr + .endfunc + + .global arm_branch_target_cache_invalidate + @ void arm_branch_target_cache_invalidate(void) + .func arm_branch_target_cache_invalidate +arm_branch_target_cache_invalidate: + mov r0, #0 + mcr p15, 0, r0, c7, c5, 6 @ BPIALL - Invalidate entire branch predictor array + bx lr + .endfunc + + .global arm_branch_target_cache_invalidate_is + @ void arm_branch_target_cache_invalidate_is(void) + .func arm_branch_target_cache_invalidate_is +arm_branch_target_cache_invalidate_is: + mov r0, #0 + mcr p15, 0, r0, c7, c1, 6 @ BPIALLIS - Invalidate entire branch predictor array Inner Shareable + bx lr + .endfunc + +@ ------------------------------------------------------------ +@ SCU +@ ------------------------------------------------------------ + + @ SCU offset from base of private peripheral space --> 0x000 + + .global scu_enable + @ void scu_enable(void) + @ Enables the SCU + .func scu_enable +scu_enable: + + mrc p15, 4, r0, c15, c0, 0 @ Read periph base address + + ldr r1, [r0, #0x0] @ Read the SCU Control Register + orr r1, r1, #0x1 @ Set bit 0 (The Enable bit) + str r1, [r0, #0x0] @ Write back modifed value + + bx lr + .endfunc + +@ ------------------------------------------------------------ + + .global scu_join_smp + @ void scu_join_smp(void) + @ Set this CPU as participating in SMP + .func scu_join_smp +scu_join_smp: + + @ SMP status is controlled by bit 6 of the CP15 Aux Ctrl Reg + + mrc p15, 0, r0, c1, c0, 1 @ Read ACTLR + orr r0, r0, #0x040 @ Set bit 6 + mcr p15, 0, r0, c1, c0, 1 @ Write ACTLR + + bx lr + .endfunc + +@ ------------------------------------------------------------ + + .global scu_leave_smp + @ void scu_leave_smp(void) + @ Set this CPU as NOT participating in SMP + .func scu_leave_smp +scu_leave_smp: + + @ SMP status is controlled by bit 6 of the CP15 Aux Ctrl Reg + + mrc p15, 0, r0, c1, c0, 1 @ Read ACTLR + bic r0, r0, #0x040 @ Clear bit 6 + mcr p15, 0, r0, c1, c0, 1 @ Write ACTLR + + bx lr + .endfunc + +@ ------------------------------------------------------------ + + .global scu_get_cpus_in_smp + @ unsigned int scu_get_cpus_in_smp(void) + @ The return value is 1 bit per core: + @ bit 0 - CPU 0 + @ bit 1 - CPU 1 + @ etc... + .func scu_get_cpus_in_smp +scu_get_cpus_in_smp: + + mrc p15, 4, r0, c15, c0, 0 @ Read periph base address + + ldr r0, [r0, #0x004] @ Read SCU Configuration register + mov r0, r0, lsr #4 @ Bits 7:4 gives the cores in SMP mode, shift then mask + and r0, r0, #0x0F + + bx lr + .endfunc + +@ ------------------------------------------------------------ + + .global scu_enable_maintenance_broadcast + @ void scu_enable_maintenance_broadcast(void) + @ Enable the broadcasting of cache & TLB maintenance operations + @ When enabled AND in SMP, broadcast all "inner sharable" + @ cache and TLM maintenance operations to other SMP cores + .func scu_enable_maintenance_broadcast +scu_enable_maintenance_broadcast: + mrc p15, 0, r0, c1, c0, 1 @ Read Aux Ctrl register + orr r0, r0, #0x01 @ Set the FW bit (bit 0) + mcr p15, 0, r0, c1, c0, 1 @ Write Aux Ctrl register + + bx lr + .endfunc + +@ ------------------------------------------------------------ + + .global scu_disable_maintenance_broadcast + @ void scu_disable_maintenance_broadcast(void) + @ Disable the broadcasting of cache & TLB maintenance operations + .func scu_disable_maintenance_broadcast +scu_disable_maintenance_broadcast: + mrc p15, 0, r0, c1, c0, 1 @ Read Aux Ctrl register + bic r0, r0, #0x01 @ Clear the FW bit (bit 0) + mcr p15, 0, r0, c1, c0, 1 @ Write Aux Ctrl register + + bx lr + .endfunc + +@ ------------------------------------------------------------ + + .global scu_secure_invalidate + @ void scu_secure_invalidate(unsigned int cpu, unsigned int ways) + @ cpu: 0x0=CPU 0 0x1=CPU 1 etc... + @ This function invalidates the SCU copy of the tag rams + @ for the specified core. typically only done at start-up. + @ Possible flow: + @ - Invalidate L1 caches + @ - Invalidate SCU copy of TAG RAMs + @ - Join SMP + .func scu_secure_invalidate +scu_secure_invalidate: + and r0, r0, #0x03 @ Mask off unused bits of CPU ID + mov r0, r0, lsl #2 @ Convert into bit offset (four bits per core) + + and r1, r1, #0x0F @ Mask off unused bits of ways + mov r1, r1, lsl r0 @ Shift ways into the correct CPU field + + mrc p15, 4, r2, c15, c0, 0 @ Read periph base address + + str r1, [r2, #0x0C] @ Write to SCU Invalidate All in Secure State + + bx lr + + .endfunc + +@ ------------------------------------------------------------ +@ End of cortexA9.s +@ ------------------------------------------------------------ + .end diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/cortex_a9.h b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/cortex_a9.h new file mode 100755 index 000000000..c445e4fb4 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/cortex_a9.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#if !defined(__CORTEX_A9_H__) +#define __CORTEX_A9_H__ + +#include +#include +#include + +//! @addtogroup cortexa9 +//! @{ + +//////////////////////////////////////////////////////////////////////////////// +// Definitions +//////////////////////////////////////////////////////////////////////////////// + +//! @name Instruction macros +//@{ +#define _ARM_NOP() asm volatile ("nop\n\t") +#define _ARM_WFI() asm volatile ("wfi\n\t") +#define _ARM_WFE() asm volatile ("wfe\n\t") +#define _ARM_SEV() asm volatile ("sev\n\t") +#define _ARM_DSB() asm volatile ("dsb\n\t") +#define _ARM_ISB() asm volatile ("isb\n\t") + +#define _ARM_MRC(coproc, opcode1, Rt, CRn, CRm, opcode2) \ + asm volatile ("mrc p" #coproc ", " #opcode1 ", %[output], c" #CRn ", c" #CRm ", " #opcode2 "\n" : [output] "=r" (Rt)) + +#define _ARM_MCR(coproc, opcode1, Rt, CRn, CRm, opcode2) \ + asm volatile ("mcr p" #coproc ", " #opcode1 ", %[input], c" #CRn ", c" #CRm ", " #opcode2 "\n" :: [input] "r" (Rt)) +//@} + +//////////////////////////////////////////////////////////////////////////////// +// Code +//////////////////////////////////////////////////////////////////////////////// + +#if defined(__cplusplus) +extern "C" { +#endif + +//! @name Misc +//@{ +//! @brief Enable or disable the IRQ and FIQ state. +bool arm_set_interrupt_state(bool enable); + +//! @brief Get current CPU ID. +int cpu_get_current(void); + +//! @brief Enable the NEON MPE. +void enable_neon_fpu(void); + +//! @brief Disable aborts on unaligned accesses. +void disable_strict_align_check(void); + +//! @brief Get base address of private perpherial space. +//! +//! @return The address of the ARM CPU's private peripherals. +uint32_t get_arm_private_peripheral_base(void); +//@} + + +//! @name Data cache operations +//@{ + +//! @brief Check if dcache is enabled or disabled. +int arm_dcache_state_query(); + +//! @brief Enables data cache at any available cache level. +//! +//! Works only if MMU is enabled! +void arm_dcache_enable(); + +//! @brief Disables the data cache at any available cache level. +void arm_dcache_disable(); + +//! @brief Invalidates the entire data cache. +void arm_dcache_invalidate(); + +//! @brief Invalidate a line of data cache. +void arm_dcache_invalidate_line(const void * addr); + +//! @brief Invalidate a number of lines of data cache. +//! +//! Number of lines depends on length parameter and size of line. +//! Size of line for A9 L1 cache is 32B. +void arm_dcache_invalidate_mlines(const void * addr, size_t length); + +//! @brief Flush (clean) all lines of cache (all sets in all ways). +void arm_dcache_flush(); + +//! @brief Flush (clean) one line of cache. +void arm_dcache_flush_line(const void * addr); + +// @brief Flush (clean) multiple lines of cache. +//! +//! Number of lines depends on length parameter and size of line. +void arm_dcache_flush_mlines(const void * addr, size_t length); +//@} + +//! @name Instrution cache operations +//@{ + +//! @brief Check if icache is enabled or disabled. +int arm_icache_state_query(); + +//! @brief Enables instruction cache at any available cache level. +//! +//! Works without enabled MMU too! +void arm_icache_enable(); + +//! @brief Disables the instruction cache at any available cache level. +void arm_icache_disable(); + +//! @brief Invalidates the entire instruction cache. +void arm_icache_invalidate(); + +//! @brief Invalidates the entire instruction cache inner shareable. +void arm_icache_invalidate_is(); + +//! @brief Invalidate a line of the instruction cache. +void arm_icache_invalidate_line(const void * addr); + +//! @brief Invalidate a number of lines of instruction cache. +//! +//! Number of lines depends on length parameter and size of line. +void arm_icache_invalidate_mlines(const void * addr, size_t length); +//@} + +//! @name TLB operations +//@{ +//! @brief Invalidate entire unified TLB. +void arm_unified_tlb_invalidate(void); + +//! @brief Invalidate entire unified TLB Inner Shareable. +void arm_unified_tlb_invalidate_is(void); +//@} + +//! @name Branch predictor operations +//@{ +//! @brief Enable branch prediction. +void arm_branch_prediction_enable(void); + +//! @brief Disable branch prediction. +void arm_branch_prediction_disable(void); + +//! @brief Invalidate entire branch predictor array. +void arm_branch_target_cache_invalidate(void); + +//! @brief Invalidate entire branch predictor array Inner Shareable +void arm_branch_target_cache_invalidate_is(void); +//@} + +//! @name SCU +//@{ +//! @brief Enables the SCU. +void scu_enable(void); + +//! @brief Set this CPU as participating in SMP. +void scu_join_smp(void); + +//! @brief Set this CPU as not participating in SMP. +void scu_leave_smp(void); + +//! @brief Determine which CPUs are participating in SMP. +//! +//! The return value is 1 bit per core: +//! - bit 0 - CPU 0 +//! - bit 1 - CPU 1 +//! - etc... +unsigned int scu_get_cpus_in_smp(void); + +//! @brief Enable the broadcasting of cache & TLB maintenance operations. +//! +//! When enabled AND in SMP, broadcast all "inner sharable" +//! cache and TLM maintenance operations to other SMP cores +void scu_enable_maintenance_broadcast(void); + +//! @brief Disable the broadcasting of cache & TLB maintenance operations. +void scu_disable_maintenance_broadcast(void); + +//! @brief Invalidates the SCU copy of the tag rams for the specified core. +//! +//! Typically only done at start-up. +//! Possible flow: +//! - Invalidate L1 caches +//! - Invalidate SCU copy of TAG RAMs +//! - Join SMP +//! +//! @param cpu 0x0=CPU 0, 0x1=CPU 1, etc... +//! @param ways The ways to invalidate. Pass 0xf to invalidate all ways. +void scu_secure_invalidate(unsigned int cpu, unsigned int ways); +//@} + +#if defined(__cplusplus) +} +#endif + +//! @} + +#endif // __CORTEX_A9_H__ +//////////////////////////////////////////////////////////////////////////////// +// EOF +//////////////////////////////////////////////////////////////////////////////// diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S index dc3eb6e2d..e8ee24286 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S @@ -1,3 +1,5 @@ +#include + .section .vectors, "ax" .code 32 @@ -12,7 +14,7 @@ ExceptionVectors: ldr pc, _IrqException ldr pc, _FiqException -.globl _start +.globl _reset .globl UndefInstrExceptionHandle .globl SwiExceptionHandle .globl PrefetchAbortExceptionHandle @@ -22,7 +24,7 @@ ExceptionVectors: .globl FiqExceptionHandle _ResetException: - .word _start + .word _reset _UndefInstrException: .word UndefInstrExceptionHandle _SwiException: @@ -48,7 +50,7 @@ _FiqException: mrs r6, spsr @/* Save CPSR */ str lr, [r0, #15*4] @/* Push PC */ str r6, [r0, #16*4] @/* Push CPSR */ - cps #Mode_SVC + cps #MODE_SVC str sp, [r0, #13*4] @/* Save calling SP */ str lr, [r0, #14*4] @/* Save calling PC */ .endm @@ -63,7 +65,7 @@ UndefInstrExceptionHandle: .globl SwiExceptionHandle SwiExceptionHandle: push_svc_reg - bl rt_hw_trap_swi + bl DoSvcCallProcess b . .align 5 @@ -89,55 +91,51 @@ ResvExceptionHandle: .globl ExceptionIsrEntry ExceptionIsrEntry: - stmfd sp!, {r0-r12,lr} + stmfd sp!, {r0-r12,lr} - bl rt_interrupt_enter - bl rt_hw_trap_irq - bl rt_interrupt_leave + bl DoIrqProcess - @ if rt_thread_switch_interrupt_flag set, jump to - @ rt_hw_context_switch_interrupt_do and don't return - ldr r0, =rt_thread_switch_interrupt_flag - ldr r1, [r0] - cmp r1, #1 - beq rt_hw_context_switch_interrupt_do + @ ldr r0, =rt_thread_switch_interrupt_flag + @ ldr r1, [r0] + @ cmp r1, #1 + @ beq rt_hw_context_switch_interrupt_do - ldmfd sp!, {r0-r12,lr} - subs pc, lr, #4 + ldmfd sp!, {r0-r12,lr} + subs pc, lr, #4 -rt_hw_context_switch_interrupt_do: - mov r1, #0 @ clear flag - str r1, [r0] +@ rt_hw_context_switch_interrupt_do: +@ mov r1, #0 @ clear flag +@ str r1, [r0] - mov r1, sp @ r1 point to {r0-r3} in stack - add sp, sp, #4*4 - ldmfd sp!, {r4-r12,lr}@ reload saved registers - mrs r0, spsr @ get cpsr of interrupt thread - sub r2, lr, #4 @ save old task's pc to r2 +@ mov r1, sp @ r1 point to {r0-r3} in stack +@ add sp, sp, #4*4 +@ ldmfd sp!, {r4-r12,lr}@ reload saved registers +@ mrs r0, spsr @ get cpsr of interrupt thread +@ sub r2, lr, #4 @ save old task's pc to r2 - @ Switch to SVC mode with no interrupt. If the usr mode guest is - @ interrupted, this will just switch to the stack of kernel space. - @ save the registers in kernel space won't trigger data abort. - msr cpsr_c, #I_Bit|F_Bit|Mode_SVC +@ @ Switch to SVC mode with no interrupt. If the usr mode guest is +@ @ interrupted, this will just switch to the stack of kernel space. +@ @ save the registers in kernel space won't trigger data abort. +@ msr cpsr_c, #I_Bit|F_Bit|Mode_SVC - stmfd sp!, {r2} @ push old task's pc - stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4 - ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread - stmfd sp!, {r1-r4} @ push old task's r0-r3 - stmfd sp!, {r0} @ push old task's cpsr +@ stmfd sp!, {r2} @ push old task's pc +@ stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4 +@ ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread +@ stmfd sp!, {r1-r4} @ push old task's r0-r3 +@ stmfd sp!, {r0} @ push old task's cpsr - ldr r4, =rt_interrupt_from_thread - ldr r5, [r4] - str sp, [r5] @ store sp in preempted tasks's TCB +@ ldr r4, =rt_interrupt_from_thread +@ ldr r5, [r4] +@ str sp, [r5] @ store sp in preempted tasks's TCB - ldr r6, =rt_interrupt_to_thread - ldr r6, [r6] - ldr sp, [r6] @ get new task's stack pointer +@ ldr r6, =rt_interrupt_to_thread +@ ldr r6, [r6] +@ ldr sp, [r6] @ get new task's stack pointer - ldmfd sp!, {r4} @ pop new task's cpsr to spsr - msr spsr_cxsf, r4 +@ ldmfd sp!, {r4} @ pop new task's cpsr to spsr +@ msr spsr_cxsf, r4 - ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr +@ ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr .align 5 diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.c b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.c deleted file mode 100644 index de9a52e32..000000000 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.c +++ /dev/null @@ -1,75 +0,0 @@ - -/** - * this function will show registers of CPU - * - * @param regs the registers point - */ -void PrintStackFrame(struct rt_hw_exp_stack *regs) -{ - rt_kprintf("Execption:\n"); - rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3); - rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7); - rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10); - rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip); - rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc); - rt_kprintf("cpsr:0x%08x\n", regs->cpsr); -} - - -/** - * The software interrupt instruction (SWI) is used for entering - * Supervisor mode, usually to request a particular supervisor - * function. - * - * @param regs system registers - * - * @note never invoke this function in application - */ -void rt_hw_trap_swi(struct rt_hw_exp_stack *regs) -{ - -} - -void rt_hw_trap_irq(void) -{ - void *param; - rt_isr_handler_t isr_func; - extern struct rt_irq_desc isr_table[]; - - // vectNum = RESERVED[31:13] | CPUID[12:10] | INTERRUPT_ID[9:0] - // send ack and get ID source - uint32_t vectNum = gic_read_irq_ack(); - - // Check that INT_ID isn't 1023 or 1022 (spurious interrupt) - if (vectNum & 0x0200) - { - gic_write_end_of_irq(vectNum); // send end of irq - } - else - { - // copy the local value to the global image of CPUID - unsigned cpu = (vectNum >> 10) & 0x7; - unsigned irq = vectNum & 0x1FF; - - /* skip warning */ - cpu = cpu; - - // Call the service routine stored in the handlers array. If there isn't - // one for this IRQ, then call the default handler. - /* get interrupt service routine */ - isr_func = isr_table[irq].handler; -#ifdef RT_USING_INTERRUPT_INFO - isr_table[irq].counter++; -#endif - if (isr_func) - { - /* Interrupt for myself. */ - param = isr_table[irq].param; - /* turn to interrupt service routine */ - isr_func(irq, param); - } - - // Signal the end of the irq. - gic_write_end_of_irq(vectNum); - } -} diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic.c b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic.c index 5249d76e4..82b337331 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic.c @@ -28,9 +28,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include -#include "core/gic.h" +#include "gic.h" #include "gic_registers.h" -#include "core/cortex_a9.h" +#include "cortex_a9.h" //////////////////////////////////////////////////////////////////////////////// // Prototypes diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic.h b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic.h new file mode 100644 index 000000000..f3eee8499 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/gic.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2011-2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __GIC_H__ +#define __GIC_H__ + +#include "sdk_types.h" + +//! @addtogroup gic +//! @{ + +//////////////////////////////////////////////////////////////////////////////// +// Definitions +//////////////////////////////////////////////////////////////////////////////// + +//! @brief Options for sending a software generated interrupt. +//! +//! These options are used for the @a filter_list parameter of the gic_send_sgi() +//! function. They control how to select which CPUs that the interrupt is +//! sent to. +enum _gicd_sgi_filter +{ + //! Forward the interrupt to the CPU interfaces specified in the @a target_list parameter. + kGicSgiFilter_UseTargetList = 0, + + //! Forward the interrupt to all CPU interfaces except that of the processor that requested + //! the interrupt. + kGicSgiFilter_AllOtherCPUs = 1, + + //! Forward the interrupt only to the CPU interface of the processor that requested the + //! interrupt. + kGicSgiFilter_OnlyThisCPU = 2 +}; + +//////////////////////////////////////////////////////////////////////////////// +// API +//////////////////////////////////////////////////////////////////////////////// + +#if defined(__cplusplus) +extern "C" { +#endif + +//! @name Initialization +//@{ +//! @brief Init interrupt handling. +//! +//! This function is intended to be called only by the primary CPU init code, so it will +//! only be called once during system bootup. +//! +//! Also inits the current CPU. You don't need to call gic_init_cpu() separately. +//! +//! @post The interrupt distributor and the current CPU interface are enabled. All interrupts +//! that were pending are cleared, and all interrupts are made secure (group 0). +void gic_init(void); + +//! @brief Init the current CPU's GIC interface. +//! +//! @post Enables the CPU interface and sets the priority mask to 255. Interrupt preemption +//! is disabled by setting the Binary Point to a value of 7. +void gic_init_cpu(void); +//@} + +//! @name GIC Interrupt Distributor Functions +//@{ +//! @brief Enable or disable the GIC Distributor. +//! +//! Enables or disables the GIC distributor passing both secure (group 0) and non-secure +//! (group 1) interrupts to the CPU interfaces. +//! +//! @param enableIt Pass true to enable or false to disable. +void gic_enable(bool enableIt); + +//! @brief Set the security mode for an interrupt. +//! +//! @param irqID The interrupt number. +//! @param isSecure Whether the interrupt is taken to secure mode. +void gic_set_irq_security(uint32_t irqID, bool isSecure); + +//! @brief Enable or disable an interrupt. +//! +//! @param irqID The number of the interrupt to control. +//! @param isEnabled Pass true to enable or false to disable. +void gic_enable_irq(uint32_t irqID, bool isEnabled); + +//! @brief Set whether a CPU will receive a particular interrupt. +//! +//! @param irqID The interrupt number. +//! @param cpuNumber The CPU number. The first CPU core is 0. +//! @param enableIt Whether to send the interrupt to the specified CPU. Pass true to enable +//! or false to disable. +void gic_set_cpu_target(uint32_t irqID, unsigned cpuNumber, bool enableIt); + +//! @brief Set an interrupt's priority. +//! +//! @param irq_id The interrupt number. +//! @param priority The priority for the interrupt. In the range of 0 through 0xff, with +//! 0 being the highest priority. +void gic_set_irq_priority(uint32_t irq_id, uint32_t priority); + +//! @brief Send a software generated interrupt to a specific CPU. +//! +//! @param irq_id The interrupt number to send. +//! @param target_list Each bit indicates a CPU to which the interrupt will be forwarded. +//! Bit 0 is CPU 0, bit 1 is CPU 1, and so on. If the value is 0, then the interrupt +//! will not be forwarded to any CPUs. This parameter is only used if @a filter_list +//! is set to #kGicSgiFilter_UseTargetList. +//! @param filter_list One of the enums of the #_gicd_sgi_filter enumeration. The selected +//! option determines which CPUs the interrupt will be sent to. If the value +//! is #kGicSgiFilter_UseTargetList, then the @a target_list parameter is used. +void gic_send_sgi(uint32_t irq_id, uint32_t target_list, uint32_t filter_list); +//@} + +//! @name GIC CPU Interface Functions +//@{ +//! @brief Enable or disable the interface to the GIC for the current CPU. +//! +//! @param enableIt Pass true to enable or false to disable. +void gic_cpu_enable(bool enableIt); + +//! @brief Set the mask of which interrupt priorities the CPU will receive. +//! +//! @param priority The lowest priority that will be passed to the current CPU. Pass 0xff to +//! allow all priority interrupts to signal the CPU. +void gic_set_cpu_priority_mask(uint32_t priority); + +//! @brief Acknowledge starting of interrupt handling and get the interrupt number. +//! +//! Normally, this function is called at the beginning of the IRQ handler. It tells the GIC +//! that you are starting to handle an interupt, and returns the number of the interrupt you +//! need to handle. After the interrupt is handled, you should call gic_write_end_of_irq() +//! to signal that the interrupt is completely handled. +//! +//! In some cases, a spurious interrupt might happen. One possibility is if another CPU handles +//! the interrupt. When a spurious interrupt occurs, the end of the interrupt should be indicated +//! but nothing else. +//! +//! @return The number for the highest priority interrupt available for the calling CPU. If +//! the return value is 1022 or 1023, a spurious interrupt has occurred. +uint32_t gic_read_irq_ack(void); + +//! @brief Signal the end of handling an interrupt. +//! +//! @param irq_id The number of the interrupt for which handling has finished. +void gic_write_end_of_irq(uint32_t irq_id); +//@} + + +#if defined(__cplusplus) +} +#endif + +//! @} + +#endif // __GIC_H__ +//////////////////////////////////////////////////////////////////////////////// +// EOF +//////////////////////////////////////////////////////////////////////////////// diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/interrupt.c b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/interrupt.c new file mode 100755 index 000000000..635857aa8 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/interrupt.c @@ -0,0 +1,92 @@ +// extern void _svcall(uintptr_t* contex); +#include +#include +#include + +unsigned long __attribute__((naked)) DisableLocalInterrupt() +{ + +} + +void __attribute__((naked)) EnableLocalInterrupt(unsigned long level) +{ + +} + +int32_t ArchEnableHwIrq(uint32_t irq_num) +{ + + return 0; +} + +int32_t ArchDisableHwIrq(uint32_t irq_num) +{ + return 0; +} + +extern void KTaskOsAssignAfterIrq(void *context); + +void IsrEntry(uint32_t irq_num) +{ + isrManager.done->incCounter(); + isrManager.done->handleIrq(irq_num); + // KTaskOsAssignAfterIrq(NULL); + isrManager.done->decCounter(); + +} + +/** + * this function will show registers of CPU + * + * @param regs the registers point + */ +void PrintStackFrame(struct ExceptionStackRegister *regs) +{ + // KPrintf("Execption:\n"); + // KPrintf("r0: 0x%08x\n", regs->r0); + // KPrintf("r1: 0x%08x\n", regs->r1); + // KPrintf("r2: 0x%08x\n", regs->r2); + // KPrintf("r3: 0x%08x\n", regs->r3); + // KPrintf("r4: 0x%08x\n", regs->r4); + // KPrintf("r5: 0x%08x\n", regs->r5); + // KPrintf("r6: 0x%08x\n", regs->r6); + // KPrintf("r7: 0x%08x\n", regs->r7); + // KPrintf("r8: 0x%08x\n", regs->r8); + // KPrintf("r9: 0x%08x\n", regs->r9); + // KPrintf("r10: 0x%08x\n", regs->r10); + // KPrintf("r11: 0x%08x\n", regs->r11); + // KPrintf("r12: 0x%08x\n", regs->r12); + // KPrintf("r13_sp: 0x%08x\n", regs->r13_sp); + // KPrintf("r14_lr: 0x%08x\n", regs->r14_lr); + // KPrintf("r15_pc: 0x%08x\n", regs->r15_pc); + // KPrintf("cpsr: 0x%08x\n", regs->cpsr); +} + + +void DoSvcCallProcess(struct ExceptionStackRegister *regs) +{ + +} + +void DoIrqProcess(void) +{ + uint32_t iar = gic_read_irq_ack(); + uint32_t irq_num = iar & 0x3ff; + + if(irq_num >= ARCH_MAX_IRQ_NUM) + { + gic_write_end_of_irq(irq_num); + return; + } + + IsrEntry(irq_num); + + gic_write_end_of_irq(irq_num); +} +// uintptr_t *Svcall(unsigned int ipsr, uintptr_t* contex ) +// { +// #ifdef TASK_ISOLATION +// _svcall(contex); +// #endif +// return contex; +// } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/link.mk b/Ubiquitous/XiZi_AIoT/link.mk new file mode 100644 index 000000000..f0ed846ef --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/link.mk @@ -0,0 +1,10 @@ +OBJS := $(shell cat make.obj) + +$(TARGET): $(OBJS) + @echo ------------------------------------------------ + @echo link $(TARGET) + @$(CROSS_COMPILE)g++ -o $@ $($(LINK_FLAGS)) $(OBJS) $(LINK_MUSLLIB) $(LIBCC) + @echo ------------------------------------------------ + @$(CROSS_COMPILE)objcopy -O binary $@ XiZi-$(BOARD)$(COMPILE_TYPE).bin + @$(CROSS_COMPILE)objcopy -O ihex $@ XiZi-$(BOARD)$(COMPILE_TYPE).hex + @$(CROSS_COMPILE)size $@ \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/path_kernel.mk b/Ubiquitous/XiZi_AIoT/path_kernel.mk new file mode 100755 index 000000000..701bf39a9 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/path_kernel.mk @@ -0,0 +1,51 @@ + +export KERNELPATHS:= -I$(BSP_ROOT) + +ifeq ($(CONFIG_LIB_MUSLLIB), y) +KERNELPATHS += -I$(KERNEL_ROOT)/services/lib/musllib/src/include \ + -I$(KERNEL_ROOT)/services/lib/musllib/include \ + -I$(KERNEL_ROOT)/services/lib/musllib/src/internal # +# chose arch for musl +ifeq ($(ARCH), arm) +KERNELPATHS += -I$(KERNEL_ROOT)/services/lib/musllib/arch/arm +endif +ifeq ($(ARCH), risc-v) +KERNELPATHS += -I$(KERNEL_ROOT)/services/lib/musllib/arch/riscv64 +endif + +endif # end of musl include path + +ifeq ($(CONFIG_LIB_NEWLIB),y) +KERNELPATHS += -I$(KERNEL_ROOT)/services/lib/newlib/include # +endif + +ifeq ($(BSP_ROOT),$(KERNEL_ROOT)/services/boards/imx6q-sabrelite) +KERNELPATHS += \ + -I$(KERNEL_ROOT)/hardkernel/arch/arm/armv7-a/cortex-a9 \ + -I$(KERNEL_ROOT)/hardkernel/abstraction \ + -I$(KERNEL_ROOT)/include \ + -I$(BSP_ROOT)/include + +ifeq ($(CONFIG_RESOURCES_LWIP),y) +KERNELPATHS += \ + -I$(KERNEL_ROOT)/resources/ethernet/LwIP \ + -I$(KERNEL_ROOT)/resources/ethernet/LwIP/include \ + -I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/compat \ + -I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip \ + -I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/netif \ + -I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/apps \ + -I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/priv \ + -I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/prot \ + -I$(KERNEL_ROOT)/resources/ethernet/LwIP/arch +endif +endif + +KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Applications/general_functions/list # + +ifeq ($(ARCH), arm) +KERNELPATHS +=-I$(KERNEL_ROOT)/arch/arm/shared \ + -I$(KERNEL_ROOT)/lib/comlibc/common # +endif + +KERNELPATHS += -I$(KERNEL_ROOT)/kernel/include # + diff --git a/Ubiquitous/XiZi_AIoT/services/Kconfig b/Ubiquitous/XiZi_AIoT/services/Kconfig new file mode 100644 index 000000000..ee3478bcb --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/Kconfig @@ -0,0 +1,4 @@ +source "$KERNEL_DIR/services/drivers/Kconfig" +source "$KERNEL_DIR/services/fs/Kconfig" +source "$KERNEL_DIR/services/lib/Kconfig" + diff --git a/Ubiquitous/XiZi_AIoT/services/Makefile b/Ubiquitous/XiZi_AIoT/services/Makefile new file mode 100644 index 000000000..d3d247fa7 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/Makefile @@ -0,0 +1,6 @@ + +SRC_DIR := boards drivers lib + + + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/boards/Makefile b/Ubiquitous/XiZi_AIoT/services/boards/Makefile new file mode 100644 index 000000000..702a453b6 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/Makefile @@ -0,0 +1,4 @@ + +SRC_DIR := $(BOARD) + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/.config b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/.config new file mode 100644 index 000000000..307c2f4c0 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/.config @@ -0,0 +1,18 @@ +# +# Automatically generated file; DO NOT EDIT. +# XiZi_AIoT Project Configuration +# +CONFIG_BOARD_IMX6Q_SABRELITE_EVB=y +CONFIG_ARCH_ARM=y + +# +# imx6q sabrelite feature +# + +# +# Lib +# +CONFIG_LIB=y +CONFIG_LIB_POSIX=y +CONFIG_LIB_NEWLIB=y +# CONFIG_LIB_MUSLLIB is not set diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Kconfig b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Kconfig new file mode 100644 index 000000000..68adb4a56 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Kconfig @@ -0,0 +1,26 @@ +mainmenu "XiZi_AIoT Project Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config KERNEL_DIR + string + option env="KERNEL_ROOT" + default "../.." + +config BOARD_IMX6Q_SABRELITE_EVB + bool + select ARCH_ARM + default y + +source "$KERNEL_DIR/hardkernel/arch/Kconfig" + +menu "imx6q sabrelite feature" + source "$BSP_DIR/third_party_driver/Kconfig" + +endmenu + + +source "$KERNEL_DIR/Kconfig" diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile new file mode 100644 index 000000000..683e42a90 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile @@ -0,0 +1,8 @@ +SRC_FILES := board.c + +SRC_DIR := third_party_driver + + + + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/board.c b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/board.c new file mode 100644 index 000000000..6de1c0977 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/board.c @@ -0,0 +1,4 @@ +void start_kernel() +{ + +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/board.h b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/board.h new file mode 100644 index 000000000..db7269dc6 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/board.h @@ -0,0 +1,6 @@ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#define PLATFORM_MAX_IRQ_NR 160 // imx6q max support 160 irq + +#endif \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/config.mk b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/config.mk new file mode 100644 index 000000000..ee27915c9 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/config.mk @@ -0,0 +1,23 @@ +export CROSS_COMPILE ?=/usr/bin/arm-none-eabi- +export DEVICE = -march=armv7-a -mtune=cortex-a9 -mfpu=vfpv3-d16 -ftree-vectorize -ffast-math -mfloat-abi=softfp +export CFLAGS := $(DEVICE) -Wall -O0 -g -gdwarf-2 +export AFLAGS := -c $(DEVICE) -x assembler-with-cpp -D__ASSEMBLY__ -gdwarf-2 +export LFLAGS := $(DEVICE) -Wl,--gc-sections,-Map=XiZi-imx6q-sabrelite.map,-cref,-u,ExceptionVectors -T $(BSP_ROOT)/link.lds +export CXXFLAGS := + +ifeq ($(CONFIG_LIB_MUSLLIB), y) +export LFLAGS += -nostdlib -nostdinc -fno-builtin -nodefaultlibs +export LIBCC := -lgcc +export LINK_MUSLLIB := $(KERNEL_ROOT)/lib/musllib/libmusl.a +endif + +# ifeq ($(CONFIG_RESOURCES_LWIP), y) +# export LINK_LWIP := $(KERNEL_ROOT)/resources/ethernet/LwIP/liblwip.a +# endif + +export DEFINES := -DHAVE_CCONFIG_H -DSTM32F407xx -DUSE_HAL_DRIVER -DHAVE_SIGINFO + +export USING_NEWLIB =1 +export USING_VFS = 1 +export ARCH = arm +export ARCH_ARMV = armv7-a diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/include/asm_defines.h b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/include/asm_defines.h new file mode 100644 index 000000000..beee15cb1 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/include/asm_defines.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2008-2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*! + * @file asm_defines.h + * @brief defines for startup assembly code + * + * @ingroup diag_util + */ + +#ifndef _ASM_DEFINES_H_ +#define _ASM_DEFINES_H_ + +//////////////////////////////////////////////////////////////////////////////// +// Definitions +//////////////////////////////////////////////////////////////////////////////// + +//! @name CPSR fields +//@{ +#define CPSR_N (1 << 31) //!< Negative +#define CPSR_Z (1 << 30) //!< Zero +#define CPSR_C (1 << 29) //!< Carry +#define CPSR_V (1 << 28) //!< Overflow +#define CPSR_Q (1 << 27) //!< Saturation +#define CPSR_E (1 << 9) //!< Endianness +#define CPSR_A (1 << 8) //!< Async abort mask +#define CPSR_I (1 << 7) //!< IRQ mask +#define CPSR_F (1 << 6) //!< FIQ mask +#define CPSR_T (1 << 5) //!< Thumb mode +#define CPSR_MODE (0x1f) //!< Current processor mode +//@} + +//! @name Mode bits in CPSR +//@{ +#define MODE_USR 0x10 //!< User mode +#define MODE_FIQ 0x11 //!< FIQ mode +#define MODE_IRQ 0x12 //!< IRQ mode +#define MODE_SVC 0x13 //!< Supervisor mode +#define MODE_ABT 0x17 //!< Abort exception mode +#define MODE_UND 0x1B //!< Undefined instruction exception mode +#define MODE_SYS 0x1F //!< System mode +//@} + +//! @name Interrupt enable bits in CPSR +//@{ +#define I_BIT 0x80 //!< When I bit is set, IRQ is disabled +#define F_BIT 0x40 //!< When F bit is set, FIQ is disabled +//@} + +//! @name Stack sizes +//@{ + +//! @brief Size of stacks for exceptions. +#define EXCEPTION_STACK_SIZE 2048 + +//! @brief Supervisor mode stack size. +//! +//! This stack is much larger because most application code runs in +//! Supervisor mode. +#define SVC_STACK_SIZE 8192 + +//@} + +#endif /*_ASM_DEFINES_H_ */ +//////////////////////////////////////////////////////////////////////////////// +// EOF +//////////////////////////////////////////////////////////////////////////////// diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/include/sdk_types.h b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/include/sdk_types.h new file mode 100644 index 000000000..0b7bc4b76 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/include/sdk_types.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2008-2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __SDK_TYPES_H__ +#define __SDK_TYPES_H__ + +//! @addtogroup sdk_common +//! @{ + +/*! + * @file sdk_types.h + * @brief Basic types used throughout the SDK. + */ + +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////// +// Definitions +//////////////////////////////////////////////////////////////////////////////// + +//! @name Alternate Boolean constants +//@{ +#define TRUE 1 +#define FALSE 0 +//@} + +//! @brief +#define NONE_CHAR (0xFF) + +//! @brief A parameter was out of range or otherwise invalid. +#define INVALID_PARAMETER (-1) + +//! @name Min/max macros +//@{ +#if !defined(MIN) + #define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#if !defined(MAX) + #define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +//@} + +//! @brief Computes the number of elements in an array. +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +//! @brief Debug print utility. +//! +//! This print function will only output text when the @a DEBUG macro is defined. +static inline void debug_printf(const char * format, ...) +{ +#if defined(DEBUG) + va_list args; + va_start(args, format); + vprintf(format, args); + va_end(args); +#endif +} + +//! @name Test results +typedef enum _test_return +{ + TEST_NOT_STARTED = -3, // present in the menu, but not run + TEST_NOT_IMPLEMENTED = -2, // present in the menu, but not functional + TEST_FAILED = -1, + TEST_PASSED = 0, + TEST_BYPASSED = 2, // user elected to exit the test before it was run + TEST_NOT_PRESENT = 3, // not present in the menu. + TEST_CONTINUE = 4 // proceed with the test. opposite of TEST_BYPASSED +} test_return_t; + +//! @name Return codes +//@{ +#define SUCCESS (0) +#define FAIL (1) +#define ERROR_GENERIC (-1) +#define ERROR_OUT_OF_MEMORY (-2) +//@} + +//! @brief Possible types of displays. +enum display_type { + DISP_DEV_NULL = 0, + DISP_DEV_TFTLCD, + DISP_DEV_LVDS, + DISP_DEV_VGA, + DISP_DEV_HDMI, + DISP_DEV_TV, + DISP_DEV_MIPI, +}; + +//! @} + +#endif // __SDK_TYPES_H__ +//////////////////////////////////////////////////////////////////////////////// +// EOF +//////////////////////////////////////////////////////////////////////////////// diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/link.lds b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/link.lds new file mode 100644 index 000000000..d6e856d1a --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/link.lds @@ -0,0 +1,96 @@ + + +STACK_SIZE = 4096; + +OUTPUT_ARCH(arm) + +SECTIONS +{ + . = 0x80100000; + + __text_start = .; + .text : + { + *(.vectors) + *(.text) + *(.text.*) + + /* section information for finsh shell */ + . = ALIGN(4); + __isrtbl_idx_start = .; + KEEP(*(.isrtbl.idx)) + __isrtbl_start = .; + KEEP(*(.isrtbl)) + __isrtbl_end = .; + . = ALIGN(4); + } + __text_end = .; + + __rodata_start = .; + .rodata : { *(.rodata) *(.rodata.*) } + __rodata_end = .; + + . = ALIGN(4); + .ctors : + { + PROVIDE(__ctors_start__ = .); + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + PROVIDE(__ctors_end__ = .); + } + + .dtors : + { + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + } + + . = ALIGN(16 * 1024); + .l1_page_table : + { + __l1_page_table_start = .; + . += 16K; + } + + . = ALIGN(8); + __data_start = .; + .data : + { + *(.data) + *(.data.*) + } + __data_end = .; + + . = ALIGN(8); + __bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + } + . = ALIGN(4); + __bss_end = .; + + .stacks : + { + __stacks_start = .; + . += STACK_SIZE; + __stacks_end = .; + stack_top = .; + } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + _end = .; +} diff --git a/Ubiquitous/XiZi_AIoT/services/lib/xxx.c b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/third_party_driver/Kconfig similarity index 100% rename from Ubiquitous/XiZi_AIoT/services/lib/xxx.c rename to Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/third_party_driver/Kconfig diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/third_party_driver/Makefile b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/third_party_driver/Makefile new file mode 100644 index 000000000..f11fc06ee --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/third_party_driver/Makefile @@ -0,0 +1,4 @@ + +SRC_DIR := + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/xsconfig.h b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/xsconfig.h new file mode 100644 index 000000000..656db7dbe --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/xsconfig.h @@ -0,0 +1,18 @@ +#ifndef XS_CONFIG_H__ +#define XS_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* XiZi_AIoT Project Configuration */ + +#define BOARD_IMX6Q_SABRELITE_EVB +#define ARCH_ARM + +/* imx6q sabrelite feature */ + +/* Lib */ + +#define LIB +#define LIB_POSIX +#define LIB_NEWLIB + +#endif diff --git a/Ubiquitous/XiZi_AIoT/services/drivers/Kconfig b/Ubiquitous/XiZi_AIoT/services/drivers/Kconfig new file mode 100644 index 000000000..e69de29bb diff --git a/Ubiquitous/XiZi_AIoT/services/drivers/Makefile b/Ubiquitous/XiZi_AIoT/services/drivers/Makefile new file mode 100644 index 000000000..f11fc06ee --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/drivers/Makefile @@ -0,0 +1,4 @@ + +SRC_DIR := + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/fs/Kconfig b/Ubiquitous/XiZi_AIoT/services/fs/Kconfig new file mode 100644 index 000000000..e69de29bb diff --git a/Ubiquitous/XiZi_AIoT/services/lib/Kconfig b/Ubiquitous/XiZi_AIoT/services/lib/Kconfig new file mode 100644 index 000000000..0727350e2 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/lib/Kconfig @@ -0,0 +1,23 @@ +menu "Lib" + +menuconfig LIB + bool "Enable libc APIs from toolchain" + default y + + if LIB + config LIB_POSIX + bool "Enable POSIX layer for poll/select, stdin etc" + default y + choice + prompt "select libc" + default LIB_NEWLIB + + config LIB_NEWLIB + bool "use newlib as libc realization." + + config LIB_MUSLLIB + bool "use musllib as libc realization." + endchoice + endif + +endmenu diff --git a/Ubiquitous/XiZi_AIoT/services/lib/Makefile b/Ubiquitous/XiZi_AIoT/services/lib/Makefile new file mode 100644 index 000000000..39648fd33 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/lib/Makefile @@ -0,0 +1,14 @@ +SRC_DIR := +MUSL_DIR := + +ifeq ($(CONFIG_LIB_NEWLIB),y) +SRC_DIR += newlib +endif + +ifeq ($(CONFIG_LIB_MUSLLIB), y) +# SRC_DIR += musllib +# MUSL_DIR += musllib +endif + +include $(KERNEL_ROOT)/compiler.mk + diff --git a/Ubiquitous/XiZi_AIoT/services/lib/newlib/Kconfig b/Ubiquitous/XiZi_AIoT/services/lib/newlib/Kconfig new file mode 100644 index 000000000..c587e3962 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/lib/newlib/Kconfig @@ -0,0 +1,6 @@ +menu LIB_NEWLIB + bool "Enable Newlib " + default y +endmenu + + diff --git a/Ubiquitous/XiZi_AIoT/services/lib/newlib/Makefile b/Ubiquitous/XiZi_AIoT/services/lib/newlib/Makefile new file mode 100644 index 000000000..04e094528 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/lib/newlib/Makefile @@ -0,0 +1,5 @@ +SRC_FILES := fs_syscalls.c time_syscalls.c mem_syscalls.c task_syscalls.c + + + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/lib/newlib/fs_syscalls.c b/Ubiquitous/XiZi_AIoT/services/lib/newlib/fs_syscalls.c new file mode 100644 index 000000000..67bd6c368 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/lib/newlib/fs_syscalls.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + +/** +* @file fs_syscalls.c +* @brief support newlib file system +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2020-09-23 +*/ + +/************************************************* +File name: fs_syscalls.c +Description: support newlib file system +Others: take RT-Thread v4.0.2/components/libc/compilers/newlib/syscalls.c for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2020-09-23 +Author: AIIT XUOS Lab +Modification: Use file system functions +*************************************************/ + +#include +#include +#include +/* wwg debug here */ +// #include + +int _fstat_r(struct _reent *ptr, int fd, struct stat *pstat) +{ + ptr->_errno = ENOTSUP; + return -1; +} + +int _link_r(struct _reent *ptr, const char *old, const char *new) +{ + ptr->_errno = ENOTSUP; + return -1; +} + +void * _sbrk_r(struct _reent *ptr, ptrdiff_t incr) +{ + return NULL; +} + +int _wait_r(struct _reent *ptr, int *status) +{ + ptr->_errno = ENOTSUP; + return -1; +} + +#ifdef FS_VFS + +#include + +int _close_r(struct _reent *ptr, int fd) +{ + return close(fd); +} + +int _isatty_r(struct _reent *ptr, int fd) +{ + if (fd >=0 && fd < 3) + return 1; + + ptr->_errno = ENOTSUP; + return -1; +} + +_off_t _lseek_r(struct _reent *ptr, int fd, _off_t pos, int whence) +{ + return lseek(fd, pos, whence); +} + +int _open_r(struct _reent *ptr, const char *file, int flags, int mode) +{ + return open(file, flags, mode); +} + +_ssize_t _read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes) +{ + return read(fd, buf, nbytes); +} + +int _stat_r(struct _reent *ptr, const char *file, struct stat *pstat) +{ + return stat(file, pstat); +} + +int _unlink_r(struct _reent *ptr, const char *file) +{ + return unlink(file); +} + +_ssize_t _write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes) +{ + return write(fd, buf, nbytes); +} + +#else /* FS_VFS */ + +int _close_r(struct _reent *ptr, int fd) +{ + ptr->_errno = ENOTSUP; + return -1; +} + +int _isatty_r(struct _reent *ptr, int fd) +{ + ptr->_errno = ENOTSUP; + return -1; +} + +_off_t _lseek_r(struct _reent *ptr, int fd, _off_t pos, int whence) +{ + ptr->_errno = ENOTSUP; + return -1; +} + +int _open_r(struct _reent *ptr, const char *file, int flags, int mode) +{ + ptr->_errno = ENOTSUP; + return -1; +} + +_ssize_t _read_r(struct _reent *ptr, int fd, void *buf, size_t nbytes) +{ + ptr->_errno = ENOTSUP; + return -1; +} + +int _stat_r(struct _reent *ptr, const char *file, struct stat *pstat) +{ + ptr->_errno = ENOTSUP; + return -1; +} + +int _unlink_r(struct _reent *ptr, const char *file) +{ + ptr->_errno = ENOTSUP; + return -1; +} + +_ssize_t _write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes) +{ + ptr->_errno = ENOTSUP; + return -1; +} + +#endif /* FS_VFS */ diff --git a/Ubiquitous/XiZi_AIoT/services/lib/newlib/include/libc.h b/Ubiquitous/XiZi_AIoT/services/lib/newlib/include/libc.h new file mode 100644 index 000000000..223bf0f64 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/lib/newlib/include/libc.h @@ -0,0 +1,29 @@ +/* +* 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. +*/ + +/** +* @file libc.h +* @brief using newlib need include +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2020-09-23 +*/ + +#ifndef _LIBC_H__ +#define _LIBC_H__ + +#include +#include +#include + +#endif + diff --git a/Ubiquitous/XiZi_AIoT/services/lib/newlib/mem_syscalls.c b/Ubiquitous/XiZi_AIoT/services/lib/newlib/mem_syscalls.c new file mode 100644 index 000000000..4a82eb6f0 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/lib/newlib/mem_syscalls.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + +/** +* @file mem_syscalls.c +* @brief support newlib memory +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2020-09-23 +*/ + +/************************************************* +File name: mem_syscalls.c +Description: support newlib memory +Others: take RT-Thread v4.0.2/components/libc/compilers/newlib/syscalls.c for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2020-09-23 +Author: AIIT XUOS Lab +Modification: Use malloc, realloc, calloc and free functions +*************************************************/ +/* wwg debug here */ +// #include +#include + +void *_malloc_r (struct _reent *ptr, size_t size) +{ + /* wwg debug here */ + // void* result = (void*)x_malloc(size); + void* result = NULL; + + if (result == NULL) + { + ptr->_errno = ENOMEM; + } + + return result; +} + +void *_realloc_r (struct _reent *ptr, void *old, size_t newlen) +{ + /* wwg debug here */ + // void* result = (void*)x_realloc(old, newlen); + void* result = NULL; + + if (result == NULL) + { + ptr->_errno = ENOMEM; + } + + return result; +} + +void *_calloc_r (struct _reent *ptr, size_t size, size_t len) +{ + /* wwg debug here */ + // void* result = (void*)x_calloc(size, len); + void* result = NULL; + + if (result == NULL) + { + ptr->_errno = ENOMEM; + } + + return result; +} + +void _free_r (struct _reent *ptr, void *address) +{ + /* wwg debug here */ + // x_free (address); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/lib/newlib/stdio.c b/Ubiquitous/XiZi_AIoT/services/lib/newlib/stdio.c new file mode 100644 index 000000000..6ae393a96 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/lib/newlib/stdio.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017/10/15 bernard the first version + */ + +/** +* @file stdio.c +* @brief support newlib stdio +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2020-09-23 +*/ + +/************************************************* +File name: stdio.c +Description: support newlib stdio +Others: take RT-Thread v4.0.2/components/libc/compilers/newlib/stdio.c for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2020-09-23 +Author: AIIT XUOS Lab +Modification: Use set and get console functions +*************************************************/ + +#include +#include +#include +#include + +#define STDIO_DEVICE_NAME_MAX 32 + +static FILE* std_console = NULL; + +/** + * This function will set system console device. + * + * @param device_name the name of device + * @param mode the mode + * + * @return file number on success; or -1 on failure + */ +int LibcStdioSetConsole(const char* device_name, int mode) +{ + FILE *fp; + char name[STDIO_DEVICE_NAME_MAX] = {0}; + char *file_mode; + + snprintf(name, strlen(device_name) + 6, "/dev/%s", device_name); + name[STDIO_DEVICE_NAME_MAX - 1] = '\0'; + + switch (mode) + { + case O_RDWR: + file_mode = "r+"; + break; + + case O_WRONLY: + file_mode = "wb"; + break; + + default: + file_mode = "rb"; + break; + } + + /* try to open file */ + fp = fopen(name, file_mode); + if (fp) + { + /* set the fp buffer */ + setvbuf(fp, NULL, _IONBF, 0); + + if (std_console) + /* try to close console device */ + fclose(std_console); + std_console = fp; + + if (mode == O_RDWR) + { + /* set _stdin as std_console */ + _GLOBAL_REENT->_stdin = std_console; + } + else + { + /* set NULL */ + _GLOBAL_REENT->_stdin = NULL; + } + + if (mode == O_RDONLY) + { + /* set the _stdout as NULL */ + _GLOBAL_REENT->_stdout = NULL; + /* set the _stderr as NULL */ + _GLOBAL_REENT->_stderr = NULL; + } + else + { + /* set the _stdout as std_console */ + _GLOBAL_REENT->_stdout = std_console; + /* set the _stderr as std_console */ + _GLOBAL_REENT->_stderr = std_console; + } + /* set the __sdidinit as 1 */ + _GLOBAL_REENT->__sdidinit = 1; + } + + if (std_console) + /* return the file number */ + return fileno(std_console); + /* failure and return -1 */ + return -1; +} + +/** + * This function will get system console device. + * + * @return file number on success; or -1 on failure + */ +int LibcStdioGetConsole(void) { + if (std_console) + /* return the file number */ + return fileno(std_console); + else + /* failure and return -1 */ + return -1; +} + +/** + * This function will initialize the c library system. + * + * @return 0 + */ +int LibcSystemInit(void) +{ +#if defined(KERNEL_CONSOLE) + HardwareDevType console; + /* try to get console device */ + console = ObtainConsole(); + if (console) + { +#if defined(LIB_POSIX) + /* set console device mode */ + LibcStdioSetConsole(console->dev_name, O_RDWR); +#else + /* set console device mode */ + LibcStdioSetConsole(console->dev_name, O_WRONLY); +#endif + } +#endif + return 0; +} diff --git a/Ubiquitous/XiZi_AIoT/services/lib/newlib/task_syscalls.c b/Ubiquitous/XiZi_AIoT/services/lib/newlib/task_syscalls.c new file mode 100644 index 000000000..14011491e --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/lib/newlib/task_syscalls.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + +/** +* @file task_syscalls.c +* @brief support newlib abort +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2020-09-23 +*/ + +/************************************************* +File name: task_syscalls.c +Description: support newlib abort +Others: take RT-Thread v4.0.2/components/libc/compilers/newlib/syscalls.c for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2020-09-23 +Author: AIIT XUOS Lab +Modification: Use abort function +*************************************************/ +/* wwg debug here */ +// #include + +void abort(void) +{ + // KTaskDescriptorType current = GetKTaskDescriptor(); + // if (current) + // { + // KPrintf("Task:%-8.*s will be aborted!\n", NAME_NUM_MAX, current->task_base_info.name); + // /* pend current task */ + // SuspendKTask(current->id.id); + // /* schedule */ + // DO_KTASK_ASSIGN; + // } + + while (1); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/lib/newlib/time_syscalls.c b/Ubiquitous/XiZi_AIoT/services/lib/newlib/time_syscalls.c new file mode 100644 index 000000000..2696d108b --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/lib/newlib/time_syscalls.c @@ -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 +// #include + +// time_t time(time_t *t) +// { +// NULL_PARAM_CHECK(t); +// time_t current = 0; + +// #ifdef RESOURCES_RTC +// struct RtcSetParam rtc_set_param; +// rtc_set_param.rtc_set_cmd = OPER_RTC_GET_TIME; +// rtc_set_param.time = ¤t; + +// RtcDrvSetFunction(RTC_DRV_NAME, &rtc_set_param); +// #endif + +// *t = current; + +// return current; +// } + +time_t time(time_t *t) +{ + time_t current = 0; + + *t = current; + + return current; +} diff --git a/Ubiquitous/XiZi_AIoT/services/tools/hosttools/xsconfig.sh b/Ubiquitous/XiZi_AIoT/services/tools/hosttools/xsconfig.sh new file mode 100755 index 000000000..b51a159aa --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/tools/hosttools/xsconfig.sh @@ -0,0 +1,91 @@ +#!/bin/bash +# Tring to create rtcnofig.h from .config +HEADER_STR=XS_CONFIG_H__ + + +function is_pkg_special_config() +{ + echo -ne $1 | egrep '^PKG_|_PATH$|_VER$' >/dev/null 2>/dev/null +} + +function is_config() +{ + echo -ne $1 | egrep '^XS_' >/dev/null 2>/dev/null +} + +function make_config_h() +{ + local CONFIG_NAME=${1} + + # destination file using file descriptor 8 + exec 8>${2} + + echo -ne "#ifndef ${HEADER_STR}\n" >&8 + echo -ne "#define ${HEADER_STR}\n\n" >&8 + + EMPTY_LINE='true' + + while read LN + do + LINE=`echo $LN | sed 's/[ \t\r\n]*$//g'` + + if [ -z "$LINE" ]; then + continue + fi + + if [ '#' = ${LINE:0:1} ]; then + if [ ${#LINE} -eq 1 ]; then + if $EMPTY_LINE; then + continue + fi + echo >&8 + EMPTY_LINE='true' + continue + fi + + if echo -ne "$LINE" | egrep '^# CONFIG_' >/dev/null 2>/dev/null; then + LINE=`printf ' %s' ${LINE:9}` + else + LINE=${LINE:1} + echo -ne "/* ${LINE} */\n" >&8 + fi + + EMPTY_LINE='false' + else + EMPTY_LINE='false' + + OLD_IFS="$IFS" + IFS='=' + SETTINGS=($LINE) + IFS="$OLD_IFS" + + if [ ${#SETTINGS[@]} -ge 2 ]; then + if echo -ne "$SETTINGS[0]" | egrep '^CONFIG_' >/dev/null 2>/dev/null; then + SETTINGS[0]="${SETTINGS[0]:7}" + fi + + if is_pkg_special_config "${SETTINGS[0]}"; then + continue + fi + +# echo "DBG---: ${SETTINGS[@]}, ${SETTINGS[*]}" + if [ "${SETTINGS[1]}" = 'y' ]; then + echo -ne "#define ${SETTINGS[0]}\n" >&8 + else + echo -ne "#define ${SETTINGS[0]} ${LINE#*=}\n" >&8 + fi + fi + fi + + done < $CONFIG_NAME + + if [ -f xsconfig_project.h ]; then + echo -ne "#include \"xsconfig_project.h\"\n" >&8 + fi + + echo -ne "\n#endif\n" >&8 + exec 8<&- +} + +make_config_h $1 $BSP_ROOT/xsconfig.h + diff --git a/Ubiquitous/XiZi_AIoT/softkernel/Kconfig b/Ubiquitous/XiZi_AIoT/softkernel/Kconfig new file mode 100644 index 000000000..e69de29bb diff --git a/Ubiquitous/XiZi_AIoT/softkernel/Makefile b/Ubiquitous/XiZi_AIoT/softkernel/Makefile new file mode 100644 index 000000000..77a92fa1d --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/softkernel/Makefile @@ -0,0 +1,4 @@ + +SRC_DIR := task + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/softkernel/task/Makefile b/Ubiquitous/XiZi_AIoT/softkernel/task/Makefile new file mode 100644 index 000000000..4ca20e597 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/softkernel/task/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := task.c schedule.c ipc.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/support/Kconfig b/Ubiquitous/XiZi_AIoT/support/Kconfig new file mode 100644 index 000000000..e69de29bb diff --git a/Ubiquitous/XiZi_AIoT/support/Makefile b/Ubiquitous/XiZi_AIoT/support/Makefile new file mode 100644 index 000000000..f11fc06ee --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/support/Makefile @@ -0,0 +1,4 @@ + +SRC_DIR := + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/testing/Kconfig b/Ubiquitous/XiZi_AIoT/testing/Kconfig new file mode 100644 index 000000000..e69de29bb diff --git a/Ubiquitous/XiZi_AIoT/testing/Makefile b/Ubiquitous/XiZi_AIoT/testing/Makefile new file mode 100644 index 000000000..f11fc06ee --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/testing/Makefile @@ -0,0 +1,4 @@ + +SRC_DIR := + +include $(KERNEL_ROOT)/compiler.mk From e4742a480c1557f2902e4874c4c4b4c551948d62 Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Wed, 4 Jan 2023 17:14:01 +0800 Subject: [PATCH 26/33] feat add modbus uart protocol for control framework, compile OK --- APP_Framework/Framework/control/Kconfig | 5 +- .../Framework/control/ipc_protocol/Kconfig | 1 + .../ipc_protocol/include/modbus_uart.h | 67 +++ ...odbus.json => test_recipe_modbus_tcp.json} | 0 .../control/ipc_protocol/modbus_uart/Kconfig | 35 ++ .../control/ipc_protocol/modbus_uart/Makefile | 2 +- .../ipc_protocol/modbus_uart/modbus_uart.c | 412 ++++++++++++++++++ .../modbus_uart/test_recipe_modbus_uart.json | 30 ++ .../Framework/control/plc_protocol/Kconfig | 1 + .../control/plc_protocol/fins/Kconfig | 1 - .../control/plc_protocol/melsec/Kconfig | 44 ++ .../control/plc_protocol/melsec/melsec.c | 12 +- .../melsec/test_recipe_melsec_1c.json | 1 + .../melsec/test_recipe_melsec_3c.json | 1 + .../Framework/control/shared/control_def.c | 7 +- .../Framework/control/shared/control_def.h | 1 + .../Framework/control/shared/control_io.c | 121 ++++- 17 files changed, 730 insertions(+), 11 deletions(-) create mode 100644 APP_Framework/Framework/control/ipc_protocol/include/modbus_uart.h rename APP_Framework/Framework/control/ipc_protocol/modbus_tcp/{test_recipe_modbus.json => test_recipe_modbus_tcp.json} (100%) create mode 100644 APP_Framework/Framework/control/ipc_protocol/modbus_uart/modbus_uart.c create mode 100644 APP_Framework/Framework/control/ipc_protocol/modbus_uart/test_recipe_modbus_uart.json diff --git a/APP_Framework/Framework/control/Kconfig b/APP_Framework/Framework/control/Kconfig index e9e0a1753..5618d752f 100755 --- a/APP_Framework/Framework/control/Kconfig +++ b/APP_Framework/Framework/control/Kconfig @@ -2,12 +2,15 @@ menuconfig SUPPORT_CONTROL_FRAMEWORK bool "support control framework" default n select TRANSFORM_LAYER_ATTRIUBUTE - select BSP_USING_LWIP select BSP_USING_SDIO select MOUNT_SDCARD_FS select LIB_USING_CJSON if SUPPORT_CONTROL_FRAMEWORK + config BSP_USING_SERIAL_485 + bool + default n + config CONTROL_RECIPE_FILE string "control framework recipe file name" default "test_recipe.json" diff --git a/APP_Framework/Framework/control/ipc_protocol/Kconfig b/APP_Framework/Framework/control/ipc_protocol/Kconfig index 3c586a36b..cd48d8cc5 100755 --- a/APP_Framework/Framework/control/ipc_protocol/Kconfig +++ b/APP_Framework/Framework/control/ipc_protocol/Kconfig @@ -1,6 +1,7 @@ config CONTROL_PROTOCOL_MODBUS_TCP bool "Using modbus_tcp control protocol" default n + select BSP_USING_LWIP if CONTROL_PROTOCOL_MODBUS_TCP source "$APP_DIR/Framework/control/ipc_protocol/modbus_tcp/Kconfig" endif diff --git a/APP_Framework/Framework/control/ipc_protocol/include/modbus_uart.h b/APP_Framework/Framework/control/ipc_protocol/include/modbus_uart.h new file mode 100644 index 000000000..f07c1604e --- /dev/null +++ b/APP_Framework/Framework/control/ipc_protocol/include/modbus_uart.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022 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 modbus_uart.h + * @brief support modbus_uart function + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2022.12.29 + */ + +#ifndef MODBUS_UART_H +#define MODBUS_UART_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MODBUS_UART_READ_CMD_LENGTH 0x08 +#define MODBUS_UART_WRITE_CMD_LENGTH 0x08 + +typedef enum +{ + READ_COIL_STATUS = 0x01, //read coil cmd + READ_INPUT_STATUS = 0x02, //read input colr cmd + READ_HOLDING_REGISTER = 0x03, //read register info cmd + READ_INPUT_REGISTER = 0x04, //read input register cmd + WRITE_SINGLE_COIL = 0x05, //write coil cmd + WRITE_SINGLE_REGISTER = 0x06, //write single register cmd + WRITE_MULTIPLE_COIL = 0x0F, //write multi coil cmd + WRITE_MULTIPLE_REGISTER = 0x10 //write multi register cmd +}ModbusUartFunctionCode; + +typedef struct +{ + BasicPlcDataInfo base_data_info; + ModbusUartFunctionCode function_code; +}ModbusUartDataInfo; + +typedef struct +{ + ModbusUartDataInfo data_info; + + UniformValueType value_type; + char value_name[20]; + + uint8_t station; + uint16_t start_address; + uint16_t quantity; +}ModbusUartReadItem; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus.json b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus_tcp.json similarity index 100% rename from APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus.json rename to APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus_tcp.json diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_uart/Kconfig b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/Kconfig index 139597f9c..bc6a0cae9 100755 --- a/APP_Framework/Framework/control/ipc_protocol/modbus_uart/Kconfig +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/Kconfig @@ -1,2 +1,37 @@ +if ADD_XIZI_FETURES + config CONTROL_FRAMEWORK_UART_485_DIR + int "control framework 485 direction pin number" + default "2" + config CONTROL_FRAMEWORK_PIN_DEV + string "control framework device pin dev path" + default "/dev/pin_dev" + + config CONTROL_FRAMEWORK_DRIVER_EXTUART + bool "Using extra uart to control framework" + default n + + config CONTROL_FRAMEWORK_UART_DEV + string "control framework device uart dev path" + default "/dev/uart3_dev3" + depends on !CONTROL_FRAMEWORK_DRIVER_EXTUART + + if CONTROL_FRAMEWORK_DRIVER_EXTUART + config CONTROL_FRAMEWORK_UART_DEV + string "control framework device extra uart dev path" + default "/dev/extuart_dev0" + + config CONTROL_FRAMEWORK_DEV_EXT_PORT + int "if control framework device using extuart, choose port" + default "0" + endif +endif + +if ADD_NUTTX_FETURES + +endif + +if ADD_RTTHREAD_FETURES + +endif diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_uart/Makefile b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/Makefile index 608656f03..f22b4fb9a 100755 --- a/APP_Framework/Framework/control/ipc_protocol/modbus_uart/Makefile +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/Makefile @@ -1,4 +1,4 @@ -SRC_FILES := +SRC_FILES := modbus_uart.c include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_uart/modbus_uart.c b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/modbus_uart.c new file mode 100644 index 000000000..ef5f0351c --- /dev/null +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/modbus_uart.c @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2022 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 modbus_uart.c + * @brief support modbus_uart function + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2022.12.29 + */ + +#include + +/*using cirtular area to receive write-data*/ +#define CA_DATA_LENGTH 512 +struct CircularAreaApp *g_write_data; + +static BasicSocketPlc plc_socket = {0}; +static uint8_t recv_buff[1024] = {0}; + +/** + * @description: CRC16 check + * @param data data buffer + * @param length data length + * @return check code + */ +static uint16_t ModbusUartCrc16(uint8_t *data, uint32_t length) +{ + int j; + uint16_t reg_crc = 0xFFFF; + + while (length--) { + reg_crc ^= *data++; + for (j = 0;j < 8;j ++) { + if(reg_crc & 0x01) + reg_crc = reg_crc >> 1 ^ 0xA001; + else + reg_crc = reg_crc >> 1; + } + } + printf(" crc = [0x%x]\n", reg_crc); + return reg_crc; +} + +/** + * @description: Modbus Uart Data Transform from Receive Buffer To Control-Data + * @param p_read_item - read item pointer + * @param recv_buff - receive buff + * @return success : 0 error : -1 + */ +static int ModbusUartTransformRecvBuffToData(ModbusUartReadItem *p_read_item, uint8_t *recv_buff) +{ + uint8_t head_length = 3; + uint8_t *data_buffer; + ModbusUartDataInfo *p_modbus_uart_data_info = &(p_read_item->data_info); + uint16_t quantity = p_read_item->quantity; + + ModbusUartFunctionCode function_code = p_modbus_uart_data_info->function_code; + uint8_t *p_data = p_modbus_uart_data_info->base_data_info.p_data; + + uint8_t bytes_count = recv_buff[2]; + + if ((WRITE_SINGLE_COIL == function_code) || (WRITE_SINGLE_REGISTER == function_code)) { + head_length = 4; + if (p_modbus_uart_data_info->base_data_info.command_ready) { + p_modbus_uart_data_info->base_data_info.command_ready = 0; + } + } + + data_buffer = recv_buff + head_length;//remove head data + + if (READ_COIL_STATUS == function_code || READ_INPUT_STATUS == function_code) { + printf("Receive data is "); + for (int i = 0;i < bytes_count;i ++) { + for (int j = 0;j < 8;j ++) { + if ((i * 8 + j) < p_read_item->quantity) { + *(uint8_t *)(p_data + i * 8 + j) = ((data_buffer[i] >> j) & 0x01) ? 1 : 0; + printf("0x%x", *(uint8_t *)(p_data + i * 8 + j)); + } + } + } + } else if (READ_HOLDING_REGISTER == function_code || READ_INPUT_REGISTER == function_code) { + printf("Receive data is "); + for (uint16_t i = 0; i < quantity; i ++) { + ((int16_t *)p_data)[i] = ((int16_t *)data_buffer)[quantity - i - 1]; + printf("0x%x 0x%x ", p_data[2 * i], p_data[2 * i + 1]); + } + } + printf("\n"); + + return 0; +} + +/** + * @description: Modbus Uart Get Data From Serial + * @param p_read_item - read item pointer + * @return success : 0 error : -1 -2 + */ +static int ModbusUartGetDataBySerial(ModbusUartReadItem *p_read_item) +{ + uint32_t read_length = 0; + memset(recv_buff, 0, sizeof(recv_buff)); + + ModbusUartDataInfo *p_modbus_uart_data_info = &(p_read_item->data_info); + BasicPlcDataInfo *p_base_data_info = &(p_modbus_uart_data_info->base_data_info); + + ControlPrintfList("SEND", p_base_data_info->p_command, p_base_data_info->command_length); + SerialWrite(p_base_data_info->p_command, p_base_data_info->command_length); + + read_length = SerialRead(recv_buff, sizeof(recv_buff)); + if (read_length) { + ControlPrintfList("RECV", recv_buff, read_length); + return ModbusUartTransformRecvBuffToData(p_read_item, recv_buff); + } +} + +/** + * @description: Modbus Uart Data Info Init + * @param p_read_item - read item pointer + * @param station - uart station number + * @param p_data - control-data pointer + * @return success : 0 error : -1 -2 + */ +static int ModbusUartInitialDataInfo(ModbusUartReadItem *p_read_item, uint8_t station, uint8_t *p_data) +{ + uint16_t command_crc = 0; + uint8_t function_code = p_read_item->data_info.function_code; + uint16_t start_address = p_read_item->start_address; + uint16_t quantity = p_read_item->quantity; + + BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info); + + switch (function_code) + { + case READ_COIL_STATUS: + case READ_INPUT_STATUS: + case READ_HOLDING_REGISTER: + case READ_INPUT_REGISTER: + p_base_data_info->command_length = MODBUS_UART_READ_CMD_LENGTH; + p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length); + p_base_data_info->p_data = p_data; + p_base_data_info->command_ready = 1; + break; + case WRITE_SINGLE_COIL: + case WRITE_SINGLE_REGISTER: + if (p_data == NULL) { + return -1; + } else { + p_base_data_info->command_length = MODBUS_UART_WRITE_CMD_LENGTH; + p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length); + p_base_data_info->p_data = p_data; + p_base_data_info->data_size = 2; + p_base_data_info->command_ready = 0; + } + break; + case WRITE_MULTIPLE_COIL: + case WRITE_MULTIPLE_REGISTER: + //to do + printf("%s unsupported function code %d\n", __func__, function_code); + return -1; + default: + return -2; + } + + memset(p_base_data_info->p_command, 0, p_base_data_info->command_length); + + p_base_data_info->p_command[0] = station; + p_base_data_info->p_command[1] = function_code; + p_base_data_info->p_command[2] = start_address >> 8; + p_base_data_info->p_command[3] = start_address; + if ((function_code != WRITE_SINGLE_COIL) && (function_code != WRITE_SINGLE_REGISTER)) { + p_base_data_info->p_command[4] = quantity >> 8; + p_base_data_info->p_command[5] = quantity; + command_crc = ModbusUartCrc16(p_base_data_info->p_command, 6); + p_base_data_info->p_command[6] = command_crc & 0xFF; + p_base_data_info->p_command[7] = (command_crc >> 8) & 0xFF; + } + + return 0; +} + +/** + * @description: Modbus Uart Format write data from "g_write_data" + * @param p_read_item - read item pointer + * @return success : 0 error : -1 -2 + */ +static int ModbusUartForamatWriteData(ModbusUartReadItem *p_read_item) +{ + int i = 0; + uint16_t command_index = 0; + int write_data_length = 0; + uint8_t write_data_buffer[32] = {0}; + + BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info); + uint8_t *p_command = p_base_data_info->p_command; + uint8_t function_code = p_read_item->data_info.function_code; + + if (function_code < WRITE_SINGLE_COIL) { + return 0; + } + + write_data_length = CircularAreaAppRead(g_write_data, write_data_buffer, p_base_data_info->data_size); + if (p_base_data_info->data_size != write_data_length) { + //printf("%s get write data %d [should be %d]failed!\n", __func__, write_data_length, p_base_data_info->data_size); + return 0; + } + + switch (function_code) + { + case WRITE_SINGLE_COIL: + case WRITE_SINGLE_REGISTER: + command_index = 4; + break; + case WRITE_MULTIPLE_COIL: + case WRITE_MULTIPLE_REGISTER: + printf("%s unsupported function code %d\n", __func__, function_code); + return -1; + default: + return -2; + } + + for (i = 0; i < write_data_length; i ++) { + p_base_data_info->p_command[command_index + i] = write_data_buffer[i]; + } + + p_base_data_info->command_ready = 1; + + return write_data_length; +} + +/** + * @description: Modbus Uart Receive Plc Data Task + * @param parameter - parameter pointer + * @return + */ +void *ReceivePlcDataTask(void *parameter) +{ + int i = 0; + uint8_t try_count = 0; + uint16_t data_length = 0; + uint8_t *modbus_uart_data; + uint16_t read_item_size = sizeof(ModbusUartReadItem); + + struct ControlProtocol *control_protocol = (struct ControlProtocol *)parameter; + struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args; + ModbusUartReadItem *modbus_uart_read_item = (ModbusUartReadItem *)control_protocol->recipe->read_item; + modbus_uart_data = control_protocol->recipe->protocol_data.data; + data_length = control_protocol->recipe->protocol_data.data_length; + + while (1) { + for (i = 0; i < control_protocol->recipe->read_item_count; i ++) { + + ModbusUartForamatWriteData((ModbusUartReadItem *)modbus_uart_read_item + i); + + ModbusUartGetDataBySerial((ModbusUartReadItem *)modbus_uart_read_item + i); + } + + /*read all variable item data, put them into circular_area*/ + if (i == control_protocol->recipe->read_item_count) { + printf("%s get %d item %d length modbus_uart_data %p\n", __func__, i, data_length, modbus_uart_data); + CircularAreaAppWrite(circular_area, modbus_uart_data, data_length, 0); + } + + /*read data every single 'read_period' ms*/ + PrivTaskDelay(control_protocol->recipe->read_period); + } +} + +/** + * @description: Modbus Uart Protocol Open + * @param control_protocol - control protocol pointer + * @return success : 0 error + */ +int ModbusUartOpen(struct ControlProtocol *control_protocol) +{ + ControlProtocolOpenDef(control_protocol); + + g_write_data = CircularAreaAppInit(CA_DATA_LENGTH); + if (NULL == g_write_data) { + printf("%s CircularAreaInit error\n", __func__); + return -1; + } + + return 0; +} + +/** + * @description: Modbus Uart Protocol Close + * @param control_protocol - control protocol pointer + * @return success : 0 error + */ +int ModbusUartClose(struct ControlProtocol *control_protocol) +{ + CircularAreaAppRelease(g_write_data); + + ControlProtocolCloseDef(); + + return 0; +} + +/** + * @description: Modbus Uart Protocol Read Data + * @param control_protocol - control protocol pointer + * @param buf - read data buffer + * @param len - read data length + * @return success : data length error : 0 + */ +int ModbusUartRead(struct ControlProtocol *control_protocol, void *buf, size_t len) +{ + struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args; + return CircularAreaAppRead(circular_area, buf, len); +} + +/** + * @description: Modbus Uart Protocol Write Data + * @param control_protocol - control protocol pointer + * @param buf - write data buffer + * @param len - write data length + * @return success : data length error : 0 + */ +int ModbusUartWrite(struct ControlProtocol *control_protocol, const void *buf, size_t len) +{ + CircularAreaAppWrite(g_write_data, (uint8_t *)buf, len, 0); + + return 0; +} + +/** + * @description: Modbus Uart Protocol Ioctl + * @param control_protocol - control protocol pointer + * @param cmd - ioctl cmd + * @param args - ioctl args + * @return success : data length error : 0 + */ +int ModbusUartIoctl(struct ControlProtocol *control_protocol, int cmd, void *args) +{ + //to do + return 0; +} + +static struct ControlDone modbusuart_protocol_done = +{ + ._open = ModbusUartOpen, + ._close = ModbusUartClose, + ._read = ModbusUartRead, + ._write = ModbusUartWrite, + ._ioctl = ModbusUartIoctl, +}; + +/** + * @description: Modbus TCP Protocol Cmd Generate + * @param p_recipe - recipe pointer + * @param protocol_format_info - protocol format info pointer + * @return success : 0 error : -1 + */ +int ModbusUartProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info) +{ + int ret = 0; + static uint8_t last_item_size = 0; + uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size; + + ModbusUartReadItem *modbusuart_read_item = (ModbusUartReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index; + + modbusuart_read_item->value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint; + strncpy(modbusuart_read_item->value_name, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_name")->valuestring, 20); + modbusuart_read_item->data_info.function_code = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "function_code")->valueint; + modbusuart_read_item->start_address = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "start_address")->valueint; + modbusuart_read_item->quantity = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "quantity")->valueint; + + ret = ModbusUartInitialDataInfo(modbusuart_read_item, + p_recipe->serial_config.station, + p_read_item_data); + + ControlPrintfList("CMD", modbusuart_read_item->data_info.base_data_info.p_command, modbusuart_read_item->data_info.base_data_info.command_length); + protocol_format_info->last_item_size = GetValueTypeMemorySize(modbusuart_read_item->value_type); + + last_item_size += protocol_format_info->last_item_size; + + return ret; + +} + +/** + * @description: Modbus TCP Protocol Init + * @param p_recipe - recipe pointer + * @return success : 0 error : -1 + */ +int ModbusUartProtocolInit(struct ControlRecipe *p_recipe) +{ + p_recipe->read_item = PrivMalloc(sizeof(ModbusUartReadItem) * p_recipe->read_item_count); + if (NULL == p_recipe->read_item) { + PrivFree(p_recipe->read_item); + return -1; + } + + memset(p_recipe->read_item, 0, sizeof(ModbusUartReadItem)); + + p_recipe->ControlProtocolFormatCmd = ModbusUartProtocolFormatCmd; + + p_recipe->done = &modbusuart_protocol_done; + + return 0; +} diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_uart/test_recipe_modbus_uart.json b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/test_recipe_modbus_uart.json new file mode 100644 index 000000000..613d010c6 --- /dev/null +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/test_recipe_modbus_uart.json @@ -0,0 +1,30 @@ +{ + "device_id": 1, + "device_name": "GJ2", + "communication_type": 1, + "serial_config": { + "station": 1, + "baud_rate": 9600, + "data_bits": 8, + "stop_bits": 1, + "check_mode": 0 + }, + "protocol_type": 3, + "read_period": 100, + "read_item_list": [ + { + "value_name": "M0", + "value_type": 1, + "function_code": 1, + "start_address": 8192, + "quantity": 1 + }, + { + "value_name": "D208", + "value_type": 9, + "function_code": 3, + "start_address": 208, + "quantity": 2 + } + ] +} \ No newline at end of file diff --git a/APP_Framework/Framework/control/plc_protocol/Kconfig b/APP_Framework/Framework/control/plc_protocol/Kconfig index 11d498f81..46f632974 100755 --- a/APP_Framework/Framework/control/plc_protocol/Kconfig +++ b/APP_Framework/Framework/control/plc_protocol/Kconfig @@ -1,6 +1,7 @@ config CONTROL_PROTOCOL_FINS bool "Using fins control protocol" default n + select BSP_USING_LWIP if CONTROL_PROTOCOL_FINS source "$APP_DIR/Framework/control/plc_protocol/fins/Kconfig" endif diff --git a/APP_Framework/Framework/control/plc_protocol/fins/Kconfig b/APP_Framework/Framework/control/plc_protocol/fins/Kconfig index 139597f9c..8b1378917 100755 --- a/APP_Framework/Framework/control/plc_protocol/fins/Kconfig +++ b/APP_Framework/Framework/control/plc_protocol/fins/Kconfig @@ -1,2 +1 @@ - diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig b/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig index 93392b091..8a8d32c5a 100755 --- a/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig +++ b/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig @@ -4,17 +4,61 @@ choice config CONTROL_PROTOCOL_MELSEC_1E bool "support melsec_1e protocol, using TCP" + select BSP_USING_LWIP config CONTROL_PROTOCOL_MELSEC_3E_Q_L bool "support melsec_3e_q_l protocol, using TCP" + select BSP_USING_LWIP config CONTROL_PROTOCOL_MELSEC_3E_IQ_R bool "support melsec_3e_iq_r protocol, using TCP" + select BSP_USING_LWIP config CONTROL_PROTOCOL_MELSEC_1C bool "support melsec_1c protocol, using SERIAL" + select BSP_USING_SERIAL_485 config CONTROL_PROTOCOL_MELSEC_3C bool "support melsec_3c protocol, using SERIAL" + select BSP_USING_SERIAL_485 endchoice +if BSP_USING_SERIAL_485 + if ADD_XIZI_FETURES + config CONTROL_FRAMEWORK_UART_485_DIR + int "control framework 485 direction pin number" + default "2" + + config CONTROL_FRAMEWORK_PIN_DEV + string "control framework device pin dev path" + default "/dev/pin_dev" + + config CONTROL_FRAMEWORK_DRIVER_EXTUART + bool "Using extra uart to control framework" + default n + + config CONTROL_FRAMEWORK_UART_DEV + string "control framework device uart dev path" + default "/dev/uart3_dev3" + depends on !CONTROL_FRAMEWORK_DRIVER_EXTUART + + if CONTROL_FRAMEWORK_DRIVER_EXTUART + config CONTROL_FRAMEWORK_UART_DEV + string "control framework device extra uart dev path" + default "/dev/extuart_dev0" + + config CONTROL_FRAMEWORK_DEV_EXT_PORT + int "if control framework device using extuart, choose port" + default "0" + endif + endif + + if ADD_NUTTX_FETURES + + endif + + if ADD_RTTHREAD_FETURES + + endif + +endif diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c index 465d2b532..584fbdaf5 100644 --- a/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c +++ b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c @@ -575,6 +575,7 @@ static int MelsecTransformRecvBuffToData(MelsecReadItem *p_read_item, uint8_t *r return 0; } +#ifdef BSP_USING_LWIP /** * @description: Melsec Get Data From Socket * @param socket - socket @@ -619,6 +620,7 @@ static int MelsecGetDataBySocket(int32_t socket, MelsecReadItem *p_read_item) } return -2; } +#endif /** * @description: Melsec Get Data From Serial @@ -673,12 +675,14 @@ void *ReceivePlcDataTask(void *parameter) if ((PROTOCOL_MELSEC_1C == control_protocol->protocol_type) || (PROTOCOL_MELSEC_3C == control_protocol->protocol_type)) { MelsecGetDataBySerial((MelsecReadItem *)melsec_read_item + i); } else { +#ifdef BSP_USING_LWIP /*only connect socket when close socket or init*/ while (ControlConnectSocket(&plc_socket) < 0) { PrivTaskDelay(1000); } MelsecGetDataBySocket(plc_socket.socket, (MelsecReadItem *)melsec_read_item + i); +#endif } } @@ -712,8 +716,12 @@ int MelsecOpen(struct ControlProtocol *control_protocol) */ int MelsecClose(struct ControlProtocol *control_protocol) { - ControlDisconnectSocket(&plc_socket); - + if ((PROTOCOL_MELSEC_1C != control_protocol->protocol_type) && (PROTOCOL_MELSEC_3C != control_protocol->protocol_type)) { +#ifdef BSP_USING_LWIP + ControlDisconnectSocket(&plc_socket); +#endif + } + ControlProtocolCloseDef(); return 0; diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1c.json b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1c.json index ee43fe00c..7c67c0263 100644 --- a/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1c.json +++ b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1c.json @@ -3,6 +3,7 @@ "device_name": "S01", "communication_type": 1, "serial_config": { + "station": 1, "baud_rate": 19200, "data_bits": 7, "stop_bits": 1, diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3c.json b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3c.json index 097acbdbd..5fb0e0dc2 100644 --- a/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3c.json +++ b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3c.json @@ -3,6 +3,7 @@ "device_name": "S02", "communication_type": 1, "serial_config": { + "station": 1, "baud_rate": 19200, "data_bits": 7, "stop_bits": 1, diff --git a/APP_Framework/Framework/control/shared/control_def.c b/APP_Framework/Framework/control/shared/control_def.c index 306b1b5f4..3168af845 100644 --- a/APP_Framework/Framework/control/shared/control_def.c +++ b/APP_Framework/Framework/control/shared/control_def.c @@ -143,12 +143,13 @@ static uint16_t GetRecipeTotalDataLength(cJSON* read_item_list_json) static void ControlBasicSerialConfig(struct ControlRecipe *p_recipe, cJSON *p_recipe_file_json) { cJSON *p_serial_config_json = cJSON_GetObjectItem(p_recipe_file_json, "serial_config"); + p_recipe->serial_config.station = cJSON_GetObjectItem(p_serial_config_json, "station")->valueint; p_recipe->serial_config.baud_rate = cJSON_GetObjectItem(p_serial_config_json, "baud_rate")->valueint; p_recipe->serial_config.data_bits = cJSON_GetObjectItem(p_serial_config_json, "data_bits")->valueint; p_recipe->serial_config.stop_bits = cJSON_GetObjectItem(p_serial_config_json, "stop_bits")->valueint; p_recipe->serial_config.check_mode = cJSON_GetObjectItem(p_serial_config_json, "check_mode")->valueint; - printf("Serial_config: baud_rate: %d, data_bits: %d, stop_bits: %d, check_mode is %d\n", - p_recipe->serial_config.baud_rate, p_recipe->serial_config.data_bits, p_recipe->serial_config.stop_bits, p_recipe->serial_config.check_mode); + printf("Serial_config:station: %d baud_rate: %d, data_bits: %d, stop_bits: %d, check_mode is %d\n", + p_recipe->serial_config.station, p_recipe->serial_config.baud_rate, p_recipe->serial_config.data_bits, p_recipe->serial_config.stop_bits, p_recipe->serial_config.check_mode); } /** @@ -209,6 +210,7 @@ void ControlPrintfList(char name[5], uint8_t *number_list, uint16_t length) printf("\n**************************************\n"); } +#ifdef BSP_USING_LWIP /** * @description: Control Framework Connect Socket * @param p_plc - basic socket plc pointer @@ -285,6 +287,7 @@ int ControlDisconnectSocket(BasicSocketPlc *p_plc) return error; } +#endif /** * @description: Control Framework Protocol Open for Sub_Protocol, Init Circular Area and Receive Data Task diff --git a/APP_Framework/Framework/control/shared/control_def.h b/APP_Framework/Framework/control/shared/control_def.h index fced6fd80..96957ad20 100644 --- a/APP_Framework/Framework/control/shared/control_def.h +++ b/APP_Framework/Framework/control/shared/control_def.h @@ -90,6 +90,7 @@ struct ProtocolData struct SerialConfig { + uint8_t station; uint32_t baud_rate; uint8_t data_bits; uint8_t stop_bits; diff --git a/APP_Framework/Framework/control/shared/control_io.c b/APP_Framework/Framework/control/shared/control_io.c index b1a8ae1c8..0bc8b77d7 100644 --- a/APP_Framework/Framework/control/shared/control_io.c +++ b/APP_Framework/Framework/control/shared/control_io.c @@ -20,6 +20,92 @@ #include +#ifdef BSP_USING_SERIAL_485 +static int pin_fd = 0; +static int uart_fd = 0; + +/** + * @description: Set Uart 485 Input + * @return + */ +static void Set485Input(void) +{ + struct PinStat pin_stat; + pin_stat.pin = CONTROL_FRAMEWORK_UART_485_DIR; + pin_stat.val = GPIO_LOW; + PrivWrite(pin_fd, &pin_stat, 1); +} + +/** + * @description: Set Uart 485 Output + * @return + */ +static void Set485Output(void) +{ + struct PinStat pin_stat; + pin_stat.pin = CONTROL_FRAMEWORK_UART_485_DIR; + pin_stat.val = GPIO_HIGH; + PrivWrite(pin_fd, &pin_stat, 1); +} + +/** + * @description: Control Framework Uart 485 Init + * @param baud_rate - baud rate + * @param data_bits - data bits + * @param stop_bits - stop bits + * @param check_mode - check mode, even、odd、none + * @return + */ +void Uart485Init(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_t check_mode) +{ + int ret = 0; + + pin_fd = PrivOpen(CONTROL_FRAMEWORK_PIN_DEV, O_RDWR); + if (pin_fd < 0) { + printf("open %s error\n", CONTROL_FRAMEWORK_PIN_DEV); + return; + } + + struct PinParam pin_param; + pin_param.cmd = GPIO_CONFIG_MODE; + pin_param.mode = GPIO_CFG_OUTPUT; + pin_param.pin = CONTROL_FRAMEWORK_UART_485_DIR; + + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = PIN_TYPE; + ioctl_cfg.args = &pin_param; + PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg); + + uart_fd = open(CONTROL_FRAMEWORK_UART_DEV, O_RDWR); + if (uart_fd < 0) { + printf("open fd error %d\n", uart_fd); + return; + } + printf("Uart485Init open fd %d\n", uart_fd); + + struct SerialDataCfg cfg; + cfg.serial_baud_rate = baud_rate; + cfg.serial_data_bits = data_bits; + cfg.serial_stop_bits = stop_bits; + cfg.serial_buffer_size = 128; + cfg.serial_parity_mode = check_mode; + cfg.serial_bit_order = 0; + cfg.serial_invert_mode = 0; +#ifdef CONTROL_FRAMEWORK_DRIVER_EXTUART + cfg.ext_uart_no = 0; + cfg.port_configure = PORT_CFG_INIT; +#endif + cfg.serial_timeout = 10000; + + if (ret != PrivIoctl(uart_fd, OPE_INT, &cfg)) { + printf("ioctl fd error %d\n", ret); + return; + } + + printf("%s done!\n", __func__); +} +#endif + /** * @description: Control Framework Socket Init * @param ip - local ip pointer @@ -48,7 +134,9 @@ void SocketInit(char *ip, char *mask, char *gw) */ void SerialInit(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_t check_mode) { - // Uart485Init(baud_rate, data_bits, stop_bits, check_mode); +#ifdef BSP_USING_SERIAL_485 + Uart485Init(baud_rate, data_bits, stop_bits, check_mode); +#endif } /** @@ -59,16 +147,41 @@ void SerialInit(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_ */ void SerialWrite(uint8_t *write_data, int length) { - //to do +#ifdef BSP_USING_SERIAL_485 + Set485Output(); + PrivTaskDelay(20); + + PrivWrite(uart_fd, write_data, length); + + PrivTaskDelay(10); + Set485Input(); +#endif } /** * @description: Control Framework Serial Read * @param read_data - read data * @param length - length - * @return + * @return read data size */ int SerialRead(uint8_t *read_data, int length) { - //to do +#ifdef BSP_USING_SERIAL_485 + int data_size = 0; + int data_recv_size = 0; + + while (data_size < length) { + data_recv_size = PrivRead(uart_fd, read_data + data_recv_size, length); + // for (int i = 0; i < data_recv_size; i ++) { + // printf("idx %d data 0x%x\n", i, recv_data[i + data_size]); + // } + + data_size += data_recv_size; + } + + //need to wait 25ms , make sure write cmd again and receive data successfully + PrivTaskDelay(25); + + return data_size; +#endif } From 9ad282c39e6cfde73c222ab52f5474861a279644 Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Fri, 6 Jan 2023 10:17:24 +0800 Subject: [PATCH 27/33] feat support LwIP in hc32f4a0 board --- .../Applications/connection_app/Makefile | 4 - .../socket_demo/lwip_tcp_socket_demo.c | 112 ++++++++--------- .../socket_demo/lwip_udp_socket_demo.c | 118 +++++++++--------- .../third_party_driver/ethernet/ethernetif.c | 42 ++++++- .../include/hardware_ethernetif.h | 2 +- 5 files changed, 155 insertions(+), 123 deletions(-) diff --git a/APP_Framework/Applications/connection_app/Makefile b/APP_Framework/Applications/connection_app/Makefile index 0cb8c9568..df4ae9b97 100755 --- a/APP_Framework/Applications/connection_app/Makefile +++ b/APP_Framework/Applications/connection_app/Makefile @@ -1,6 +1,3 @@ - -ifeq ($(CONFIG_SOCKET_DEMO),y) - include $(KERNEL_ROOT)/.config ifeq ($(CONFIG_ADD_NUTTX_FETURES),y) @@ -21,4 +18,3 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y) include $(KERNEL_ROOT)/compiler.mk endif -endif diff --git a/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c b/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c index b6e4f9428..48f147fe9 100755 --- a/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c +++ b/APP_Framework/Applications/connection_app/socket_demo/lwip_tcp_socket_demo.c @@ -21,7 +21,7 @@ #include #ifdef ADD_XIZI_FETURES -#include "sys_arch.h" +#include #include #include "lwip/sys.h" #endif @@ -33,9 +33,17 @@ #include "stdio.h" #endif -#define TCP_DEMO_BUF_SIZE 65535 +#define TCP_DEMO_BUF_SIZE 65535 +#define TCP_DEMO_SEND_TIMES 20 +#define LWIP_TCP_DEMO_TASK_STACK_SIZE 4096 +#define LWIP_TCP_DEMO_TASK_PRIO 20 -char tcp_socket_ip[] = {192, 168, 250, 252}; +static pthread_t tcp_client_task; +static pthread_t tcp_server_task; + +static char tcp_demo_ipaddr[] = {192, 168, 131, 77}; +static char tcp_demo_netmask[] = {255, 255, 254, 0}; +static char tcp_demo_gwaddr[] = {192, 168, 131, 1}; #ifdef ADD_NUTTX_FETURES #define lw_print printf @@ -46,8 +54,8 @@ char tcp_socket_ip[] = {192, 168, 250, 252}; #define LWIP_TARGET_PORT 4840 #endif -uint16_t tcp_socket_port = LWIP_TARGET_PORT; -char tcp_ip_str[128] = {0}; +static uint16_t tcp_socket_port = 8888; +static char tcp_ip_str[128] = {0}; /******************************************************************************/ void TcpSocketConfigParam(char *ip_str) @@ -55,35 +63,23 @@ void TcpSocketConfigParam(char *ip_str) int ip1, ip2, ip3, ip4, port = 0; if(ip_str == NULL) - { return; - } - if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port)) - { + if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port)) { printf("config ip %s port %d\n", ip_str, port); strcpy(tcp_ip_str, ip_str); - tcp_socket_ip[0] = ip1; - tcp_socket_ip[1] = ip2; - tcp_socket_ip[2] = ip3; - tcp_socket_ip[3] = ip4; if(port) tcp_socket_port = port; return; } - if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) - { + if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) { printf("config ip %s\n", ip_str); - tcp_socket_ip[0] = ip1; - tcp_socket_ip[1] = ip2; - tcp_socket_ip[2] = ip3; - tcp_socket_ip[3] = ip4; strcpy(tcp_ip_str, ip_str); } } -static void TcpSocketRecvTask(void *arg) +static void *TcpSocketRecvTask(void *arg) { int fd = -1, clientfd; int recv_len; @@ -91,18 +87,15 @@ static void TcpSocketRecvTask(void *arg) struct sockaddr_in tcp_addr; socklen_t addr_len; - while(1) - { + while(1) { recv_buf = (char *)malloc(TCP_DEMO_BUF_SIZE); - if (recv_buf == NULL) - { + if (recv_buf == NULL) { lw_error("No memory\n"); continue; } fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) - { + if (fd < 0) { lw_error("Socket error\n"); free(recv_buf); continue; @@ -113,8 +106,7 @@ static void TcpSocketRecvTask(void *arg) tcp_addr.sin_port = htons(tcp_socket_port); memset(&(tcp_addr.sin_zero), 0, sizeof(tcp_addr.sin_zero)); - if (bind(fd, (struct sockaddr *)&tcp_addr, sizeof(struct sockaddr)) == -1) - { + if (bind(fd, (struct sockaddr *)&tcp_addr, sizeof(struct sockaddr)) == -1) { lw_error("Unable to bind\n"); close(fd); free(recv_buf); @@ -125,8 +117,7 @@ static void TcpSocketRecvTask(void *arg) lw_notice("\nLocal Port:%d\n", tcp_socket_port); // setup socket fd as listening mode - if (listen(fd, 5) != 0 ) - { + if (listen(fd, 5) != 0 ) { lw_error("Unable to listen\n"); close(fd); free(recv_buf); @@ -137,13 +128,11 @@ static void TcpSocketRecvTask(void *arg) clientfd = accept(fd, (struct sockaddr *)&tcp_addr, (socklen_t*)&addr_len); lw_notice("client %s connected\n", inet_ntoa(tcp_addr.sin_addr)); - while(1) - { + while(1) { memset(recv_buf, 0, TCP_DEMO_BUF_SIZE); recv_len = recvfrom(clientfd, recv_buf, TCP_DEMO_BUF_SIZE, 0, (struct sockaddr *)&tcp_addr, &addr_len); - if(recv_len > 0) - { + if(recv_len > 0) { lw_notice("Receive from : %s\n", inet_ntoa(tcp_addr.sin_addr)); lw_notice("Receive data : %d - %s\n\n", recv_len, recv_buf); } @@ -157,26 +146,33 @@ static void TcpSocketRecvTask(void *arg) void TcpSocketRecvTest(int argc, char *argv[]) { - if(argc >= 2) - { + if(argc >= 2) { lw_print("lw: [%s] target ip %s\n", __func__, argv[1]); TcpSocketConfigParam(argv[1]); } #ifdef ADD_XIZI_FETURES - lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, tcp_socket_ip); - sys_thread_new("TcpSocketRecvTask", TcpSocketRecvTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); + lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr); + + pthread_attr_t attr; + attr.schedparam.sched_priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; #endif #ifdef ADD_NUTTX_FETURES - TcpSocketRecvTask(NULL); + pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER; + attr.priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; #endif + + PrivTaskCreate(&tcp_server_task, &attr, &TcpSocketRecvTask, NULL); + PrivTaskStartup(&tcp_server_task); } PRIV_SHELL_CMD_FUNCTION(TcpSocketRecvTest, a tcp receive sample, PRIV_SHELL_CMD_MAIN_ATTR); -static void TcpSocketSendTask(void *arg) +static void *TcpSocketSendTask(void *arg) { - int cnt = LWIP_DEMO_TIMES; + int cnt = TCP_DEMO_SEND_TIMES; int fd = -1; int ret; char send_msg[128]; @@ -186,10 +182,9 @@ static void TcpSocketSendTask(void *arg) memset(send_msg, 0, sizeof(send_msg)); fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) - { + if (fd < 0) { lw_print("Socket error\n"); - return; + return NULL; } struct sockaddr_in tcp_sock; @@ -200,17 +195,15 @@ static void TcpSocketSendTask(void *arg) memset(&(tcp_sock.sin_zero), 0, sizeof(tcp_sock.sin_zero)); ret = connect(fd, (struct sockaddr *)&tcp_sock, sizeof(struct sockaddr)); - if (ret) - { - lw_print("Unable to connect %s = %d\n", tcp_ip_str, ret); + if (ret < 0) { + lw_print("Unable to connect %s:%d = %d\n", tcp_ip_str, tcp_socket_port, ret); close(fd); - return; + return NULL; } lw_print("TCP connect %s:%d success, start to send.\n", tcp_ip_str, tcp_socket_port); - while (cnt --) - { + while (cnt --) { lw_print("Lwip client is running.\n"); snprintf(send_msg, sizeof(send_msg), "TCP test package times %d\r\n", cnt); send(fd, send_msg, strlen(send_msg), 0); @@ -219,24 +212,31 @@ static void TcpSocketSendTask(void *arg) } close(fd); - return; + return NULL; } void TcpSocketSendTest(int argc, char *argv[]) { - if(argc >= 2) - { + if(argc >= 2) { lw_print("lw: [%s] target ip %s\n", __func__, argv[1]); TcpSocketConfigParam(argv[1]); } #ifdef ADD_XIZI_FETURES - lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, tcp_socket_ip); - sys_thread_new("Tcp Socket Send", TcpSocketSendTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); + lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr); + + pthread_attr_t attr; + attr.schedparam.sched_priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; #endif #ifdef ADD_NUTTX_FETURES - TcpSocketSendTask(NULL); + pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER; + attr.priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; #endif + + PrivTaskCreate(&tcp_client_task, &attr, &TcpSocketSendTask, NULL); + PrivTaskStartup(&tcp_client_task); } PRIV_SHELL_CMD_FUNCTION(TcpSocketSendTest, a tcp send sample, PRIV_SHELL_CMD_MAIN_ATTR); diff --git a/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c b/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c index 51c94a6c3..30a8a6a59 100755 --- a/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c +++ b/APP_Framework/Applications/connection_app/socket_demo/lwip_udp_socket_demo.c @@ -20,7 +20,7 @@ #include #ifdef ADD_XIZI_FETURES -#include "sys_arch.h" +#include #include "lwip/sockets.h" #endif @@ -38,11 +38,20 @@ #define lw_print printf #endif -#define UDP_BUF_SIZE 65536 +#define UDP_DEMO_BUF_SIZE 65535 +#define UDP_DEMO_SEND_TIMES 20 +#define LWIP_UDP_DEMO_TASK_STACK_SIZE 4096 +#define LWIP_UDP_DEMO_TASK_PRIO 20 -char udp_socket_ip[] = {192, 168, 250, 252}; -char udp_ip_str[128] = {0}; -uint16_t udp_socket_port = LWIP_LOCAL_PORT; +static pthread_t udp_client_task; +static pthread_t udp_server_task; + +static char udp_demo_ipaddr[] = {192, 168, 131, 77}; +static char udp_demo_netmask[] = {255, 255, 254, 0}; +static char udp_demo_gwaddr[] = {192, 168, 131, 1}; + +static char udp_ip_str[128] = {0}; +static uint16_t udp_socket_port = 8888; /*****************************************************************************/ void UdpSocketConfigParam(char *ip_str) @@ -50,53 +59,38 @@ void UdpSocketConfigParam(char *ip_str) int ip1, ip2, ip3, ip4, port = 0; if(ip_str == NULL) - { return; - } - if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port)) - { + if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port)) { printf("config ip %s port %d\n", ip_str, port); strcpy(udp_ip_str, ip_str); - udp_socket_ip[0] = ip1; - udp_socket_ip[1] = ip2; - udp_socket_ip[2] = ip3; - udp_socket_ip[3] = ip4; if(port) udp_socket_port = port; return; } - if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) - { + if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) { printf("config ip %s\n", ip_str); - udp_socket_ip[0] = ip1; - udp_socket_ip[1] = ip2; - udp_socket_ip[2] = ip3; - udp_socket_ip[3] = ip4; strcpy(udp_ip_str, ip_str); } } -static void UdpSocketRecvTask(void *arg) +static void *UdpSocketRecvTask(void *arg) { int fd = -1; char *recv_buf; struct sockaddr_in udp_addr, server_addr; int recv_len; - while(1) - { - recv_buf = (char *)malloc(UDP_BUF_SIZE); - if(recv_buf == NULL) - { + while(1) { + recv_buf = (char *)PrivMalloc(UDP_DEMO_BUF_SIZE); + if(recv_buf == NULL) { lw_error("No memory\n"); continue; } fd = socket(AF_INET, SOCK_DGRAM, 0); - if(fd < 0) - { + if(fd < 0) { lw_error("Socket error\n"); free(recv_buf); continue; @@ -107,8 +101,7 @@ static void UdpSocketRecvTask(void *arg) udp_addr.sin_port = htons(udp_socket_port); memset(&(udp_addr.sin_zero), 0, sizeof(udp_addr.sin_zero)); - if(bind(fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1) - { + if(bind(fd, (struct sockaddr *)&udp_addr, sizeof(struct sockaddr)) == -1) { lw_error("Unable to bind\n"); close(fd); free(recv_buf); @@ -118,12 +111,10 @@ static void UdpSocketRecvTask(void *arg) lw_notice("UDP bind success, start to receive.\n"); lw_notice("\n\nLocal Port:%d\n\n", udp_socket_port); - while(1) - { - memset(recv_buf, 0, UDP_BUF_SIZE); - recv_len = recv(fd, recv_buf, UDP_BUF_SIZE, 0); - if(recv_len > 0) - { + while(1) { + memset(recv_buf, 0, UDP_DEMO_BUF_SIZE); + recv_len = recv(fd, recv_buf, UDP_DEMO_BUF_SIZE, 0); + if(recv_len > 0) { lw_notice("Receive from : %s\n", inet_ntoa(server_addr.sin_addr)); lw_notice("Receive data : %s\n\n", recv_buf); } @@ -137,36 +128,41 @@ static void UdpSocketRecvTask(void *arg) void UdpSocketRecvTest(int argc, char *argv[]) { - if(argc >= 2) - { + if(argc >= 2) { lw_notice("lw: [%s] target ip %s\n", __func__, argv[1]); UdpSocketConfigParam(argv[1]); } #ifdef ADD_XIZI_FETURES - lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, udp_socket_ip); - sys_thread_new("UdpSocketRecvTask", UdpSocketRecvTask, NULL, - LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); + lwip_config_tcp(0, udp_demo_ipaddr, udp_demo_netmask, udp_demo_gwaddr); + + pthread_attr_t attr; + attr.schedparam.sched_priority = LWIP_UDP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE; #endif #ifdef ADD_NUTTX_FETURES - UdpSocketRecvTask(NULL); + pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER; + attr.priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; #endif + + PrivTaskCreate(&udp_server_task, &attr, &UdpSocketRecvTask, NULL); + PrivTaskStartup(&udp_server_task); } PRIV_SHELL_CMD_FUNCTION(UdpSocketRecvTest, a udp receive sample, PRIV_SHELL_CMD_MAIN_ATTR); -static void UdpSocketSendTask(void *arg) +static void *UdpSocketSendTask(void *arg) { - int cnt = LWIP_DEMO_TIMES; + int cnt = UDP_DEMO_SEND_TIMES; char send_str[128]; int fd = -1; memset(send_str, 0, sizeof(send_str)); fd = socket(AF_INET, SOCK_DGRAM, 0); - if(fd < 0) - { + if(fd < 0) { lw_error("Socket error\n"); - return; + return NULL; } struct sockaddr_in udp_sock; @@ -175,19 +171,17 @@ static void UdpSocketSendTask(void *arg) udp_sock.sin_addr.s_addr = inet_addr(udp_ip_str); memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero)); - if(connect(fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr))) - { - lw_error("Unable to connect\n"); + if(connect(fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr)) < 0) { + lw_error("Unable to connect %s:%d\n", udp_ip_str, udp_socket_port); close(fd); - return; + return NULL; } lw_print("UDP connect %s:%d success, start to send.\n", udp_ip_str, udp_socket_port); - while(cnt --) - { + while(cnt --) { snprintf(send_str, sizeof(send_str), "UDP test package times %d\r\n", cnt); send(fd, send_str, strlen(send_str), 0); lw_notice("Send UDP msg: %s ", send_str); @@ -195,25 +189,31 @@ static void UdpSocketSendTask(void *arg) } close(fd); - return; + return NULL; } void UdpSocketSendTest(int argc, char *argv[]) { - if(argc >= 2) - { + if(argc >= 2) { lw_notice("lw: [%s] target ip %s\n", __func__, argv[1]); UdpSocketConfigParam(argv[1]); } #ifdef ADD_XIZI_FETURES - lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, udp_socket_ip); - sys_thread_new("UdpSocketSendTask", UdpSocketSendTask, NULL, LWIP_TASK_STACK_SIZE, - LWIP_DEMO_TASK_PRIO); + lwip_config_tcp(0, udp_demo_ipaddr, udp_demo_netmask, udp_demo_gwaddr); + + pthread_attr_t attr; + attr.schedparam.sched_priority = LWIP_UDP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE; #endif #ifdef ADD_NUTTX_FETURES - UdpSocketSendTask(NULL); + pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER; + attr.priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; #endif + + PrivTaskCreate(&udp_client_task, &attr, &UdpSocketSendTask, NULL); + PrivTaskStartup(&udp_client_task); } PRIV_SHELL_CMD_FUNCTION(UdpSocketSendTest, a udp send sample, PRIV_SHELL_CMD_MAIN_ATTR); diff --git a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/ethernet/ethernetif.c b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/ethernet/ethernetif.c index c50831630..f792d669f 100644 --- a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/ethernet/ethernetif.c +++ b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/ethernet/ethernetif.c @@ -39,7 +39,8 @@ Modification: 3、add ETH_RST_PORT and ETH_RST_PIN; 4、add ETH_LINK_LED_PORT and ETH_LINK_LED_PIN; 5、add ethernetif_config_enet_set; -6、add ETHERNET_LOOPBACK_TEST with testnetif and txPbuf. +6、add ETHERNET_LOOPBACK_TEST with testnetif and txPbuf; +7、modify ethernetif_init() and ethernetif_input() to support LwIP. *************************************************/ /******************************************************************************* @@ -282,6 +283,10 @@ static int32_t low_level_init(struct netif *netif) netif->hwaddr[5] = (EthHandle.stcCommInit).au8MacAddr[5]; /* maximum transfer unit */ netif->mtu = 1500U; + + /* device capabilities */ + netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + /* Enable MAC and DMA transmission and reception */ (void)ETH_Start(); @@ -322,9 +327,9 @@ static int32_t low_level_init(struct netif *netif) * - LL_OK: The packet could be sent * - LL_ERR: The packet couldn't be sent */ -int32_t low_level_output(struct netif *netif, struct pbuf *p) +err_t low_level_output(struct netif *netif, struct pbuf *p) { - int32_t i32Ret; + err_t i32Ret; struct pbuf *q; uint8_t *txBuffer; __IO stc_eth_dma_desc_t *DmaTxDesc; @@ -474,8 +479,22 @@ static struct pbuf *low_level_input(struct netif *netif) */ err_t ethernetif_init(struct netif *netif) { +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ netif->name[0] = IFNAME0; netif->name[1] = IFNAME1; + +#ifndef ETHERNET_LOOPBACK_TEST + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = ðarp_output; + netif->linkoutput = &low_level_output; +#endif + /* initialize the hardware */ return low_level_init(netif); } @@ -487,15 +506,32 @@ err_t ethernetif_init(struct netif *netif) */ void ethernetif_input(struct netif *netif) { + err_t err; struct pbuf *p; /* Move received packet into a new pbuf */ p = low_level_input(netif); + +#ifndef ETHERNET_LOOPBACK_TEST + /* No packet could be read, silently ignore this */ + if (NULL == p) { + return; + } + + /* Entry point to the LwIP stack */ + err = netif->input(p, netif); + if (err != (err_t)ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + (void)pbuf_free(p); + } +#endif +#ifdef ETHERNET_LOOPBACK_TEST /* No packet could be read, silently ignore this */ if (p != NULL) { EthernetIF_InputCallback(netif, p); free(p); } +#endif } /** diff --git a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/include/hardware_ethernetif.h b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/include/hardware_ethernetif.h index 0fb839584..e07b5495e 100644 --- a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/include/hardware_ethernetif.h +++ b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/include/hardware_ethernetif.h @@ -135,7 +135,7 @@ extern "C" */ err_t ethernetif_init(struct netif *netif); void ethernetif_input(struct netif *netif); -int32_t low_level_output(struct netif *netif, struct pbuf *p); +err_t low_level_output(struct netif *netif, struct pbuf *p); void EthernetIF_CheckLink(struct netif *netif); void EthernetIF_UpdateLink(struct netif *netif); From f8b845ca6202f66cae9503d506dd27d2b10a9b08 Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Fri, 6 Jan 2023 17:25:11 +0800 Subject: [PATCH 28/33] optimize control framework using socket, support LwIP and W5500(need to add init/socket apis) --- APP_Framework/Framework/control/Kconfig | 20 ++++++++++++++++++- .../Framework/control/ipc_protocol/Kconfig | 2 +- .../ipc_protocol/modbus_tcp/modbus_tcp.c | 6 ++++++ .../Framework/control/plc_protocol/Kconfig | 2 +- .../control/plc_protocol/fins/fins.c | 6 ++++++ .../control/plc_protocol/melsec/Kconfig | 18 ++++++++--------- .../control/plc_protocol/melsec/melsec.c | 6 +++--- .../Framework/control/shared/control_def.c | 9 ++++++++- .../Framework/control/shared/control_io.c | 13 ++++++++---- .../Framework/control/shared/control_io.h | 10 ++++++++++ 10 files changed, 72 insertions(+), 20 deletions(-) diff --git a/APP_Framework/Framework/control/Kconfig b/APP_Framework/Framework/control/Kconfig index 5618d752f..7d757e4ab 100755 --- a/APP_Framework/Framework/control/Kconfig +++ b/APP_Framework/Framework/control/Kconfig @@ -7,10 +7,28 @@ menuconfig SUPPORT_CONTROL_FRAMEWORK select LIB_USING_CJSON if SUPPORT_CONTROL_FRAMEWORK - config BSP_USING_SERIAL_485 + config CONTROL_USING_SERIAL_485 bool default n + config CONTROL_USING_SOCKET + bool + default n + if CONTROL_USING_SOCKET + choice + prompt "select socket lib" + default CONTROL_SOCKET_LWIP + + config CONTROL_SOCKET_LWIP + bool "support socket, using LwIP" + select BSP_USING_LWIP + + config CONTROL_SOCKET_W5500 + bool "support socket, using W5500" + select BSP_USING_W5500 + endchoice + endif + config CONTROL_RECIPE_FILE string "control framework recipe file name" default "test_recipe.json" diff --git a/APP_Framework/Framework/control/ipc_protocol/Kconfig b/APP_Framework/Framework/control/ipc_protocol/Kconfig index cd48d8cc5..2e97d8832 100755 --- a/APP_Framework/Framework/control/ipc_protocol/Kconfig +++ b/APP_Framework/Framework/control/ipc_protocol/Kconfig @@ -1,7 +1,7 @@ config CONTROL_PROTOCOL_MODBUS_TCP bool "Using modbus_tcp control protocol" default n - select BSP_USING_LWIP + select CONTROL_USING_SOCKET if CONTROL_PROTOCOL_MODBUS_TCP source "$APP_DIR/Framework/control/ipc_protocol/modbus_tcp/Kconfig" endif diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c index a731695b8..dfd0f3577 100755 --- a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c @@ -75,6 +75,7 @@ static void ModbusTcpTransformRecvBuffToData(ModbusTcpReadItem *p_read_item, uin printf("\n"); } +#ifdef CONTROL_USING_SOCKET /** * @description: Modbus Tcp Get Data From Socket * @param socket - socket @@ -133,6 +134,7 @@ static int ModbusTcpGetData(int32_t socket, ModbusTcpReadItem *p_read_item) } return -2; } +#endif /** * @description: Modbus Tcp Data Info Init @@ -312,6 +314,7 @@ void *ReceivePlcDataTask(void *parameter) while (1) { for (i = 0; i < control_protocol->recipe->read_item_count; i ++) { +#ifdef CONTROL_USING_SOCKET /*only connect socket when close socket or init*/ while (ControlConnectSocket(&plc_socket) < 0) { PrivTaskDelay(1000); @@ -320,6 +323,7 @@ void *ReceivePlcDataTask(void *parameter) ModbusTcpForamatWriteData((ModbusTcpReadItem *)modbus_tcp_read_item + i); ModbusTcpGetData(plc_socket.socket, (ModbusTcpReadItem *)modbus_tcp_read_item + i); +#endif } /*read all variable item data, put them into circular_area*/ @@ -360,7 +364,9 @@ int ModbusTcpClose(struct ControlProtocol *control_protocol) { CircularAreaAppRelease(g_write_data); +#ifdef CONTROL_USING_SOCKET ControlDisconnectSocket(&plc_socket); +#endif ControlProtocolCloseDef(); diff --git a/APP_Framework/Framework/control/plc_protocol/Kconfig b/APP_Framework/Framework/control/plc_protocol/Kconfig index 46f632974..91e27b474 100755 --- a/APP_Framework/Framework/control/plc_protocol/Kconfig +++ b/APP_Framework/Framework/control/plc_protocol/Kconfig @@ -1,7 +1,7 @@ config CONTROL_PROTOCOL_FINS bool "Using fins control protocol" default n - select BSP_USING_LWIP + select CONTROL_USING_SOCKET if CONTROL_PROTOCOL_FINS source "$APP_DIR/Framework/control/plc_protocol/fins/Kconfig" endif diff --git a/APP_Framework/Framework/control/plc_protocol/fins/fins.c b/APP_Framework/Framework/control/plc_protocol/fins/fins.c index 1b0419a88..0a8c20125 100644 --- a/APP_Framework/Framework/control/plc_protocol/fins/fins.c +++ b/APP_Framework/Framework/control/plc_protocol/fins/fins.c @@ -154,6 +154,7 @@ static int FinsTransformRecvBuffToData(FinsReadItem *p_read_item, uint8_t *recv_ return 0; } +#ifdef CONTROL_USING_SOCKET /** * @description: Fins Protocol Handshake * @param socket - socket @@ -242,6 +243,7 @@ static int FinsGetData(int32_t socket, FinsReadItem *p_read_item) } return -2; } +#endif /** * @description: Fins Data Info Init @@ -303,6 +305,7 @@ void *ReceivePlcDataTask(void *parameter) while (1) { for (i = 0; i < control_protocol->recipe->read_item_count; i ++) { +#ifdef CONTROL_USING_SOCKET /*only connect socket when close socket or init*/ while (ControlConnectSocket(&plc_socket) < 0) { PrivTaskDelay(1000); @@ -320,6 +323,7 @@ void *ReceivePlcDataTask(void *parameter) plc_socket.secondary_connect_flag = 1; FinsGetData(plc_socket.socket, (FinsReadItem *)fins_read_item + i); +#endif } /*read all variable item data, put them into circular_area*/ @@ -352,7 +356,9 @@ int FinsOpen(struct ControlProtocol *control_protocol) */ int FinsClose(struct ControlProtocol *control_protocol) { +#ifdef CONTROL_USING_SOCKET ControlDisconnectSocket(&plc_socket); +#endif ControlProtocolCloseDef(); diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig b/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig index 8a8d32c5a..c441642b9 100755 --- a/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig +++ b/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig @@ -3,27 +3,27 @@ choice default CONTROL_PROTOCOL_MELSEC_1E config CONTROL_PROTOCOL_MELSEC_1E - bool "support melsec_1e protocol, using TCP" - select BSP_USING_LWIP + bool "support melsec_1e protocol, using SOCKET" + select CONTROL_USING_SOCKET config CONTROL_PROTOCOL_MELSEC_3E_Q_L - bool "support melsec_3e_q_l protocol, using TCP" - select BSP_USING_LWIP + bool "support melsec_3e_q_l protocol, using SOCKET" + select CONTROL_USING_SOCKET config CONTROL_PROTOCOL_MELSEC_3E_IQ_R - bool "support melsec_3e_iq_r protocol, using TCP" - select BSP_USING_LWIP + bool "support melsec_3e_iq_r protocol, using SOCKET" + select CONTROL_USING_SOCKET config CONTROL_PROTOCOL_MELSEC_1C bool "support melsec_1c protocol, using SERIAL" - select BSP_USING_SERIAL_485 + select CONTROL_USING_SERIAL_485 config CONTROL_PROTOCOL_MELSEC_3C bool "support melsec_3c protocol, using SERIAL" - select BSP_USING_SERIAL_485 + select CONTROL_USING_SERIAL_485 endchoice -if BSP_USING_SERIAL_485 +if CONTROL_USING_SERIAL_485 if ADD_XIZI_FETURES config CONTROL_FRAMEWORK_UART_485_DIR int "control framework 485 direction pin number" diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c index 584fbdaf5..27b97a831 100644 --- a/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c +++ b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c @@ -575,7 +575,7 @@ static int MelsecTransformRecvBuffToData(MelsecReadItem *p_read_item, uint8_t *r return 0; } -#ifdef BSP_USING_LWIP +#ifdef CONTROL_USING_SOCKET /** * @description: Melsec Get Data From Socket * @param socket - socket @@ -675,7 +675,7 @@ void *ReceivePlcDataTask(void *parameter) if ((PROTOCOL_MELSEC_1C == control_protocol->protocol_type) || (PROTOCOL_MELSEC_3C == control_protocol->protocol_type)) { MelsecGetDataBySerial((MelsecReadItem *)melsec_read_item + i); } else { -#ifdef BSP_USING_LWIP +#ifdef CONTROL_USING_SOCKET /*only connect socket when close socket or init*/ while (ControlConnectSocket(&plc_socket) < 0) { PrivTaskDelay(1000); @@ -717,7 +717,7 @@ int MelsecOpen(struct ControlProtocol *control_protocol) int MelsecClose(struct ControlProtocol *control_protocol) { if ((PROTOCOL_MELSEC_1C != control_protocol->protocol_type) && (PROTOCOL_MELSEC_3C != control_protocol->protocol_type)) { -#ifdef BSP_USING_LWIP +#ifdef CONTROL_USING_SOCKET ControlDisconnectSocket(&plc_socket); #endif } diff --git a/APP_Framework/Framework/control/shared/control_def.c b/APP_Framework/Framework/control/shared/control_def.c index 3168af845..c19ae9757 100644 --- a/APP_Framework/Framework/control/shared/control_def.c +++ b/APP_Framework/Framework/control/shared/control_def.c @@ -41,6 +41,10 @@ extern int MelsecProtocolInit(struct ControlRecipe *p_recipe); extern int ModbusTcpProtocolInit(struct ControlRecipe *p_recipe); #endif +#ifdef CONTROL_PROTOCOL_MODBUS_UART +extern int ModbusUartProtocolInit(struct ControlRecipe *p_recipe); +#endif + /* CONTROL FRAMEWORK READ DATA FORMAT: | HEAD |device_id|read data length|read item count| data | @@ -73,6 +77,9 @@ static struct ControlProtocolInitParam protocol_init[] = #ifdef CONTROL_PROTOCOL_MODBUS_TCP { PROTOCOL_MODBUS_TCP, ModbusTcpProtocolInit }, #endif +#ifdef CONTROL_PROTOCOL_MODBUS_UART + { PROTOCOL_MODBUS_UART, ModbusUartProtocolInit }, +#endif { PROTOCOL_END, NULL }, }; @@ -210,7 +217,7 @@ void ControlPrintfList(char name[5], uint8_t *number_list, uint16_t length) printf("\n**************************************\n"); } -#ifdef BSP_USING_LWIP +#ifdef CONTROL_USING_SOCKET /** * @description: Control Framework Connect Socket * @param p_plc - basic socket plc pointer diff --git a/APP_Framework/Framework/control/shared/control_io.c b/APP_Framework/Framework/control/shared/control_io.c index 0bc8b77d7..4ad09b789 100644 --- a/APP_Framework/Framework/control/shared/control_io.c +++ b/APP_Framework/Framework/control/shared/control_io.c @@ -20,7 +20,7 @@ #include -#ifdef BSP_USING_SERIAL_485 +#ifdef CONTROL_USING_SERIAL_485 static int pin_fd = 0; static int uart_fd = 0; @@ -119,9 +119,14 @@ void SocketInit(char *ip, char *mask, char *gw) ip[0], ip[1], ip[2], ip[3], mask[0], mask[1], mask[2], mask[3], gw[0], gw[1], gw[2], gw[3]); +#ifdef CONTROL_USING_SOCKET #ifdef BSP_USING_LWIP lwip_config_tcp(0, ip, mask, gw); #endif +#ifdef BSP_USING_W5500 + //to do +#endif +#endif } /** @@ -134,7 +139,7 @@ void SocketInit(char *ip, char *mask, char *gw) */ void SerialInit(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_t check_mode) { -#ifdef BSP_USING_SERIAL_485 +#ifdef CONTROL_USING_SERIAL_485 Uart485Init(baud_rate, data_bits, stop_bits, check_mode); #endif } @@ -147,7 +152,7 @@ void SerialInit(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8_ */ void SerialWrite(uint8_t *write_data, int length) { -#ifdef BSP_USING_SERIAL_485 +#ifdef CONTROL_USING_SERIAL_485 Set485Output(); PrivTaskDelay(20); @@ -166,7 +171,7 @@ void SerialWrite(uint8_t *write_data, int length) */ int SerialRead(uint8_t *read_data, int length) { -#ifdef BSP_USING_SERIAL_485 +#ifdef CONTROL_USING_SERIAL_485 int data_size = 0; int data_recv_size = 0; diff --git a/APP_Framework/Framework/control/shared/control_io.h b/APP_Framework/Framework/control/shared/control_io.h index ada560ae2..9446916a6 100644 --- a/APP_Framework/Framework/control/shared/control_io.h +++ b/APP_Framework/Framework/control/shared/control_io.h @@ -24,20 +24,30 @@ #include #include +#ifdef CONTROL_USING_SOCKET #ifdef BSP_USING_LWIP #include "lwip/sys.h" #include "lwip/sockets.h" #endif +#endif #ifdef __cplusplus extern "C" { #endif +#ifdef CONTROL_USING_SOCKET #ifdef BSP_USING_LWIP #define socket_write lwip_write #define socket_read lwip_read #endif +#ifdef BSP_USING_W5500 +//to do +#define socket_write +#define socket_read +#endif +#endif + /*Control Framework Socket Init*/ void SocketInit(char *ip, char *mask, char *gw); From c621db2ca73d1757d54e13c72a73383e5d59ec4d Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Tue, 10 Jan 2023 17:21:10 +0800 Subject: [PATCH 29/33] add imxrt1052 board mdelay function --- .../arch/arm/cortex-m7/interrupt_vector.S | 2 +- .../XiZi_IIoT/board/ok1052-c/.defconfig | 294 ++++++++++++++++++ Ubiquitous/XiZi_IIoT/board/ok1052-c/board.c | 27 +- .../ethernet/enet_ethernetif.c | 11 +- .../XiZi_IIoT/board/xidatong-arm32/.defconfig | 294 ++++++++++++++++++ .../XiZi_IIoT/board/xidatong-arm32/board.c | 28 +- .../ethernet/enet_ethernetif.c | 11 +- .../board/xiwangtong-arm32/.defconfig | 294 ++++++++++++++++++ .../XiZi_IIoT/board/xiwangtong-arm32/board.c | 28 +- .../ethernet/enet_ethernetif.c | 11 +- 10 files changed, 975 insertions(+), 25 deletions(-) create mode 100644 Ubiquitous/XiZi_IIoT/board/ok1052-c/.defconfig create mode 100644 Ubiquitous/XiZi_IIoT/board/xidatong-arm32/.defconfig create mode 100644 Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/.defconfig diff --git a/Ubiquitous/XiZi_IIoT/arch/arm/cortex-m7/interrupt_vector.S b/Ubiquitous/XiZi_IIoT/arch/arm/cortex-m7/interrupt_vector.S index 6397b2f71..a93de8a75 100644 --- a/Ubiquitous/XiZi_IIoT/arch/arm/cortex-m7/interrupt_vector.S +++ b/Ubiquitous/XiZi_IIoT/arch/arm/cortex-m7/interrupt_vector.S @@ -58,7 +58,7 @@ __isr_vector: .long IsrEntry /* Debug Monitor Handler*/ .long 0 /* Reserved*/ .long PendSV_Handler /* PendSV Handler*/ - .long IsrEntry /* SysTick Handler*/ + .long SysTick_Handler /* SysTick Handler*/ /* External Interrupts*/ .long IsrEntry /* DMA channel 0/16 transfer complete*/ diff --git a/Ubiquitous/XiZi_IIoT/board/ok1052-c/.defconfig b/Ubiquitous/XiZi_IIoT/board/ok1052-c/.defconfig new file mode 100644 index 000000000..555b84bcf --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ok1052-c/.defconfig @@ -0,0 +1,294 @@ +# +# Automatically generated file; DO NOT EDIT. +# XiZi_IIoT Project Configuration +# +CONFIG_BOARD_CORTEX_M7_EVB=y +CONFIG_ARCH_ARM=y + +# +# ok1052-c feature +# +CONFIG_BSP_USING_LPUART=y +CONFIG_BSP_USING_LPUART1=y +CONFIG_SERIAL_BUS_NAME_1="uart1" +CONFIG_SERIAL_DRV_NAME_1="uart1_drv" +CONFIG_SERIAL_1_DEVICE_NAME_0="uart1_dev1" +CONFIG_BSP_USING_LPUART2=y +CONFIG_SERIAL_BUS_NAME_2="uart2" +CONFIG_SERIAL_DRV_NAME_2="uart2_drv" +CONFIG_SERIAL_2_DEVICE_NAME_0="uart2_dev2" +CONFIG_BSP_USING_LPUART3=y +CONFIG_SERIAL_BUS_NAME_3="uart3" +CONFIG_SERIAL_DRV_NAME_3="uart3_drv" +CONFIG_SERIAL_3_DEVICE_NAME_0="uart3_dev3" +# CONFIG_BSP_USING_LPUART4 is not set +# CONFIG_BSP_USING_LPUART8 is not set +# CONFIG_BSP_USING_CH438 is not set +CONFIG_BSP_USING_GPIO=y +CONFIG_PIN_BUS_NAME="pin" +CONFIG_PIN_DRIVER_NAME="pin_drv" +CONFIG_PIN_DEVICE_NAME="pin_dev" +# CONFIG_BSP_USING_I2C is not set +# CONFIG_BSP_USING_LWIP is not set +# CONFIG_BSP_USING_SEMC is not set +# CONFIG_BSP_USING_SDIO is not set +# CONFIG_BSP_USING_LCD is not set +# CONFIG_BSP_USING_TOUCH is not set +# CONFIG_BSP_USING_USB is not set +# CONFIG_BSP_USING_WDT is not set + +# +# config default board resources +# + +# +# config board app name +# +CONFIG_BOARD_APP_NAME="/XiUOS_xidatong_app.bin" + +# +# config board service table +# +CONFIG_SERVICE_TABLE_ADDRESS=0x2007F0000 +CONFIG___STACKSIZE__=4096 + +# +# config board peripheral +# +# CONFIG_MOUNT_SDCARD is not set +# CONFIG_MOUNT_USB is not set + +# +# Hardware feature +# +CONFIG_RESOURCES_SERIAL=y +CONFIG_SERIAL_USING_DMA=y +CONFIG_SERIAL_RB_BUFSZ=128 +CONFIG_RESOURCES_PIN=y + +# +# Kernel feature +# + +# +# separate compile(choose none for compile once) +# +# CONFIG_SEPARATE_COMPILE is not set +# CONFIG_COMPILER_APP is not set +# CONFIG_APP_STARTUP_FROM_SDCARD is not set +CONFIG_APP_STARTUP_FROM_FLASH=y +# CONFIG_COMPILER_KERNEL is not set + +# +# Memory Management +# +# CONFIG_KERNEL_MEMBLOCK is not set +CONFIG_MEM_ALIGN_SIZE=8 +# CONFIG_MEM_EXTERN_SRAM is not set +CONFIG_MM_PAGE_SIZE=4096 + +# +# Using small memory allocator +# +CONFIG_KERNEL_SMALL_MEM_ALLOC=y +CONFIG_SMALL_NUMBER_32B=64 +CONFIG_SMALL_NUMBER_64B=32 + +# +# Task feature +# +CONFIG_USER_APPLICATION=y +# CONFIG_TASK_ISOLATION is not set + +# +# Inter-Task communication +# +CONFIG_KERNEL_SEMAPHORE=y +CONFIG_KERNEL_MUTEX=y +CONFIG_KERNEL_EVENT=y +CONFIG_KERNEL_MESSAGEQUEUE=y +CONFIG_KERNEL_SOFTTIMER=y +CONFIG_SCHED_POLICY_RR_REMAINSLICE=y +# CONFIG_SCHED_POLICY_RR is not set +# CONFIG_SCHED_POLICY_FIFO is not set +# CONFIG_KTASK_PRIORITY_8 is not set +CONFIG_KTASK_PRIORITY_32=y +# CONFIG_KTASK_PRIORITY_256 is not set +CONFIG_KTASK_PRIORITY_MAX=32 +CONFIG_TICK_PER_SECOND=1000 +CONFIG_KERNEL_STACK_OVERFLOW_CHECK=y +CONFIG_IDLE_KTASK_STACKSIZE=1024 +CONFIG_ZOMBIE_KTASK_STACKSIZE=2048 + +# +# Kernel Console +# +CONFIG_KERNEL_CONSOLE=y +CONFIG_KERNEL_BANNER=y +CONFIG_KERNEL_CONSOLEBUF_SIZE=128 + +# +# Kernel Hook +# +# CONFIG_KERNEL_HOOK is not set + +# +# Command shell +# +CONFIG_TOOL_SHELL=y +CONFIG_SHELL_ENTER_CR=y +CONFIG_SHELL_ENTER_LF=y +CONFIG_SHELL_ENTER_CR_AND_LF=y +# CONFIG_SHELL_ENTER_CRLF is not set + +# +# Set shell user control +# +CONFIG_SHELL_DEFAULT_USER="letter" +CONFIG_SHELL_DEFAULT_USER_PASSWORD="" +CONFIG_SHELL_LOCK_TIMEOUT=10000 + +# +# Set shell config param +# +CONFIG_SHELL_TASK_STACK_SIZE=4096 +CONFIG_SHELL_TASK_PRIORITY=20 +CONFIG_SHELL_MAX_NUMBER=5 +CONFIG_SHELL_PARAMETER_MAX_NUMBER=8 +CONFIG_SHELL_HISTORY_MAX_NUMBER=5 +CONFIG_SHELL_PRINT_BUFFER=128 +CONFIG_SHELL_HELP_SHOW_PERMISSION=y +# CONFIG_SHELL_HELP_LIST_USER is not set +CONFIG_SHELL_HELP_LIST_VAR=y +# CONFIG_SHELL_HELP_LIST_KEY is not set + +# +# Kernel data structure Manage +# +CONFIG_KERNEL_QUEUEMANAGE=y +CONFIG_KERNEL_WORKQUEUE=y +CONFIG_WORKQUEUE_KTASK_STACKSIZE=2048 +CONFIG_WORKQUEUE_KTASK_PRIORITY=23 +CONFIG_QUEUE_MAX=16 +CONFIG_KERNEL_WAITQUEUE=y +CONFIG_KERNEL_DATAQUEUE=y +# CONFIG_KERNEL_CIRCULAR_AREA is not set +# CONFIG_KERNEL_AVL_TREE is not set + +# +# Kernel components init +# +CONFIG_KERNEL_COMPONENTS_INIT=y +CONFIG_ENV_INIT_KTASK_STACK_SIZE=8192 +CONFIG_KERNEL_USER_MAIN=y +CONFIG_NAME_NUM_MAX=32 +# CONFIG_KERNEL_DEBUG is not set +# CONFIG_ARCH_SMP is not set + +# +# hash table config +# +CONFIG_ID_HTABLE_SIZE=16 +CONFIG_ID_NUM_MAX=128 +# CONFIG_KERNEL_TEST is not set + +# +# Lib +# +CONFIG_LIB=y +CONFIG_LIB_POSIX=y +CONFIG_LIB_NEWLIB=y +# CONFIG_LIB_MUSLLIB is not set + +# +# C++ features +# +# CONFIG_LIB_CPLUSPLUS is not set + +# +# File system +# +CONFIG_FS_VFS=y +CONFIG_VFS_USING_WORKDIR=y +CONFIG_FS_VFS_DEVFS=y +CONFIG_FS_VFS_FATFS=y +# CONFIG_FS_CH376 is not set +# CONFIG_FS_LWEXT4 is not set + +# +# APP_Framework +# + +# +# Framework +# +CONFIG_TRANSFORM_LAYER_ATTRIUBUTE=y +CONFIG_ADD_XIZI_FETURES=y +# CONFIG_ADD_NUTTX_FETURES is not set +# CONFIG_ADD_RTTHREAD_FETURES is not set +# CONFIG_SUPPORT_SENSOR_FRAMEWORK is not set +# CONFIG_SUPPORT_CONNECTION_FRAMEWORK is not set +# CONFIG_SUPPORT_KNOWING_FRAMEWORK is not set +# CONFIG_SUPPORT_CONTROL_FRAMEWORK is not set + +# +# Security +# +# CONFIG_CRYPTO is not set +# CONFIG_MBEDTLS is not set + +# +# Applications +# + +# +# config stack size and priority of main task +# +CONFIG_MAIN_KTASK_STACK_SIZE=4096 +CONFIG_MAIN_KTASK_PRIORITY=16 + +# +# ota app +# +# CONFIG_APPLICATION_OTA is not set + +# +# test app +# +# CONFIG_USER_TEST is not set + +# +# connection app +# +# CONFIG_APPLICATION_CONNECTION is not set + +# +# control app +# + +# +# knowing app +# +# CONFIG_APPLICATION_KNOWING is not set + +# +# sensor app +# +# CONFIG_APPLICATION_SENSOR is not set +# CONFIG_USING_EMBEDDED_DATABASE_APP is not set +# CONFIG_APP_USING_WEBNET is not set + +# +# lib +# +CONFIG_APP_SELECT_NEWLIB=y +# CONFIG_APP_SELECT_OTHER_LIB is not set +# CONFIG_LIB_USING_CJSON is not set +# CONFIG_LIB_USING_QUEUE is not set +# CONFIG_LIB_LV is not set + +# +# LVGL configuration +# +# CONFIG_LV_CONF_MINIMAL is not set +# CONFIG_USING_EMBEDDED_DATABASE is not set diff --git a/Ubiquitous/XiZi_IIoT/board/ok1052-c/board.c b/Ubiquitous/XiZi_IIoT/board/ok1052-c/board.c index d891bfd50..842fa63d0 100644 --- a/Ubiquitous/XiZi_IIoT/board/ok1052-c/board.c +++ b/Ubiquitous/XiZi_IIoT/board/ok1052-c/board.c @@ -364,6 +364,32 @@ status_t BOARD_Camera_I2C_ReceiveSCCB( #endif /* SDK_I2C_BASED_COMPONENT_USED */ #endif +void ImxrtMsDelay(uint32 ms) +{ + uint64 ticks = 0; + uint32 told, tnow, tcnt = 0; + uint32 reload = SysTick->LOAD; + + ticks = ((uint64)ms * ((uint64)reload + 1) * TICK_PER_SECOND) / 1000; + told = SysTick->VAL; + + //KPrintf("%s reload %u ms %u ticks %u told %u\n", __func__, reload, ms, ticks, told); + + while (1) { + tnow = SysTick->VAL; + if (tnow != told) { + if (tnow < told) { + tcnt += told - tnow; + } else { + tcnt += reload - tnow + told; + } + told = tnow; + if (tcnt >= ticks) { + break; + } + } + } +} void BOARD_SD_Pin_Config(uint32_t speed, uint32_t strength) { @@ -574,7 +600,6 @@ void SysTick_Handler(int irqn, void *arg) { TickAndTaskTimesliceUpdate(); } -DECLARE_HW_IRQ(SYSTICK_IRQN, SysTick_Handler, NONE); #ifdef BSP_USING_LPUART void imxrt_uart_pins_init(void) diff --git a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c index 4560f454a..764637188 100755 --- a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c +++ b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c @@ -81,14 +81,11 @@ /******************************************************************************* * Code ******************************************************************************/ +extern void ImxrtMsDelay(uint32 ms); -void enet_delay(void) +void enet_delay(uint32 ms) { - volatile uint32_t i = 0; - for (i = 0; i < 1000000; ++i) - { - __asm("NOP"); /* delay */ - } + ImxrtMsDelay(ms); } void Time_Update_LwIP(void) @@ -124,7 +121,7 @@ void ethernetif_gpio_init(void) GPIO_PinInit(GPIO1, 3, &gpio_config); /* pull up the ENET_INT before RESET. */ GPIO_WritePinOutput(GPIO1, 3, 0); - enet_delay(); + enet_delay(30); GPIO_WritePinOutput(GPIO1, 3, 1); } diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/.defconfig b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/.defconfig new file mode 100644 index 000000000..ad4f5b2b4 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/.defconfig @@ -0,0 +1,294 @@ +# +# Automatically generated file; DO NOT EDIT. +# XiZi_IIoT Project Configuration +# +CONFIG_BOARD_CORTEX_M7_EVB=y +CONFIG_ARCH_ARM=y + +# +# xidatong-arm32 feature +# +CONFIG_BSP_USING_LPUART=y +CONFIG_BSP_USING_LPUART1=y +CONFIG_SERIAL_BUS_NAME_1="uart1" +CONFIG_SERIAL_DRV_NAME_1="uart1_drv" +CONFIG_SERIAL_1_DEVICE_NAME_0="uart1_dev1" +CONFIG_BSP_USING_LPUART2=y +CONFIG_SERIAL_BUS_NAME_2="uart2" +CONFIG_SERIAL_DRV_NAME_2="uart2_drv" +CONFIG_SERIAL_2_DEVICE_NAME_0="uart2_dev2" +CONFIG_BSP_USING_LPUART3=y +CONFIG_SERIAL_BUS_NAME_3="uart3" +CONFIG_SERIAL_DRV_NAME_3="uart3_drv" +CONFIG_SERIAL_3_DEVICE_NAME_0="uart3_dev3" +# CONFIG_BSP_USING_LPUART4 is not set +# CONFIG_BSP_USING_LPUART8 is not set +# CONFIG_BSP_USING_CH438 is not set +CONFIG_BSP_USING_GPIO=y +CONFIG_PIN_BUS_NAME="pin" +CONFIG_PIN_DRIVER_NAME="pin_drv" +CONFIG_PIN_DEVICE_NAME="pin_dev" +# CONFIG_BSP_USING_I2C is not set +# CONFIG_BSP_USING_LWIP is not set +# CONFIG_BSP_USING_SEMC is not set +# CONFIG_BSP_USING_SDIO is not set +# CONFIG_BSP_USING_LCD is not set +# CONFIG_BSP_USING_TOUCH is not set +# CONFIG_BSP_USING_USB is not set +# CONFIG_BSP_USING_WDT is not set + +# +# config default board resources +# + +# +# config board app name +# +CONFIG_BOARD_APP_NAME="/XiUOS_xidatong_app.bin" + +# +# config board service table +# +CONFIG_SERVICE_TABLE_ADDRESS=0x2007F0000 +CONFIG___STACKSIZE__=4096 + +# +# config board peripheral +# +# CONFIG_MOUNT_SDCARD is not set +# CONFIG_MOUNT_USB is not set + +# +# Hardware feature +# +CONFIG_RESOURCES_SERIAL=y +CONFIG_SERIAL_USING_DMA=y +CONFIG_SERIAL_RB_BUFSZ=128 +CONFIG_RESOURCES_PIN=y + +# +# Kernel feature +# + +# +# separate compile(choose none for compile once) +# +# CONFIG_SEPARATE_COMPILE is not set +# CONFIG_COMPILER_APP is not set +# CONFIG_APP_STARTUP_FROM_SDCARD is not set +CONFIG_APP_STARTUP_FROM_FLASH=y +# CONFIG_COMPILER_KERNEL is not set + +# +# Memory Management +# +# CONFIG_KERNEL_MEMBLOCK is not set +CONFIG_MEM_ALIGN_SIZE=8 +# CONFIG_MEM_EXTERN_SRAM is not set +CONFIG_MM_PAGE_SIZE=4096 + +# +# Using small memory allocator +# +CONFIG_KERNEL_SMALL_MEM_ALLOC=y +CONFIG_SMALL_NUMBER_32B=64 +CONFIG_SMALL_NUMBER_64B=32 + +# +# Task feature +# +CONFIG_USER_APPLICATION=y +# CONFIG_TASK_ISOLATION is not set + +# +# Inter-Task communication +# +CONFIG_KERNEL_SEMAPHORE=y +CONFIG_KERNEL_MUTEX=y +CONFIG_KERNEL_EVENT=y +CONFIG_KERNEL_MESSAGEQUEUE=y +CONFIG_KERNEL_SOFTTIMER=y +CONFIG_SCHED_POLICY_RR_REMAINSLICE=y +# CONFIG_SCHED_POLICY_RR is not set +# CONFIG_SCHED_POLICY_FIFO is not set +# CONFIG_KTASK_PRIORITY_8 is not set +CONFIG_KTASK_PRIORITY_32=y +# CONFIG_KTASK_PRIORITY_256 is not set +CONFIG_KTASK_PRIORITY_MAX=32 +CONFIG_TICK_PER_SECOND=1000 +CONFIG_KERNEL_STACK_OVERFLOW_CHECK=y +CONFIG_IDLE_KTASK_STACKSIZE=1024 +CONFIG_ZOMBIE_KTASK_STACKSIZE=2048 + +# +# Kernel Console +# +CONFIG_KERNEL_CONSOLE=y +CONFIG_KERNEL_BANNER=y +CONFIG_KERNEL_CONSOLEBUF_SIZE=128 + +# +# Kernel Hook +# +# CONFIG_KERNEL_HOOK is not set + +# +# Command shell +# +CONFIG_TOOL_SHELL=y +CONFIG_SHELL_ENTER_CR=y +CONFIG_SHELL_ENTER_LF=y +CONFIG_SHELL_ENTER_CR_AND_LF=y +# CONFIG_SHELL_ENTER_CRLF is not set + +# +# Set shell user control +# +CONFIG_SHELL_DEFAULT_USER="letter" +CONFIG_SHELL_DEFAULT_USER_PASSWORD="" +CONFIG_SHELL_LOCK_TIMEOUT=10000 + +# +# Set shell config param +# +CONFIG_SHELL_TASK_STACK_SIZE=4096 +CONFIG_SHELL_TASK_PRIORITY=20 +CONFIG_SHELL_MAX_NUMBER=5 +CONFIG_SHELL_PARAMETER_MAX_NUMBER=8 +CONFIG_SHELL_HISTORY_MAX_NUMBER=5 +CONFIG_SHELL_PRINT_BUFFER=128 +CONFIG_SHELL_HELP_SHOW_PERMISSION=y +# CONFIG_SHELL_HELP_LIST_USER is not set +CONFIG_SHELL_HELP_LIST_VAR=y +# CONFIG_SHELL_HELP_LIST_KEY is not set + +# +# Kernel data structure Manage +# +CONFIG_KERNEL_QUEUEMANAGE=y +CONFIG_KERNEL_WORKQUEUE=y +CONFIG_WORKQUEUE_KTASK_STACKSIZE=2048 +CONFIG_WORKQUEUE_KTASK_PRIORITY=23 +CONFIG_QUEUE_MAX=16 +CONFIG_KERNEL_WAITQUEUE=y +CONFIG_KERNEL_DATAQUEUE=y +# CONFIG_KERNEL_CIRCULAR_AREA is not set +# CONFIG_KERNEL_AVL_TREE is not set + +# +# Kernel components init +# +CONFIG_KERNEL_COMPONENTS_INIT=y +CONFIG_ENV_INIT_KTASK_STACK_SIZE=8192 +CONFIG_KERNEL_USER_MAIN=y +CONFIG_NAME_NUM_MAX=32 +# CONFIG_KERNEL_DEBUG is not set +# CONFIG_ARCH_SMP is not set + +# +# hash table config +# +CONFIG_ID_HTABLE_SIZE=16 +CONFIG_ID_NUM_MAX=128 +# CONFIG_KERNEL_TEST is not set + +# +# Lib +# +CONFIG_LIB=y +CONFIG_LIB_POSIX=y +CONFIG_LIB_NEWLIB=y +# CONFIG_LIB_MUSLLIB is not set + +# +# C++ features +# +# CONFIG_LIB_CPLUSPLUS is not set + +# +# File system +# +CONFIG_FS_VFS=y +CONFIG_VFS_USING_WORKDIR=y +CONFIG_FS_VFS_DEVFS=y +CONFIG_FS_VFS_FATFS=y +# CONFIG_FS_CH376 is not set +# CONFIG_FS_LWEXT4 is not set + +# +# APP_Framework +# + +# +# Framework +# +CONFIG_TRANSFORM_LAYER_ATTRIUBUTE=y +CONFIG_ADD_XIZI_FETURES=y +# CONFIG_ADD_NUTTX_FETURES is not set +# CONFIG_ADD_RTTHREAD_FETURES is not set +# CONFIG_SUPPORT_SENSOR_FRAMEWORK is not set +# CONFIG_SUPPORT_CONNECTION_FRAMEWORK is not set +# CONFIG_SUPPORT_KNOWING_FRAMEWORK is not set +# CONFIG_SUPPORT_CONTROL_FRAMEWORK is not set + +# +# Security +# +# CONFIG_CRYPTO is not set +# CONFIG_MBEDTLS is not set + +# +# Applications +# + +# +# config stack size and priority of main task +# +CONFIG_MAIN_KTASK_STACK_SIZE=4096 +CONFIG_MAIN_KTASK_PRIORITY=16 + +# +# ota app +# +# CONFIG_APPLICATION_OTA is not set + +# +# test app +# +# CONFIG_USER_TEST is not set + +# +# connection app +# +# CONFIG_APPLICATION_CONNECTION is not set + +# +# control app +# + +# +# knowing app +# +# CONFIG_APPLICATION_KNOWING is not set + +# +# sensor app +# +# CONFIG_APPLICATION_SENSOR is not set +# CONFIG_USING_EMBEDDED_DATABASE_APP is not set +# CONFIG_APP_USING_WEBNET is not set + +# +# lib +# +CONFIG_APP_SELECT_NEWLIB=y +# CONFIG_APP_SELECT_OTHER_LIB is not set +# CONFIG_LIB_USING_CJSON is not set +# CONFIG_LIB_USING_QUEUE is not set +# CONFIG_LIB_LV is not set + +# +# LVGL configuration +# +# CONFIG_LV_CONF_MINIMAL is not set +# CONFIG_USING_EMBEDDED_DATABASE is not set diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/board.c b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/board.c index 2d9236270..af87f9229 100644 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/board.c +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/board.c @@ -83,6 +83,33 @@ extern int Imxrt1052HwLcdInit(void); extern int HwTouchInit(); #endif +void ImxrtMsDelay(uint32 ms) +{ + uint64 ticks = 0; + uint32 told, tnow, tcnt = 0; + uint32 reload = SysTick->LOAD; + + ticks = ((uint64)ms * ((uint64)reload + 1) * TICK_PER_SECOND) / 1000; + told = SysTick->VAL; + + //KPrintf("%s reload %u ms %u ticks %u told %u\n", __func__, reload, ms, ticks, told); + + while (1) { + tnow = SysTick->VAL; + if (tnow != told) { + if (tnow < told) { + tcnt += told - tnow; + } else { + tcnt += reload - tnow + told; + } + told = tnow; + if (tcnt >= ticks) { + break; + } + } + } +} + void BOARD_SD_Pin_Config(uint32_t speed, uint32_t strength) { IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_00_USDHC1_CMD, @@ -291,7 +318,6 @@ void SysTick_Handler(int irqn, void *arg) { TickAndTaskTimesliceUpdate(); } -DECLARE_HW_IRQ(SYSTICK_IRQN, SysTick_Handler, NONE); struct InitSequenceDesc _board_init[] = { diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/enet_ethernetif.c b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/enet_ethernetif.c index 3df2f6e40..1b32163dd 100755 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/enet_ethernetif.c +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/enet_ethernetif.c @@ -81,14 +81,11 @@ /******************************************************************************* * Code ******************************************************************************/ +extern void ImxrtMsDelay(uint32 ms); -void enet_delay(void) +void enet_delay(uint32 ms) { - volatile uint32_t i = 0; - for (i = 0; i < 10000000; ++i) - { - __asm("NOP"); /* delay */ - } + ImxrtMsDelay(ms); } void Time_Update_LwIP(void) @@ -126,7 +123,7 @@ void ethernetif_gpio_init(void) /* pull up the ENET_INT before RESET. */ GPIO_WritePinOutput(GPIO1, 10, 1); GPIO_WritePinOutput(GPIO1, 3, 0); - enet_delay(); + enet_delay(30); GPIO_WritePinOutput(GPIO1, 3, 1); } diff --git a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/.defconfig b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/.defconfig new file mode 100644 index 000000000..3c7407613 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/.defconfig @@ -0,0 +1,294 @@ +# +# Automatically generated file; DO NOT EDIT. +# XiZi_IIoT Project Configuration +# +CONFIG_BOARD_CORTEX_M7_EVB=y +CONFIG_ARCH_ARM=y + +# +# xiwangtong-arm32 feature +# +CONFIG_BSP_USING_LPUART=y +CONFIG_BSP_USING_LPUART1=y +CONFIG_SERIAL_BUS_NAME_1="uart1" +CONFIG_SERIAL_DRV_NAME_1="uart1_drv" +CONFIG_SERIAL_1_DEVICE_NAME_0="uart1_dev1" +CONFIG_BSP_USING_LPUART2=y +CONFIG_SERIAL_BUS_NAME_2="uart2" +CONFIG_SERIAL_DRV_NAME_2="uart2_drv" +CONFIG_SERIAL_2_DEVICE_NAME_0="uart2_dev2" +CONFIG_BSP_USING_LPUART3=y +CONFIG_SERIAL_BUS_NAME_3="uart3" +CONFIG_SERIAL_DRV_NAME_3="uart3_drv" +CONFIG_SERIAL_3_DEVICE_NAME_0="uart3_dev3" +# CONFIG_BSP_USING_LPUART4 is not set +# CONFIG_BSP_USING_LPUART8 is not set +# CONFIG_BSP_USING_CH438 is not set +CONFIG_BSP_USING_GPIO=y +CONFIG_PIN_BUS_NAME="pin" +CONFIG_PIN_DRIVER_NAME="pin_drv" +CONFIG_PIN_DEVICE_NAME="pin_dev" +# CONFIG_BSP_USING_I2C is not set +# CONFIG_BSP_USING_LWIP is not set +# CONFIG_BSP_USING_SEMC is not set +# CONFIG_BSP_USING_SDIO is not set +# CONFIG_BSP_USING_LCD is not set +# CONFIG_BSP_USING_TOUCH is not set +# CONFIG_BSP_USING_USB is not set +# CONFIG_BSP_USING_WDT is not set + +# +# config default board resources +# + +# +# config board app name +# +CONFIG_BOARD_APP_NAME="/XiUOS_xidatong_app.bin" + +# +# config board service table +# +CONFIG_SERVICE_TABLE_ADDRESS=0x2007F0000 +CONFIG___STACKSIZE__=4096 + +# +# config board peripheral +# +# CONFIG_MOUNT_SDCARD is not set +# CONFIG_MOUNT_USB is not set + +# +# Hardware feature +# +CONFIG_RESOURCES_SERIAL=y +CONFIG_SERIAL_USING_DMA=y +CONFIG_SERIAL_RB_BUFSZ=128 +CONFIG_RESOURCES_PIN=y + +# +# Kernel feature +# + +# +# separate compile(choose none for compile once) +# +# CONFIG_SEPARATE_COMPILE is not set +# CONFIG_COMPILER_APP is not set +# CONFIG_APP_STARTUP_FROM_SDCARD is not set +CONFIG_APP_STARTUP_FROM_FLASH=y +# CONFIG_COMPILER_KERNEL is not set + +# +# Memory Management +# +# CONFIG_KERNEL_MEMBLOCK is not set +CONFIG_MEM_ALIGN_SIZE=8 +# CONFIG_MEM_EXTERN_SRAM is not set +CONFIG_MM_PAGE_SIZE=4096 + +# +# Using small memory allocator +# +CONFIG_KERNEL_SMALL_MEM_ALLOC=y +CONFIG_SMALL_NUMBER_32B=64 +CONFIG_SMALL_NUMBER_64B=32 + +# +# Task feature +# +CONFIG_USER_APPLICATION=y +# CONFIG_TASK_ISOLATION is not set + +# +# Inter-Task communication +# +CONFIG_KERNEL_SEMAPHORE=y +CONFIG_KERNEL_MUTEX=y +CONFIG_KERNEL_EVENT=y +CONFIG_KERNEL_MESSAGEQUEUE=y +CONFIG_KERNEL_SOFTTIMER=y +CONFIG_SCHED_POLICY_RR_REMAINSLICE=y +# CONFIG_SCHED_POLICY_RR is not set +# CONFIG_SCHED_POLICY_FIFO is not set +# CONFIG_KTASK_PRIORITY_8 is not set +CONFIG_KTASK_PRIORITY_32=y +# CONFIG_KTASK_PRIORITY_256 is not set +CONFIG_KTASK_PRIORITY_MAX=32 +CONFIG_TICK_PER_SECOND=1000 +CONFIG_KERNEL_STACK_OVERFLOW_CHECK=y +CONFIG_IDLE_KTASK_STACKSIZE=1024 +CONFIG_ZOMBIE_KTASK_STACKSIZE=2048 + +# +# Kernel Console +# +CONFIG_KERNEL_CONSOLE=y +CONFIG_KERNEL_BANNER=y +CONFIG_KERNEL_CONSOLEBUF_SIZE=128 + +# +# Kernel Hook +# +# CONFIG_KERNEL_HOOK is not set + +# +# Command shell +# +CONFIG_TOOL_SHELL=y +CONFIG_SHELL_ENTER_CR=y +CONFIG_SHELL_ENTER_LF=y +CONFIG_SHELL_ENTER_CR_AND_LF=y +# CONFIG_SHELL_ENTER_CRLF is not set + +# +# Set shell user control +# +CONFIG_SHELL_DEFAULT_USER="letter" +CONFIG_SHELL_DEFAULT_USER_PASSWORD="" +CONFIG_SHELL_LOCK_TIMEOUT=10000 + +# +# Set shell config param +# +CONFIG_SHELL_TASK_STACK_SIZE=4096 +CONFIG_SHELL_TASK_PRIORITY=20 +CONFIG_SHELL_MAX_NUMBER=5 +CONFIG_SHELL_PARAMETER_MAX_NUMBER=8 +CONFIG_SHELL_HISTORY_MAX_NUMBER=5 +CONFIG_SHELL_PRINT_BUFFER=128 +CONFIG_SHELL_HELP_SHOW_PERMISSION=y +# CONFIG_SHELL_HELP_LIST_USER is not set +CONFIG_SHELL_HELP_LIST_VAR=y +# CONFIG_SHELL_HELP_LIST_KEY is not set + +# +# Kernel data structure Manage +# +CONFIG_KERNEL_QUEUEMANAGE=y +CONFIG_KERNEL_WORKQUEUE=y +CONFIG_WORKQUEUE_KTASK_STACKSIZE=2048 +CONFIG_WORKQUEUE_KTASK_PRIORITY=23 +CONFIG_QUEUE_MAX=16 +CONFIG_KERNEL_WAITQUEUE=y +CONFIG_KERNEL_DATAQUEUE=y +# CONFIG_KERNEL_CIRCULAR_AREA is not set +# CONFIG_KERNEL_AVL_TREE is not set + +# +# Kernel components init +# +CONFIG_KERNEL_COMPONENTS_INIT=y +CONFIG_ENV_INIT_KTASK_STACK_SIZE=8192 +CONFIG_KERNEL_USER_MAIN=y +CONFIG_NAME_NUM_MAX=32 +# CONFIG_KERNEL_DEBUG is not set +# CONFIG_ARCH_SMP is not set + +# +# hash table config +# +CONFIG_ID_HTABLE_SIZE=16 +CONFIG_ID_NUM_MAX=128 +# CONFIG_KERNEL_TEST is not set + +# +# Lib +# +CONFIG_LIB=y +CONFIG_LIB_POSIX=y +CONFIG_LIB_NEWLIB=y +# CONFIG_LIB_MUSLLIB is not set + +# +# C++ features +# +# CONFIG_LIB_CPLUSPLUS is not set + +# +# File system +# +CONFIG_FS_VFS=y +CONFIG_VFS_USING_WORKDIR=y +CONFIG_FS_VFS_DEVFS=y +CONFIG_FS_VFS_FATFS=y +# CONFIG_FS_CH376 is not set +# CONFIG_FS_LWEXT4 is not set + +# +# APP_Framework +# + +# +# Framework +# +CONFIG_TRANSFORM_LAYER_ATTRIUBUTE=y +CONFIG_ADD_XIZI_FETURES=y +# CONFIG_ADD_NUTTX_FETURES is not set +# CONFIG_ADD_RTTHREAD_FETURES is not set +# CONFIG_SUPPORT_SENSOR_FRAMEWORK is not set +# CONFIG_SUPPORT_CONNECTION_FRAMEWORK is not set +# CONFIG_SUPPORT_KNOWING_FRAMEWORK is not set +# CONFIG_SUPPORT_CONTROL_FRAMEWORK is not set + +# +# Security +# +# CONFIG_CRYPTO is not set +# CONFIG_MBEDTLS is not set + +# +# Applications +# + +# +# config stack size and priority of main task +# +CONFIG_MAIN_KTASK_STACK_SIZE=4096 +CONFIG_MAIN_KTASK_PRIORITY=16 + +# +# ota app +# +# CONFIG_APPLICATION_OTA is not set + +# +# test app +# +# CONFIG_USER_TEST is not set + +# +# connection app +# +# CONFIG_APPLICATION_CONNECTION is not set + +# +# control app +# + +# +# knowing app +# +# CONFIG_APPLICATION_KNOWING is not set + +# +# sensor app +# +# CONFIG_APPLICATION_SENSOR is not set +# CONFIG_USING_EMBEDDED_DATABASE_APP is not set +# CONFIG_APP_USING_WEBNET is not set + +# +# lib +# +CONFIG_APP_SELECT_NEWLIB=y +# CONFIG_APP_SELECT_OTHER_LIB is not set +# CONFIG_LIB_USING_CJSON is not set +# CONFIG_LIB_USING_QUEUE is not set +# CONFIG_LIB_LV is not set + +# +# LVGL configuration +# +# CONFIG_LV_CONF_MINIMAL is not set +# CONFIG_USING_EMBEDDED_DATABASE is not set diff --git a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/board.c b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/board.c index 165a7025c..4127bd0fd 100644 --- a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/board.c +++ b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/board.c @@ -83,6 +83,33 @@ extern int Imxrt1052HwLcdInit(void); extern int HwTouchInit(); #endif +void ImxrtMsDelay(uint32 ms) +{ + uint64 ticks = 0; + uint32 told, tnow, tcnt = 0; + uint32 reload = SysTick->LOAD; + + ticks = ((uint64)ms * ((uint64)reload + 1) * TICK_PER_SECOND) / 1000; + told = SysTick->VAL; + + //KPrintf("%s reload %u ms %u ticks %u told %u\n", __func__, reload, ms, ticks, told); + + while (1) { + tnow = SysTick->VAL; + if (tnow != told) { + if (tnow < told) { + tcnt += told - tnow; + } else { + tcnt += reload - tnow + told; + } + told = tnow; + if (tcnt >= ticks) { + break; + } + } + } +} + void BOARD_SD_Pin_Config(uint32_t speed, uint32_t strength) { IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_00_USDHC1_CMD, @@ -291,7 +318,6 @@ void SysTick_Handler(int irqn, void *arg) { TickAndTaskTimesliceUpdate(); } -DECLARE_HW_IRQ(SYSTICK_IRQN, SysTick_Handler, NONE); struct InitSequenceDesc _board_init[] = { diff --git a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/enet_ethernetif.c b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/enet_ethernetif.c index 6360d9911..31d211a37 100755 --- a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/enet_ethernetif.c +++ b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/enet_ethernetif.c @@ -81,14 +81,11 @@ /******************************************************************************* * Code ******************************************************************************/ +extern void ImxrtMsDelay(uint32 ms); -void enet_delay(void) +void enet_delay(uint32 ms) { - volatile uint32_t i = 0; - for (i = 0; i < 1000000; ++i) - { - __asm("NOP"); /* delay */ - } + ImxrtMsDelay(ms); } void Time_Update_LwIP(void) @@ -112,7 +109,7 @@ void ethernetif_gpio_init(void) /* pull up the ENET_INT before RESET. */ GPIO_WritePinOutput(GPIO1, 10, 1); GPIO_WritePinOutput(GPIO1, 3, 0); - enet_delay(); + enet_delay(30); GPIO_WritePinOutput(GPIO1, 3, 1); } From 8001b073411dcc7a69853465b69a15ae5310b28b Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Tue, 10 Jan 2023 17:49:20 +0800 Subject: [PATCH 30/33] fix Calculte error --- APP_Framework/Framework/transform_layer/xizi/transform.c | 2 +- Ubiquitous/XiZi_IIoT/fs/shared/src/poll.c | 2 +- Ubiquitous/XiZi_IIoT/kernel/include/xs_ktick.h | 4 ++-- Ubiquitous/XiZi_IIoT/kernel/memory/gatherblock.c | 2 +- Ubiquitous/XiZi_IIoT/kernel/thread/event.c | 2 +- Ubiquitous/XiZi_IIoT/kernel/thread/ktask.c | 2 +- Ubiquitous/XiZi_IIoT/kernel/thread/msgqueue.c | 4 ++-- Ubiquitous/XiZi_IIoT/kernel/thread/mutex.c | 2 +- Ubiquitous/XiZi_IIoT/kernel/thread/semaphore.c | 2 +- Ubiquitous/XiZi_IIoT/kernel/thread/tick.c | 4 ++-- Ubiquitous/XiZi_IIoT/tool/shell/letter-shell/shell.h | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.c b/APP_Framework/Framework/transform_layer/xizi/transform.c index f2d53d155..5d6d3c591 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.c +++ b/APP_Framework/Framework/transform_layer/xizi/transform.c @@ -104,7 +104,7 @@ int PrivTaskDelay(int32_t ms) #ifndef SEPARATE_COMPILE uint32_t PrivGetTickTime() { - return CalculteTimeMsFromTick(CurrentTicksGain()); + return CalculateTimeMsFromTick(CurrentTicksGain()); } #endif /*********************fs**************************/ diff --git a/Ubiquitous/XiZi_IIoT/fs/shared/src/poll.c b/Ubiquitous/XiZi_IIoT/fs/shared/src/poll.c index efd25bb27..178a3e1b5 100644 --- a/Ubiquitous/XiZi_IIoT/fs/shared/src/poll.c +++ b/Ubiquitous/XiZi_IIoT/fs/shared/src/poll.c @@ -86,7 +86,7 @@ static int PollWaitTimeout(struct poll_table *pt, int msec) thread = pt->polling_thread; - timeout = CalculteTickFromTimeMs(msec); + timeout = CalculateTickFromTimeMs(msec); level = CriticalAreaLock(); diff --git a/Ubiquitous/XiZi_IIoT/kernel/include/xs_ktick.h b/Ubiquitous/XiZi_IIoT/kernel/include/xs_ktick.h index faaf195d9..c56751c1f 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/include/xs_ktick.h +++ b/Ubiquitous/XiZi_IIoT/kernel/include/xs_ktick.h @@ -26,7 +26,7 @@ x_ticks_t CurrentTicksGain(void); void TickAndTaskTimesliceUpdate(void); -x_ticks_t CalculteTickFromTimeMs(uint32 ms); -uint32 CalculteTimeMsFromTick(x_ticks_t ticks); +x_ticks_t CalculateTickFromTimeMs(uint32 ms); +uint32 CalculateTimeMsFromTick(x_ticks_t ticks); #endif diff --git a/Ubiquitous/XiZi_IIoT/kernel/memory/gatherblock.c b/Ubiquitous/XiZi_IIoT/kernel/memory/gatherblock.c index a4a0d482c..6ac255725 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/memory/gatherblock.c +++ b/Ubiquitous/XiZi_IIoT/kernel/memory/gatherblock.c @@ -304,7 +304,7 @@ void *AllocBlockMemGather(GatherMemType gm_handler, int32 msec) /* get descriptor of task */ task = GetKTaskDescriptor(); - wait_time = CalculteTickFromTimeMs(msec); + wait_time = CalculateTickFromTimeMs(msec); critical_value = CriticalAreaLock(); /* no free gatherblock*/ diff --git a/Ubiquitous/XiZi_IIoT/kernel/thread/event.c b/Ubiquitous/XiZi_IIoT/kernel/thread/event.c index 871486f7f..4217b9676 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/thread/event.c +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/event.c @@ -153,7 +153,7 @@ static int32 _EventProcess(struct Event *event, uint32 events, uint32 options, i task = GetKTaskDescriptor(); task->exstatus = EOK; - timeout = CalculteTickFromTimeMs(msec); + timeout = CalculateTickFromTimeMs(msec); lock = CriticalAreaLock(); diff --git a/Ubiquitous/XiZi_IIoT/kernel/thread/ktask.c b/Ubiquitous/XiZi_IIoT/kernel/thread/ktask.c index a06236b91..e72ea0d16 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/thread/ktask.c +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/ktask.c @@ -220,7 +220,7 @@ x_err_t _MdelayKTask(KTaskDescriptorType task, uint32 ms) return -EINVALED; } - ticks = CalculteTickFromTimeMs(ms); + ticks = CalculateTickFromTimeMs(ms); return _DelayKTask(task, ticks); } diff --git a/Ubiquitous/XiZi_IIoT/kernel/thread/msgqueue.c b/Ubiquitous/XiZi_IIoT/kernel/thread/msgqueue.c index 8d2be3c79..ee58bc0d7 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/thread/msgqueue.c +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/msgqueue.c @@ -99,7 +99,7 @@ static x_err_t _MsgQueueSend(struct MsgQueue *mq, if(WAITING_FOREVER == msec) timeout = WAITING_FOREVER; else - timeout = CalculteTickFromTimeMs(msec); + timeout = CalculateTickFromTimeMs(msec); lock = CriticalAreaLock(); if (mq->num_msgs >= mq->max_msgs && timeout == 0) { @@ -207,7 +207,7 @@ static x_err_t _MsgQueueRecv(struct MsgQueue *mq, tick_delta = 0; task = GetKTaskDescriptor(); - timeout = CalculteTickFromTimeMs(msec); + timeout = CalculateTickFromTimeMs(msec); lock = CriticalAreaLock(); if (mq->index == 0 && timeout == 0) { diff --git a/Ubiquitous/XiZi_IIoT/kernel/thread/mutex.c b/Ubiquitous/XiZi_IIoT/kernel/thread/mutex.c index 88c1177a9..ff4aaded2 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/thread/mutex.c +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/mutex.c @@ -83,7 +83,7 @@ static int32 _MutexObtain(struct Mutex *mutex, int32 msec) NULL_PARAM_CHECK(mutex); task = GetKTaskDescriptor(); - wait_time = CalculteTickFromTimeMs(msec); + wait_time = CalculateTickFromTimeMs(msec); lock = CriticalAreaLock(); SYS_KDEBUG_LOG(KDBG_IPC, diff --git a/Ubiquitous/XiZi_IIoT/kernel/thread/semaphore.c b/Ubiquitous/XiZi_IIoT/kernel/thread/semaphore.c index ac6f6eeb3..54ff78629 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/thread/semaphore.c +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/semaphore.c @@ -97,7 +97,7 @@ static int32 _SemaphoreObtain(struct Semaphore *sem, int32 msec) if(WAITING_FOREVER == msec) wait_time = WAITING_FOREVER; else - wait_time = CalculteTickFromTimeMs(msec); + wait_time = CalculateTickFromTimeMs(msec); lock = CriticalAreaLock(); SYS_KDEBUG_LOG(KDBG_IPC, ("obtain semaphore: id %d, value %d, by task %s\n", diff --git a/Ubiquitous/XiZi_IIoT/kernel/thread/tick.c b/Ubiquitous/XiZi_IIoT/kernel/thread/tick.c index 49f75f38c..30156d39e 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/thread/tick.c +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/tick.c @@ -96,7 +96,7 @@ void TickAndTaskTimesliceUpdate(void) */ #define MIN_TICKS 1 -x_ticks_t CalculteTickFromTimeMs(uint32 ms) +x_ticks_t CalculateTickFromTimeMs(uint32 ms) { uint32 tmp = 0; x_ticks_t ticks = 0; @@ -121,7 +121,7 @@ x_ticks_t CalculteTickFromTimeMs(uint32 ms) * @param ticks ticks need to be converted * @return ms */ -uint32 CalculteTimeMsFromTick(x_ticks_t ticks) +uint32 CalculateTimeMsFromTick(x_ticks_t ticks) { uint32 ms = 0; diff --git a/Ubiquitous/XiZi_IIoT/tool/shell/letter-shell/shell.h b/Ubiquitous/XiZi_IIoT/tool/shell/letter-shell/shell.h index 75084d63c..6e55fd27e 100644 --- a/Ubiquitous/XiZi_IIoT/tool/shell/letter-shell/shell.h +++ b/Ubiquitous/XiZi_IIoT/tool/shell/letter-shell/shell.h @@ -25,7 +25,7 @@ * you cannot use double-clicking the tab to complete the command help, * and you cannot use the shell timeout lock */ -#define SHELL_GET_TICK() CalculteTimeMsFromTick(CurrentTicksGain()) +#define SHELL_GET_TICK() CalculateTimeMsFromTick(CurrentTicksGain()) /** From 806492e271720726ed7a61f8b8c0353b66d147c1 Mon Sep 17 00:00:00 2001 From: Wang_Weigen Date: Wed, 11 Jan 2023 14:32:41 +0800 Subject: [PATCH 31/33] =?UTF-8?q?1=E3=80=81modify=20the=20'link.lds'=20fil?= =?UTF-8?q?e=20accroding=20to=20sdk;2=E3=80=81add=20irq=20enable=20and=20d?= =?UTF-8?q?isable=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ubiquitous/XiZi_AIoT/.config | 18 + .../XiZi_AIoT/hardkernel/abstraction/isr.h | 2 +- .../arm/armv7-a/cortex-a9/arch_interrupt.h | 8 + .../arch/arm/armv7-a/cortex-a9/boot.S | 35 +- .../arch/arm/armv7-a/cortex-a9/exception.S | 2 +- .../arch/arm/armv7-a/cortex-a9/interrupt.c | 29 +- .../services/boards/imx6q-sabrelite/Makefile | 2 +- .../services/boards/imx6q-sabrelite/config.mk | 2 +- .../boards/imx6q-sabrelite/hab_defines.h | 2222 +++++++++++++++++ .../imx6q-sabrelite/include/hab_defines.h | 2222 +++++++++++++++++ .../services/boards/imx6q-sabrelite/ivt.c | 82 + .../services/boards/imx6q-sabrelite/link.lds | 98 +- 12 files changed, 4684 insertions(+), 38 deletions(-) create mode 100644 Ubiquitous/XiZi_AIoT/.config create mode 100755 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/hab_defines.h create mode 100755 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/include/hab_defines.h create mode 100755 Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/ivt.c diff --git a/Ubiquitous/XiZi_AIoT/.config b/Ubiquitous/XiZi_AIoT/.config new file mode 100644 index 000000000..307c2f4c0 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/.config @@ -0,0 +1,18 @@ +# +# Automatically generated file; DO NOT EDIT. +# XiZi_AIoT Project Configuration +# +CONFIG_BOARD_IMX6Q_SABRELITE_EVB=y +CONFIG_ARCH_ARM=y + +# +# imx6q sabrelite feature +# + +# +# Lib +# +CONFIG_LIB=y +CONFIG_LIB_POSIX=y +CONFIG_LIB_NEWLIB=y +# CONFIG_LIB_MUSLLIB is not set diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/isr.h b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/isr.h index edd939952..584e9b578 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/isr.h +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/isr.h @@ -81,7 +81,7 @@ struct InterruptServiceRoutines { extern struct InterruptServiceRoutines isrManager ; -unsigned long DisableLocalInterrupt(); +uint32_t DisableLocalInterrupt(); void EnableLocalInterrupt(unsigned long level); #define DISABLE_INTERRUPT DisableLocalInterrupt diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/arch_interrupt.h b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/arch_interrupt.h index 95233993c..b26d3e80c 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/arch_interrupt.h +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/arch_interrupt.h @@ -22,6 +22,14 @@ int32_t ArchEnableHwIrq(uint32_t irq_num); int32_t ArchDisableHwIrq(uint32_t irq_num); +//! @brief +typedef enum { + CPU_0, + CPU_1, + CPU_2, + CPU_3, +} cpuid_e; + struct ExceptionStackRegister { uint32_t r0; diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S index a10b5ef7a..49d0d456f 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/boot.S @@ -1,18 +1,8 @@ - -@ .equ Mode_USR, 0x10 -@ .equ Mode_FIQ, 0x11 -@ .equ Mode_IRQ, 0x12 -@ .equ Mode_SVC, 0x13 -@ .equ Mode_ABT, 0x17 -@ .equ Mode_UND, 0x1B -@ .equ Mode_SYS, 0x1F #include -@ .equ I_BIT, 0x80 @ when I bit is set, IRQ is disabled -@ .equ F_BIT, 0x40 @ when F bit is set, FIQ is disabled - -.equ STACK_SIZE, 0x00000100 +.global ExceptionVectors +.section ".startup","ax" .globl _reset _reset: @@ -30,7 +20,6 @@ _reset: bic r0, #(1 << 0) /* mmu */ mcr p15, 0, r0, c1, c0, 0 - ldr r0, =stack_top @ Set the startup stack for svc @@ -39,26 +28,38 @@ _reset: @ Enter Undefined Instruction Mode and set its Stack Pointer msr cpsr_c, #MODE_UND|I_BIT|F_BIT mov sp, r0 - sub r0, r0, #STACK_SIZE + sub r0, r0, #EXCEPTION_STACK_SIZE @ Enter Abort Mode and set its Stack Pointer msr cpsr_c, #MODE_ABT|I_BIT|F_BIT mov sp, r0 - sub r0, r0, #STACK_SIZE + sub r0, r0, #EXCEPTION_STACK_SIZE @ Enter FIQ Mode and set its Stack Pointer msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT mov sp, r0 - sub r0, r0, #STACK_SIZE + sub r0, r0, #EXCEPTION_STACK_SIZE @ Enter IRQ Mode and set its Stack Pointer msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT mov sp, r0 - sub r0, r0, #STACK_SIZE + sub r0, r0, #EXCEPTION_STACK_SIZE /* come back to SVC mode */ msr cpsr_c, #MODE_SVC|I_BIT|F_BIT + /* + * copy the vector table into the RAM vectors + * this assumes that the RAM vectors size is divisible by 3 words (12 bytes) + */ + ldr r1,=__ram_vectors_start + ldr r2,=__ram_vectors_end + ldr r3,=ExceptionVectors +1: cmp r1,r2 + ldmlt r3!,{r4,r5,r6} + stmlt r1!,{r4,r5,r6} + blt 1b + /* clear .bss */ mov r0, #0 /* get a zero */ ldr r1,=__bss_start /* bss start */ diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S index e8ee24286..bc9a68213 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S @@ -1,6 +1,6 @@ #include -.section .vectors, "ax" +.section .text.vectors, "ax" .code 32 .globl ExceptionVectors diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/interrupt.c b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/interrupt.c index 635857aa8..3105805d1 100755 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/interrupt.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/interrupt.c @@ -3,24 +3,43 @@ #include #include -unsigned long __attribute__((naked)) DisableLocalInterrupt() +uint32_t DisableLocalInterrupt(void) { - + uint32_t intSave; + __asm__ __volatile__( + "mrs %0, cpsr \n" + "cpsid if " + : "=r"(intSave) + : + : "memory"); + return intSave; } -void __attribute__((naked)) EnableLocalInterrupt(unsigned long level) +void EnableLocalInterrupt(unsigned long level) { - + uint32_t intSave; + __asm__ __volatile__( + "mrs %0, cpsr \n" + "cpsie if " + : "=r"(intSave) + : + : "memory"); + return; } int32_t ArchEnableHwIrq(uint32_t irq_num) { - + // gic_set_irq_priority(irq_num, priority); + gic_set_irq_security(irq_num, false); // set IRQ as non-secure + // gic_set_cpu_target(irq_num, CPU_0, true); + gic_enable_irq(irq_num, true); return 0; } int32_t ArchDisableHwIrq(uint32_t irq_num) { + gic_enable_irq(irq_num, false); + // gic_set_cpu_target(irq_num, CPU_0, false); return 0; } diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile index 683e42a90..e929933ca 100644 --- a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile @@ -1,4 +1,4 @@ -SRC_FILES := board.c +SRC_FILES := board.c ivt.c SRC_DIR := third_party_driver diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/config.mk b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/config.mk index ee27915c9..d36fb19fe 100644 --- a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/config.mk +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/config.mk @@ -15,7 +15,7 @@ endif # export LINK_LWIP := $(KERNEL_ROOT)/resources/ethernet/LwIP/liblwip.a # endif -export DEFINES := -DHAVE_CCONFIG_H -DSTM32F407xx -DUSE_HAL_DRIVER -DHAVE_SIGINFO +export DEFINES := -DHAVE_CCONFIG_H export USING_NEWLIB =1 export USING_VFS = 1 diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/hab_defines.h b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/hab_defines.h new file mode 100755 index 000000000..1fcf5d544 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/hab_defines.h @@ -0,0 +1,2222 @@ +/* + * Copyright (c) 2008-2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*! + * @file hab_defines.h + * @brief defines for data structures and macros used for enabling secure boot + * + * @ingroup diag_init + */ +#ifndef HAB_DEFINES_H +#define HAB_DEFINES_H +/*=========================================================================== + INCLUDE FILES +=============================================================================*/ +#include /* for integer types */ +#include /* for bool type */ +#include /* for NULL and offsetof() */ +/*=========================================================================== + CONSTANTS +=============================================================================*/ +/** @addtogroup struct + * @{ + */ + +#define HDR_BYTES 4 /* cannot use sizeof(hab_hdr_t) in preprocessor */ + +/** @name External data structure tags + * @anchor dat_tag + * + * Tag values 0x00 .. 0xef are reserved for HAB. Values 0xf0 .. 0xff + * are available for custom use. + */ +/*@{*/ +#define HAB_TAG_IVT 0xd1 /**< Image Vector Table */ +#define HAB_TAG_DCD 0xd2 /**< Device Configuration Data */ +#define HAB_TAG_CSF 0xd4 /**< Command Sequence File */ +#define HAB_TAG_CRT 0xd7 /**< Certificate */ +#define HAB_TAG_SIG 0xd8 /**< Signature */ +#define HAB_TAG_EVT 0xdb /**< Event */ +#define HAB_TAG_RVT 0xdd /**< ROM Vector Table */ +#define HAB_TAG_WRP 0x81 /**< Wrapped Key */ +#define HAB_TAG_MAC 0xac /**< Message Authentication Code */ +/* Values 00 ... 7e reserved for internal use. Values b0 ... cf reserved for + * CSF commands. Values e0 ... ef reserved for key types. + * + * Available values: 82, 84, 87, 88, 8b, 8d, 8e, 90, 93, 95, 96, 99, 9a, + * 9c, 9f, a0, a3, a5, a6, a9, aa, af + * + * Custom values: f0, f3, f5, f6, f9, fa, fc, ff + */ +/*@}*/ + +/** @name HAB version */ +/*@{*/ +#define HAB_MAJOR_VERSION 4 /**< Major version of this HAB release */ +#define HAB_MINOR_VERSION 1 /**< Minor version of this HAB release */ +#define HAB_VER_MAJ_WIDTH 4 /**< Major version field width */ +#define HAB_VER_MAJ_SHIFT 4 /**< Major version field offset */ +#define HAB_VER_MIN_WIDTH 4 /**< Minor version field width */ +#define HAB_VER_MIN_SHIFT 0 /**< Minor version field offset */ +/** Full version of this HAB release @hideinitializer */ +#define HAB_VERSION HAB_VER(HAB_MAJOR_VERSION, HAB_MINOR_VERSION) +/** Base version for this HAB release @hideinitializer */ +#define HAB_BASE_VERSION HAB_VER(HAB_MAJOR_VERSION, 0) + +/*@}*/ + +/* @} struct */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup cmd + * @{ + */ + +/** @name Command tags + * @anchor cmd_tag + * + * Tag values 0xb0 .. 0xcf are reserved for HAB. Values 0xf0 .. 0xff + * are available for custom use. + */ +/*@{*/ +#define HAB_CMD_SET 0xb1 /**< Set */ +#define HAB_CMD_INS_KEY 0xbe /**< Install Key */ +#define HAB_CMD_AUT_DAT 0xca /**< Authenticate Data */ +#define HAB_CMD_WRT_DAT 0xcc /**< Write Data */ +#define HAB_CMD_CHK_DAT 0xcf /**< Check Data */ +#define HAB_CMD_NOP 0xc0 /**< No Operation */ +#define HAB_CMD_INIT 0xb4 /**< Initialise */ +#define HAB_CMD_UNLK 0xb2 /**< Unlock */ +#ifdef HAB_FUTURE +#define HAB_CMD_RMV_KEY /**< Remove Key */ +#define HAB_CMD_INS_REF /**< Install Reference Data */ +#define HAB_CMD_INS_PLG /**< Install Plugin */ +#define HAB_CMD_RMV_PLG /**< Remove Plugin */ +#define HAB_CMD_CHK_VER /**< Check SW Version */ +#endif +/* Remaining values: b7, b8, bb, bd, c3, c5, c6, c9 */ +/*@}*/ + +/* @} cmd */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup pcl + * @{ + */ + +/** @name Protocol tags + * @anchor pcl_tag + * + * Tag values 0x00 .. 0xef are reserved for HAB. Values 0xf0 .. 0xff are + * available for custom use. + */ +/*@{*/ +#define HAB_PCL_SRK 0x03 /**< SRK certificate format */ +#define HAB_PCL_X509 0x09 /**< X.509v3 certificate format */ +#define HAB_PCL_CMS 0xc5 /**< CMS/PKCS#7 signature format */ +#define HAB_PCL_BLOB 0xbb /**< SHW-specific wrapped key format */ +#define HAB_PCL_AEAD 0xa3 /**< Proprietary AEAD MAC format */ +#ifdef HAB_FUTURE +#define HAB_PCL_WTLS 0x05 /**< OMA WTLS certificate format */ +#define HAB_PCL_FSL 0x0f /**< FSL bound signature protocol */ +#define HAB_PCL_HMAC 0x30 /**< NIST HMAC message authentication */ +#define HAB_PCL_CBCMAC 0x33 /**< CBC-MAC message authentication */ +#endif +/*@}*/ + +/* Available values: 06, 0a, 0c, 11, 12, 14, 17, 18, 1b, 1d, 1e, 21, 22, 24, + * 27, 28, 2b, 2d, 2e, 35, 36, 39, 3a, 3c, 3f, 41, 42, 44, 47, 48, 4b, 4d, 4e, + * 50, 53, 55, 56, 59, 5a, 5c, 5f, 60, 63, 65, 66, 69, 6a, 6c, 6f, 71, 72, 74, + * 77, 78, 7b, 7d, 7e, 81, 82, 84, 87, 88, 8b, 8d, 8e, 90, 93, 95, 96, 99, 9a, + * 9c, 9f, a0, a5, a6, a9, aa, ac, af, b1, b2, b4, b7, b8, bd, be, c0, c3, c6, + * c9, ca, cc, cf, d1, d2, d4, d7, d8, db, dd, de, e1, e2, e4, e7, e8, eb, ed, + * ee + * + * Custom values: f0, f3, f5, f6, f9, fa, fc, ff + */ + +/* @} pcl */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup alg + * @{ + */ + +/** @name Algorithm types + * @anchor alg_typ + * + * The most-significant nibble of an algorithm ID denotes the algorithm + * type. Algorithms of the same type share the same interface. + * + * Types 0x0 .. 0xc are reserved for HAB. Types 0xd .. 0xf are available for + * custom use. Within each reserved type N in 0 .. c, tag values 0xN0 .. 0xNc + * are reserved for HAB. Values 0xNd .. 0xNf are available for custom use. + */ +/*@{*/ +#define HAB_ALG_ANY 0x0 /**< Algorithm type ANY */ +#define HAB_ALG_HASH 0x1 /**< Hash algorithm type */ +#define HAB_ALG_SIG 0x2 /**< Signature algorithm type */ +#define HAB_ALG_FF 0x3 /**< Finite field arithmetic */ +#define HAB_ALG_EC 0x4 /**< Elliptic curve arithmetic */ +#define HAB_ALG_CIPHER 0x5 /**< Cipher algorithm type */ +#define HAB_ALG_MODE 0x6 /**< Cipher/hash modes */ +#define HAB_ALG_WRAP 0x7 /**< Key wrap algorithm type */ +/*@}*/ + +/** @name Algorithm type ANY + * + * Algorithms of type ANY have no common interface: the protocol must know + * what to do. + */ +/*@{*/ +#ifdef HAB_FUTURE +#define HAB_ALG_RANDOM /**< Random number generation */ +#endif +/* Available values: 03, 05, 06, 09, 0a, 0c, 0f + */ +/*@}*/ + +/** @name Hash algorithms */ +/*@{*/ +#define HAB_ALG_SHA1 0x11 /**< SHA-1 algorithm ID */ +#define HAB_ALG_SHA256 0x17 /**< SHA-256 algorithm ID */ +#define HAB_ALG_SHA512 0x1b /**< SHA-512 algorithm ID */ +/* Available values: 0x14, 0x12, 18, 1d, 1e + */ +/*@}*/ + +/** @name Signature algorithms */ +/*@{*/ +#define HAB_ALG_PKCS1 0x21 /**< PKCS#1 RSA signature algorithm */ +#ifdef HAB_FUTURE +#define HAB_ALG_DSA /**< NIST DSA signature algorithm */ +#define HAB_ALG_ECDSA /**< NIST ECDSA signature algorithm */ +#endif +/* Available values: 22, 24, 27, 28, 2b, 2d, 2e + */ +/*@}*/ + +/** @name Cipher algorithms */ +/*@{*/ +#define HAB_ALG_AES 0x55 /**< AES algorithm ID */ +/* Available values: 50, 53, 56, 59, 5a, 5c, 5f + */ +/*@}*/ + +/** @name Cipher or hash modes */ +/*@{*/ +#define HAB_MODE_CCM 0x66 /**< Counter with CBC-MAC */ +#ifdef HAB_FUTURE +#define HAB_MODE_HMAC /**< HMAC hash mode */ +#endif +/* Available values: 60, 63, 65, 69, 6a, 6c, 6f + */ +/*@}*/ + +/** @name Key wrap algorithms */ +/*@{*/ +#define HAB_ALG_BLOB 0x71 /**< SHW-specific key wrap */ +/* Available values: 72, 74, 77, 78, 7b, 7d, 7e + */ +/*@}*/ + +/* Available values: 81, 82, 84, 87, 88, 8b, 8d, 8e, 90, 93, 95, 96, 99, 9a, + * 9c, 9f, a0, a3, a5, a6, a9, aa, ac, af, b1, b2, b4, b7, b8, bb, bd, be, c0, + * c3, c5, c6, c9, ca, cc, cf, d1, d2, d4, d7, d8, db, dd, de, e1, e2, e4, e7, + * e8, eb, ed, ee, f0, f3, f5, f6, f9, fa, fc, ff + */ + +/* @} alg */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup eng + * @{ + */ + +/** @name Engine plugin tags + * @anchor eng_tag + * + * Tag values 0x00 .. 0xef and 0xff are reserved for HAB. Values 0xf0 .. 0xfe + * are available for custom use. + */ +/*@{*/ +#define HAB_ENG_ANY 0x00 /**< First compatible engine will be + * selected automatically (no engine + * configuration parameters are allowed). + */ +#define HAB_ENG_SCC 0x03 /**< Security controller */ +#define HAB_ENG_RTIC 0x05 /**< Run-time integrity checker */ +#define HAB_ENG_SAHARA 0x06 /**< Crypto accelerator */ +#define HAB_ENG_CSU 0x0a /**< Central Security Unit */ +#define HAB_ENG_SRTC 0x0c /**< Secure clock */ +#ifdef HAB_FUTURE +#define HAB_ENG_RNG 0x09 /**< Standalone random number generator */ +#define HAB_ENG_SJC 0x0f /**< Secure JTAG controller */ +#define HAB_ENG_WDOG 0x11 /**< Watchdog timer */ +#define HAB_ENG_SRC 0x12 /**< System Reset Controller */ +#define HAB_ENG_SPBA 0x14 /**< Shared Peripheral Bus Arbiter */ +#define HAB_ENG_IIM 0x17 /**< Fuse controller */ +#define HAB_ENG_IOMUX 0x18 /**< IO multiplexer */ +#endif +#define HAB_ENG_DCP 0x1b /**< Data Co-Processor */ +#define HAB_ENG_CAAM 0x1d /**< Cryptographic Acceleration and + Assurance Module */ +#define HAB_ENG_SNVS 0x1e /**< Secure Non-Volatile Storage */ +#define HAB_ENG_OCOTP 0x21 /**< Fuse controller */ +/** @cond rom */ +#define HAB_ENG_DTCP 0x22 /**< DTCP co-processor */ +#define HAB_ENG_ROM 0x36 /**< Protected ROM area */ +#define HAB_ENG_HDCP 0x24 /**< HDCP co-processor */ +#define HAB_ENG_RTL 0x77 /**< @rom RTL simulation engine */ +/** @endcond */ +#define HAB_ENG_SW 0xff /**< Software engine */ +/* Available values: 27, 28, 2b, 2d, 2e, 30, 33, 35, + * 39, 3a, 3c, 3f, 41, 42, 44, 47, 48, 4b, 4d, 4e, 50, 53, 55, 56, 59, 5a, + * 5c, 5f, 60, 63, 65, 66, 69, 6a, 6c, 6f, 71, 72, 74, 78, 7b, 7d, 7e, 81, + * 82, 84, 87, 88, 8b, 8d, 8e, 90, 93, 95, 96, 99, 9a, 9c, 9f, a0, a3, a5, a6, + * a9, aa, ac, af, b1, b2, b4, b7, b8, bb, bd, be, c0, c3, c5, c6, c9, ca, cc, + * cf, d1, d2, d4, d7, d8, db, dd, de, e1, e2, e4, e7, e8, eb, ed, ee + * + * Custom values: f0, f3, f5, f6, f9, fa, fc + */ +/*@}*/ + +/* @} eng */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup sah + * @{ + */ + +/** Maximum data blocks in a single hash */ +#define HAB_SAHARA_BLOCK_MAX 12 + +/** @cond rom */ +/** @rom DMA storage requirement + * + * This figure is derived in several parts: + * - each hash operation needs a 6-word descriptor structure + * - each data block needs a 3-word link structure + * - the result needs a 3-word link structure + * - at least 40 bytes are required for SHA-256 result and memory manager + * overhead: 64 bytes allows some small overhead. + */ +#define HAB_SAHARA_DMA_MIN_BYTES (24 + HAB_SAHARA_BLOCK_MAX * 12 + 12 + 64) +/** @endcond */ + +/* @} sah */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup dcp + * @{ + */ + +/** Maximum data blocks in a single hash */ +#define HAB_DCP_BLOCK_MAX 6 + +/** @cond rom */ +/** @rom DMA storage requirement + * + * This figure is derived in two parts: + * - each data block needs an 8-word work packet (descriptor) + * - at least 40 bytes are required for SHA-256 result and memory manager + * overhead: 64 bytes allows some small overhead. + */ +#define HAB_DCP_DMA_MIN_BYTES (64 + HAB_DCP_BLOCK_MAX * 32) +/** @endcond */ + +/* @} dcp */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup rtic + * @{ + */ + +/** Maximum data blocks in a single hash */ +#define HAB_RTIC_BLOCK_MAX 2 + +/* @} rtic */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup scc + * @{ + */ + +/** @cond rom */ +/** @rom DMA storage requirement + * + * This figure is derived in several stages, and assumes plaintext and + * ciphertext buffers are both allocated in the DMA region : + * - 4 blocks of plaintext required + * - 4 blocks of ciphertext required + * - each block is 16 bytes long + * - the plaintext address must be block-aligned (up to 15 bytes overhead) + * - the ciphertext address must be block-aligned (up to 3 bytes overhead) + * - at least 8 bytes of memory manager overhead: allow 32 for comfort + */ +#define HAB_SCC_DMA_MIN_BYTES ( (4+4)*16 + 15 + 3 + 32) +/** @endcond */ + +/* @} scc */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup caam + * @{ + */ + +/** Maximum data blocks in an @ref cmd_aut_dat command */ +#define HAB_CAAM_BLOCK_MAX 8 + +/** @cond rom */ +/** @rom Hash DMA storage requirement + * + * This figure is derived in several parts: + * - each hash operation needs + * - a 7-word descriptor, and + * - a 32-byte result buffer (for SHA-256), + * - giving a base requirement of (7*4 + 32) = 60 bytes + * - each data block needs a 4-word link structure + * - memory manager overhead is at least 8 bytes: 16 bytes allows flexibility + */ +#define HAB_CAAM_HSH_DMA_MIN_BYTES (60 + HAB_CAAM_BLOCK_MAX * 16 + 16) + +/** @rom AEAD DMA storage requirement + * + * This figure is derived in several parts: + * - each AEAD operation needs + * - a 16-word descriptor, + * - a 32-byte initial context value (B0 and CTR0), and + * - a 16-byte MAC value, + * - giving a base requirement of (16*4 + 32 + 16) = 112 bytes + * - each data block needs a 4-word link structure + * - memory manager overhead is at least 8 bytes: 16 bytes allows flexibility + */ +#define HAB_CAAM_CCM_DMA_MIN_BYTES (112 + HAB_CAAM_BLOCK_MAX * 16 + 16) + +/** @rom RNG DMA storage requirement + * + * This figure is derived in several parts: + * - each DRNG test operation allocates a DMA area with + * - a 1-word header, and + * - a 3-word job ring area, and + * - a 54-word descriptor, + * - requiring a total 58*4 = 232 bytes + * - each DRNG test operation also allocates a DMA area with + * - a 1-word header, and + * - a 32-byte result buffer + * - requiring a total 4 + 32 = 36 bytes + */ +#define HAB_CAAM_RNG_DMA_MIN_BYTES (232 + 32) +/** @endcond */ + +/* @} caam */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup key + * @{ + */ + +/** @name Key types + * @anchor key_types + * + * Tag values 0xe0 .. 0xef are reserved for HAB. Values 0xf0 .. 0xff + * are available for custom use. + */ +/*@{*/ +#define HAB_KEY_PUBLIC 0xe1 /**< Public key type: data present */ +#define HAB_KEY_SECRET 0xe2 /**< Secret key type: data present */ +#define HAB_KEY_MASTER 0xed /**< Master KEK type */ +#define HAB_KEY_HASH 0xee /**< Any key type: hash only */ +/* Available values: e4, e7, e8, eb + * + * Custom values: f0, f3, f5, f6, f9, fa, fc, ff + */ +/*@}*/ + +/** @name Public key store indices */ +/*@{*/ +#define HAB_IDX_SRK 0 /**< Super-Root Key index */ +#define HAB_IDX_CSFK 1 /**< CSF key index */ +/*@}*/ + +/** @name Key Counts */ +/*@{*/ +#define HAB_SRK_MIN 1 /**< Minimum Super-Root Key count */ +#define HAB_SRK_MAX 4 /**< Maximum Super-Root Key count */ +#define HAB_KEY_PUBLIC_MAX 5 /**< Maximum installed public key count + * (incl Super-Root Key) + */ +#define HAB_KEY_SECRET_MAX 4 /**< Maximum installed secret key count + * (excl Master KEKs) + */ +/*@}*/ + +/* @} key */ + +/*---------------------------------------------------------------------------*/ + +#ifdef HAB_FUTURE +/** @addtogroup key_ecdsa + * @{ + */ + +/** @name Bitfield definitions */ +/*@{*/ +#define HAB_KEY_ECDSA_FLG_WIDTH 8 /**< Width of @a flg field */ +#define HAB_KEY_ECDSA_FLG_SHIFT 0 /**< Offset of @a flg field */ +#define HAB_KEY_ECDSA_TYP_WIDTH 8 /**< Width of @a typ field */ +#define HAB_KEY_ECDSA_TYP_SHIFT 24 /**< Offset of @a typ field */ +#define HAB_KEY_ECDSA_SIZ_WIDTH 8 /**< Width of @a siz field */ +#define HAB_KEY_ECDSA_SIZ_SHIFT 16 /**< Offset of @a siz field */ +#define HAB_KEY_ECDSA_REDBITS_WIDTH 16 /**< Width of @a red_bits field */ +#define HAB_KEY_ECDSA_REDBITS_SHIFT 0 /**< Offset of @a red_bits field */ +/*@}*/ + +/* @} key_ecdsa */ +#endif + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup key_pkcs1 + * @{ + */ + +/** @name Bitfield definitions */ +/*@{*/ +#define HAB_KEY_PKCS1_FLG_WIDTH 8 /**< Width of @a flg field */ +#define HAB_KEY_PKCS1_FLG_SHIFT 0 /**< Offset of @a flg field */ +#define HAB_KEY_PKCS1_MODBYTES_WIDTH 16 /**< Width of mod_bytes field */ +#define HAB_KEY_PKCS1_MODBYTES_SHIFT 16 /**< Offset of mod_bytes field */ +#define HAB_KEY_PKCS1_EXPBYTES_WIDTH 16 /**< Width of exp_bytes field */ +#define HAB_KEY_PKCS1_EXPBYTES_SHIFT 0 /**< Offset of exp_bytes field */ +/*@}*/ + +/** @name Binding flag bitfield definitions */ +/*@}*/ +#define HAB_KEY_BND_FLG_WIDTH 5 /**< Width of binding flags */ +#define HAB_KEY_BND_FLG_SHIFT 2 /**< Offset of binding flags */ +/*@}*/ + +/* @} key_pkcs1 */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup cmd_wrt_dat + * @{ + */ + +/** @name Parameter bitfield definitions. + * + * Apply to both @ref cmd_wrt_dat and @ref cmd_chk_dat commands. */ +/*@{*/ +#define HAB_CMD_WRT_DAT_FLAGS_WIDTH 5 /**< @a flags field width */ +#define HAB_CMD_WRT_DAT_FLAGS_SHIFT 3 /**< @a flags field offset */ +#define HAB_CMD_WRT_DAT_BYTES_WIDTH 3 /**< @a bytes field width */ +#define HAB_CMD_WRT_DAT_BYTES_SHIFT 0 /**< @a bytes field offset */ +/*@}*/ + +/* @} cmd_wrt_dat */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup bnd_obj + * @{ + */ + +/** @name Binding object IDs + * @anchor bnd_ids + * + * The ASN.1 object identifiers used to identify HAB binding attributes are + * defined in the following arc: + * +@verbatim + id-fsl OBJECT IDENTIFIER ::= { + joint-iso-itu-t(2) country(16) us(840) organization(1) fsl(123456) } + + id-habBnd OBJECT IDENTIFIER ::= { + id-fsl hab(32) binding-objects(16) } + + id-habBnd-dat OBJECT IDENTIFIER ::= { + id-habBnd dat(1) } + + id-habBnd-cfg OBJECT IDENTIFIER ::= { + id-habBnd cfg(3) } + + id-habBnd-fid OBJECT IDENTIFIER ::= { + id-habBnd fid(5) } + + id-habBnd-mid OBJECT IDENTIFIER ::= { + id-habBnd mid(6) } + + id-habBnd-cid OBJECT IDENTIFIER ::= { + id-habBnd cid(9) } +@endverbatim + * + * The ASN.1 object identifiers used to identify HAB binding attributes are + * single component extensions of id-habBnd using a component value less than + * 128 (so that the component can be DER-encoded in a single byte). + * + * The DER encoding of an object identifier in this arc is the concatenation + * of the DER prefix with the single byte identifier for the required binding + * object. Binding object attribute values are encoded as an ASN.1 SET with + * a single OCTET STRING member. + */ +/*@{*/ + +/** DER prefix + * + * @todo update description and encoding of binding object identifiers with + * real fsl value instead of fsl(123456) encoded as 0x87, 0xc4, 0x40, and + * confirm chosen values for hab(32) and binding-objects(16). + */ +#define HAB_BND_DER_PREFIX \ + {0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x87, 0xc4, 0x40, 0x20, 0x10} +#define HAB_BND_DAT 0x01 /**< Data type (mandatory) */ +#define HAB_BND_CFG 0x03 /**< Security configuration */ +#define HAB_BND_FID 0x05 /**< Fabrication UID */ +#define HAB_BND_MID 0x06 /**< Manufacturing ID */ +#define HAB_BND_CID 0x09 /**< Caller ID */ +/* Available values: 0a, 0c, 0f, 11, 12, 14, 17, 18, 1b, 1d, 1e, 21, 22, 24, + * 27, 28, 2b, 2d, 2e, 30, 33, 35, 36, 39, 3a, 3c, 3f, 41, 42, 44, 47, 48, 4b, + * 4d, 4e, 50, 53, 55, 56, 59, 5a, 5c, 5f, 60, 63, 65, 66, 69, 6a, 6c, 6f, 71, + * 72, 74, 77, 78, 7b, 7d, 7e + */ +/*@}*/ + + +/** @name Caller IDs + * + * Only the ROM caller ID is defined, but other caller IDs may be defined by + * later boot stages. + */ +/*@{*/ +#define HAB_CID_ROM 0 /**< ROM Caller ID */ +/*@}*/ + +/* @} bnd_obj */ + +#ifdef HAB_FUTURE +/** @addtogroup sig_fsl + * @{ + */ + +#define HAB_BND_DAT_BYTES 512 /**< Maximum binding data size */ + +/* @} sig_fsl */ +#endif + +/*=========================================================================== + MACROS +=============================================================================*/ +/* + * Helper macros + */ +#define HAB_CMD_UNS 0xff + +#define DEFAULT_IMG_KEY_IDX 2 + +#define GEN_MASK(width) \ + ((1UL << (width)) - 1) + +#define GEN_FIELD(f, width, shift) \ + (((f) & GEN_MASK(width)) << (shift)) + +#define PACK_UINT32(a, b, c, d) \ + ((uint32_t) ( (((uint32_t)(a) & 0xFF) << 24) \ + |(((uint32_t)(b) & 0xFF) << 16) \ + |(((uint32_t)(c) & 0xFF) << 8) \ + |(((uint32_t)(d) & 0xFF)) ) ) + +#define EXPAND_UINT32(w) \ + (uint8_t)((w)>>24), (uint8_t)((w)>>16), (uint8_t)((w)>>8), (uint8_t)(w) + +#define EXPAND_UINT16(w) \ + (uint8_t)((w)>>8), (uint8_t)(w) + +#define HDR(tag, bytes, par) \ + (uint8_t)(tag), (uint8_t)((bytes)>>8), (uint8_t)(bytes), (uint8_t)(par) + +#define HAB_VER(maj, min) \ + (GEN_FIELD((maj), HAB_VER_MAJ_WIDTH, HAB_VER_MAJ_SHIFT) \ + | GEN_FIELD((min), HAB_VER_MIN_WIDTH, HAB_VER_MIN_SHIFT)) + +#define DCD_DATA(addr, data) EXPAND_UINT32(addr), EXPAND_UINT32(data) + +/* + * CSF header + */ + +#define CSF_HDR(bytes, HABVER) \ + HDR(HAB_TAG_CSF, (bytes), HABVER) + + +/* + * DCD header + */ + +#define DCD_HDR(bytes, HABVER) \ + HDR(HAB_TAG_DCD, (bytes), HABVER) + +/* + * IVT header (goes in the struct's hab_hdr_t field, not a byte array) + */ +#define IVT_HDR(bytes, HABVER) \ + {HAB_TAG_IVT, {(uint8_t)((bytes)>>8), (uint8_t)(bytes)}, HABVER} + +/* + * Write Data + */ + +#define WRT_DAT(flags, bytes, address, val_msk) \ + HDR(HAB_CMD_WRT_DAT, WRT_DAT_BYTES, WRT_DAT_PAR((flags), (bytes))), \ + EXPAND_UINT32(address), \ + EXPAND_UINT32(val_msk) + +#define WRT_DAT_BYTES 12 + +#define MULTI_WRT_DAT(flags, bytes, address1, val_msk1, address2, \ + val_msk2, address3, val_msk3) \ + HDR(HAB_CMD_WRT_DAT, MULTI_WRT_DAT_BYTES, WRT_DAT_PAR((flags), (bytes))), \ + EXPAND_UINT32(address1), \ + EXPAND_UINT32(val_msk1), \ + EXPAND_UINT32(address2), \ + EXPAND_UINT32(val_msk2), \ + EXPAND_UINT32(address3), \ + EXPAND_UINT32(val_msk3) + +#define MULTI_WRT_DAT_BYTES 28 + +#define WRT_DAT_PAR(flags, bytes) \ + (GEN_FIELD((flags), \ + HAB_CMD_WRT_DAT_FLAGS_WIDTH, \ + HAB_CMD_WRT_DAT_FLAGS_SHIFT) \ + | GEN_FIELD((bytes), \ + HAB_CMD_WRT_DAT_BYTES_WIDTH, \ + HAB_CMD_WRT_DAT_BYTES_SHIFT)) + +/* + * Check Data (forever) + */ + +#define CHK_DAT_FOREVER(flags, bytes, address, mask) \ + HDR(HAB_CMD_CHK_DAT, CHK_DAT_FOREVER_BYTES, WRT_DAT_PAR((flags), (bytes))), \ + EXPAND_UINT32(address), \ + EXPAND_UINT32(mask) + +#define CHK_DAT_FOREVER_BYTES 12 + +/* + * Check Data (polled) + */ +#define HAB_CMD_CHK_DAT_COUNT 100 + +#define CHK_DAT(flags, bytes, address, mask, count) \ + HDR(HAB_CMD_CHK_DAT, CHK_DAT_BYTES, WRT_DAT_PAR((flags), (bytes))), \ + EXPAND_UINT32(address), \ + EXPAND_UINT32(mask), \ + EXPAND_UINT32(count) + +#define CHK_DAT_BYTES 16 + +/* + * Set (generic - used internally only, or to generate invalid commands) + */ + +#define SET(bytes, itm, value) \ + HDR(HAB_CMD_SET, (bytes), (itm)), \ + EXPAND_UINT32(value) + +/* + * Set (MID location) + */ + +#define SET_MID(bank, row, bit, fuses) \ + HDR(HAB_CMD_SET, SET_MID_BYTES, HAB_VAR_CFG_ITM_MID), \ + (bank), (row), (bit), (fuses) + +#define SET_MID_BYTES 8 + +/* + * Set (default ENG) + */ + +#define SET_ENG(alg, eng, cfg) \ + HDR(HAB_CMD_SET, SET_ENG_BYTES, HAB_VAR_CFG_ITM_ENG), \ + 0, (alg), (eng), (cfg) + +#define SET_ENG_BYTES 8 + +/* + * Init (engine) + */ + +#define INIT(eng) \ + HDR(HAB_CMD_INIT, INIT_BYTES, (eng)) + +#define INIT_BYTES 4 + +/* + * Unlk (engine) + */ + +#define UNLK(eng, ...) \ + UNLK_ ## eng(__VA_ARGS__) + +#define UNLK_BYTES(eng, ...) \ + UNLK_BYTES_ ## eng(__VA_ARGS__) + +#define UNLK_HDR(eng, ...) \ + HDR(HAB_CMD_UNLK, UNLK_BYTES_ ## eng(__VA_ARGS__), eng) + +#define UNLK_FLG(flg) \ + 0, 0, 0, (uint8_t)(flg) + +#define UNLK_FLG_BYTES 4 + +#define UNLK_HAB_ENG_SRTC(dnc) UNLK_HDR(HAB_ENG_SRTC) +#define UNLK_BYTES_HAB_ENG_SRTC(dnc) HDR_BYTES + +#define UNLK_HAB_ENG_SNVS(flg) UNLK_HDR(HAB_ENG_SNVS), UNLK_FLG(flg) +#define UNLK_BYTES_HAB_ENG_SNVS(flg) (HDR_BYTES + UNLK_FLG_BYTES) + +#define UNLK_HAB_ENG_CAAM(flg) UNLK_HDR(HAB_ENG_CAAM), UNLK_FLG(flg) +#define UNLK_BYTES_HAB_ENG_CAAM(flg) (HDR_BYTES + UNLK_FLG_BYTES) + +/* The next definition uses a GCC extension employing ## to swallow the + * trailing comma in case the macro is called with only the fixed arguments + * (i.e. flg here). This extension appears to work in the GNU compatible mode + * of RVDS and GHS compilers. + */ +#define UNLK_HAB_ENG_OCOTP(flg, ...) \ + UNLK_HDR(HAB_ENG_OCOTP, flg), UNLK_FLG(flg), ## __VA_ARGS__ + +#define UNLK_BYTES_HAB_ENG_OCOTP(flg, ...) \ + (HDR_BYTES + UNLK_FLG_BYTES \ + + ( ((flg) & (HAB_OCOTP_UNLOCK_FIELD_RETURN \ + |HAB_OCOTP_UNLOCK_JTAG \ + |HAB_OCOTP_UNLOCK_SCS)) \ + ? STUB_FAB_UID_BYTES \ + : 0 )) + +#if 0 +/* Note: no comma after HDR(). Supplied by _VAL macro if needed */ +#define UNLK(eng, val) \ + HDR(HAB_CMD_UNLK, UNLK_BYTES_ ## eng, (eng)) \ + UNLK_VAL_ ## eng(val) + +#define UNLK_BYTES(eng) \ + UNLK_BYTES_ ## eng + +#define UNLK_BYTES_HAB_ENG_SRTC HDR_BYTES +#define UNLK_VAL_HAB_ENG_SRTC(val) /* no val field */ +#define UNLK_BYTES_HAB_ENG_SNVS (HDR_BYTES + 4) +#define UNLK_VAL_HAB_ENG_SNVS(val) ,0,0,0,((val)&0xff) +#define UNLK_BYTES_HAB_ENG_CAAM (HDR_BYTES + 4) +#define UNLK_VAL_HAB_ENG_CAAM(val) ,0,0,0,((val)&0xff) +#endif + +/* + * NOP + */ + +#define NOP() \ + HDR(HAB_CMD_NOP, NOP_BYTES, 0xae) /* third param is ignored */ + +#define NOP_BYTES 4 + +/* + * Install Key (generic - used internally only) + */ + +#define INS_KEY(bytes, flg, pcl, alg, src, tgt, crt) \ + HDR(HAB_CMD_INS_KEY, (bytes), (flg)), \ + (pcl), (alg), (src), (tgt), \ + EXPAND_UINT32(crt) + +#define INS_KEY_BASE_BYTES 12 + +/* + * Install Key (SRK) + */ + +#define INS_SRK(flg, alg, src, crt) \ + INS_KEY(INS_SRK_BYTES, (flg), \ + HAB_PCL_SRK, (alg), (src), HAB_IDX_SRK, \ + (crt)) + +#define INS_SRK_BYTES INS_KEY_BASE_BYTES + +/* + * Install Key (CSFK) + */ + +#define INS_CSFK(flg, pcl, crt) \ + INS_KEY(INS_CSFK_BYTES, (flg) | HAB_CMD_INS_KEY_CSF, \ + (pcl), HAB_ALG_ANY, HAB_IDX_SRK, HAB_IDX_CSFK, \ + (crt)) + +#define INS_CSFK_BYTES INS_KEY_BASE_BYTES + +/* + * Install Key (IMGK - no hash) + */ + +#define INS_IMGK(flg, pcl, src, tgt, crt) \ + INS_KEY(INS_IMGK_BYTES, (flg), \ + (pcl), HAB_ALG_ANY, (src), (tgt), \ + (crt)) + +#define INS_IMGK_BYTES INS_KEY_BASE_BYTES + + +/* + * Install Key (IMGK - with hash). Must be followed by the crt_hsh contents + * (e.g. using #include). The length field depends on using one of the + * standard HAB algorithm names, with no adornments like casts or + * parentheses. Note that the length macro cannot be used here: the ## + * must appear in the body of this macro to prevent the alg parameter from + * being expanded first. + */ + +#define INS_IMGK_HASH(flg, pcl, alg, src, tgt, crt) \ + INS_KEY(INS_KEY_BASE_BYTES + BYTES_ ## alg, (flg) | HAB_CMD_INS_KEY_HSH, \ + (pcl), (alg), (src), (tgt), \ + (crt)) + +/* + * Same as above but the hash length is fixed to the length of SHA1, + * but the algorithm remains unchanged. + */ +#define INS_IMGK_INV_HASH(flg, pcl, alg, src, tgt, crt) \ + INS_KEY(INS_IMGK_HASH_BYTES(HAB_ALG_SHA1), (flg) | HAB_CMD_INS_KEY_HSH, \ + (pcl), (alg), (src), (tgt), \ + (crt)) + + +#define INS_IMGK_HASH_BYTES(alg) \ + (INS_KEY_BASE_BYTES + BYTES_ ## alg) + +#define BYTES_HAB_ALG_SHA1 20 +#define BYTES_HAB_ALG_SHA256 32 +#define BYTES_HAB_ALG_SHA512 64 +/* dummy value for invalid hash alg - same as default hash algorithm */ +#define DEFAULT_HASH_ALG_BYTES BYTES_HAB_ALG_SHA256 +#define BYTES_HAB_ALG_PKCS1 DEFAULT_HASH_ALG_BYTES + +/* + * Authenticate Data (generic - used internally only) + */ + +#define AUT_DAT(bytes, flg, key, pcl, eng, cfg, sig_start) \ + HDR(HAB_CMD_AUT_DAT, (bytes), (flg)), \ + (key), (pcl), (eng), (cfg), \ + EXPAND_UINT32(sig_start) + +#define AUT_DAT_BASE_BYTES 12 + +/* + * Authenticate Data (CSF) + */ + +#define AUT_CSF(flg, pcl, eng, cfg, sig_start) \ + AUT_DAT(AUT_CSF_BYTES, (flg), \ + HAB_IDX_CSFK, (pcl), (eng), (cfg), \ + (sig_start)) + +#define AUT_CSF_BYTES AUT_DAT_BASE_BYTES + +/* + * Authenticate Data (Image) + */ + +#define AUT_IMG(blocks, flg, key, pcl, eng, cfg, sig_start) \ + AUT_DAT(AUT_IMG_BYTES(blocks), (flg), \ + (key), (pcl), (eng), (cfg), \ + (sig_start)) + +#define AUT_IMG_BYTES(blocks) \ + (AUT_DAT_BASE_BYTES + 8*(blocks)) + +/** Supported widths of data commands. + * @ingroup cmd_wrt_dat + */ +typedef enum hab_data_width +{ + HAB_DATA_WIDTH_BYTE = 1, /**< 8-bit value */ + HAB_DATA_WIDTH_HALF = 2, /**< 16-bit value */ + HAB_DATA_WIDTH_WORD = 4 /**< 32-bit value */ +} hab_data_width_t; + + +/** Flags for Write Data commands. + * @ingroup cmd_wrt_dat + */ +typedef enum hab_cmd_wrt_dat_flg +{ + HAB_CMD_WRT_DAT_MSK = 1, /**< Mask/value flag: if set, only specific + * bits may be overwritten at target address + * (otherwise all bits may be overwritten) + */ + HAB_CMD_WRT_DAT_SET = 2 /**< Set/clear flag: if #HAB_CMD_WRT_DAT_MSK + * set, bits at the target address overwritten + * with this flag (otherwise it is ignored) + */ +} hab_cmd_wrt_dat_flg_t; + +/** Flags for Check Data commands. + * @ingroup cmd_chk_dat + */ +typedef enum hab_cmd_chk_dat_flg +{ + HAB_CMD_CHK_DAT_SET = 2, /**< Set/clear flag: bits set in mask must + * match this flag + */ + HAB_CMD_CHK_DAT_ANY = 4 /**< Any/all flag: if clear, all bits set in + * mask must match (otherwise any bit + * suffices) + */ +} hab_cmd_chk_dat_flg_t; + +/** Flags for Authenticate Data commands. + * @ingroup cmd_aut_dat + */ +typedef enum hab_cmd_aut_dat_flg +{ + HAB_CMD_AUT_DAT_CLR = 0, /**< No flags set */ + HAB_CMD_AUT_DAT_ABS = 1 /**< Absolute signature address */ +} hab_cmd_aut_dat_flg_t; + +/** Flags for Install Key commands. + * @ingroup cmd_ins_key + */ +typedef enum hab_cmd_ins_key_flg +{ + HAB_CMD_INS_KEY_CLR = 0, /**< No flags set */ + HAB_CMD_INS_KEY_ABS = 1, /**< Absolute certificate address */ + HAB_CMD_INS_KEY_CSF = 2, /**< Install CSF key */ + HAB_CMD_INS_KEY_DAT = 4, /**< Key binds to Data Type */ + HAB_CMD_INS_KEY_CFG = 8, /**< Key binds to Configuration */ + HAB_CMD_INS_KEY_FID = 16, /**< Key binds to Fabrication UID */ + HAB_CMD_INS_KEY_MID = 32, /**< Key binds to Manufacturing ID */ + HAB_CMD_INS_KEY_CID = 64, /**< Key binds to Caller ID */ + HAB_CMD_INS_KEY_HSH = 128 /**< Certificate hash present */ +} hab_cmd_ins_key_flg_t; + +/** Key flags. + * @ingroup key_pkcs1 + * + * @ifrom + * + * The binding flags given here align with those in #hab_cmd_ins_key_flg + * + * @endrom + * + */ +typedef enum hab_key_flg +{ + /* Two more flag values available */ + HAB_KEY_FLG_DAT = 4, /**< Key binds to Data Type */ + HAB_KEY_FLG_CFG = 8, /**< Key binds to Configuration */ + HAB_KEY_FLG_FID = 16, /**< Key binds to Fabrication UID */ + HAB_KEY_FLG_MID = 32, /**< Key binds to Manufacturing ID */ + HAB_KEY_FLG_CID = 64, /**< Key binds to Caller ID */ + HAB_KEY_FLG_CA = 128 /**< CA key */ +} hab_key_flg_t; + +/** Secret key flags. + * @ingroup crt_blob + */ +typedef enum hab_key_secret_flg +{ + /* Seven more flag values available */ + HAB_KEY_FLG_KEK = 128 /**< KEK */ +} hab_key_secret_flg_t; + +/** Binding data types + * @ingroup bnd_obj + */ +typedef enum hab_dat { + HAB_DAT_CSF = 0x0f, /**< CSF signature */ + HAB_DAT_IMG = 0x33, /**< Image signature */ +#ifdef HAB_FUTURE + HAB_DAT_PLG = 0x3c, /**< Plugin signature */ +#endif + HAB_DAT_MAX +} hab_dat_t; + +/* Available values: 55, 5a, 66, 69, 96, 99, a5, aa, c3, cc, f0, ff + */ + +/** Target check types + * @ingroup chk_tgt + */ +typedef enum hab_target { + HAB_TGT_MEMORY = 0x0f, /**< Check memory white list */ + HAB_TGT_PERIPHERAL = 0xf0, /**< Check peripheral white list */ + HAB_TGT_ANY = 0x55, /**< Check memory & peripheral white list */ + HAB_TGT_MAX +} hab_target_t; + +/** Security configuration types + * @ingroup status + */ +typedef enum hab_config { +/** @cond rom */ + HAB_CFG_FAB = 0x00, /**< @rom Un-programmed IC */ +/** @endcond */ + HAB_CFG_RETURN = 0x33, /**< Field Return IC */ + HAB_CFG_OPEN = 0xf0, /**< Non-secure IC */ + HAB_CFG_CLOSED = 0xcc /**< Secure IC */ +} hab_config_t; +/* Available values: 0f, 3c, 55, 5a, 66, 69, 96, 99, a5, aa, ff + */ + +/** Security state types + * @ingroup status + */ +typedef enum hab_state { + HAB_STATE_INITIAL = 0x33, /**< Initialising state (transitory) */ + HAB_STATE_CHECK = 0x55, /**< Check state (non-secure) */ + HAB_STATE_NONSECURE = 0x66, /**< Non-secure state */ + HAB_STATE_TRUSTED = 0x99, /**< Trusted state */ + HAB_STATE_SECURE = 0xaa, /**< Secure state */ + HAB_STATE_FAIL_SOFT = 0xcc, /**< Soft fail state */ + HAB_STATE_FAIL_HARD = 0xff, /**< Hard fail state (terminal) */ + HAB_STATE_NONE = 0xf0, /**< No security state machine */ + HAB_STATE_MAX +} hab_state_t; +/* Available values: 00, 0f, 3c, 5a, 69, 96, a5, c3 + */ + +/** HAB status types + * @ingroup status + */ +typedef enum hab_status { + HAB_STS_ANY = 0x00, /**< Match any status in + * hab_rvt.report_event() + */ + HAB_FAILURE = 0x33, /**< Operation failed */ + HAB_WARNING = 0x69, /**< Operation completed with warning */ + HAB_SUCCESS = 0xf0, /**< Operation completed successfully */ + HAB_STS_MAX +} hab_status_t; + +/** Failure or warning reasons + * @ingroup evt + * + * Values 0x80 ... 0xff are reserved for internal use. + */ +typedef enum hab_reason { + HAB_RSN_ANY = 0x00, /**< Match any reason in + * hab_rvt.report_event() + */ + HAB_ENG_FAIL = 0x30, /**< Engine failure. */ + HAB_INV_ADDRESS = 0x22, /**< Invalid address: access denied. */ + HAB_INV_ASSERTION = 0x0c, /**< Invalid assertion. */ + HAB_INV_CALL = 0x28, /**< Function called out of sequence. */ + HAB_INV_CERTIFICATE = 0x21, /**< Invalid certificate. */ + HAB_INV_COMMAND = 0x06, /**< Invalid command: command malformed. */ + HAB_INV_CSF = 0x11, /**< Invalid @ref csf. */ + HAB_INV_DCD = 0x27, /**< Invalid @ref dcd. */ + HAB_INV_INDEX = 0x0f, /**< Invalid index: access denied. */ + HAB_INV_IVT = 0x05, /**< Invalid @ref ivt. */ + HAB_INV_KEY = 0x1d, /**< Invalid key. */ + HAB_INV_RETURN = 0x1e, /**< Failed callback function. */ + HAB_INV_SIGNATURE = 0x18, /**< Invalid signature. */ + HAB_INV_SIZE = 0x17, /**< Invalid data size. */ + HAB_MEM_FAIL = 0x2e, /**< Memory failure. */ + HAB_OVR_COUNT = 0x2b, /**< Expired poll count. */ + HAB_OVR_STORAGE = 0x2d, /**< Exhausted storage region. */ + HAB_UNS_ALGORITHM = 0x12, /**< Unsupported algorithm. */ + HAB_UNS_COMMAND = 0x03, /**< Unsupported command. */ + HAB_UNS_ENGINE = 0x0a, /**< Unsupported engine. */ + HAB_UNS_ITEM = 0x24, /**< Unsupported configuration item. */ + HAB_UNS_KEY = 0x1b, /**< Unsupported key type or parameters. */ + HAB_UNS_PROTOCOL = 0x14, /**< Unsupported protocol. */ + HAB_UNS_STATE = 0x09, /**< Unsuitable state. */ + HAB_RSN_MAX +} hab_reason_t; +/* Available values: 33, 35, 36, 39, 3a, 3c, 3f, 41, 42, 44, + * 47, 48, 4b, 4d, 4e, 50, 53, 55, 56, 59, 5a, 5c, 5f, 60, 63, 65, 66, 69, 6a, + * 6c, 6f, 71, 72, 74, 77, 78, 7b, 7d, 7e + */ + +/** Audit logging contexts. + * @ingroup evt + * + * This list is sorted in order of increasing priority: where two contexts + * might apply, the latter one is used. + * + * Values 0x40 .. 0x5f are reserved for internal use. + */ +typedef enum hab_context { + HAB_CTX_ANY = 0x00, /**< Match any context in + * hab_rvt.report_event() + */ +/** @cond rom */ + HAB_CTX_FAB = 0xff, /**< @rom Event logged in hab_fab_test() */ +/** @endcond */ + HAB_CTX_ENTRY = 0xe1, /**< Event logged in hab_rvt.entry() */ + HAB_CTX_TARGET = 0x33, /**< Event logged in hab_rvt.check_target() */ + HAB_CTX_AUTHENTICATE = 0x0a, /**< Event logged in + * hab_rvt.authenticate_image() + */ + HAB_CTX_DCD = 0xdd, /**< Event logged in hab_rvt.run_dcd() */ + HAB_CTX_CSF = 0xcf, /**< Event logged in hab_rvt.run_csf() */ + HAB_CTX_COMMAND = 0xc0, /**< Event logged executing @ref csf or @ref + * dcd command + */ + HAB_CTX_AUT_DAT = 0xdb, /**< Authenticated data block */ + HAB_CTX_ASSERT = 0xa0, /**< Event logged in hab_rvt.assert() */ + HAB_CTX_EXIT = 0xee, /**< Event logged in hab_rvt.exit() */ + HAB_CTX_MAX +} hab_context_t; + +/** Assertion types. + * @ingroup assert + */ +typedef enum hab_assertion { + HAB_ASSERT_BLOCK = 0, /**< Assert that a memory block was authenticated */ + HAB_ASSERT_MAX +} hab_assertion_t; + +/** RTIC configuration flags + * @ingroup rtic + */ +typedef enum hab_rtic_config { + HAB_RTIC_IN_SWAP8 = 0x01, /**< Set BYTE SWAP bit (reverse bytes within + * word on input to RTIC) */ + HAB_RTIC_IN_SWAP16 = 0x02, /**< Set HALF WORD SWAP bit (reverse + * half-words within word on input to + * RTIC) */ + HAB_RTIC_OUT_SWAP8 = 0x08, /**< Set HASH RESULT BYTE SWAP bit (reverse + * bytes within word on output from RTIC) */ + HAB_RTIC_KEEP = 0x80 /**< Retain reference hash value for later + * monitoring */ +} hab_rtic_config_t; + +/** SAHARA configuration flags + * @ingroup sah + */ +typedef enum hab_sahara_config { + HAB_SAHARA_IN_SWAP8 = 0x01, /**< Set MESS BYTE SWAP bit (reverse message + * bytes within word on input to + * SAHARA) */ + HAB_SAHARA_IN_SWAP16 = 0x02, /**< Set MESS HALF WORD SWAP bit (reverse + * message half-words within word on input + * to SAHARA) */ + /* no SWAP32 for SAHARA message - leave 0x04 value unassigned */ + /* no SWAP8 for SAHARA descriptors/links - leave 0x08 value unassigned */ + HAB_SAHARA_DSC_BE8_16 = 0x10, /**< Interpret descriptors and links as for + * BE-8 16-bit memory. */ + HAB_SAHARA_DSC_BE8_32 = 0x20 /**< Interpret descriptors and links as for + * BE-8 32-bit memory. */ +} hab_sahara_config_t; + +/** CAAM configuration flags + * @ingroup caam + */ +typedef enum hab_caam_config { + HAB_CAAM_IN_SWAP8 = 0x01, /**< Set Message Byte Swap Input bit (reverse + * message bytes within word on input to + * CAAM) */ + HAB_CAAM_IN_SWAP16 = 0x02, /**< Set Message Half Word Swap Input bit + * (reverse message half-words within word + * on input to CAAM) */ + /* no SWAP32 for CAAM message - leave 0x04 value unassigned */ + HAB_CAAM_OUT_SWAP8 = 0x08, /**< Set Message Byte Swap Output bit + * (reverse message bytes within word on + * output from CAAM) */ + HAB_CAAM_OUT_SWAP16 = 0x10, /**< Set Message Half Word Swap Output bit + * (reverse message half-words within word + * on output from CAAM) */ + /* no SWAP32 for CAAM message - leave 0x20 value unassigned */ + HAB_CAAM_DSC_SWAP8 = 0x40, /**< Set Control Byte Swap Input/Output bits + * (reverse descriptor/link bytes within + * word on input to or output from CAAM) */ + HAB_CAAM_DSC_SWAP16 = 0x80 /**< Set Control Half Word Swap Input/Output + * bits (reverse descriptor/link half-words + * within word on input to or output from + * CAAM) */ +} hab_caam_config_t; + +/** CAAM unlock flags + * @ingroup caam + */ +typedef enum hab_caam_unlock_flag { + HAB_CAAM_UNLOCK_MID = 0x01, /**< Leave Job Ring and DECO master ID + * registers unlocked */ + HAB_CAAM_UNLOCK_RNG = 0x02 /**< Leave RNG state handle 0 + * uninstantiated, do not generate + * descriptor keys, do not set AES DPA + * mask, do not block state handle 0 test + * instantiation */ +} hab_caam_unlock_flag_t; + +/** SNVS unlock flags + * @ingroup snvs + */ +typedef enum hab_snvs_unlock_flag { + HAB_SNVS_UNLOCK_LP_SWR = 0x01, /**< Leave LP SW reset unlocked */ + HAB_SNVS_UNLOCK_ZMK_WRITE = 0x02 /**< Leave Zeroisable Master Key write + * unlocked */ +} hab_snvs_unlock_flag_t; + +/** SNVS master keys + * @ingroup snvs + * + * @remark Note that the first two master key selections are completely + * interchangeable. + */ +typedef enum hab_snvs_keys { + HAB_SNVS_OTPMK = 0, /**< OTP master key */ + HAB_SNVS_OTPMK_ALIAS = 1, /**< OTP master key (alias) */ + HAB_SNVS_ZMK = 2, /**< Zeroisable master key */ + HAB_SNVS_CMK = 3 /**< Combined master key */ +} hab_snvs_keys_t; + + +/** OCOTP unlock flags + * @ingroup ocotp + */ +typedef enum hab_ocotp_unlock_flag { + HAB_OCOTP_UNLOCK_FIELD_RETURN = 0x01, /**< Leave Field Return activation + * unlocked */ + HAB_OCOTP_UNLOCK_SRK_REVOKE = 0x02, /**< Leave SRK revocation unlocked */ + HAB_OCOTP_UNLOCK_SCS = 0x04, /**< Leave SCS register unlocked */ + HAB_OCOTP_UNLOCK_JTAG = 0x08 /**< Unlock JTAG using SCS HAB_JDE + * bit */ +} hab_ocotp_unlock_flag_t; + +/** DCP configuration flags + * @ingroup dcp + * + * @warning The byte-swapping controls produce unpredictable results unless + * the input data block lengths are multiples of 4 bytes. + */ +typedef enum hab_dcp_config { + HAB_DCP_IN_SWAP8 = 0x01, /**< Set INPUT BYTE SWAP bit (reverse bytes + * within words on input to DCP) */ + /* no SWAP16 for DCP - leave 0x02 value unassigned */ + HAB_DCP_IN_SWAP32 = 0x04, /**< Set INPUT WORD SWAP bit (ignored for + * hashing) */ + HAB_DCP_OUT_SWAP8 = 0x08, /**< Set OUPUT BYTE SWAP bit (reverse bytes + * within words on output from DCP) */ + /* no SWAP16 for DCP - leave 0x10 value unassigned */ + HAB_DCP_OUT_SWAP32 = 0x20 /**< Set OUTPUT WORD SWAP bit (ignored for + * hashing) */ +} hab_dcp_config_t; + +#ifdef HAB_FUTURE +/** EC key specification types. + * @ingroup key_ecdsa + */ +typedef enum hab_ec_spec { + /** Named curve specification. The curve specification is a DER-encoded + * object identifier. Supported object identifiers are listed under @ref + * key_ecdsa_profile "ECDSA key profile". + */ + HAB_EC_SPEC_NAMED_CURVE = 0x01 +} hab_ec_spec_t; +#endif + +/** Variable configuration items + * @ingroup cmd_set + */ +typedef enum hab_var_cfg_itm { + HAB_VAR_CFG_ITM_MID = 0x01, /**< Manufacturing ID (MID) fuse locations */ + HAB_VAR_CFG_ITM_ENG = 0x03 /**< Preferred engine for a given algorithm */ +} hab_var_cfg_itm_t; + +/*=========================================================================== + ENUMS +=============================================================================*/ + +/*=========================================================================== + STRUCTURES AND OTHER TYPEDEFS +=============================================================================*/ + +/** Header field components + * @ingroup hdr + */ +typedef struct hab_hdr { + uint8_t tag; /**< Tag field */ + uint8_t len[2]; /**< Length field in bytes (big-endian) */ + uint8_t par; /**< Parameters field */ +} hab_hdr_t; + +/** Loader callback. + * @ingroup auth_img + * + * @par Purpose + * + * This function must be supplied by the library caller if required. It is + * intended to finalise image loading in those boot modes where only a portion + * of the image is loaded to a temporary initial location prior to device + * configuration. + * + * @par Operation + * + * This function is called during hab_rvt.authenticate_image() between running + * the @ref dcd and @ref csf. The operation of this function is defined by + * the caller. + * + * @param[in,out] start Initial (possibly partial) image load address on + * entry. Final image load address on exit. + * + * @param[in,out] bytes Initial (possibly partial) image size on entry. Final + * image size on exit. + * + * @param[in] boot_data Initial @ref ivt Boot Data load address. + * + * @remark The interpretation of the Boot Data is defined by the caller. + * Different boot components or modes may use different boot data, or even + * different loader callback functions. + * + * @warning It should not be assumed by this function that the Boot Data is + * valid or authentic. + * + * @warning It is the responsibility of the loader callback to check the final + * image load addresses using hab_rvt.check_target() prior to copying any image + * data. + * + * @pre The (possibly partial) image has been loaded in the initial load + * address, and the Boot Data is within the initial image. + * + * @pre The @ref dcd has been run, if provided. + * + * @post The final image load addresses pass hab_rvt.check_target(). + * + * @retval #HAB_SUCCESS if all operations completed successfully, + * + * @retval #HAB_FAILURE otherwise. + */ +typedef hab_status_t (*hab_loader_callback_f)( + void** start, + size_t* bytes, + const void* boot_data); + +/*---------------------------------------------------------------------------*/ + +/** Image entry function prototype + * @ingroup rvt + * + * This typedef serves as the return type for hab_rvt.authenticate_image(). It + * specifies a void-void function pointer, but can be cast to another function + * pointer type if required. + */ +typedef void (*hab_image_entry_f)(void); + +/*---------------------------------------------------------------------------*/ + +/** @ref rvt structure + * @ingroup rvt + * + * @par Format + * + * The @ref rvt consists of a @ref hdr followed by a list of addresses as + * described further below. + */ +struct hab_rvt { + + /** @ref hdr with tag #HAB_TAG_RVT, length and HAB version fields + * (see @ref data) + */ + hab_hdr_t hdr; + + /** Enter and initialise HAB library. + * @ingroup entry + * + * @par Purpose + * + * This function initialises the HAB library and @ref shw plugins. It is + * intended for use by post-ROM boot stage components, via the @ref rvt, + * prior to calling any other HAB functions other than + * hab_rvt.report_event() and hab_rvt.report_status(). + * + * @ifrom It is also intended for use by the boot ROM via hab_rvt.entry(). + * @endrom + * + * @par Operation + * + * This function performs the following operations every time it is called: + * + * - Initialise the HAB library internal state + * - Initialise the internal secret key store (cleared at the next + * hab_rvt.exit()) + * - Run the entry sequence of each available @ref shw plugin + * + * When first called from boot ROM, this function also performs the + * following operations prior to those given above: + * + * - Initialise the internal public key store (persists beyond + * hab_rvt.exit()) + * - Run the self-test sequence of each available @ref shw plugin + * - If a state machine is present and enabled, change the security state + * as follows: + * - If the IC is configured as #HAB_CFG_OPEN or #HAB_CFG_RETURN, move to + * #HAB_STATE_NONSECURE + * - If the IC is configured as #HAB_CFG_CLOSED, move to + * #HAB_STATE_TRUSTED + * - Otherwise, leave the security state unchanged + * + * If any failure occurs in the operations above: + * + * - An audit event is logged + * - All remaining operations are abandoned (except that all @ref shw + * self-test and entry sequences are still executed) + * - If a state machine is present and enabled, the security state is set + * as follows: + * - @ifrom Unless the IC is configured as #HAB_CFG_FAB,@endrom move to + * #HAB_STATE_NONSECURE. Note that if a security violation has been + * detected by the HW, the final state will be #HAB_STATE_FAIL_SOFT or + * #HAB_STATE_FAIL_HARD depending on the HW configuration. + * + * @warning Boot sequences may comprise several images with each launching + * the next as well as alternative images should one boot device or boot + * image be unavailable or unusable. The authentication of each image in + * a boot sequence must be bracketed by its own hab_rvt.entry() + * ... hab_rvt.exit() pair in order to ensure that security state + * information gathered for one image cannot be misapplied to another + * image. + * + * @ifrom + * + * @warning This applies to each boot path in boot ROM as well, except for + * the fabrication test path. + * + * @endrom + * + * @post HAB library internal state is initialised. + * + * @post Available @ref shw plugins are initialised. + * + * @post If a failure or warning occurs during @ref shw plugin + * initialisation, an audit event is logged with the relevant @ref eng + * tag. The status and reason logged are described in the relevant @ref + * shw plugin documentation. + * + * @post Security state is initialised, if a state machine is present and + * enabled. + * + * @retval #HAB_SUCCESS on an IC not configured as #HAB_CFG_CLOSED, + * although unsuccessful operations will still generate audit log events, + * + * @retval #HAB_SUCCESS on other ICs if all commands completed + * without failure (even if warnings were generated), + * + * @retval #HAB_FAILURE otherwise. + */ + hab_status_t (*entry)(void); + + /** Finalise and exit HAB library. + * @ingroup exit + * + * @par Purpose + * + * This function finalises the HAB library and @ref shw plugins. It is + * intended for use by post-ROM boot stage components, via the @ref rvt, + * after calling other HAB functions and prior to launching the next boot + * stage or switching to another boot path. + * + * @ifrom It is also intended for use by the boot ROM via hab_rvt.exit(). + * @endrom + * + * @par Operation + * + * This function performs the following operations: + * + * - Finalise the HAB library internal state + * - Clear the internal secret key store + * - Run the finalisation sequence of each available @ref shw plugin + * + * If any failure occurs, an audit event is logged and all remaining + * operations are abandoned (except that all @ref shw exit sequences are + * still executed). + * + * @warning See warnings for hab_rvt.entry(). + * + * @post #HAB_ASSERT_BLOCK records are cleared from audit log. Note that + * other event records are not cleared. + * + * @post Any public keys installed by @ref csf commands remain active. + * + * @post Any secret keys installed by @ref csf commands are deleted. + * + * @post Available @ref shw plugins are in their final state as described + * in the relevant sections. + * + * @post If a failure or warning occurs, an audit event is logged with the + * @ref eng tag of the @ref shw plugin concerned. The status and reason + * logged are described in the relevant @ref shw plugin documentation. + * + * @retval #HAB_SUCCESS on an IC not configured as #HAB_CFG_CLOSED, + * although unsuccessful operations will still generate audit log events, + * + * @retval #HAB_SUCCESS on other ICs if all commands completed + * without failure (even if warnings were generated), + * + * @retval #HAB_FAILURE otherwise. + */ + hab_status_t (*exit)(void); + + /** Check target address + * @ingroup chk_tgt + * + * @par Purpose + * + * This function reports whether or not a given target region is allowed + * for either peripheral configuration or image loading in memory. It is + * intended for use by post-ROM boot stage components, via the @ref rvt, + * in order to avoid configuring security-sensitive peripherals, or + * loading images over sensitive memory regions or outside recognised + * memory devices in the address map. + * + * @ifrom It is also available for use by the boot ROM, both directly via + * hab_rvt.check_target() and indirectly via hab_rvt.authenticate_image(). + * @endrom + * + * @par Operation + * + * The lists of allowed target regions vary by IC and core, and should be + * taken from the @ref ref_rug. + * + * @ifrom The allowed register sets for peripheral configuration and memory + * regions for image loading are defined in the @ref hal by + * #hab_hal_peripheral and #hab_hal_memory respectively. @endrom + * + * @param[in] type Type of target (memory, peripheral or any in which both + * the memory and peripheral regions are checked) + * + * @param[in] start Address of target region + * + * @param[in] bytes Size of target region + * + * @post if the given target region goes beyond the allowed regions, an + * audit event is logged with status #HAB_FAILURE and reason + * #HAB_INV_ADDRESS, together with the call parameters. See the @ref evt + * record documentation for details. + * + * @post For successful commands, no audit event is logged. + * + * @retval #HAB_SUCCESS on an IC not configured as #HAB_CFG_CLOSED, + * although unsuccessful operations will still generate audit log events, + * + * @retval #HAB_SUCCESS if the given target region lies wholly within the + * allowed regions for the requested type of target. + * + * @retval #HAB_FAILURE otherwise + */ + hab_status_t (*check_target)(hab_target_t type, + const void* start, + size_t bytes); + + /** Authenticate image. + * @ingroup auth_img + * + * @par Purpose + * + * This function combines DCD, CSF and Assert functions in a standard + * sequence in order to authenticate a loaded image. It is intended for + * use by post-ROM boot stage components, via the @ref rvt. Support for + * images partially loaded to an initial location is provided via a + * callback function. + * + * @ifrom It is also available for use by the boot ROM via + * hab_rvt.authenticate_image(). @endrom + * + * @par Operation + * + * This function performs the following sequence of operations: + * - Check that the initial image load addresses pass + * hab_rvt.check_target(). + * - Check that the IVT offset lies within the initial image bounds. + * - Check that the @ref ivt @a self and @a entry pointers are not NULL + * - Check the @ref ivt header for consistency and compatability. + * - If provided in the @ref ivt, calculate the @ref dcd initial location, + * check that it lies within the initial image bounds, and run the @ref + * dcd commands. + * - If provided in the @ref ivt, calculate the Boot Data initial location + * and check that it lies within the initial image bounds. + * - If provided in the parameters, invoke the callback function with the + * initial image bounds and initial location of the @ref ivt Boot Data. + * + * From this point on, the full image is assumed to be in its final + * location. The following operations will be performed on all IC + * configurations (#hab_config), but will be only enforced on an IC + * configured as #HAB_CFG_CLOSED: + * - Check that the final image load addresses pass hab_rvt.check_target(). + * - Check that the CSF lies within the image bounds, and run the CSF + * commands. + * - Check that all of the following data have been authenticated (using + * their final locations): + * - IVT; + * - DCD (if provided); + * - Boot Data (initial byte if provided); + * - Entry point (initial word). + * + * @param[in] cid Caller ID, used to identify which SW issued this call. + * + * @param[in] ivt_offset Offset in bytes of the IVT from the image start + * address. + * + * @param[in,out] start Initial (possibly partial) image load address on + * entry. Final image load address on exit. + * + * @param[in,out] bytes Initial (possibly partial) image size on entry. + * Final image size on exit. + * + * @param[in] loader Callback function to load the full image to its final + * load address. Set to NULL if not required. + * + * @remark Caller ID may be bound to signatures verified using keys + * installed with #HAB_CMD_INS_KEY_CID flag. See @ref cmd_ins_key and @ref + * bnd_obj for details. + * + * @remark A @a loader callback function may be supplied even if the image + * is already loaded to its final location on entry. + * + * @remark Boot Data (boot_data in @ref ivt) will be ignored if the + * @a loader callback function point is set to Null. + * + * @warning The @a loader callback function should lie within existing + * authenticated areas. @ifrom Or within the ROM. @endrom + * + * @warning It is the responsibility of the caller to check the initial + * image load addresses using hab_rvt.check_target() prior to loading the + * initial image and calling this function. + * + * @warning After completion of hab_rvt.authenticate_image(), the caller + * should test using hab_rvt.assert() that the Boot Data was + * authenticated. + * + * @post The post-conditions of the functions hab_rvt.check_target(), + * hab_rvt.run_dcd(), hab_rvt.run_csf() and hab_rvt.assert() apply also to + * this function. In particular, any audit events logged within the given + * functions have the context field appropriate to that function rather + * than #HAB_CTX_AUTHENTICATE. In addition, the side-effects and + * post-conditions of any callback function supplied apply. + * + * @post If a failure or warning occurs outside these contexts, an audit + * event is logged with status: + * - #HAB_FAILURE, with further reasons: + * - #HAB_INV_ADDRESS: initial or final image addresses outside allowed + * regions + * - #HAB_INV_ADDRESS: IVT, DCD, Boot Data or CSF outside image bounds + * - #HAB_INV_ADDRESS: IVT @a self or @a entry pointer is NULL + * - #HAB_INV_CALL: hab_rvt.entry() not run successfully prior to call + * - #HAB_INV_IVT: IVT malformed + * - #HAB_INV_IVT: IVT version number is less than HAB library version + * - #HAB_INV_RETURN: Callback function failed + * + * @retval entry field from @ref ivt on an IC not configured as + * #HAB_CFG_CLOSED provided that the following conditions are met + * (other unsuccessful operations will generate audit log events): + * - the @a start pointer and the pointer it locates are not NULL + * - the initial @ref ivt location is not NULL + * - the @ref ivt @ref hdr (given in the @a hdr field) is valid + * - the final @ref ivt location (given by the @a self field) is not NULL + * - any loader callback completed successfully, + * + * @retval entry field from @ref ivt on other ICs if all operations + * completed without failure (even if warnings were generated), + * + * @retval NULL otherwise. + */ + hab_image_entry_f (*authenticate_image)(uint8_t cid, + ptrdiff_t ivt_offset, + void** start, + size_t* bytes, + hab_loader_callback_f loader); + + /** Execute a boot configuration script. + * @ingroup run_dcd + * + * @par Purpose + * + * This function configures the IC based upon a @ref dcd table. It is + * intended for use by post-ROM boot stage components, via the @ref rvt. + * This function may be invoked as often as required for each boot stage. + * + * @ifrom It is also intended for use by the boot ROM, both directly via + * hab_rvt.run_dcd() and indirectly via hab_rvt.authenticate_image(). + * @endrom + * + * The difference between the configuration functionality in this function + * and hab_rvt.run_csf() arises because the @ref dcd table is not + * authenticated prior to running the commands. Hence, there is a more + * limited range of commands allowed, and a limited range of parameters to + * allowed commands. + * + * @par Operation + * + * This function performs the following operations: + * - Checks the @ref hdr for compatibility and consistency + * - Makes an internal copy of the @ref dcd table + * - Executes the commands in sequence from the internal copy of the @ref + * dcd + * + * If any failure occurs, an audit event is logged and all remaining + * operations are abandoned. + * + * @param[in] dcd Address of the @ref dcd. + * + * @warning It is the responsibility of the caller to ensure that the @a + * dcd parameter points to a valid memory location. + * + * @warning The @ref dcd must be authenticated by a subsequent @ref csf + * command prior to launching the next boot image, in order to avoid + * unauthorised configurations which may subvert secure operation. + * Although the content of the next boot stage's CSF may be out of scope + * for the hab_rvt.run_dcd() caller, it is possible to enforce this + * constraint by using hab_rvt.assert() to ensure that both the DCD and + * any pointers used to locate it have been authenticated. + * + * @warning Each invocation of hab_rvt.run_dcd() must occur between a pair + * of hab_rvt.entry() and hab_rvt.exit() calls, although multiple + * hab_rvt.run_dcd() calls (and other HAB calls) may be made in one + * bracket. This constraint applies whether hab_rvt.run_dcd() is + * successful or not: a subsequent call to hab_rvt.exit() is required + * prior to launching the authenticated image or switching to another boot + * target. + * + * @post Many commands may cause side-effects. See the @ref dcd + * documentation. + * + * @post If a failure or warning occurs within a command handler, an audit + * event is logged with the offending command, copied from the DCD. The + * status and reason logged are described in the relevant command + * documentation. + * + * @post For other failures or warning, the status logged is: + * - #HAB_WARNING, with further reasons: + * - #HAB_UNS_COMMAND: unsupported command encountered, where DCD + * version and HAB library version differ + * - #HAB_FAILURE, with further reasons: + * - #HAB_INV_ADDRESS: NULL @a dcd parameter + * - #HAB_INV_CALL: hab_rvt.entry() not run successfully prior to call + * - #HAB_INV_COMMAND: command not allowed in DCD + * - #HAB_UNS_COMMAND: unrecognised command encountered, where DCD + * version and HAB library version match + * - #HAB_INV_DCD: DCD malformed or too large + * - #HAB_INV_DCD: DCD version number is less than HAB library version + * @retval #HAB_SUCCESS on an IC not configured as #HAB_CFG_CLOSED, + * although unsuccessful operations will still generate audit log events, + * + * @retval #HAB_SUCCESS on other ICs if all commands completed + * without failure (even if warnings were generated), + * + * @retval #HAB_FAILURE otherwise. + */ + hab_status_t (*run_dcd)(const uint8_t* dcd); + + /** Execute an authentication script. + * @ingroup run_csf + * + * @par Purpose + * + * This function authenticates SW images and configures the IC based upon + * a @ref csf. It is intended for use by post-ROM boot stage components, + * via the @ref rvt. This function may be invoked as often as required + * for each boot stage. + * + * @ifrom It is also available for use by the boot ROM via hab_rvt.run_csf, + * although it is anticipated that the boot ROM will mostly call this + * function indirectly via hab_rvt.authenticate_image(). @endrom + * + * @par Operation + * + * This function performs the following operations: + * - Checks the @ref hdr for compatibility and consistency + * - Makes an internal copy of the @ref csf + * - Executes the commands in sequence from the internal copy of the @ref + * csf + * + * The internal copy of the @ref csf is authenticated by an explicit + * command in the sequence. Prior to authentication, a limited set of + * commands is available to: + * - Install a Super-Root key (unless previously installed) + * - Install a CSF key (unless previously installed) + * - Specify any variable configuration items + * - Authenticate the CSF + * + * Subsequent to CSF authentication, the full set of commands is available. + * + * If any failure occurs, an audit event is logged and all remaining + * operations are abandoned. + * + * @param[in] csf Address of the @ref csf. + * + * @param[in] cid Caller ID, used to identify which SW issued this call. + * + * @remark Caller ID may be bound to signatures verified using keys + * installed with #HAB_CMD_INS_KEY_CID flag. See @ref cmd_ins_key and @ref + * bnd_obj for details. + * + * @warning It is the responsibility of the caller to ensure that the @a + * csf parameter points to a valid memory location. + * + * @warning Each invocation of hab_rvt.run_csf() must occur between a pair + * of hab_rvt.entry() and hab_rvt.exit() calls, although multiple + * hab_rvt.run_csf() calls (and other HAB calls) may be made in one + * bracket. This constraint applies whether hab_rvt.run_csf() is + * successful or not: a subsequent call to hab_rvt.exit() is required + * prior to launching the authenticated image or switching to another boot + * target. + * + * @post Many commands may cause side-effects. See the @ref csf + * documentation. In particular, note that keys installed by the @ref csf + * remain available for use in subsequent operations. + * + * @post If a failure or warning occurs within a command handler, an audit + * event is logged with the offending command, copied from the CSF. The + * status and reason logged are described in the relevant command + * documentation. + * + * @post For other failures or warning, the status logged is: + * - #HAB_WARNING, with further reasons: + * - #HAB_UNS_COMMAND: unsupported command encountered, where CSF + * version and HAB library version differ + * - #HAB_FAILURE, with further reasons: + * - #HAB_INV_ADDRESS: NULL @a csf parameter + * - #HAB_INV_CALL: hab_rvt.entry() not run successfully prior to call + * - #HAB_INV_COMMAND: command not allowed prior to CSF authentication + * - #HAB_UNS_COMMAND: unrecognised command encountered, where CSF + * version and HAB library version match + * - #HAB_INV_CSF: CSF not authenticated + * - #HAB_INV_CSF: CSF malformed or too large + * - #HAB_INV_CSF: CSF version number is less than HAB library version + * + * @retval #HAB_SUCCESS on an IC not configured as #HAB_CFG_CLOSED, + * although unsuccessful operations will still generate audit log events, + * + * @retval #HAB_SUCCESS on other ICs if all commands completed + * without failure (even if warnings were generated), + * + * @retval #HAB_FAILURE otherwise. + */ + hab_status_t (*run_csf)(const uint8_t* csf, + uint8_t cid); + + /** Test an assertion against the audit log. + * @ingroup assert + * + * @par Purpose + * + * This function allows the audit log to be interrogated. It is intended + * for use by post-ROM boot stage components, via the @ref rvt, to + * determine the state of authentication operations. This function may be + * invoked as often as required for each boot stage. + * + * @ifrom It is also available for use by the boot ROM, both directly via + * hab_rvt.assert() and indirectly via hab_rvt.authenticate_image(). + * @endrom + * + * @par Operation + * + * This function checks the required assertion as detailed below. + * + * @param[in] type Assertion type. + * + * @param[in] data Assertion data. + * + * @param[in] count Data size or count. + * + * @par Memory block authentication: + * For #HAB_ASSERT_BLOCK assertion type, hab_rvt.assert() checks that the + * given memory block has been authenticated after running a CSF. The + * parameters are interpreted as follows: + * + * @par + * - @a data: memory block starting address + * - @a count: memory block size (in bytes) + * + * @par + * + * A simple interpretation of "memory block has been authenticated" is + * taken, such that the given block must lie wholly within a single + * contiguous block authenticated while running a CSF. A given memory + * block covered by the union of several neighboring or overlapping + * authenticated blocks could fail the test with this interpretation, but + * it is assumed that such cases will not arise in practice. + * + * @post If the assertion fails, an audit event is logged with status + * #HAB_FAILURE and reason #HAB_INV_ASSERTION, together with the call + * parameters. See the @ref evt record documentation for details. + * + * @post For successful commands, no audit event is logged. + * + * @retval #HAB_SUCCESS on an IC not configured as #HAB_CFG_CLOSED, + * although unsuccessful operations will still generate audit log events, + * + * @retval #HAB_SUCCESS on other ICs if the assertion is confirmed + * + * @retval #HAB_FAILURE otherwise + */ + hab_status_t (*assert)(hab_assertion_t type, + const void* data, + uint32_t count); + + /** Report an event from the audit log. + * @ingroup event + * + * @par Purpose + * + * This function allows the audit log to be interrogated. It is intended + * for use by post-ROM boot stage components, via the @ref rvt, to + * determine the state of authentication operations. This function may + * be called outside an hab_rvt.entry() / hab_rvt.exit() pair. + * + * @ifrom It is also available for use by the boot ROM, where it may be + * used to report boot failures as part of a tethered boot + * protocol. @endrom + * + * @par Operation + * + * This function performs the following operations: + * - Scans the audit log for a matching event + * - Copies the required details to the output parameters (if found) + * + * @param[in] status Status level of required event. + * + * @param[in] index Index of required event at given status level. + * + * @param[out] event @ref evt record. + * + * @param[in,out] bytes Size of @a event buffer on entry, size of event + * record on exit. + * + * @remark Use @a status = #HAB_STS_ANY to match any logged event, + * regardless of the status value logged. + * + * @remark Use @a index = 0 to return the first matching event, @a index = + * 1 to return the second matching event, and so on. + * + * @remark The data logged with each event is context-dependent. Refer to + * @ref evt record documentation. + * + * @warning Parameter @a bytes may not be NULL. + * + * @warning If the @a event buffer is a NULL pointer or too small to fit + * the event record, the required size is written to @a bytes, but no + * part of the event record is copied to the output buffer. + * + * @retval #HAB_SUCCESS if the required event is found, and the event + * record is copied to the output buffer. + * + * @retval #HAB_SUCCESS if the required event is found and @a event buffer + * passed is a NULL pointer. + * + * @retval #HAB_FAILURE otherwise + */ + hab_status_t (*report_event)(hab_status_t status, + uint32_t index, + uint8_t* event, + size_t* bytes); + + /** Report security status. + * @ingroup status + * + * @par Purpose + * + * This function reports the security configuration and state of the IC as + * well as searching the audit log to determine the status of the boot + * process. It is intended for use by post-ROM boot stage components, via + * the @ref rvt. This function may be called outside an + * hab_rvt.entry() / hab_rvt.exit() pair. + * + * @ifrom It is also available for use by the boot ROM, and should be used + * rather than the HAL function hab_hal_read_sec_cfg(). @endrom + * + * @par Operation + * + * This function reads the fuses which indicate the security + * configuration. The fusemap varies by IC, and should be taken from the + * @ref ref_rug. It also uses the @ref shw state machine, if present and + * enabled, to report on the security state. + * + * @param[out] config Security configuration, NULL if not required + * + * @param[out] state Security state, NULL if not required + * + * @remark If no @ref shw state machine is present and enabled, the state + * #HAB_STATE_NONE will be output. + * + * @retval #HAB_SUCCESS if no warning or failure audit events have been + * logged. + * + * @retval #HAB_WARNING otherwise, if only warning events have been logged. + * + * @retval #HAB_FAILURE otherwise + */ + hab_status_t (*report_status)(hab_config_t* config, hab_state_t* state); + + /** Enter failsafe boot mode. + * @ingroup safe + * + * @par Purpose + * + * This function provides a safe path when image authentication has failed + * and all possible boot paths have been exhausted. It is intended for + * use by post-ROM boot stage components, via the @ref rvt. + * + * @ifrom It is also available for use by the boot ROM via + * hab_rvt.failsafe(). @endrom + * + * @par Operation + * + * The precise details of this function vary by IC and core, and should be + * taken from @ref ref_rug. + * + * @warning This function does not return. + * + * @remark Since this function does not return, it implicitly performs the + * functionality of hab_rvt.exit() in order to ensure an appropriate + * configuration of the @ref shw plugins. + * + * @remark Two typical implementations are: + * - a low-level provisioning protocol in which an image is downloaded to + * RAM from an external host, authenticated and launched. The downloaded + * image may communicate with tools on the external host to report the + * reasons for boot failure, and may re-provision the end-product with + * authentic boot images. + * - a failsafe boot mode which does not allow execution to leave the ROM + * until the IC is reset. + */ + void (*failsafe)(void); +}; + +/** @ref rvt type + * @ingroup rvt + */ +typedef struct hab_rvt hab_rvt_t; + +/*---------------------------------------------------------------------------*/ + +/** @ref ivt structure + * @ingroup ivt + * + * @par Format + * + * An @ref ivt consists of a @ref hdr followed by a list of addresses as + * described further below. + * + * @warning The @a entry address may not be NULL. + * + * @warning On an IC not configured as #HAB_CFG_CLOSED, the + * @a csf address may be NULL. If it is not NULL, the @ref csf will be + * processed, but any failures should be non-fatal. + * + * @warning On an IC configured as #HAB_CFG_CLOSED, the @a + * csf address may not be NULL, and @ref csf failures are typically fatal. + * + * @remark The Boot Data located using the @a boot_data field is interpreted + * by the HAB caller in a boot-mode specific manner. This may be used by the + * boot ROM as to determine the load address and boot device configuration for + * images loaded from block devices (see @ref ref_rug for details). + * + * @remark All addresses given in the IVT, including the Boot Data (if + * present) are those for the final load location. + * + * @anchor ila + * + * @par Initial load addresses + * + * The @a self field is used to calculate addresses in boot modes where an + * initial portion of the image is loaded to an initial location. In such + * cases, the IVT, Boot Data (if present) and DCD (if present) are used in + * configuring the IC and loading the full image to its final location. Only + * the IVT, Boot Data (if present) and DCD (if present) are required to be + * within the initial image portion. + * + * The method for calculating an initial load address for the DCD is + * illustrated in the following C fragment. Similar calculations apply to + * other fields. + * +@verbatim + hab_ivt_t* ivt_initial = ; + const void* dcd_initial = ivt_initial->dcd; + if (ivt_initial->dcd != NULL) + dcd_initial = (const uint8_t*)ivt_initial + + (ivt_initial->dcd - ivt_initial->self) +@endverbatim + */ +struct hab_ivt { + /** @ref hdr with tag #HAB_TAG_IVT, length and HAB version fields + * (see @ref data) + */ + hab_hdr_t hdr; + /** Absolute address of the first instruction to execute from the + * image + */ + hab_image_entry_f entry; + /** Reserved in this version of HAB: should be NULL. */ + const void* reserved1; + /** Absolute address of the image DCD: may be NULL. */ + const void* dcd; + /** Absolute address of the Boot Data: may be NULL, but not interpreted + * any further by HAB + */ + const void* boot_data; + /** Absolute address of the IVT.*/ + const void* self; + /** Absolute address of the image CSF.*/ + const void* csf; + /** Reserved in this version of HAB: should be zero. */ + uint32_t reserved2; +}; + +/** @ref ivt type + * @ingroup ivt + */ +typedef struct hab_ivt hab_ivt_t; + +/*=========================================================================== + FUNCTION PROTOTYPES +=============================================================================*/ +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* HAB_DEFINES_H */ diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/include/hab_defines.h b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/include/hab_defines.h new file mode 100755 index 000000000..1fcf5d544 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/include/hab_defines.h @@ -0,0 +1,2222 @@ +/* + * Copyright (c) 2008-2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*! + * @file hab_defines.h + * @brief defines for data structures and macros used for enabling secure boot + * + * @ingroup diag_init + */ +#ifndef HAB_DEFINES_H +#define HAB_DEFINES_H +/*=========================================================================== + INCLUDE FILES +=============================================================================*/ +#include /* for integer types */ +#include /* for bool type */ +#include /* for NULL and offsetof() */ +/*=========================================================================== + CONSTANTS +=============================================================================*/ +/** @addtogroup struct + * @{ + */ + +#define HDR_BYTES 4 /* cannot use sizeof(hab_hdr_t) in preprocessor */ + +/** @name External data structure tags + * @anchor dat_tag + * + * Tag values 0x00 .. 0xef are reserved for HAB. Values 0xf0 .. 0xff + * are available for custom use. + */ +/*@{*/ +#define HAB_TAG_IVT 0xd1 /**< Image Vector Table */ +#define HAB_TAG_DCD 0xd2 /**< Device Configuration Data */ +#define HAB_TAG_CSF 0xd4 /**< Command Sequence File */ +#define HAB_TAG_CRT 0xd7 /**< Certificate */ +#define HAB_TAG_SIG 0xd8 /**< Signature */ +#define HAB_TAG_EVT 0xdb /**< Event */ +#define HAB_TAG_RVT 0xdd /**< ROM Vector Table */ +#define HAB_TAG_WRP 0x81 /**< Wrapped Key */ +#define HAB_TAG_MAC 0xac /**< Message Authentication Code */ +/* Values 00 ... 7e reserved for internal use. Values b0 ... cf reserved for + * CSF commands. Values e0 ... ef reserved for key types. + * + * Available values: 82, 84, 87, 88, 8b, 8d, 8e, 90, 93, 95, 96, 99, 9a, + * 9c, 9f, a0, a3, a5, a6, a9, aa, af + * + * Custom values: f0, f3, f5, f6, f9, fa, fc, ff + */ +/*@}*/ + +/** @name HAB version */ +/*@{*/ +#define HAB_MAJOR_VERSION 4 /**< Major version of this HAB release */ +#define HAB_MINOR_VERSION 1 /**< Minor version of this HAB release */ +#define HAB_VER_MAJ_WIDTH 4 /**< Major version field width */ +#define HAB_VER_MAJ_SHIFT 4 /**< Major version field offset */ +#define HAB_VER_MIN_WIDTH 4 /**< Minor version field width */ +#define HAB_VER_MIN_SHIFT 0 /**< Minor version field offset */ +/** Full version of this HAB release @hideinitializer */ +#define HAB_VERSION HAB_VER(HAB_MAJOR_VERSION, HAB_MINOR_VERSION) +/** Base version for this HAB release @hideinitializer */ +#define HAB_BASE_VERSION HAB_VER(HAB_MAJOR_VERSION, 0) + +/*@}*/ + +/* @} struct */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup cmd + * @{ + */ + +/** @name Command tags + * @anchor cmd_tag + * + * Tag values 0xb0 .. 0xcf are reserved for HAB. Values 0xf0 .. 0xff + * are available for custom use. + */ +/*@{*/ +#define HAB_CMD_SET 0xb1 /**< Set */ +#define HAB_CMD_INS_KEY 0xbe /**< Install Key */ +#define HAB_CMD_AUT_DAT 0xca /**< Authenticate Data */ +#define HAB_CMD_WRT_DAT 0xcc /**< Write Data */ +#define HAB_CMD_CHK_DAT 0xcf /**< Check Data */ +#define HAB_CMD_NOP 0xc0 /**< No Operation */ +#define HAB_CMD_INIT 0xb4 /**< Initialise */ +#define HAB_CMD_UNLK 0xb2 /**< Unlock */ +#ifdef HAB_FUTURE +#define HAB_CMD_RMV_KEY /**< Remove Key */ +#define HAB_CMD_INS_REF /**< Install Reference Data */ +#define HAB_CMD_INS_PLG /**< Install Plugin */ +#define HAB_CMD_RMV_PLG /**< Remove Plugin */ +#define HAB_CMD_CHK_VER /**< Check SW Version */ +#endif +/* Remaining values: b7, b8, bb, bd, c3, c5, c6, c9 */ +/*@}*/ + +/* @} cmd */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup pcl + * @{ + */ + +/** @name Protocol tags + * @anchor pcl_tag + * + * Tag values 0x00 .. 0xef are reserved for HAB. Values 0xf0 .. 0xff are + * available for custom use. + */ +/*@{*/ +#define HAB_PCL_SRK 0x03 /**< SRK certificate format */ +#define HAB_PCL_X509 0x09 /**< X.509v3 certificate format */ +#define HAB_PCL_CMS 0xc5 /**< CMS/PKCS#7 signature format */ +#define HAB_PCL_BLOB 0xbb /**< SHW-specific wrapped key format */ +#define HAB_PCL_AEAD 0xa3 /**< Proprietary AEAD MAC format */ +#ifdef HAB_FUTURE +#define HAB_PCL_WTLS 0x05 /**< OMA WTLS certificate format */ +#define HAB_PCL_FSL 0x0f /**< FSL bound signature protocol */ +#define HAB_PCL_HMAC 0x30 /**< NIST HMAC message authentication */ +#define HAB_PCL_CBCMAC 0x33 /**< CBC-MAC message authentication */ +#endif +/*@}*/ + +/* Available values: 06, 0a, 0c, 11, 12, 14, 17, 18, 1b, 1d, 1e, 21, 22, 24, + * 27, 28, 2b, 2d, 2e, 35, 36, 39, 3a, 3c, 3f, 41, 42, 44, 47, 48, 4b, 4d, 4e, + * 50, 53, 55, 56, 59, 5a, 5c, 5f, 60, 63, 65, 66, 69, 6a, 6c, 6f, 71, 72, 74, + * 77, 78, 7b, 7d, 7e, 81, 82, 84, 87, 88, 8b, 8d, 8e, 90, 93, 95, 96, 99, 9a, + * 9c, 9f, a0, a5, a6, a9, aa, ac, af, b1, b2, b4, b7, b8, bd, be, c0, c3, c6, + * c9, ca, cc, cf, d1, d2, d4, d7, d8, db, dd, de, e1, e2, e4, e7, e8, eb, ed, + * ee + * + * Custom values: f0, f3, f5, f6, f9, fa, fc, ff + */ + +/* @} pcl */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup alg + * @{ + */ + +/** @name Algorithm types + * @anchor alg_typ + * + * The most-significant nibble of an algorithm ID denotes the algorithm + * type. Algorithms of the same type share the same interface. + * + * Types 0x0 .. 0xc are reserved for HAB. Types 0xd .. 0xf are available for + * custom use. Within each reserved type N in 0 .. c, tag values 0xN0 .. 0xNc + * are reserved for HAB. Values 0xNd .. 0xNf are available for custom use. + */ +/*@{*/ +#define HAB_ALG_ANY 0x0 /**< Algorithm type ANY */ +#define HAB_ALG_HASH 0x1 /**< Hash algorithm type */ +#define HAB_ALG_SIG 0x2 /**< Signature algorithm type */ +#define HAB_ALG_FF 0x3 /**< Finite field arithmetic */ +#define HAB_ALG_EC 0x4 /**< Elliptic curve arithmetic */ +#define HAB_ALG_CIPHER 0x5 /**< Cipher algorithm type */ +#define HAB_ALG_MODE 0x6 /**< Cipher/hash modes */ +#define HAB_ALG_WRAP 0x7 /**< Key wrap algorithm type */ +/*@}*/ + +/** @name Algorithm type ANY + * + * Algorithms of type ANY have no common interface: the protocol must know + * what to do. + */ +/*@{*/ +#ifdef HAB_FUTURE +#define HAB_ALG_RANDOM /**< Random number generation */ +#endif +/* Available values: 03, 05, 06, 09, 0a, 0c, 0f + */ +/*@}*/ + +/** @name Hash algorithms */ +/*@{*/ +#define HAB_ALG_SHA1 0x11 /**< SHA-1 algorithm ID */ +#define HAB_ALG_SHA256 0x17 /**< SHA-256 algorithm ID */ +#define HAB_ALG_SHA512 0x1b /**< SHA-512 algorithm ID */ +/* Available values: 0x14, 0x12, 18, 1d, 1e + */ +/*@}*/ + +/** @name Signature algorithms */ +/*@{*/ +#define HAB_ALG_PKCS1 0x21 /**< PKCS#1 RSA signature algorithm */ +#ifdef HAB_FUTURE +#define HAB_ALG_DSA /**< NIST DSA signature algorithm */ +#define HAB_ALG_ECDSA /**< NIST ECDSA signature algorithm */ +#endif +/* Available values: 22, 24, 27, 28, 2b, 2d, 2e + */ +/*@}*/ + +/** @name Cipher algorithms */ +/*@{*/ +#define HAB_ALG_AES 0x55 /**< AES algorithm ID */ +/* Available values: 50, 53, 56, 59, 5a, 5c, 5f + */ +/*@}*/ + +/** @name Cipher or hash modes */ +/*@{*/ +#define HAB_MODE_CCM 0x66 /**< Counter with CBC-MAC */ +#ifdef HAB_FUTURE +#define HAB_MODE_HMAC /**< HMAC hash mode */ +#endif +/* Available values: 60, 63, 65, 69, 6a, 6c, 6f + */ +/*@}*/ + +/** @name Key wrap algorithms */ +/*@{*/ +#define HAB_ALG_BLOB 0x71 /**< SHW-specific key wrap */ +/* Available values: 72, 74, 77, 78, 7b, 7d, 7e + */ +/*@}*/ + +/* Available values: 81, 82, 84, 87, 88, 8b, 8d, 8e, 90, 93, 95, 96, 99, 9a, + * 9c, 9f, a0, a3, a5, a6, a9, aa, ac, af, b1, b2, b4, b7, b8, bb, bd, be, c0, + * c3, c5, c6, c9, ca, cc, cf, d1, d2, d4, d7, d8, db, dd, de, e1, e2, e4, e7, + * e8, eb, ed, ee, f0, f3, f5, f6, f9, fa, fc, ff + */ + +/* @} alg */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup eng + * @{ + */ + +/** @name Engine plugin tags + * @anchor eng_tag + * + * Tag values 0x00 .. 0xef and 0xff are reserved for HAB. Values 0xf0 .. 0xfe + * are available for custom use. + */ +/*@{*/ +#define HAB_ENG_ANY 0x00 /**< First compatible engine will be + * selected automatically (no engine + * configuration parameters are allowed). + */ +#define HAB_ENG_SCC 0x03 /**< Security controller */ +#define HAB_ENG_RTIC 0x05 /**< Run-time integrity checker */ +#define HAB_ENG_SAHARA 0x06 /**< Crypto accelerator */ +#define HAB_ENG_CSU 0x0a /**< Central Security Unit */ +#define HAB_ENG_SRTC 0x0c /**< Secure clock */ +#ifdef HAB_FUTURE +#define HAB_ENG_RNG 0x09 /**< Standalone random number generator */ +#define HAB_ENG_SJC 0x0f /**< Secure JTAG controller */ +#define HAB_ENG_WDOG 0x11 /**< Watchdog timer */ +#define HAB_ENG_SRC 0x12 /**< System Reset Controller */ +#define HAB_ENG_SPBA 0x14 /**< Shared Peripheral Bus Arbiter */ +#define HAB_ENG_IIM 0x17 /**< Fuse controller */ +#define HAB_ENG_IOMUX 0x18 /**< IO multiplexer */ +#endif +#define HAB_ENG_DCP 0x1b /**< Data Co-Processor */ +#define HAB_ENG_CAAM 0x1d /**< Cryptographic Acceleration and + Assurance Module */ +#define HAB_ENG_SNVS 0x1e /**< Secure Non-Volatile Storage */ +#define HAB_ENG_OCOTP 0x21 /**< Fuse controller */ +/** @cond rom */ +#define HAB_ENG_DTCP 0x22 /**< DTCP co-processor */ +#define HAB_ENG_ROM 0x36 /**< Protected ROM area */ +#define HAB_ENG_HDCP 0x24 /**< HDCP co-processor */ +#define HAB_ENG_RTL 0x77 /**< @rom RTL simulation engine */ +/** @endcond */ +#define HAB_ENG_SW 0xff /**< Software engine */ +/* Available values: 27, 28, 2b, 2d, 2e, 30, 33, 35, + * 39, 3a, 3c, 3f, 41, 42, 44, 47, 48, 4b, 4d, 4e, 50, 53, 55, 56, 59, 5a, + * 5c, 5f, 60, 63, 65, 66, 69, 6a, 6c, 6f, 71, 72, 74, 78, 7b, 7d, 7e, 81, + * 82, 84, 87, 88, 8b, 8d, 8e, 90, 93, 95, 96, 99, 9a, 9c, 9f, a0, a3, a5, a6, + * a9, aa, ac, af, b1, b2, b4, b7, b8, bb, bd, be, c0, c3, c5, c6, c9, ca, cc, + * cf, d1, d2, d4, d7, d8, db, dd, de, e1, e2, e4, e7, e8, eb, ed, ee + * + * Custom values: f0, f3, f5, f6, f9, fa, fc + */ +/*@}*/ + +/* @} eng */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup sah + * @{ + */ + +/** Maximum data blocks in a single hash */ +#define HAB_SAHARA_BLOCK_MAX 12 + +/** @cond rom */ +/** @rom DMA storage requirement + * + * This figure is derived in several parts: + * - each hash operation needs a 6-word descriptor structure + * - each data block needs a 3-word link structure + * - the result needs a 3-word link structure + * - at least 40 bytes are required for SHA-256 result and memory manager + * overhead: 64 bytes allows some small overhead. + */ +#define HAB_SAHARA_DMA_MIN_BYTES (24 + HAB_SAHARA_BLOCK_MAX * 12 + 12 + 64) +/** @endcond */ + +/* @} sah */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup dcp + * @{ + */ + +/** Maximum data blocks in a single hash */ +#define HAB_DCP_BLOCK_MAX 6 + +/** @cond rom */ +/** @rom DMA storage requirement + * + * This figure is derived in two parts: + * - each data block needs an 8-word work packet (descriptor) + * - at least 40 bytes are required for SHA-256 result and memory manager + * overhead: 64 bytes allows some small overhead. + */ +#define HAB_DCP_DMA_MIN_BYTES (64 + HAB_DCP_BLOCK_MAX * 32) +/** @endcond */ + +/* @} dcp */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup rtic + * @{ + */ + +/** Maximum data blocks in a single hash */ +#define HAB_RTIC_BLOCK_MAX 2 + +/* @} rtic */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup scc + * @{ + */ + +/** @cond rom */ +/** @rom DMA storage requirement + * + * This figure is derived in several stages, and assumes plaintext and + * ciphertext buffers are both allocated in the DMA region : + * - 4 blocks of plaintext required + * - 4 blocks of ciphertext required + * - each block is 16 bytes long + * - the plaintext address must be block-aligned (up to 15 bytes overhead) + * - the ciphertext address must be block-aligned (up to 3 bytes overhead) + * - at least 8 bytes of memory manager overhead: allow 32 for comfort + */ +#define HAB_SCC_DMA_MIN_BYTES ( (4+4)*16 + 15 + 3 + 32) +/** @endcond */ + +/* @} scc */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup caam + * @{ + */ + +/** Maximum data blocks in an @ref cmd_aut_dat command */ +#define HAB_CAAM_BLOCK_MAX 8 + +/** @cond rom */ +/** @rom Hash DMA storage requirement + * + * This figure is derived in several parts: + * - each hash operation needs + * - a 7-word descriptor, and + * - a 32-byte result buffer (for SHA-256), + * - giving a base requirement of (7*4 + 32) = 60 bytes + * - each data block needs a 4-word link structure + * - memory manager overhead is at least 8 bytes: 16 bytes allows flexibility + */ +#define HAB_CAAM_HSH_DMA_MIN_BYTES (60 + HAB_CAAM_BLOCK_MAX * 16 + 16) + +/** @rom AEAD DMA storage requirement + * + * This figure is derived in several parts: + * - each AEAD operation needs + * - a 16-word descriptor, + * - a 32-byte initial context value (B0 and CTR0), and + * - a 16-byte MAC value, + * - giving a base requirement of (16*4 + 32 + 16) = 112 bytes + * - each data block needs a 4-word link structure + * - memory manager overhead is at least 8 bytes: 16 bytes allows flexibility + */ +#define HAB_CAAM_CCM_DMA_MIN_BYTES (112 + HAB_CAAM_BLOCK_MAX * 16 + 16) + +/** @rom RNG DMA storage requirement + * + * This figure is derived in several parts: + * - each DRNG test operation allocates a DMA area with + * - a 1-word header, and + * - a 3-word job ring area, and + * - a 54-word descriptor, + * - requiring a total 58*4 = 232 bytes + * - each DRNG test operation also allocates a DMA area with + * - a 1-word header, and + * - a 32-byte result buffer + * - requiring a total 4 + 32 = 36 bytes + */ +#define HAB_CAAM_RNG_DMA_MIN_BYTES (232 + 32) +/** @endcond */ + +/* @} caam */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup key + * @{ + */ + +/** @name Key types + * @anchor key_types + * + * Tag values 0xe0 .. 0xef are reserved for HAB. Values 0xf0 .. 0xff + * are available for custom use. + */ +/*@{*/ +#define HAB_KEY_PUBLIC 0xe1 /**< Public key type: data present */ +#define HAB_KEY_SECRET 0xe2 /**< Secret key type: data present */ +#define HAB_KEY_MASTER 0xed /**< Master KEK type */ +#define HAB_KEY_HASH 0xee /**< Any key type: hash only */ +/* Available values: e4, e7, e8, eb + * + * Custom values: f0, f3, f5, f6, f9, fa, fc, ff + */ +/*@}*/ + +/** @name Public key store indices */ +/*@{*/ +#define HAB_IDX_SRK 0 /**< Super-Root Key index */ +#define HAB_IDX_CSFK 1 /**< CSF key index */ +/*@}*/ + +/** @name Key Counts */ +/*@{*/ +#define HAB_SRK_MIN 1 /**< Minimum Super-Root Key count */ +#define HAB_SRK_MAX 4 /**< Maximum Super-Root Key count */ +#define HAB_KEY_PUBLIC_MAX 5 /**< Maximum installed public key count + * (incl Super-Root Key) + */ +#define HAB_KEY_SECRET_MAX 4 /**< Maximum installed secret key count + * (excl Master KEKs) + */ +/*@}*/ + +/* @} key */ + +/*---------------------------------------------------------------------------*/ + +#ifdef HAB_FUTURE +/** @addtogroup key_ecdsa + * @{ + */ + +/** @name Bitfield definitions */ +/*@{*/ +#define HAB_KEY_ECDSA_FLG_WIDTH 8 /**< Width of @a flg field */ +#define HAB_KEY_ECDSA_FLG_SHIFT 0 /**< Offset of @a flg field */ +#define HAB_KEY_ECDSA_TYP_WIDTH 8 /**< Width of @a typ field */ +#define HAB_KEY_ECDSA_TYP_SHIFT 24 /**< Offset of @a typ field */ +#define HAB_KEY_ECDSA_SIZ_WIDTH 8 /**< Width of @a siz field */ +#define HAB_KEY_ECDSA_SIZ_SHIFT 16 /**< Offset of @a siz field */ +#define HAB_KEY_ECDSA_REDBITS_WIDTH 16 /**< Width of @a red_bits field */ +#define HAB_KEY_ECDSA_REDBITS_SHIFT 0 /**< Offset of @a red_bits field */ +/*@}*/ + +/* @} key_ecdsa */ +#endif + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup key_pkcs1 + * @{ + */ + +/** @name Bitfield definitions */ +/*@{*/ +#define HAB_KEY_PKCS1_FLG_WIDTH 8 /**< Width of @a flg field */ +#define HAB_KEY_PKCS1_FLG_SHIFT 0 /**< Offset of @a flg field */ +#define HAB_KEY_PKCS1_MODBYTES_WIDTH 16 /**< Width of mod_bytes field */ +#define HAB_KEY_PKCS1_MODBYTES_SHIFT 16 /**< Offset of mod_bytes field */ +#define HAB_KEY_PKCS1_EXPBYTES_WIDTH 16 /**< Width of exp_bytes field */ +#define HAB_KEY_PKCS1_EXPBYTES_SHIFT 0 /**< Offset of exp_bytes field */ +/*@}*/ + +/** @name Binding flag bitfield definitions */ +/*@}*/ +#define HAB_KEY_BND_FLG_WIDTH 5 /**< Width of binding flags */ +#define HAB_KEY_BND_FLG_SHIFT 2 /**< Offset of binding flags */ +/*@}*/ + +/* @} key_pkcs1 */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup cmd_wrt_dat + * @{ + */ + +/** @name Parameter bitfield definitions. + * + * Apply to both @ref cmd_wrt_dat and @ref cmd_chk_dat commands. */ +/*@{*/ +#define HAB_CMD_WRT_DAT_FLAGS_WIDTH 5 /**< @a flags field width */ +#define HAB_CMD_WRT_DAT_FLAGS_SHIFT 3 /**< @a flags field offset */ +#define HAB_CMD_WRT_DAT_BYTES_WIDTH 3 /**< @a bytes field width */ +#define HAB_CMD_WRT_DAT_BYTES_SHIFT 0 /**< @a bytes field offset */ +/*@}*/ + +/* @} cmd_wrt_dat */ + +/*---------------------------------------------------------------------------*/ + +/** @addtogroup bnd_obj + * @{ + */ + +/** @name Binding object IDs + * @anchor bnd_ids + * + * The ASN.1 object identifiers used to identify HAB binding attributes are + * defined in the following arc: + * +@verbatim + id-fsl OBJECT IDENTIFIER ::= { + joint-iso-itu-t(2) country(16) us(840) organization(1) fsl(123456) } + + id-habBnd OBJECT IDENTIFIER ::= { + id-fsl hab(32) binding-objects(16) } + + id-habBnd-dat OBJECT IDENTIFIER ::= { + id-habBnd dat(1) } + + id-habBnd-cfg OBJECT IDENTIFIER ::= { + id-habBnd cfg(3) } + + id-habBnd-fid OBJECT IDENTIFIER ::= { + id-habBnd fid(5) } + + id-habBnd-mid OBJECT IDENTIFIER ::= { + id-habBnd mid(6) } + + id-habBnd-cid OBJECT IDENTIFIER ::= { + id-habBnd cid(9) } +@endverbatim + * + * The ASN.1 object identifiers used to identify HAB binding attributes are + * single component extensions of id-habBnd using a component value less than + * 128 (so that the component can be DER-encoded in a single byte). + * + * The DER encoding of an object identifier in this arc is the concatenation + * of the DER prefix with the single byte identifier for the required binding + * object. Binding object attribute values are encoded as an ASN.1 SET with + * a single OCTET STRING member. + */ +/*@{*/ + +/** DER prefix + * + * @todo update description and encoding of binding object identifiers with + * real fsl value instead of fsl(123456) encoded as 0x87, 0xc4, 0x40, and + * confirm chosen values for hab(32) and binding-objects(16). + */ +#define HAB_BND_DER_PREFIX \ + {0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x87, 0xc4, 0x40, 0x20, 0x10} +#define HAB_BND_DAT 0x01 /**< Data type (mandatory) */ +#define HAB_BND_CFG 0x03 /**< Security configuration */ +#define HAB_BND_FID 0x05 /**< Fabrication UID */ +#define HAB_BND_MID 0x06 /**< Manufacturing ID */ +#define HAB_BND_CID 0x09 /**< Caller ID */ +/* Available values: 0a, 0c, 0f, 11, 12, 14, 17, 18, 1b, 1d, 1e, 21, 22, 24, + * 27, 28, 2b, 2d, 2e, 30, 33, 35, 36, 39, 3a, 3c, 3f, 41, 42, 44, 47, 48, 4b, + * 4d, 4e, 50, 53, 55, 56, 59, 5a, 5c, 5f, 60, 63, 65, 66, 69, 6a, 6c, 6f, 71, + * 72, 74, 77, 78, 7b, 7d, 7e + */ +/*@}*/ + + +/** @name Caller IDs + * + * Only the ROM caller ID is defined, but other caller IDs may be defined by + * later boot stages. + */ +/*@{*/ +#define HAB_CID_ROM 0 /**< ROM Caller ID */ +/*@}*/ + +/* @} bnd_obj */ + +#ifdef HAB_FUTURE +/** @addtogroup sig_fsl + * @{ + */ + +#define HAB_BND_DAT_BYTES 512 /**< Maximum binding data size */ + +/* @} sig_fsl */ +#endif + +/*=========================================================================== + MACROS +=============================================================================*/ +/* + * Helper macros + */ +#define HAB_CMD_UNS 0xff + +#define DEFAULT_IMG_KEY_IDX 2 + +#define GEN_MASK(width) \ + ((1UL << (width)) - 1) + +#define GEN_FIELD(f, width, shift) \ + (((f) & GEN_MASK(width)) << (shift)) + +#define PACK_UINT32(a, b, c, d) \ + ((uint32_t) ( (((uint32_t)(a) & 0xFF) << 24) \ + |(((uint32_t)(b) & 0xFF) << 16) \ + |(((uint32_t)(c) & 0xFF) << 8) \ + |(((uint32_t)(d) & 0xFF)) ) ) + +#define EXPAND_UINT32(w) \ + (uint8_t)((w)>>24), (uint8_t)((w)>>16), (uint8_t)((w)>>8), (uint8_t)(w) + +#define EXPAND_UINT16(w) \ + (uint8_t)((w)>>8), (uint8_t)(w) + +#define HDR(tag, bytes, par) \ + (uint8_t)(tag), (uint8_t)((bytes)>>8), (uint8_t)(bytes), (uint8_t)(par) + +#define HAB_VER(maj, min) \ + (GEN_FIELD((maj), HAB_VER_MAJ_WIDTH, HAB_VER_MAJ_SHIFT) \ + | GEN_FIELD((min), HAB_VER_MIN_WIDTH, HAB_VER_MIN_SHIFT)) + +#define DCD_DATA(addr, data) EXPAND_UINT32(addr), EXPAND_UINT32(data) + +/* + * CSF header + */ + +#define CSF_HDR(bytes, HABVER) \ + HDR(HAB_TAG_CSF, (bytes), HABVER) + + +/* + * DCD header + */ + +#define DCD_HDR(bytes, HABVER) \ + HDR(HAB_TAG_DCD, (bytes), HABVER) + +/* + * IVT header (goes in the struct's hab_hdr_t field, not a byte array) + */ +#define IVT_HDR(bytes, HABVER) \ + {HAB_TAG_IVT, {(uint8_t)((bytes)>>8), (uint8_t)(bytes)}, HABVER} + +/* + * Write Data + */ + +#define WRT_DAT(flags, bytes, address, val_msk) \ + HDR(HAB_CMD_WRT_DAT, WRT_DAT_BYTES, WRT_DAT_PAR((flags), (bytes))), \ + EXPAND_UINT32(address), \ + EXPAND_UINT32(val_msk) + +#define WRT_DAT_BYTES 12 + +#define MULTI_WRT_DAT(flags, bytes, address1, val_msk1, address2, \ + val_msk2, address3, val_msk3) \ + HDR(HAB_CMD_WRT_DAT, MULTI_WRT_DAT_BYTES, WRT_DAT_PAR((flags), (bytes))), \ + EXPAND_UINT32(address1), \ + EXPAND_UINT32(val_msk1), \ + EXPAND_UINT32(address2), \ + EXPAND_UINT32(val_msk2), \ + EXPAND_UINT32(address3), \ + EXPAND_UINT32(val_msk3) + +#define MULTI_WRT_DAT_BYTES 28 + +#define WRT_DAT_PAR(flags, bytes) \ + (GEN_FIELD((flags), \ + HAB_CMD_WRT_DAT_FLAGS_WIDTH, \ + HAB_CMD_WRT_DAT_FLAGS_SHIFT) \ + | GEN_FIELD((bytes), \ + HAB_CMD_WRT_DAT_BYTES_WIDTH, \ + HAB_CMD_WRT_DAT_BYTES_SHIFT)) + +/* + * Check Data (forever) + */ + +#define CHK_DAT_FOREVER(flags, bytes, address, mask) \ + HDR(HAB_CMD_CHK_DAT, CHK_DAT_FOREVER_BYTES, WRT_DAT_PAR((flags), (bytes))), \ + EXPAND_UINT32(address), \ + EXPAND_UINT32(mask) + +#define CHK_DAT_FOREVER_BYTES 12 + +/* + * Check Data (polled) + */ +#define HAB_CMD_CHK_DAT_COUNT 100 + +#define CHK_DAT(flags, bytes, address, mask, count) \ + HDR(HAB_CMD_CHK_DAT, CHK_DAT_BYTES, WRT_DAT_PAR((flags), (bytes))), \ + EXPAND_UINT32(address), \ + EXPAND_UINT32(mask), \ + EXPAND_UINT32(count) + +#define CHK_DAT_BYTES 16 + +/* + * Set (generic - used internally only, or to generate invalid commands) + */ + +#define SET(bytes, itm, value) \ + HDR(HAB_CMD_SET, (bytes), (itm)), \ + EXPAND_UINT32(value) + +/* + * Set (MID location) + */ + +#define SET_MID(bank, row, bit, fuses) \ + HDR(HAB_CMD_SET, SET_MID_BYTES, HAB_VAR_CFG_ITM_MID), \ + (bank), (row), (bit), (fuses) + +#define SET_MID_BYTES 8 + +/* + * Set (default ENG) + */ + +#define SET_ENG(alg, eng, cfg) \ + HDR(HAB_CMD_SET, SET_ENG_BYTES, HAB_VAR_CFG_ITM_ENG), \ + 0, (alg), (eng), (cfg) + +#define SET_ENG_BYTES 8 + +/* + * Init (engine) + */ + +#define INIT(eng) \ + HDR(HAB_CMD_INIT, INIT_BYTES, (eng)) + +#define INIT_BYTES 4 + +/* + * Unlk (engine) + */ + +#define UNLK(eng, ...) \ + UNLK_ ## eng(__VA_ARGS__) + +#define UNLK_BYTES(eng, ...) \ + UNLK_BYTES_ ## eng(__VA_ARGS__) + +#define UNLK_HDR(eng, ...) \ + HDR(HAB_CMD_UNLK, UNLK_BYTES_ ## eng(__VA_ARGS__), eng) + +#define UNLK_FLG(flg) \ + 0, 0, 0, (uint8_t)(flg) + +#define UNLK_FLG_BYTES 4 + +#define UNLK_HAB_ENG_SRTC(dnc) UNLK_HDR(HAB_ENG_SRTC) +#define UNLK_BYTES_HAB_ENG_SRTC(dnc) HDR_BYTES + +#define UNLK_HAB_ENG_SNVS(flg) UNLK_HDR(HAB_ENG_SNVS), UNLK_FLG(flg) +#define UNLK_BYTES_HAB_ENG_SNVS(flg) (HDR_BYTES + UNLK_FLG_BYTES) + +#define UNLK_HAB_ENG_CAAM(flg) UNLK_HDR(HAB_ENG_CAAM), UNLK_FLG(flg) +#define UNLK_BYTES_HAB_ENG_CAAM(flg) (HDR_BYTES + UNLK_FLG_BYTES) + +/* The next definition uses a GCC extension employing ## to swallow the + * trailing comma in case the macro is called with only the fixed arguments + * (i.e. flg here). This extension appears to work in the GNU compatible mode + * of RVDS and GHS compilers. + */ +#define UNLK_HAB_ENG_OCOTP(flg, ...) \ + UNLK_HDR(HAB_ENG_OCOTP, flg), UNLK_FLG(flg), ## __VA_ARGS__ + +#define UNLK_BYTES_HAB_ENG_OCOTP(flg, ...) \ + (HDR_BYTES + UNLK_FLG_BYTES \ + + ( ((flg) & (HAB_OCOTP_UNLOCK_FIELD_RETURN \ + |HAB_OCOTP_UNLOCK_JTAG \ + |HAB_OCOTP_UNLOCK_SCS)) \ + ? STUB_FAB_UID_BYTES \ + : 0 )) + +#if 0 +/* Note: no comma after HDR(). Supplied by _VAL macro if needed */ +#define UNLK(eng, val) \ + HDR(HAB_CMD_UNLK, UNLK_BYTES_ ## eng, (eng)) \ + UNLK_VAL_ ## eng(val) + +#define UNLK_BYTES(eng) \ + UNLK_BYTES_ ## eng + +#define UNLK_BYTES_HAB_ENG_SRTC HDR_BYTES +#define UNLK_VAL_HAB_ENG_SRTC(val) /* no val field */ +#define UNLK_BYTES_HAB_ENG_SNVS (HDR_BYTES + 4) +#define UNLK_VAL_HAB_ENG_SNVS(val) ,0,0,0,((val)&0xff) +#define UNLK_BYTES_HAB_ENG_CAAM (HDR_BYTES + 4) +#define UNLK_VAL_HAB_ENG_CAAM(val) ,0,0,0,((val)&0xff) +#endif + +/* + * NOP + */ + +#define NOP() \ + HDR(HAB_CMD_NOP, NOP_BYTES, 0xae) /* third param is ignored */ + +#define NOP_BYTES 4 + +/* + * Install Key (generic - used internally only) + */ + +#define INS_KEY(bytes, flg, pcl, alg, src, tgt, crt) \ + HDR(HAB_CMD_INS_KEY, (bytes), (flg)), \ + (pcl), (alg), (src), (tgt), \ + EXPAND_UINT32(crt) + +#define INS_KEY_BASE_BYTES 12 + +/* + * Install Key (SRK) + */ + +#define INS_SRK(flg, alg, src, crt) \ + INS_KEY(INS_SRK_BYTES, (flg), \ + HAB_PCL_SRK, (alg), (src), HAB_IDX_SRK, \ + (crt)) + +#define INS_SRK_BYTES INS_KEY_BASE_BYTES + +/* + * Install Key (CSFK) + */ + +#define INS_CSFK(flg, pcl, crt) \ + INS_KEY(INS_CSFK_BYTES, (flg) | HAB_CMD_INS_KEY_CSF, \ + (pcl), HAB_ALG_ANY, HAB_IDX_SRK, HAB_IDX_CSFK, \ + (crt)) + +#define INS_CSFK_BYTES INS_KEY_BASE_BYTES + +/* + * Install Key (IMGK - no hash) + */ + +#define INS_IMGK(flg, pcl, src, tgt, crt) \ + INS_KEY(INS_IMGK_BYTES, (flg), \ + (pcl), HAB_ALG_ANY, (src), (tgt), \ + (crt)) + +#define INS_IMGK_BYTES INS_KEY_BASE_BYTES + + +/* + * Install Key (IMGK - with hash). Must be followed by the crt_hsh contents + * (e.g. using #include). The length field depends on using one of the + * standard HAB algorithm names, with no adornments like casts or + * parentheses. Note that the length macro cannot be used here: the ## + * must appear in the body of this macro to prevent the alg parameter from + * being expanded first. + */ + +#define INS_IMGK_HASH(flg, pcl, alg, src, tgt, crt) \ + INS_KEY(INS_KEY_BASE_BYTES + BYTES_ ## alg, (flg) | HAB_CMD_INS_KEY_HSH, \ + (pcl), (alg), (src), (tgt), \ + (crt)) + +/* + * Same as above but the hash length is fixed to the length of SHA1, + * but the algorithm remains unchanged. + */ +#define INS_IMGK_INV_HASH(flg, pcl, alg, src, tgt, crt) \ + INS_KEY(INS_IMGK_HASH_BYTES(HAB_ALG_SHA1), (flg) | HAB_CMD_INS_KEY_HSH, \ + (pcl), (alg), (src), (tgt), \ + (crt)) + + +#define INS_IMGK_HASH_BYTES(alg) \ + (INS_KEY_BASE_BYTES + BYTES_ ## alg) + +#define BYTES_HAB_ALG_SHA1 20 +#define BYTES_HAB_ALG_SHA256 32 +#define BYTES_HAB_ALG_SHA512 64 +/* dummy value for invalid hash alg - same as default hash algorithm */ +#define DEFAULT_HASH_ALG_BYTES BYTES_HAB_ALG_SHA256 +#define BYTES_HAB_ALG_PKCS1 DEFAULT_HASH_ALG_BYTES + +/* + * Authenticate Data (generic - used internally only) + */ + +#define AUT_DAT(bytes, flg, key, pcl, eng, cfg, sig_start) \ + HDR(HAB_CMD_AUT_DAT, (bytes), (flg)), \ + (key), (pcl), (eng), (cfg), \ + EXPAND_UINT32(sig_start) + +#define AUT_DAT_BASE_BYTES 12 + +/* + * Authenticate Data (CSF) + */ + +#define AUT_CSF(flg, pcl, eng, cfg, sig_start) \ + AUT_DAT(AUT_CSF_BYTES, (flg), \ + HAB_IDX_CSFK, (pcl), (eng), (cfg), \ + (sig_start)) + +#define AUT_CSF_BYTES AUT_DAT_BASE_BYTES + +/* + * Authenticate Data (Image) + */ + +#define AUT_IMG(blocks, flg, key, pcl, eng, cfg, sig_start) \ + AUT_DAT(AUT_IMG_BYTES(blocks), (flg), \ + (key), (pcl), (eng), (cfg), \ + (sig_start)) + +#define AUT_IMG_BYTES(blocks) \ + (AUT_DAT_BASE_BYTES + 8*(blocks)) + +/** Supported widths of data commands. + * @ingroup cmd_wrt_dat + */ +typedef enum hab_data_width +{ + HAB_DATA_WIDTH_BYTE = 1, /**< 8-bit value */ + HAB_DATA_WIDTH_HALF = 2, /**< 16-bit value */ + HAB_DATA_WIDTH_WORD = 4 /**< 32-bit value */ +} hab_data_width_t; + + +/** Flags for Write Data commands. + * @ingroup cmd_wrt_dat + */ +typedef enum hab_cmd_wrt_dat_flg +{ + HAB_CMD_WRT_DAT_MSK = 1, /**< Mask/value flag: if set, only specific + * bits may be overwritten at target address + * (otherwise all bits may be overwritten) + */ + HAB_CMD_WRT_DAT_SET = 2 /**< Set/clear flag: if #HAB_CMD_WRT_DAT_MSK + * set, bits at the target address overwritten + * with this flag (otherwise it is ignored) + */ +} hab_cmd_wrt_dat_flg_t; + +/** Flags for Check Data commands. + * @ingroup cmd_chk_dat + */ +typedef enum hab_cmd_chk_dat_flg +{ + HAB_CMD_CHK_DAT_SET = 2, /**< Set/clear flag: bits set in mask must + * match this flag + */ + HAB_CMD_CHK_DAT_ANY = 4 /**< Any/all flag: if clear, all bits set in + * mask must match (otherwise any bit + * suffices) + */ +} hab_cmd_chk_dat_flg_t; + +/** Flags for Authenticate Data commands. + * @ingroup cmd_aut_dat + */ +typedef enum hab_cmd_aut_dat_flg +{ + HAB_CMD_AUT_DAT_CLR = 0, /**< No flags set */ + HAB_CMD_AUT_DAT_ABS = 1 /**< Absolute signature address */ +} hab_cmd_aut_dat_flg_t; + +/** Flags for Install Key commands. + * @ingroup cmd_ins_key + */ +typedef enum hab_cmd_ins_key_flg +{ + HAB_CMD_INS_KEY_CLR = 0, /**< No flags set */ + HAB_CMD_INS_KEY_ABS = 1, /**< Absolute certificate address */ + HAB_CMD_INS_KEY_CSF = 2, /**< Install CSF key */ + HAB_CMD_INS_KEY_DAT = 4, /**< Key binds to Data Type */ + HAB_CMD_INS_KEY_CFG = 8, /**< Key binds to Configuration */ + HAB_CMD_INS_KEY_FID = 16, /**< Key binds to Fabrication UID */ + HAB_CMD_INS_KEY_MID = 32, /**< Key binds to Manufacturing ID */ + HAB_CMD_INS_KEY_CID = 64, /**< Key binds to Caller ID */ + HAB_CMD_INS_KEY_HSH = 128 /**< Certificate hash present */ +} hab_cmd_ins_key_flg_t; + +/** Key flags. + * @ingroup key_pkcs1 + * + * @ifrom + * + * The binding flags given here align with those in #hab_cmd_ins_key_flg + * + * @endrom + * + */ +typedef enum hab_key_flg +{ + /* Two more flag values available */ + HAB_KEY_FLG_DAT = 4, /**< Key binds to Data Type */ + HAB_KEY_FLG_CFG = 8, /**< Key binds to Configuration */ + HAB_KEY_FLG_FID = 16, /**< Key binds to Fabrication UID */ + HAB_KEY_FLG_MID = 32, /**< Key binds to Manufacturing ID */ + HAB_KEY_FLG_CID = 64, /**< Key binds to Caller ID */ + HAB_KEY_FLG_CA = 128 /**< CA key */ +} hab_key_flg_t; + +/** Secret key flags. + * @ingroup crt_blob + */ +typedef enum hab_key_secret_flg +{ + /* Seven more flag values available */ + HAB_KEY_FLG_KEK = 128 /**< KEK */ +} hab_key_secret_flg_t; + +/** Binding data types + * @ingroup bnd_obj + */ +typedef enum hab_dat { + HAB_DAT_CSF = 0x0f, /**< CSF signature */ + HAB_DAT_IMG = 0x33, /**< Image signature */ +#ifdef HAB_FUTURE + HAB_DAT_PLG = 0x3c, /**< Plugin signature */ +#endif + HAB_DAT_MAX +} hab_dat_t; + +/* Available values: 55, 5a, 66, 69, 96, 99, a5, aa, c3, cc, f0, ff + */ + +/** Target check types + * @ingroup chk_tgt + */ +typedef enum hab_target { + HAB_TGT_MEMORY = 0x0f, /**< Check memory white list */ + HAB_TGT_PERIPHERAL = 0xf0, /**< Check peripheral white list */ + HAB_TGT_ANY = 0x55, /**< Check memory & peripheral white list */ + HAB_TGT_MAX +} hab_target_t; + +/** Security configuration types + * @ingroup status + */ +typedef enum hab_config { +/** @cond rom */ + HAB_CFG_FAB = 0x00, /**< @rom Un-programmed IC */ +/** @endcond */ + HAB_CFG_RETURN = 0x33, /**< Field Return IC */ + HAB_CFG_OPEN = 0xf0, /**< Non-secure IC */ + HAB_CFG_CLOSED = 0xcc /**< Secure IC */ +} hab_config_t; +/* Available values: 0f, 3c, 55, 5a, 66, 69, 96, 99, a5, aa, ff + */ + +/** Security state types + * @ingroup status + */ +typedef enum hab_state { + HAB_STATE_INITIAL = 0x33, /**< Initialising state (transitory) */ + HAB_STATE_CHECK = 0x55, /**< Check state (non-secure) */ + HAB_STATE_NONSECURE = 0x66, /**< Non-secure state */ + HAB_STATE_TRUSTED = 0x99, /**< Trusted state */ + HAB_STATE_SECURE = 0xaa, /**< Secure state */ + HAB_STATE_FAIL_SOFT = 0xcc, /**< Soft fail state */ + HAB_STATE_FAIL_HARD = 0xff, /**< Hard fail state (terminal) */ + HAB_STATE_NONE = 0xf0, /**< No security state machine */ + HAB_STATE_MAX +} hab_state_t; +/* Available values: 00, 0f, 3c, 5a, 69, 96, a5, c3 + */ + +/** HAB status types + * @ingroup status + */ +typedef enum hab_status { + HAB_STS_ANY = 0x00, /**< Match any status in + * hab_rvt.report_event() + */ + HAB_FAILURE = 0x33, /**< Operation failed */ + HAB_WARNING = 0x69, /**< Operation completed with warning */ + HAB_SUCCESS = 0xf0, /**< Operation completed successfully */ + HAB_STS_MAX +} hab_status_t; + +/** Failure or warning reasons + * @ingroup evt + * + * Values 0x80 ... 0xff are reserved for internal use. + */ +typedef enum hab_reason { + HAB_RSN_ANY = 0x00, /**< Match any reason in + * hab_rvt.report_event() + */ + HAB_ENG_FAIL = 0x30, /**< Engine failure. */ + HAB_INV_ADDRESS = 0x22, /**< Invalid address: access denied. */ + HAB_INV_ASSERTION = 0x0c, /**< Invalid assertion. */ + HAB_INV_CALL = 0x28, /**< Function called out of sequence. */ + HAB_INV_CERTIFICATE = 0x21, /**< Invalid certificate. */ + HAB_INV_COMMAND = 0x06, /**< Invalid command: command malformed. */ + HAB_INV_CSF = 0x11, /**< Invalid @ref csf. */ + HAB_INV_DCD = 0x27, /**< Invalid @ref dcd. */ + HAB_INV_INDEX = 0x0f, /**< Invalid index: access denied. */ + HAB_INV_IVT = 0x05, /**< Invalid @ref ivt. */ + HAB_INV_KEY = 0x1d, /**< Invalid key. */ + HAB_INV_RETURN = 0x1e, /**< Failed callback function. */ + HAB_INV_SIGNATURE = 0x18, /**< Invalid signature. */ + HAB_INV_SIZE = 0x17, /**< Invalid data size. */ + HAB_MEM_FAIL = 0x2e, /**< Memory failure. */ + HAB_OVR_COUNT = 0x2b, /**< Expired poll count. */ + HAB_OVR_STORAGE = 0x2d, /**< Exhausted storage region. */ + HAB_UNS_ALGORITHM = 0x12, /**< Unsupported algorithm. */ + HAB_UNS_COMMAND = 0x03, /**< Unsupported command. */ + HAB_UNS_ENGINE = 0x0a, /**< Unsupported engine. */ + HAB_UNS_ITEM = 0x24, /**< Unsupported configuration item. */ + HAB_UNS_KEY = 0x1b, /**< Unsupported key type or parameters. */ + HAB_UNS_PROTOCOL = 0x14, /**< Unsupported protocol. */ + HAB_UNS_STATE = 0x09, /**< Unsuitable state. */ + HAB_RSN_MAX +} hab_reason_t; +/* Available values: 33, 35, 36, 39, 3a, 3c, 3f, 41, 42, 44, + * 47, 48, 4b, 4d, 4e, 50, 53, 55, 56, 59, 5a, 5c, 5f, 60, 63, 65, 66, 69, 6a, + * 6c, 6f, 71, 72, 74, 77, 78, 7b, 7d, 7e + */ + +/** Audit logging contexts. + * @ingroup evt + * + * This list is sorted in order of increasing priority: where two contexts + * might apply, the latter one is used. + * + * Values 0x40 .. 0x5f are reserved for internal use. + */ +typedef enum hab_context { + HAB_CTX_ANY = 0x00, /**< Match any context in + * hab_rvt.report_event() + */ +/** @cond rom */ + HAB_CTX_FAB = 0xff, /**< @rom Event logged in hab_fab_test() */ +/** @endcond */ + HAB_CTX_ENTRY = 0xe1, /**< Event logged in hab_rvt.entry() */ + HAB_CTX_TARGET = 0x33, /**< Event logged in hab_rvt.check_target() */ + HAB_CTX_AUTHENTICATE = 0x0a, /**< Event logged in + * hab_rvt.authenticate_image() + */ + HAB_CTX_DCD = 0xdd, /**< Event logged in hab_rvt.run_dcd() */ + HAB_CTX_CSF = 0xcf, /**< Event logged in hab_rvt.run_csf() */ + HAB_CTX_COMMAND = 0xc0, /**< Event logged executing @ref csf or @ref + * dcd command + */ + HAB_CTX_AUT_DAT = 0xdb, /**< Authenticated data block */ + HAB_CTX_ASSERT = 0xa0, /**< Event logged in hab_rvt.assert() */ + HAB_CTX_EXIT = 0xee, /**< Event logged in hab_rvt.exit() */ + HAB_CTX_MAX +} hab_context_t; + +/** Assertion types. + * @ingroup assert + */ +typedef enum hab_assertion { + HAB_ASSERT_BLOCK = 0, /**< Assert that a memory block was authenticated */ + HAB_ASSERT_MAX +} hab_assertion_t; + +/** RTIC configuration flags + * @ingroup rtic + */ +typedef enum hab_rtic_config { + HAB_RTIC_IN_SWAP8 = 0x01, /**< Set BYTE SWAP bit (reverse bytes within + * word on input to RTIC) */ + HAB_RTIC_IN_SWAP16 = 0x02, /**< Set HALF WORD SWAP bit (reverse + * half-words within word on input to + * RTIC) */ + HAB_RTIC_OUT_SWAP8 = 0x08, /**< Set HASH RESULT BYTE SWAP bit (reverse + * bytes within word on output from RTIC) */ + HAB_RTIC_KEEP = 0x80 /**< Retain reference hash value for later + * monitoring */ +} hab_rtic_config_t; + +/** SAHARA configuration flags + * @ingroup sah + */ +typedef enum hab_sahara_config { + HAB_SAHARA_IN_SWAP8 = 0x01, /**< Set MESS BYTE SWAP bit (reverse message + * bytes within word on input to + * SAHARA) */ + HAB_SAHARA_IN_SWAP16 = 0x02, /**< Set MESS HALF WORD SWAP bit (reverse + * message half-words within word on input + * to SAHARA) */ + /* no SWAP32 for SAHARA message - leave 0x04 value unassigned */ + /* no SWAP8 for SAHARA descriptors/links - leave 0x08 value unassigned */ + HAB_SAHARA_DSC_BE8_16 = 0x10, /**< Interpret descriptors and links as for + * BE-8 16-bit memory. */ + HAB_SAHARA_DSC_BE8_32 = 0x20 /**< Interpret descriptors and links as for + * BE-8 32-bit memory. */ +} hab_sahara_config_t; + +/** CAAM configuration flags + * @ingroup caam + */ +typedef enum hab_caam_config { + HAB_CAAM_IN_SWAP8 = 0x01, /**< Set Message Byte Swap Input bit (reverse + * message bytes within word on input to + * CAAM) */ + HAB_CAAM_IN_SWAP16 = 0x02, /**< Set Message Half Word Swap Input bit + * (reverse message half-words within word + * on input to CAAM) */ + /* no SWAP32 for CAAM message - leave 0x04 value unassigned */ + HAB_CAAM_OUT_SWAP8 = 0x08, /**< Set Message Byte Swap Output bit + * (reverse message bytes within word on + * output from CAAM) */ + HAB_CAAM_OUT_SWAP16 = 0x10, /**< Set Message Half Word Swap Output bit + * (reverse message half-words within word + * on output from CAAM) */ + /* no SWAP32 for CAAM message - leave 0x20 value unassigned */ + HAB_CAAM_DSC_SWAP8 = 0x40, /**< Set Control Byte Swap Input/Output bits + * (reverse descriptor/link bytes within + * word on input to or output from CAAM) */ + HAB_CAAM_DSC_SWAP16 = 0x80 /**< Set Control Half Word Swap Input/Output + * bits (reverse descriptor/link half-words + * within word on input to or output from + * CAAM) */ +} hab_caam_config_t; + +/** CAAM unlock flags + * @ingroup caam + */ +typedef enum hab_caam_unlock_flag { + HAB_CAAM_UNLOCK_MID = 0x01, /**< Leave Job Ring and DECO master ID + * registers unlocked */ + HAB_CAAM_UNLOCK_RNG = 0x02 /**< Leave RNG state handle 0 + * uninstantiated, do not generate + * descriptor keys, do not set AES DPA + * mask, do not block state handle 0 test + * instantiation */ +} hab_caam_unlock_flag_t; + +/** SNVS unlock flags + * @ingroup snvs + */ +typedef enum hab_snvs_unlock_flag { + HAB_SNVS_UNLOCK_LP_SWR = 0x01, /**< Leave LP SW reset unlocked */ + HAB_SNVS_UNLOCK_ZMK_WRITE = 0x02 /**< Leave Zeroisable Master Key write + * unlocked */ +} hab_snvs_unlock_flag_t; + +/** SNVS master keys + * @ingroup snvs + * + * @remark Note that the first two master key selections are completely + * interchangeable. + */ +typedef enum hab_snvs_keys { + HAB_SNVS_OTPMK = 0, /**< OTP master key */ + HAB_SNVS_OTPMK_ALIAS = 1, /**< OTP master key (alias) */ + HAB_SNVS_ZMK = 2, /**< Zeroisable master key */ + HAB_SNVS_CMK = 3 /**< Combined master key */ +} hab_snvs_keys_t; + + +/** OCOTP unlock flags + * @ingroup ocotp + */ +typedef enum hab_ocotp_unlock_flag { + HAB_OCOTP_UNLOCK_FIELD_RETURN = 0x01, /**< Leave Field Return activation + * unlocked */ + HAB_OCOTP_UNLOCK_SRK_REVOKE = 0x02, /**< Leave SRK revocation unlocked */ + HAB_OCOTP_UNLOCK_SCS = 0x04, /**< Leave SCS register unlocked */ + HAB_OCOTP_UNLOCK_JTAG = 0x08 /**< Unlock JTAG using SCS HAB_JDE + * bit */ +} hab_ocotp_unlock_flag_t; + +/** DCP configuration flags + * @ingroup dcp + * + * @warning The byte-swapping controls produce unpredictable results unless + * the input data block lengths are multiples of 4 bytes. + */ +typedef enum hab_dcp_config { + HAB_DCP_IN_SWAP8 = 0x01, /**< Set INPUT BYTE SWAP bit (reverse bytes + * within words on input to DCP) */ + /* no SWAP16 for DCP - leave 0x02 value unassigned */ + HAB_DCP_IN_SWAP32 = 0x04, /**< Set INPUT WORD SWAP bit (ignored for + * hashing) */ + HAB_DCP_OUT_SWAP8 = 0x08, /**< Set OUPUT BYTE SWAP bit (reverse bytes + * within words on output from DCP) */ + /* no SWAP16 for DCP - leave 0x10 value unassigned */ + HAB_DCP_OUT_SWAP32 = 0x20 /**< Set OUTPUT WORD SWAP bit (ignored for + * hashing) */ +} hab_dcp_config_t; + +#ifdef HAB_FUTURE +/** EC key specification types. + * @ingroup key_ecdsa + */ +typedef enum hab_ec_spec { + /** Named curve specification. The curve specification is a DER-encoded + * object identifier. Supported object identifiers are listed under @ref + * key_ecdsa_profile "ECDSA key profile". + */ + HAB_EC_SPEC_NAMED_CURVE = 0x01 +} hab_ec_spec_t; +#endif + +/** Variable configuration items + * @ingroup cmd_set + */ +typedef enum hab_var_cfg_itm { + HAB_VAR_CFG_ITM_MID = 0x01, /**< Manufacturing ID (MID) fuse locations */ + HAB_VAR_CFG_ITM_ENG = 0x03 /**< Preferred engine for a given algorithm */ +} hab_var_cfg_itm_t; + +/*=========================================================================== + ENUMS +=============================================================================*/ + +/*=========================================================================== + STRUCTURES AND OTHER TYPEDEFS +=============================================================================*/ + +/** Header field components + * @ingroup hdr + */ +typedef struct hab_hdr { + uint8_t tag; /**< Tag field */ + uint8_t len[2]; /**< Length field in bytes (big-endian) */ + uint8_t par; /**< Parameters field */ +} hab_hdr_t; + +/** Loader callback. + * @ingroup auth_img + * + * @par Purpose + * + * This function must be supplied by the library caller if required. It is + * intended to finalise image loading in those boot modes where only a portion + * of the image is loaded to a temporary initial location prior to device + * configuration. + * + * @par Operation + * + * This function is called during hab_rvt.authenticate_image() between running + * the @ref dcd and @ref csf. The operation of this function is defined by + * the caller. + * + * @param[in,out] start Initial (possibly partial) image load address on + * entry. Final image load address on exit. + * + * @param[in,out] bytes Initial (possibly partial) image size on entry. Final + * image size on exit. + * + * @param[in] boot_data Initial @ref ivt Boot Data load address. + * + * @remark The interpretation of the Boot Data is defined by the caller. + * Different boot components or modes may use different boot data, or even + * different loader callback functions. + * + * @warning It should not be assumed by this function that the Boot Data is + * valid or authentic. + * + * @warning It is the responsibility of the loader callback to check the final + * image load addresses using hab_rvt.check_target() prior to copying any image + * data. + * + * @pre The (possibly partial) image has been loaded in the initial load + * address, and the Boot Data is within the initial image. + * + * @pre The @ref dcd has been run, if provided. + * + * @post The final image load addresses pass hab_rvt.check_target(). + * + * @retval #HAB_SUCCESS if all operations completed successfully, + * + * @retval #HAB_FAILURE otherwise. + */ +typedef hab_status_t (*hab_loader_callback_f)( + void** start, + size_t* bytes, + const void* boot_data); + +/*---------------------------------------------------------------------------*/ + +/** Image entry function prototype + * @ingroup rvt + * + * This typedef serves as the return type for hab_rvt.authenticate_image(). It + * specifies a void-void function pointer, but can be cast to another function + * pointer type if required. + */ +typedef void (*hab_image_entry_f)(void); + +/*---------------------------------------------------------------------------*/ + +/** @ref rvt structure + * @ingroup rvt + * + * @par Format + * + * The @ref rvt consists of a @ref hdr followed by a list of addresses as + * described further below. + */ +struct hab_rvt { + + /** @ref hdr with tag #HAB_TAG_RVT, length and HAB version fields + * (see @ref data) + */ + hab_hdr_t hdr; + + /** Enter and initialise HAB library. + * @ingroup entry + * + * @par Purpose + * + * This function initialises the HAB library and @ref shw plugins. It is + * intended for use by post-ROM boot stage components, via the @ref rvt, + * prior to calling any other HAB functions other than + * hab_rvt.report_event() and hab_rvt.report_status(). + * + * @ifrom It is also intended for use by the boot ROM via hab_rvt.entry(). + * @endrom + * + * @par Operation + * + * This function performs the following operations every time it is called: + * + * - Initialise the HAB library internal state + * - Initialise the internal secret key store (cleared at the next + * hab_rvt.exit()) + * - Run the entry sequence of each available @ref shw plugin + * + * When first called from boot ROM, this function also performs the + * following operations prior to those given above: + * + * - Initialise the internal public key store (persists beyond + * hab_rvt.exit()) + * - Run the self-test sequence of each available @ref shw plugin + * - If a state machine is present and enabled, change the security state + * as follows: + * - If the IC is configured as #HAB_CFG_OPEN or #HAB_CFG_RETURN, move to + * #HAB_STATE_NONSECURE + * - If the IC is configured as #HAB_CFG_CLOSED, move to + * #HAB_STATE_TRUSTED + * - Otherwise, leave the security state unchanged + * + * If any failure occurs in the operations above: + * + * - An audit event is logged + * - All remaining operations are abandoned (except that all @ref shw + * self-test and entry sequences are still executed) + * - If a state machine is present and enabled, the security state is set + * as follows: + * - @ifrom Unless the IC is configured as #HAB_CFG_FAB,@endrom move to + * #HAB_STATE_NONSECURE. Note that if a security violation has been + * detected by the HW, the final state will be #HAB_STATE_FAIL_SOFT or + * #HAB_STATE_FAIL_HARD depending on the HW configuration. + * + * @warning Boot sequences may comprise several images with each launching + * the next as well as alternative images should one boot device or boot + * image be unavailable or unusable. The authentication of each image in + * a boot sequence must be bracketed by its own hab_rvt.entry() + * ... hab_rvt.exit() pair in order to ensure that security state + * information gathered for one image cannot be misapplied to another + * image. + * + * @ifrom + * + * @warning This applies to each boot path in boot ROM as well, except for + * the fabrication test path. + * + * @endrom + * + * @post HAB library internal state is initialised. + * + * @post Available @ref shw plugins are initialised. + * + * @post If a failure or warning occurs during @ref shw plugin + * initialisation, an audit event is logged with the relevant @ref eng + * tag. The status and reason logged are described in the relevant @ref + * shw plugin documentation. + * + * @post Security state is initialised, if a state machine is present and + * enabled. + * + * @retval #HAB_SUCCESS on an IC not configured as #HAB_CFG_CLOSED, + * although unsuccessful operations will still generate audit log events, + * + * @retval #HAB_SUCCESS on other ICs if all commands completed + * without failure (even if warnings were generated), + * + * @retval #HAB_FAILURE otherwise. + */ + hab_status_t (*entry)(void); + + /** Finalise and exit HAB library. + * @ingroup exit + * + * @par Purpose + * + * This function finalises the HAB library and @ref shw plugins. It is + * intended for use by post-ROM boot stage components, via the @ref rvt, + * after calling other HAB functions and prior to launching the next boot + * stage or switching to another boot path. + * + * @ifrom It is also intended for use by the boot ROM via hab_rvt.exit(). + * @endrom + * + * @par Operation + * + * This function performs the following operations: + * + * - Finalise the HAB library internal state + * - Clear the internal secret key store + * - Run the finalisation sequence of each available @ref shw plugin + * + * If any failure occurs, an audit event is logged and all remaining + * operations are abandoned (except that all @ref shw exit sequences are + * still executed). + * + * @warning See warnings for hab_rvt.entry(). + * + * @post #HAB_ASSERT_BLOCK records are cleared from audit log. Note that + * other event records are not cleared. + * + * @post Any public keys installed by @ref csf commands remain active. + * + * @post Any secret keys installed by @ref csf commands are deleted. + * + * @post Available @ref shw plugins are in their final state as described + * in the relevant sections. + * + * @post If a failure or warning occurs, an audit event is logged with the + * @ref eng tag of the @ref shw plugin concerned. The status and reason + * logged are described in the relevant @ref shw plugin documentation. + * + * @retval #HAB_SUCCESS on an IC not configured as #HAB_CFG_CLOSED, + * although unsuccessful operations will still generate audit log events, + * + * @retval #HAB_SUCCESS on other ICs if all commands completed + * without failure (even if warnings were generated), + * + * @retval #HAB_FAILURE otherwise. + */ + hab_status_t (*exit)(void); + + /** Check target address + * @ingroup chk_tgt + * + * @par Purpose + * + * This function reports whether or not a given target region is allowed + * for either peripheral configuration or image loading in memory. It is + * intended for use by post-ROM boot stage components, via the @ref rvt, + * in order to avoid configuring security-sensitive peripherals, or + * loading images over sensitive memory regions or outside recognised + * memory devices in the address map. + * + * @ifrom It is also available for use by the boot ROM, both directly via + * hab_rvt.check_target() and indirectly via hab_rvt.authenticate_image(). + * @endrom + * + * @par Operation + * + * The lists of allowed target regions vary by IC and core, and should be + * taken from the @ref ref_rug. + * + * @ifrom The allowed register sets for peripheral configuration and memory + * regions for image loading are defined in the @ref hal by + * #hab_hal_peripheral and #hab_hal_memory respectively. @endrom + * + * @param[in] type Type of target (memory, peripheral or any in which both + * the memory and peripheral regions are checked) + * + * @param[in] start Address of target region + * + * @param[in] bytes Size of target region + * + * @post if the given target region goes beyond the allowed regions, an + * audit event is logged with status #HAB_FAILURE and reason + * #HAB_INV_ADDRESS, together with the call parameters. See the @ref evt + * record documentation for details. + * + * @post For successful commands, no audit event is logged. + * + * @retval #HAB_SUCCESS on an IC not configured as #HAB_CFG_CLOSED, + * although unsuccessful operations will still generate audit log events, + * + * @retval #HAB_SUCCESS if the given target region lies wholly within the + * allowed regions for the requested type of target. + * + * @retval #HAB_FAILURE otherwise + */ + hab_status_t (*check_target)(hab_target_t type, + const void* start, + size_t bytes); + + /** Authenticate image. + * @ingroup auth_img + * + * @par Purpose + * + * This function combines DCD, CSF and Assert functions in a standard + * sequence in order to authenticate a loaded image. It is intended for + * use by post-ROM boot stage components, via the @ref rvt. Support for + * images partially loaded to an initial location is provided via a + * callback function. + * + * @ifrom It is also available for use by the boot ROM via + * hab_rvt.authenticate_image(). @endrom + * + * @par Operation + * + * This function performs the following sequence of operations: + * - Check that the initial image load addresses pass + * hab_rvt.check_target(). + * - Check that the IVT offset lies within the initial image bounds. + * - Check that the @ref ivt @a self and @a entry pointers are not NULL + * - Check the @ref ivt header for consistency and compatability. + * - If provided in the @ref ivt, calculate the @ref dcd initial location, + * check that it lies within the initial image bounds, and run the @ref + * dcd commands. + * - If provided in the @ref ivt, calculate the Boot Data initial location + * and check that it lies within the initial image bounds. + * - If provided in the parameters, invoke the callback function with the + * initial image bounds and initial location of the @ref ivt Boot Data. + * + * From this point on, the full image is assumed to be in its final + * location. The following operations will be performed on all IC + * configurations (#hab_config), but will be only enforced on an IC + * configured as #HAB_CFG_CLOSED: + * - Check that the final image load addresses pass hab_rvt.check_target(). + * - Check that the CSF lies within the image bounds, and run the CSF + * commands. + * - Check that all of the following data have been authenticated (using + * their final locations): + * - IVT; + * - DCD (if provided); + * - Boot Data (initial byte if provided); + * - Entry point (initial word). + * + * @param[in] cid Caller ID, used to identify which SW issued this call. + * + * @param[in] ivt_offset Offset in bytes of the IVT from the image start + * address. + * + * @param[in,out] start Initial (possibly partial) image load address on + * entry. Final image load address on exit. + * + * @param[in,out] bytes Initial (possibly partial) image size on entry. + * Final image size on exit. + * + * @param[in] loader Callback function to load the full image to its final + * load address. Set to NULL if not required. + * + * @remark Caller ID may be bound to signatures verified using keys + * installed with #HAB_CMD_INS_KEY_CID flag. See @ref cmd_ins_key and @ref + * bnd_obj for details. + * + * @remark A @a loader callback function may be supplied even if the image + * is already loaded to its final location on entry. + * + * @remark Boot Data (boot_data in @ref ivt) will be ignored if the + * @a loader callback function point is set to Null. + * + * @warning The @a loader callback function should lie within existing + * authenticated areas. @ifrom Or within the ROM. @endrom + * + * @warning It is the responsibility of the caller to check the initial + * image load addresses using hab_rvt.check_target() prior to loading the + * initial image and calling this function. + * + * @warning After completion of hab_rvt.authenticate_image(), the caller + * should test using hab_rvt.assert() that the Boot Data was + * authenticated. + * + * @post The post-conditions of the functions hab_rvt.check_target(), + * hab_rvt.run_dcd(), hab_rvt.run_csf() and hab_rvt.assert() apply also to + * this function. In particular, any audit events logged within the given + * functions have the context field appropriate to that function rather + * than #HAB_CTX_AUTHENTICATE. In addition, the side-effects and + * post-conditions of any callback function supplied apply. + * + * @post If a failure or warning occurs outside these contexts, an audit + * event is logged with status: + * - #HAB_FAILURE, with further reasons: + * - #HAB_INV_ADDRESS: initial or final image addresses outside allowed + * regions + * - #HAB_INV_ADDRESS: IVT, DCD, Boot Data or CSF outside image bounds + * - #HAB_INV_ADDRESS: IVT @a self or @a entry pointer is NULL + * - #HAB_INV_CALL: hab_rvt.entry() not run successfully prior to call + * - #HAB_INV_IVT: IVT malformed + * - #HAB_INV_IVT: IVT version number is less than HAB library version + * - #HAB_INV_RETURN: Callback function failed + * + * @retval entry field from @ref ivt on an IC not configured as + * #HAB_CFG_CLOSED provided that the following conditions are met + * (other unsuccessful operations will generate audit log events): + * - the @a start pointer and the pointer it locates are not NULL + * - the initial @ref ivt location is not NULL + * - the @ref ivt @ref hdr (given in the @a hdr field) is valid + * - the final @ref ivt location (given by the @a self field) is not NULL + * - any loader callback completed successfully, + * + * @retval entry field from @ref ivt on other ICs if all operations + * completed without failure (even if warnings were generated), + * + * @retval NULL otherwise. + */ + hab_image_entry_f (*authenticate_image)(uint8_t cid, + ptrdiff_t ivt_offset, + void** start, + size_t* bytes, + hab_loader_callback_f loader); + + /** Execute a boot configuration script. + * @ingroup run_dcd + * + * @par Purpose + * + * This function configures the IC based upon a @ref dcd table. It is + * intended for use by post-ROM boot stage components, via the @ref rvt. + * This function may be invoked as often as required for each boot stage. + * + * @ifrom It is also intended for use by the boot ROM, both directly via + * hab_rvt.run_dcd() and indirectly via hab_rvt.authenticate_image(). + * @endrom + * + * The difference between the configuration functionality in this function + * and hab_rvt.run_csf() arises because the @ref dcd table is not + * authenticated prior to running the commands. Hence, there is a more + * limited range of commands allowed, and a limited range of parameters to + * allowed commands. + * + * @par Operation + * + * This function performs the following operations: + * - Checks the @ref hdr for compatibility and consistency + * - Makes an internal copy of the @ref dcd table + * - Executes the commands in sequence from the internal copy of the @ref + * dcd + * + * If any failure occurs, an audit event is logged and all remaining + * operations are abandoned. + * + * @param[in] dcd Address of the @ref dcd. + * + * @warning It is the responsibility of the caller to ensure that the @a + * dcd parameter points to a valid memory location. + * + * @warning The @ref dcd must be authenticated by a subsequent @ref csf + * command prior to launching the next boot image, in order to avoid + * unauthorised configurations which may subvert secure operation. + * Although the content of the next boot stage's CSF may be out of scope + * for the hab_rvt.run_dcd() caller, it is possible to enforce this + * constraint by using hab_rvt.assert() to ensure that both the DCD and + * any pointers used to locate it have been authenticated. + * + * @warning Each invocation of hab_rvt.run_dcd() must occur between a pair + * of hab_rvt.entry() and hab_rvt.exit() calls, although multiple + * hab_rvt.run_dcd() calls (and other HAB calls) may be made in one + * bracket. This constraint applies whether hab_rvt.run_dcd() is + * successful or not: a subsequent call to hab_rvt.exit() is required + * prior to launching the authenticated image or switching to another boot + * target. + * + * @post Many commands may cause side-effects. See the @ref dcd + * documentation. + * + * @post If a failure or warning occurs within a command handler, an audit + * event is logged with the offending command, copied from the DCD. The + * status and reason logged are described in the relevant command + * documentation. + * + * @post For other failures or warning, the status logged is: + * - #HAB_WARNING, with further reasons: + * - #HAB_UNS_COMMAND: unsupported command encountered, where DCD + * version and HAB library version differ + * - #HAB_FAILURE, with further reasons: + * - #HAB_INV_ADDRESS: NULL @a dcd parameter + * - #HAB_INV_CALL: hab_rvt.entry() not run successfully prior to call + * - #HAB_INV_COMMAND: command not allowed in DCD + * - #HAB_UNS_COMMAND: unrecognised command encountered, where DCD + * version and HAB library version match + * - #HAB_INV_DCD: DCD malformed or too large + * - #HAB_INV_DCD: DCD version number is less than HAB library version + * @retval #HAB_SUCCESS on an IC not configured as #HAB_CFG_CLOSED, + * although unsuccessful operations will still generate audit log events, + * + * @retval #HAB_SUCCESS on other ICs if all commands completed + * without failure (even if warnings were generated), + * + * @retval #HAB_FAILURE otherwise. + */ + hab_status_t (*run_dcd)(const uint8_t* dcd); + + /** Execute an authentication script. + * @ingroup run_csf + * + * @par Purpose + * + * This function authenticates SW images and configures the IC based upon + * a @ref csf. It is intended for use by post-ROM boot stage components, + * via the @ref rvt. This function may be invoked as often as required + * for each boot stage. + * + * @ifrom It is also available for use by the boot ROM via hab_rvt.run_csf, + * although it is anticipated that the boot ROM will mostly call this + * function indirectly via hab_rvt.authenticate_image(). @endrom + * + * @par Operation + * + * This function performs the following operations: + * - Checks the @ref hdr for compatibility and consistency + * - Makes an internal copy of the @ref csf + * - Executes the commands in sequence from the internal copy of the @ref + * csf + * + * The internal copy of the @ref csf is authenticated by an explicit + * command in the sequence. Prior to authentication, a limited set of + * commands is available to: + * - Install a Super-Root key (unless previously installed) + * - Install a CSF key (unless previously installed) + * - Specify any variable configuration items + * - Authenticate the CSF + * + * Subsequent to CSF authentication, the full set of commands is available. + * + * If any failure occurs, an audit event is logged and all remaining + * operations are abandoned. + * + * @param[in] csf Address of the @ref csf. + * + * @param[in] cid Caller ID, used to identify which SW issued this call. + * + * @remark Caller ID may be bound to signatures verified using keys + * installed with #HAB_CMD_INS_KEY_CID flag. See @ref cmd_ins_key and @ref + * bnd_obj for details. + * + * @warning It is the responsibility of the caller to ensure that the @a + * csf parameter points to a valid memory location. + * + * @warning Each invocation of hab_rvt.run_csf() must occur between a pair + * of hab_rvt.entry() and hab_rvt.exit() calls, although multiple + * hab_rvt.run_csf() calls (and other HAB calls) may be made in one + * bracket. This constraint applies whether hab_rvt.run_csf() is + * successful or not: a subsequent call to hab_rvt.exit() is required + * prior to launching the authenticated image or switching to another boot + * target. + * + * @post Many commands may cause side-effects. See the @ref csf + * documentation. In particular, note that keys installed by the @ref csf + * remain available for use in subsequent operations. + * + * @post If a failure or warning occurs within a command handler, an audit + * event is logged with the offending command, copied from the CSF. The + * status and reason logged are described in the relevant command + * documentation. + * + * @post For other failures or warning, the status logged is: + * - #HAB_WARNING, with further reasons: + * - #HAB_UNS_COMMAND: unsupported command encountered, where CSF + * version and HAB library version differ + * - #HAB_FAILURE, with further reasons: + * - #HAB_INV_ADDRESS: NULL @a csf parameter + * - #HAB_INV_CALL: hab_rvt.entry() not run successfully prior to call + * - #HAB_INV_COMMAND: command not allowed prior to CSF authentication + * - #HAB_UNS_COMMAND: unrecognised command encountered, where CSF + * version and HAB library version match + * - #HAB_INV_CSF: CSF not authenticated + * - #HAB_INV_CSF: CSF malformed or too large + * - #HAB_INV_CSF: CSF version number is less than HAB library version + * + * @retval #HAB_SUCCESS on an IC not configured as #HAB_CFG_CLOSED, + * although unsuccessful operations will still generate audit log events, + * + * @retval #HAB_SUCCESS on other ICs if all commands completed + * without failure (even if warnings were generated), + * + * @retval #HAB_FAILURE otherwise. + */ + hab_status_t (*run_csf)(const uint8_t* csf, + uint8_t cid); + + /** Test an assertion against the audit log. + * @ingroup assert + * + * @par Purpose + * + * This function allows the audit log to be interrogated. It is intended + * for use by post-ROM boot stage components, via the @ref rvt, to + * determine the state of authentication operations. This function may be + * invoked as often as required for each boot stage. + * + * @ifrom It is also available for use by the boot ROM, both directly via + * hab_rvt.assert() and indirectly via hab_rvt.authenticate_image(). + * @endrom + * + * @par Operation + * + * This function checks the required assertion as detailed below. + * + * @param[in] type Assertion type. + * + * @param[in] data Assertion data. + * + * @param[in] count Data size or count. + * + * @par Memory block authentication: + * For #HAB_ASSERT_BLOCK assertion type, hab_rvt.assert() checks that the + * given memory block has been authenticated after running a CSF. The + * parameters are interpreted as follows: + * + * @par + * - @a data: memory block starting address + * - @a count: memory block size (in bytes) + * + * @par + * + * A simple interpretation of "memory block has been authenticated" is + * taken, such that the given block must lie wholly within a single + * contiguous block authenticated while running a CSF. A given memory + * block covered by the union of several neighboring or overlapping + * authenticated blocks could fail the test with this interpretation, but + * it is assumed that such cases will not arise in practice. + * + * @post If the assertion fails, an audit event is logged with status + * #HAB_FAILURE and reason #HAB_INV_ASSERTION, together with the call + * parameters. See the @ref evt record documentation for details. + * + * @post For successful commands, no audit event is logged. + * + * @retval #HAB_SUCCESS on an IC not configured as #HAB_CFG_CLOSED, + * although unsuccessful operations will still generate audit log events, + * + * @retval #HAB_SUCCESS on other ICs if the assertion is confirmed + * + * @retval #HAB_FAILURE otherwise + */ + hab_status_t (*assert)(hab_assertion_t type, + const void* data, + uint32_t count); + + /** Report an event from the audit log. + * @ingroup event + * + * @par Purpose + * + * This function allows the audit log to be interrogated. It is intended + * for use by post-ROM boot stage components, via the @ref rvt, to + * determine the state of authentication operations. This function may + * be called outside an hab_rvt.entry() / hab_rvt.exit() pair. + * + * @ifrom It is also available for use by the boot ROM, where it may be + * used to report boot failures as part of a tethered boot + * protocol. @endrom + * + * @par Operation + * + * This function performs the following operations: + * - Scans the audit log for a matching event + * - Copies the required details to the output parameters (if found) + * + * @param[in] status Status level of required event. + * + * @param[in] index Index of required event at given status level. + * + * @param[out] event @ref evt record. + * + * @param[in,out] bytes Size of @a event buffer on entry, size of event + * record on exit. + * + * @remark Use @a status = #HAB_STS_ANY to match any logged event, + * regardless of the status value logged. + * + * @remark Use @a index = 0 to return the first matching event, @a index = + * 1 to return the second matching event, and so on. + * + * @remark The data logged with each event is context-dependent. Refer to + * @ref evt record documentation. + * + * @warning Parameter @a bytes may not be NULL. + * + * @warning If the @a event buffer is a NULL pointer or too small to fit + * the event record, the required size is written to @a bytes, but no + * part of the event record is copied to the output buffer. + * + * @retval #HAB_SUCCESS if the required event is found, and the event + * record is copied to the output buffer. + * + * @retval #HAB_SUCCESS if the required event is found and @a event buffer + * passed is a NULL pointer. + * + * @retval #HAB_FAILURE otherwise + */ + hab_status_t (*report_event)(hab_status_t status, + uint32_t index, + uint8_t* event, + size_t* bytes); + + /** Report security status. + * @ingroup status + * + * @par Purpose + * + * This function reports the security configuration and state of the IC as + * well as searching the audit log to determine the status of the boot + * process. It is intended for use by post-ROM boot stage components, via + * the @ref rvt. This function may be called outside an + * hab_rvt.entry() / hab_rvt.exit() pair. + * + * @ifrom It is also available for use by the boot ROM, and should be used + * rather than the HAL function hab_hal_read_sec_cfg(). @endrom + * + * @par Operation + * + * This function reads the fuses which indicate the security + * configuration. The fusemap varies by IC, and should be taken from the + * @ref ref_rug. It also uses the @ref shw state machine, if present and + * enabled, to report on the security state. + * + * @param[out] config Security configuration, NULL if not required + * + * @param[out] state Security state, NULL if not required + * + * @remark If no @ref shw state machine is present and enabled, the state + * #HAB_STATE_NONE will be output. + * + * @retval #HAB_SUCCESS if no warning or failure audit events have been + * logged. + * + * @retval #HAB_WARNING otherwise, if only warning events have been logged. + * + * @retval #HAB_FAILURE otherwise + */ + hab_status_t (*report_status)(hab_config_t* config, hab_state_t* state); + + /** Enter failsafe boot mode. + * @ingroup safe + * + * @par Purpose + * + * This function provides a safe path when image authentication has failed + * and all possible boot paths have been exhausted. It is intended for + * use by post-ROM boot stage components, via the @ref rvt. + * + * @ifrom It is also available for use by the boot ROM via + * hab_rvt.failsafe(). @endrom + * + * @par Operation + * + * The precise details of this function vary by IC and core, and should be + * taken from @ref ref_rug. + * + * @warning This function does not return. + * + * @remark Since this function does not return, it implicitly performs the + * functionality of hab_rvt.exit() in order to ensure an appropriate + * configuration of the @ref shw plugins. + * + * @remark Two typical implementations are: + * - a low-level provisioning protocol in which an image is downloaded to + * RAM from an external host, authenticated and launched. The downloaded + * image may communicate with tools on the external host to report the + * reasons for boot failure, and may re-provision the end-product with + * authentic boot images. + * - a failsafe boot mode which does not allow execution to leave the ROM + * until the IC is reset. + */ + void (*failsafe)(void); +}; + +/** @ref rvt type + * @ingroup rvt + */ +typedef struct hab_rvt hab_rvt_t; + +/*---------------------------------------------------------------------------*/ + +/** @ref ivt structure + * @ingroup ivt + * + * @par Format + * + * An @ref ivt consists of a @ref hdr followed by a list of addresses as + * described further below. + * + * @warning The @a entry address may not be NULL. + * + * @warning On an IC not configured as #HAB_CFG_CLOSED, the + * @a csf address may be NULL. If it is not NULL, the @ref csf will be + * processed, but any failures should be non-fatal. + * + * @warning On an IC configured as #HAB_CFG_CLOSED, the @a + * csf address may not be NULL, and @ref csf failures are typically fatal. + * + * @remark The Boot Data located using the @a boot_data field is interpreted + * by the HAB caller in a boot-mode specific manner. This may be used by the + * boot ROM as to determine the load address and boot device configuration for + * images loaded from block devices (see @ref ref_rug for details). + * + * @remark All addresses given in the IVT, including the Boot Data (if + * present) are those for the final load location. + * + * @anchor ila + * + * @par Initial load addresses + * + * The @a self field is used to calculate addresses in boot modes where an + * initial portion of the image is loaded to an initial location. In such + * cases, the IVT, Boot Data (if present) and DCD (if present) are used in + * configuring the IC and loading the full image to its final location. Only + * the IVT, Boot Data (if present) and DCD (if present) are required to be + * within the initial image portion. + * + * The method for calculating an initial load address for the DCD is + * illustrated in the following C fragment. Similar calculations apply to + * other fields. + * +@verbatim + hab_ivt_t* ivt_initial = ; + const void* dcd_initial = ivt_initial->dcd; + if (ivt_initial->dcd != NULL) + dcd_initial = (const uint8_t*)ivt_initial + + (ivt_initial->dcd - ivt_initial->self) +@endverbatim + */ +struct hab_ivt { + /** @ref hdr with tag #HAB_TAG_IVT, length and HAB version fields + * (see @ref data) + */ + hab_hdr_t hdr; + /** Absolute address of the first instruction to execute from the + * image + */ + hab_image_entry_f entry; + /** Reserved in this version of HAB: should be NULL. */ + const void* reserved1; + /** Absolute address of the image DCD: may be NULL. */ + const void* dcd; + /** Absolute address of the Boot Data: may be NULL, but not interpreted + * any further by HAB + */ + const void* boot_data; + /** Absolute address of the IVT.*/ + const void* self; + /** Absolute address of the image CSF.*/ + const void* csf; + /** Reserved in this version of HAB: should be zero. */ + uint32_t reserved2; +}; + +/** @ref ivt type + * @ingroup ivt + */ +typedef struct hab_ivt hab_ivt_t; + +/*=========================================================================== + FUNCTION PROTOTYPES +=============================================================================*/ +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* HAB_DEFINES_H */ diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/ivt.c b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/ivt.c new file mode 100755 index 000000000..e49b865c9 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/ivt.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2010-2012, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +extern unsigned * _start_image_add; +extern unsigned * __start_boot_data; +extern unsigned * _image_size; + +extern unsigned * __hab_data; + +extern uint8_t input_dcd_hdr[]; + +extern void _reset(void); + +struct hab_ivt input_ivt __attribute__ ((section (".ivt"))) ={ + /** @ref hdr word with tag #HAB_TAG_IVT, length and HAB version fields + * (see @ref data) + */ + IVT_HDR(sizeof(struct hab_ivt), HAB_VER(4, 0)), + /** Absolute address of the first instruction to execute from the + * image + */ + (hab_image_entry_f)_reset, + + /** Reserved in this version of HAB: should be NULL. */ + NULL, + /** Absolute address of the image DCD: may be NULL. */ + &input_dcd_hdr, + /** Absolute address of the Boot Data: may be NULL, but not interpreted + * any further by HAB + */ + &__start_boot_data, + /** Absolute address of the IVT.*/ + (const void*) (&input_ivt), + + /** Absolute address of the image CSF.*/ + (const void*) &__hab_data, + + /** Reserved in this version of HAB: should be zero. */ + 0 +}; + +typedef struct { + uint32_t start; /**< Start address of the image */ + uint32_t size; /**< Size of the image */ + uint32_t plugin; /**< Plugin flag */ +} boot_data_t; + +boot_data_t bd __attribute__ ((section (".boot_data"))) ={ + (uint32_t) &_start_image_add, + (uint32_t) &_image_size, + 0, +}; + diff --git a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/link.lds b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/link.lds index d6e856d1a..67abbe98d 100644 --- a/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/link.lds +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/link.lds @@ -1,17 +1,88 @@ -STACK_SIZE = 4096; +STACK_SIZE = 48*1024; +L1_PAGE_TABLE_SIZE = 16K; +RAM_VECTORS_SIZE = 72; +OUTPUT_FORMAT("elf32-littlearm") OUTPUT_ARCH(arm) +MEMORY +{ + OCRAM (rwx) : ORIGIN = 0x00900000, LENGTH = 256K + DDR (rwx) : ORIGIN = 0x10000000, LENGTH = 2048M +} + SECTIONS { - . = 0x80100000; +/* + * -- OCRAM -- + * + * Nothing in OCRAM can be loaded at boot, because the boot image must be a contiguous + * region of memory. + */ + /* MMU L1 page table */ + .l1_page_table (NOLOAD) : + { + __l1_page_table_start = .; + . += L1_PAGE_TABLE_SIZE; + } > OCRAM + + /* allocate a heap in ocram */ + .heap.ocram (NOLOAD) : ALIGN(4) + { + __heap_ocram_start = .; + . += LENGTH(OCRAM) - L1_PAGE_TABLE_SIZE - RAM_VECTORS_SIZE ; + __heap_ocram_end = .; + } > OCRAM + + /* RAM vector table comes at the end of OCRAM */ + .ram_vectors (ORIGIN(OCRAM) + LENGTH(OCRAM) - RAM_VECTORS_SIZE) (NOLOAD) : + { + __ram_vectors_start = .; + . += RAM_VECTORS_SIZE; + __ram_vectors_end = .; + } > OCRAM + +/* + * -- DDR -- + */ + + /* -- read-only sections -- */ + + _start_image_add = ORIGIN(DDR); + + .ivt (ORIGIN(DDR)) : + { + . = . + 0x400; + *(.ivt) + } > DDR + + .boot_data : + { + __start_boot_data = .; + *(.boot_data) + } > DDR + + /* aligned to ease the hexdump read of generated binary */ + .dcd_hdr : ALIGN(16) + { + __start_dcd = .; + *(.dcd_hdr) + } > DDR + .dcd_wrt_cmd : + { + *(.dcd_wrt_cmd) + } > DDR + .dcd_data : + { + *(.dcd_data) + } > DDR __text_start = .; .text : { - *(.vectors) + *(.startup) *(.text) *(.text.*) @@ -23,11 +94,14 @@ SECTIONS KEEP(*(.isrtbl)) __isrtbl_end = .; . = ALIGN(4); - } + } > DDR __text_end = .; __rodata_start = .; - .rodata : { *(.rodata) *(.rodata.*) } + .rodata : + { + *(.rodata) *(.rodata.*) + } > DDR __rodata_end = .; . = ALIGN(4); @@ -37,7 +111,7 @@ SECTIONS KEEP(*(SORT(.ctors.*))) KEEP(*(.ctors)) PROVIDE(__ctors_end__ = .); - } + } > DDR .dtors : { @@ -45,14 +119,14 @@ SECTIONS KEEP(*(SORT(.dtors.*))) KEEP(*(.dtors)) PROVIDE(__dtors_end__ = .); - } + } > DDR - . = ALIGN(16 * 1024); + /* . = ALIGN(16 * 1024); .l1_page_table : { __l1_page_table_start = .; . += 16K; - } + } */ . = ALIGN(8); __data_start = .; @@ -60,7 +134,7 @@ SECTIONS { *(.data) *(.data.*) - } + } > DDR __data_end = .; . = ALIGN(8); @@ -71,7 +145,7 @@ SECTIONS *(.bss.*) *(COMMON) . = ALIGN(4); - } + } > DDR . = ALIGN(4); __bss_end = .; @@ -81,7 +155,7 @@ SECTIONS . += STACK_SIZE; __stacks_end = .; stack_top = .; - } + } > DDR /* Stabs debugging sections. */ .stab 0 : { *(.stab) } From fb11970cabd9a5d06f65e323051c427886964fce Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Fri, 13 Jan 2023 10:29:20 +0800 Subject: [PATCH 32/33] fix serial ioctl error in control framework --- APP_Framework/Framework/control/ipc_protocol/Kconfig | 1 + APP_Framework/Framework/control/shared/control_io.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/APP_Framework/Framework/control/ipc_protocol/Kconfig b/APP_Framework/Framework/control/ipc_protocol/Kconfig index 2e97d8832..55c7718f1 100755 --- a/APP_Framework/Framework/control/ipc_protocol/Kconfig +++ b/APP_Framework/Framework/control/ipc_protocol/Kconfig @@ -9,6 +9,7 @@ endif config CONTROL_PROTOCOL_MODBUS_UART bool "Using modbus_uart control protocol" default n + select CONTROL_USING_SERIAL_485 if CONTROL_PROTOCOL_MODBUS_UART source "$APP_DIR/Framework/control/ipc_protocol/modbus_uart/Kconfig" endif diff --git a/APP_Framework/Framework/control/shared/control_io.c b/APP_Framework/Framework/control/shared/control_io.c index 4ad09b789..5fdf3119c 100644 --- a/APP_Framework/Framework/control/shared/control_io.c +++ b/APP_Framework/Framework/control/shared/control_io.c @@ -81,7 +81,8 @@ void Uart485Init(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8 printf("open fd error %d\n", uart_fd); return; } - printf("Uart485Init open fd %d\n", uart_fd); + printf("Uart485Init open fd %d baud_rate %d data_bits %d stop_bits %d check_mode %d\n", + uart_fd, baud_rate, data_bits, stop_bits, check_mode); struct SerialDataCfg cfg; cfg.serial_baud_rate = baud_rate; @@ -97,7 +98,10 @@ void Uart485Init(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uint8 #endif cfg.serial_timeout = 10000; - if (ret != PrivIoctl(uart_fd, OPE_INT, &cfg)) { + ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; + ioctl_cfg.args = &cfg; + ret = PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg); + if (0 != ret) { printf("ioctl fd error %d\n", ret); return; } From 55654af2756fb98c00d70597dc298ac100d62693 Mon Sep 17 00:00:00 2001 From: Liu_Weichao Date: Fri, 13 Jan 2023 15:35:34 +0800 Subject: [PATCH 33/33] fix serial receive data bug in control framework on xidatong-arm32 board --- .../ipc_protocol/modbus_uart/modbus_uart.c | 18 +++++++++++++++--- .../modbus_uart/test_recipe_modbus_uart.json | 2 +- .../Framework/control/shared/control_io.c | 10 +++------- .../XiZi_IIoT/resources/serial/dev_serial.c | 2 ++ 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_uart/modbus_uart.c b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/modbus_uart.c index ef5f0351c..bd86ecf0c 100644 --- a/APP_Framework/Framework/control/ipc_protocol/modbus_uart/modbus_uart.c +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/modbus_uart.c @@ -107,16 +107,28 @@ static int ModbusUartTransformRecvBuffToData(ModbusUartReadItem *p_read_item, ui */ static int ModbusUartGetDataBySerial(ModbusUartReadItem *p_read_item) { - uint32_t read_length = 0; + uint32_t cmd_length, read_length = 0; memset(recv_buff, 0, sizeof(recv_buff)); ModbusUartDataInfo *p_modbus_uart_data_info = &(p_read_item->data_info); - BasicPlcDataInfo *p_base_data_info = &(p_modbus_uart_data_info->base_data_info); + BasicPlcDataInfo *p_base_data_info = &(p_modbus_uart_data_info->base_data_info); + ModbusUartFunctionCode function_code = p_modbus_uart_data_info->function_code; ControlPrintfList("SEND", p_base_data_info->p_command, p_base_data_info->command_length); SerialWrite(p_base_data_info->p_command, p_base_data_info->command_length); - read_length = SerialRead(recv_buff, sizeof(recv_buff)); + if (READ_COIL_STATUS == function_code || READ_INPUT_STATUS == function_code) { + cmd_length = 6; + } else if (READ_HOLDING_REGISTER == function_code || READ_INPUT_REGISTER == function_code) { + cmd_length = 7; + } else if (WRITE_SINGLE_COIL == function_code || WRITE_SINGLE_REGISTER == function_code) { + cmd_length = 8; + } else { + //MULTIPLE_COIL and MULTIPLE_REGISTER to do + cmd_length = 0; + } + + read_length = SerialRead(recv_buff, cmd_length); if (read_length) { ControlPrintfList("RECV", recv_buff, read_length); return ModbusUartTransformRecvBuffToData(p_read_item, recv_buff); diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_uart/test_recipe_modbus_uart.json b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/test_recipe_modbus_uart.json index 613d010c6..1f5cf41de 100644 --- a/APP_Framework/Framework/control/ipc_protocol/modbus_uart/test_recipe_modbus_uart.json +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/test_recipe_modbus_uart.json @@ -24,7 +24,7 @@ "value_type": 9, "function_code": 3, "start_address": 208, - "quantity": 2 + "quantity": 1 } ] } \ No newline at end of file diff --git a/APP_Framework/Framework/control/shared/control_io.c b/APP_Framework/Framework/control/shared/control_io.c index 5fdf3119c..fbb01b7ec 100644 --- a/APP_Framework/Framework/control/shared/control_io.c +++ b/APP_Framework/Framework/control/shared/control_io.c @@ -162,7 +162,7 @@ void SerialWrite(uint8_t *write_data, int length) PrivWrite(uart_fd, write_data, length); - PrivTaskDelay(10); + PrivTaskDelay(15); Set485Input(); #endif } @@ -181,15 +181,11 @@ int SerialRead(uint8_t *read_data, int length) while (data_size < length) { data_recv_size = PrivRead(uart_fd, read_data + data_recv_size, length); - // for (int i = 0; i < data_recv_size; i ++) { - // printf("idx %d data 0x%x\n", i, recv_data[i + data_size]); - // } - data_size += data_recv_size; } - //need to wait 25ms , make sure write cmd again and receive data successfully - PrivTaskDelay(25); + //need to wait 30ms , make sure write cmd again and receive data successfully + PrivTaskDelay(30); return data_size; #endif diff --git a/Ubiquitous/XiZi_IIoT/resources/serial/dev_serial.c b/Ubiquitous/XiZi_IIoT/resources/serial/dev_serial.c index 43c94addd..428e1c935 100644 --- a/Ubiquitous/XiZi_IIoT/resources/serial/dev_serial.c +++ b/Ubiquitous/XiZi_IIoT/resources/serial/dev_serial.c @@ -154,6 +154,8 @@ static inline int SerialDevIntRead(struct SerialHardwareDevice *serial_dev, stru CriticalAreaUnLock(lock); + MdelayKTask(20); + *read_data = get_char; read_data++; read_length--;