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/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/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..3aa5ac1e0 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.c +++ b/APP_Framework/Framework/transform_layer/xizi/transform.c @@ -154,7 +154,6 @@ int PrivIoctl(int fd, int cmd, void *args) { int ret; struct PrivIoctlCfg *ioctl_cfg = (struct PrivIoctlCfg *)args; - switch (ioctl_cfg->ioctl_driver_type) { case SERIAL_TYPE: @@ -163,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/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/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/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/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/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);