diff --git a/APP_Framework/Applications/app_test/Kconfig b/APP_Framework/Applications/app_test/Kconfig index 1c2965bd2..12537ed19 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -192,6 +192,23 @@ menu "test app" bool "Config test lcd device" default n + 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 68801066a..74d981eac 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_ETHERNET),y) + SRC_FILES += test_ethernet.c + endif include $(KERNEL_ROOT)/compiler.mk endif 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/Applications/app_test/test_ethernet.c b/APP_Framework/Applications/app_test/test_ethernet.c new file mode 100644 index 000000000..6e551c004 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ethernet.c @@ -0,0 +1,173 @@ +#include +#include +#include + +#include + +#define BUFF_SIZE 128 +#define RECV_SIZE 16 +#define TCP_PORT 12345 + +const static uint32_t sn = 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(sn, buf, buf_size); + if (ret < 0) { + wiz_sock_close(sn); + 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(sn)) { + case SOCK_CLOSE_WAIT: + wiz_sock_disconnect(sn); + break; + case SOCK_CLOSED: + wiz_socket(sn, Sn_MR_TCP, 5000, 0x00); + break; + case SOCK_INIT: + KPrintf("[SOCKET CLIENT] sock init.\n"); + wiz_sock_connect(sn, dst_ip, dst_port); + break; + case SOCK_ESTABLISHED: + 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(sn, buf, buf_size); + if (ret < 0) { + wiz_sock_close(sn); + 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], 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("read ret is %d\n",ret); + if(ret>0){ + printf("client recv msg successfully!\n"); + printf("%s\n",buf); + } + }; + PrivTaskDelay(1000); + } + + + + + 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_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/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..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) @@ -10,6 +7,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 @@ -17,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/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/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/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/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); diff --git a/APP_Framework/Framework/control/Kconfig b/APP_Framework/Framework/control/Kconfig index e9e0a1753..7d757e4ab 100755 --- a/APP_Framework/Framework/control/Kconfig +++ b/APP_Framework/Framework/control/Kconfig @@ -2,12 +2,33 @@ 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 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 bc72c4672..55c7718f1 100755 --- a/APP_Framework/Framework/control/ipc_protocol/Kconfig +++ b/APP_Framework/Framework/control/ipc_protocol/Kconfig @@ -1,8 +1,15 @@ config CONTROL_PROTOCOL_MODBUS_TCP bool "Using modbus_tcp control protocol" default n + select CONTROL_USING_SOCKET +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 - + 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/ipc_protocol/include/modbus_tcp.h b/APP_Framework/Framework/control/ipc_protocol/include/modbus_tcp.h new file mode 100755 index 000000000..3d1532ace --- /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 0x01 +#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/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/modbus_tcp.c b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c index 9fc2d4c6a..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 @@ -15,6 +15,465 @@ * @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 void 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; + + ModbusTcpFunctionCode function_code = p_modbus_tcp_data_info->function_code; + uint8_t *p_data = p_modbus_tcp_data_info->base_data_info.p_data; + + uint8_t bytes_count = recv_buff[8]; + + 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) { + 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"); +} + +#ifdef CONTROL_USING_SOCKET +/** + * @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!\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! 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); + ModbusTcpTransformRecvBuffToData(p_read_item, recv_buff); + + return 0; + } + } + + if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) { + printf("Send command failed, errno is %d!\n", errno); + continue; + } else { + return -1; + } + } + return -2; +} +#endif + +/** + * @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; + } + + memset(p_base_data_info->p_command, 0, p_base_data_info->command_length); + + 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[5] = 0x09; + } + + 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[10] = quantity >> 8; + p_base_data_info->p_command[11] = 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!\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 = 10; + break; + 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 + i] = write_data_buffer[i]; + } + + p_base_data_info->command_ready = 1; + + 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 ++) { +#ifdef CONTROL_USING_SOCKET + /*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); +#endif + } + + /*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); + +#ifdef CONTROL_USING_SOCKET + ControlDisconnectSocket(&plc_socket); +#endif + + 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_tcp.json b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus_tcp.json new file mode 100644 index 000000000..b08980aaf --- /dev/null +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus_tcp.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/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..bd86ecf0c --- /dev/null +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_uart/modbus_uart.c @@ -0,0 +1,424 @@ +/* + * 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 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); + 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); + + 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); + } +} + +/** + * @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..1f5cf41de --- /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": 1 + } + ] +} \ 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 9839fe26e..91e27b474 100755 --- a/APP_Framework/Framework/control/plc_protocol/Kconfig +++ b/APP_Framework/Framework/control/plc_protocol/Kconfig @@ -1,15 +1,28 @@ config CONTROL_PROTOCOL_FINS bool "Using fins control protocol" default n + select CONTROL_USING_SOCKET +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/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/fins/fins.c b/APP_Framework/Framework/control/plc_protocol/fins/fins.c index 1c20eba77..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*/ @@ -328,7 +332,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); } } @@ -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(); @@ -390,6 +396,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 +413,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 +436,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/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..c441642b9 100755 --- a/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig +++ b/APP_Framework/Framework/control/plc_protocol/melsec/Kconfig @@ -1,2 +1,64 @@ +choice + prompt "select melsec protocol" + default CONTROL_PROTOCOL_MELSEC_1E + config CONTROL_PROTOCOL_MELSEC_1E + 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 SOCKET" + select CONTROL_USING_SOCKET + config CONTROL_PROTOCOL_MELSEC_3E_IQ_R + 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 CONTROL_USING_SERIAL_485 + + config CONTROL_PROTOCOL_MELSEC_3C + bool "support melsec_3c protocol, using SERIAL" + select CONTROL_USING_SERIAL_485 +endchoice + +if CONTROL_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/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..27b97a831 --- /dev/null +++ b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c @@ -0,0 +1,805 @@ +/* +* 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) +{ + 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; +} + +#ifdef CONTROL_USING_SOCKET +/** + * @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) +{ + 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; +} +#endif + +/** + * @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) +{ + 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); + } +} + +/** + * @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 ++) { + + if ((PROTOCOL_MELSEC_1C == control_protocol->protocol_type) || (PROTOCOL_MELSEC_3C == control_protocol->protocol_type)) { + MelsecGetDataBySerial((MelsecReadItem *)melsec_read_item + i); + } else { +#ifdef CONTROL_USING_SOCKET + /*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 + } + } + + /*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' ms*/ + 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) +{ + if ((PROTOCOL_MELSEC_1C != control_protocol->protocol_type) && (PROTOCOL_MELSEC_3C != control_protocol->protocol_type)) { +#ifdef CONTROL_USING_SOCKET + ControlDisconnectSocket(&plc_socket); +#endif + } + + 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; + 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; + 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 = 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; + + 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; +} + +/** + * @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; + } + + memset(p_recipe->read_item, 0, sizeof(MelsecReadItem)); + + p_recipe->ControlProtocolFormatCmd = MelsecProtocolFormatCmd; + + p_recipe->done = &melsec_protocol_done; + + 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 new file mode 100644 index 000000000..7c67c0263 --- /dev/null +++ b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_1c.json @@ -0,0 +1,34 @@ +{ + "device_id": 769, + "device_name": "S01", + "communication_type": 1, + "serial_config": { + "station": 1, + "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..5fb0e0dc2 --- /dev/null +++ b/APP_Framework/Framework/control/plc_protocol/melsec/test_recipe_melsec_3c.json @@ -0,0 +1,34 @@ +{ + "device_id": 770, + "device_name": "S02", + "communication_type": 1, + "serial_config": { + "station": 1, + "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_def.c b/APP_Framework/Framework/control/shared/control_def.c index 27ab2d761..c19ae9757 100644 --- a/APP_Framework/Framework/control/shared/control_def.c +++ b/APP_Framework/Framework/control/shared/control_def.c @@ -33,6 +33,18 @@ 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 + +#ifdef CONTROL_PROTOCOL_MODBUS_TCP +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 | @@ -55,6 +67,19 @@ 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 +#ifdef CONTROL_PROTOCOL_MODBUS_TCP + { PROTOCOL_MODBUS_TCP, ModbusTcpProtocolInit }, +#endif +#ifdef CONTROL_PROTOCOL_MODBUS_UART + { PROTOCOL_MODBUS_UART, ModbusUartProtocolInit }, +#endif { PROTOCOL_END, NULL }, }; @@ -125,12 +150,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); } /** @@ -184,13 +210,14 @@ 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]); } printf("\n**************************************\n"); } +#ifdef CONTROL_USING_SOCKET /** * @description: Control Framework Connect Socket * @param p_plc - basic socket plc pointer @@ -267,6 +294,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 9126c6c1d..96957ad20 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; @@ -89,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 eb7172883..fbb01b7ec 100644 --- a/APP_Framework/Framework/control/shared/control_io.c +++ b/APP_Framework/Framework/control/shared/control_io.c @@ -20,6 +20,96 @@ #include +#ifdef CONTROL_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 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; + 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; + + 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; + } + + printf("%s done!\n", __func__); +} +#endif + /** * @description: Control Framework Socket Init * @param ip - local ip pointer @@ -33,9 +123,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 } /** @@ -48,5 +143,50 @@ 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 CONTROL_USING_SERIAL_485 + Uart485Init(baud_rate, data_bits, stop_bits, check_mode); +#endif +} + +/** + * @description: Control Framework Serial Write + * @param write_data - write data + * @param length - length + * @return + */ +void SerialWrite(uint8_t *write_data, int length) +{ +#ifdef CONTROL_USING_SERIAL_485 + Set485Output(); + PrivTaskDelay(20); + + PrivWrite(uart_fd, write_data, length); + + PrivTaskDelay(15); + Set485Input(); +#endif +} + +/** + * @description: Control Framework Serial Read + * @param read_data - read data + * @param length - length + * @return read data size + */ +int SerialRead(uint8_t *read_data, int length) +{ +#ifdef CONTROL_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); + data_size += data_recv_size; + } + + //need to wait 30ms , make sure write cmd again and receive data successfully + PrivTaskDelay(30); + + return data_size; +#endif } diff --git a/APP_Framework/Framework/control/shared/control_io.h b/APP_Framework/Framework/control/shared/control_io.h index 52c501486..9446916a6 100644 --- a/APP_Framework/Framework/control/shared/control_io.h +++ b/APP_Framework/Framework/control/shared/control_io.h @@ -24,26 +24,42 @@ #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); /*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 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 fa5819f4f..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,5 +3,16 @@ 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" + +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/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/Readme.md b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md new file mode 100644 index 000000000..3ca0ceec6 --- /dev/null +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md @@ -0,0 +1,35 @@ +# 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 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*. 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..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 @@ -1,25 +1,29 @@ #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; - #define THREAD_PRIORITY_D (11) + +static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX - 1; +static _ioctl_shoot_para shoot_para_t = {0}; + 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 kpu_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; -static _ioctl_shoot_para shoot_para_t = {0}; -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; @@ -29,6 +33,7 @@ volatile uint32_t g_ai_done_flag; static void ai_done(void *ctx) { g_ai_done_flag = 1; } + void k210_detect(char *json_file_path) { int ret = 0; @@ -36,45 +41,72 @@ 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) { + if (!detect_params.is_valid) + { return; } - g_fd = open("/dev/ov2640", O_RDONLY); - if (g_fd < 0) { - printf("open ov2640 fail !!"); +#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) + { + printf("open %s fail !!", CAMERA_DEV_DRIVER); return; } + + // 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); - if (NULL == showbuffer) { - close(g_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); - if (NULL == kpurgbbuffer) { - close(g_fd); - rt_free_align(showbuffer); - printf("kpurgbbuffer apply memory fail !!"); - return; - } + 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; + + // alloc the memory for camera and kpu running model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); - if (NULL == model_data) { - rt_free_align(showbuffer); - rt_free_align(kpurgbbuffer); - close(g_fd); + if (NULL == model_data) + { + free(showbuffer); + free(kpurgbbuffer); + 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) + { + 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) + { + PrivClose(camera_fd); + free(showbuffer); + printf("kpurgbbuffer 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 */ @@ -83,83 +115,123 @@ 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); - kmodel_fd = open(kmodel_path, O_RDONLY); - if (kmodel_fd < 0) { + 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); + + if (kmodel_fd < 0) + { printf("open kmodel fail"); - close(g_fd); + PrivClose(camera_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); return; - } else { - size = read(kmodel_fd, model_data, detect_params.kmodel_size); - if (size != detect_params.kmodel_size) { + } + else + { + 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(g_fd); - close(kmodel_fd); + PrivClose(camera_fd); + PrivClose(kmodel_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); return; - - } else { + } + else + { + PrivClose(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 + - detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0])), - (uint32_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 + - 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)); - if (kpu_load_kmodel(&detect_task, model_data_align) != 0) { + (uintptr_t)(kpurgbbuffer + + 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]), + (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)); +#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]; + 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); +#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(g_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; 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]; } 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); /* åˆ›å»ŗēŗæēØ‹ 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(g_fd); + PrivClose(camera_fd); } } // #ifdef __RT_THREAD_H__ @@ -168,39 +240,93 @@ 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; + 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; - 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); + while (1) + { 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 (EOF == ret) + { printf("ov2640 can't wait event flag"); - rt_free(showbuffer); - close(g_fd); + free(showbuffer); + PrivClose(camera_fd); pthread_exit(NULL); return NULL; } - if (dmalock_sync_take(&dma_ch, 2000)) { + + 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)) + { printf("Fail to take DMA channel"); } kpu_run_kmodel(&detect_task, kpurgbbuffer, DMAC_CHANNEL5, ai_done, NULL); while (!g_ai_done_flag) ; dmalock_release(dma_ch); +#elif defined ADD_XIZI_FETURES + 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 */ - - 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, @@ -208,13 +334,29 @@ static void *thread_detect_entry(void *parameter) detect_info.obj[cnt].prob); } #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); +#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 + (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; + PrivWrite(lcd_fd, &graph_param, NULL_PARAMETER); + } #endif - usleep(500); - if (1 == if_exit) { + +#endif + if (1 == if_exit) + { if_exit = 0; printf("thread_detect_entry exit"); pthread_exit(NULL); @@ -224,10 +366,11 @@ static void *thread_detect_entry(void *parameter) void detect_delete() { - if (showbuffer != NULL) { + if (showbuffer != NULL) + { int ret = 0; - close(g_fd); - close(kmodel_fd); + PrivClose(camera_fd); + PrivClose(kmodel_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); @@ -235,46 +378,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/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/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/APP_Framework/Framework/transform_layer/xizi/transform.c b/APP_Framework/Framework/transform_layer/xizi/transform.c index f2d53d155..8995c7906 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**************************/ @@ -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,17 +162,16 @@ 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: case WDT_TYPE: case CAMERA_TYPE: + case KPU_TYPE: ret = ioctl(fd, cmd, ioctl_cfg->args); break; default: diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.h b/APP_Framework/Framework/transform_layer/xizi/transform.h index 7514d9297..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, }; @@ -227,6 +228,36 @@ 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, +}; + +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 @@ -236,6 +267,35 @@ struct RtcDrvConfigureParam #define MY_INDEV_X BSP_LCD_Y_MAX #define MY_INDEV_Y BSP_LCD_X_MAX +#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 0xA2U +#define REG_SCCB_WRITE 0xA3U +#define SCCB_REG_LENGTH 0x08U + +#define SET_DISPLAY_ADDR (0xD1) +#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 +#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/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..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 @@ -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,28 @@ 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) +{ + attr->stacksize = stack_size; + return 0; +} + void pthread_exit(void *value_ptr){ //todo add exit value UserTaskQuit(); 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 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/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/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..584e9b578 --- /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 ; + +uint32_t 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-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/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..b26d3e80c --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/arch_interrupt.h @@ -0,0 +1,54 @@ +/* +* 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); + +//! @brief +typedef enum { + CPU_0, + CPU_1, + CPU_2, + CPU_3, +} cpuid_e; + +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 e69de29bb..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 @@ -0,0 +1,92 @@ +#include + +.global ExceptionVectors + +.section ".startup","ax" +.globl _reset + +_reset: + + /* 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, #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, #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, #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, #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 */ + 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/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 new file mode 100644 index 000000000..bc9a68213 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/exception.S @@ -0,0 +1,145 @@ +#include + +.section .text.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 +.globl UndefInstrExceptionHandle +.globl SwiExceptionHandle +.globl PrefetchAbortExceptionHandle +.globl DataAbortExceptionHandle +.globl ResvExceptionHandle +.globl ExceptionIsrEntry +.globl FiqExceptionHandle + +_ResetException: + .word _reset +_UndefInstrException: + .word UndefInstrExceptionHandle +_SwiException: + .word SwiExceptionHandle +_PrefetchAbortException: + .word PrefetchAbortExceptionHandle +_DataAbortAbortException: + .word DataAbortExceptionHandle +_ResvException: + .word ResvExceptionHandle +_IrqException: + .word ExceptionIsrEntry +_FiqException: + .word FiqExceptionHandle + + .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: +1: + b 1b + +.align 5 +.globl SwiExceptionHandle +SwiExceptionHandle: + push_svc_reg + bl DoSvcCallProcess + b . + +.align 5 +.globl PrefetchAbortExceptionHandle +PrefetchAbortExceptionHandle: +1: + b 1b + +.align 5 +.globl DataAbortExceptionHandle +DataAbortExceptionHandle: +1: + b 1b + +.align 5 +.globl ResvExceptionHandle +ResvExceptionHandle: +1: + b 1b + +.section .text.isr, "ax" +.align 5 +.globl ExceptionIsrEntry +ExceptionIsrEntry: + + stmfd sp!, {r0-r12,lr} + + bl DoIrqProcess + + @ 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: +1: + b 1b 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..82b337331 --- /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 "gic.h" +#include "gic_registers.h" +#include "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.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/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_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..3105805d1 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/interrupt.c @@ -0,0 +1,111 @@ +// extern void _svcall(uintptr_t* contex); +#include +#include +#include + +uint32_t DisableLocalInterrupt(void) +{ + uint32_t intSave; + __asm__ __volatile__( + "mrs %0, cpsr \n" + "cpsid if " + : "=r"(intSave) + : + : "memory"); + return intSave; +} + +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; +} + +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..e929933ca --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/Makefile @@ -0,0 +1,8 @@ +SRC_FILES := board.c ivt.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..d36fb19fe --- /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 + +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/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/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/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/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/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 new file mode 100644 index 000000000..67abbe98d --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/link.lds @@ -0,0 +1,170 @@ + + +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 +{ +/* + * -- 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 : + { + *(.startup) + *(.text) + *(.text.*) + + /* section information for finsh shell */ + . = ALIGN(4); + __isrtbl_idx_start = .; + KEEP(*(.isrtbl.idx)) + __isrtbl_start = .; + KEEP(*(.isrtbl)) + __isrtbl_end = .; + . = ALIGN(4); + } > DDR + __text_end = .; + + __rodata_start = .; + .rodata : + { + *(.rodata) *(.rodata.*) + } > DDR + __rodata_end = .; + + . = ALIGN(4); + .ctors : + { + PROVIDE(__ctors_start__ = .); + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + PROVIDE(__ctors_end__ = .); + } > DDR + + .dtors : + { + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + } > DDR + + /* . = ALIGN(16 * 1024); + .l1_page_table : + { + __l1_page_table_start = .; + . += 16K; + } */ + + . = ALIGN(8); + __data_start = .; + .data : + { + *(.data) + *(.data.*) + } > DDR + __data_end = .; + + . = ALIGN(8); + __bss_start = .; + .bss : + { + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + } > DDR + . = ALIGN(4); + __bss_end = .; + + .stacks : + { + __stacks_start = .; + . += STACK_SIZE; + __stacks_end = .; + stack_top = .; + } > DDR + + /* 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/hardkernel/abstraction/interrupt.c b/Ubiquitous/XiZi_AIoT/services/boards/imx6q-sabrelite/third_party_driver/Kconfig old mode 100755 new mode 100644 similarity index 100% rename from Ubiquitous/XiZi_AIoT/hardkernel/abstraction/interrupt.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/lib/xxx.c b/Ubiquitous/XiZi_AIoT/services/drivers/Kconfig similarity index 100% rename from Ubiquitous/XiZi_AIoT/services/lib/xxx.c rename to Ubiquitous/XiZi_AIoT/services/drivers/Kconfig 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 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/edu-riscv64/board.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c index ad4ec5406..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" @@ -70,6 +71,8 @@ extern int HwLcdInit(void); extern int HwSpiInit(void); extern int HwSoftSPIInit(void); extern int HwWiznetInit(void); +extern int HwDvpInit(void); +extern int HwKpuInit(void); #include #ifdef MOUNT_USB @@ -220,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/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/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..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 @@ -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; @@ -115,25 +122,74 @@ 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; } +/** + * @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; int cmd_type = args->configure_cmd; 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: 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 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; + 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; + + // 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/ethernet/connect_w5500.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c index 22803ee9e..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,13 +22,12 @@ 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}, - .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}; @@ -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) { @@ -473,33 +472,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..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 @@ -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), @@ -106,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/connect_dvp.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h index 178fc5ddd..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,6 +25,44 @@ extern "C" { #endif +#define REG_SCCB_READ 0xA2U +#define REG_SCCB_WRITE 0xA3U +#define SCCB_REG_LENGTH 0x08U + +#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 + + +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/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/include/drv_io_config.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h index 4c4f86972..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 @@ -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 */ } @@ -97,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 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/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 */ 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..279af3459 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig @@ -0,0 +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 new file mode 100644 index 000000000..3d79cd367 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile @@ -0,0 +1,4 @@ +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/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..01e2d21b5 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c @@ -0,0 +1,1640 @@ +#include "kpu.h" +#include +#include +#include +#include +#include +#include "printf.h" +#include "dmac.h" +#include +#include "bsp.h" +#include +#include +#include "plic.h" +#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; + + 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(); +} + +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; + 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 + }; + 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) + 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/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 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); 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 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) */ } 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 1a64fc4f2..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[] = { @@ -300,7 +326,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/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/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) { 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); } 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/path_kernel.mk b/Ubiquitous/XiZi_IIoT/path_kernel.mk index ee0a7c992..bca1aec03 100755 --- a/Ubiquitous/XiZi_IIoT/path_kernel.mk +++ b/Ubiquitous/XiZi_IIoT/path_kernel.mk @@ -475,6 +475,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) @@ -495,6 +498,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/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/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; }; 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; +} 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--; 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..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,10 +847,9 @@ static uint32 SdReadMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const uint read_param.size = 1; start_time = 0; - + read[0] = 0; 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); @@ -860,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; @@ -922,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; @@ -1035,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 ++) { @@ -1058,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); @@ -1233,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); 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()) /**