From d8ac0998b27d950f15e6a09552556145e6e1f9be Mon Sep 17 00:00:00 2001 From: wuzheng Date: Mon, 28 Nov 2022 09:38:35 +0800 Subject: [PATCH 01/15] fix configure network problem and configure fpio for w5500 --- .../ethernet/connect_w5500.c | 65 ++++++++++++------- .../third_party_driver/gpio/drv_io_config.c | 5 ++ .../include/drv_io_config.h | 3 +- .../third_party_driver/spi/Kconfig | 8 +-- 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c index 22803ee9e..ba1e0b810 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c @@ -26,9 +26,9 @@ const uint32_t socket_tcp = 0; const uint32_t g_wiznet_buf_size = 2048; static wiz_NetInfo g_wiz_netinfo = {.mac = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11}, - .ip = {192, 168, 31, 13}, - .sn = {255, 255, 255, 0}, - .gw = {192, 168, 31, 1}, + .ip = {192, 168, 131, 42}, + .sn = {255, 255, 254, 0}, + .gw = {192, 168, 130, 1}, .dns = {0, 0, 0, 0}, .dhcp = NETINFO_STATIC}; @@ -473,33 +473,52 @@ void ifconfig() { SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), ifconfig, ifconfig, printf w5500 configurations); -void char_arr_assign(uint8_t **dst, uint32_t *src, uint32_t len) { +void char_arr_assign(uint8_t *dst, uint32_t *src, int len) { for (int i = 0; i < len; ++i) { - (*dst)[i] = (uint8_t)(src[i]); + dst[i] = (uint8_t)(src[i]); } } -void config_w5500_network(char *mac, char *ip, char *sn, char *gw, char *dns) { +char *network_param_name[] = {"ip", "sn", "gw"}; + +void config_w5500_network(int argc, char *argv[]) { + if (argc < 2) { + KPrintf("[W5500] Network config require params.\n"); + return; + } + wiz_NetInfo wiz_netinfo; - uint32_t tmp_arr[4]; - // config netinfo - sscanf(mac, "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1], &tmp_arr[2], - &tmp_arr[3]); - char_arr_assign((uint8_t **)&wiz_netinfo.mac, tmp_arr, 4); - sscanf(ip, "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1], &tmp_arr[2], &tmp_arr[3]); - char_arr_assign((uint8_t **)&wiz_netinfo.ip, tmp_arr, 4); - sscanf(sn, "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1], &tmp_arr[2], &tmp_arr[3]); - char_arr_assign((uint8_t **)&wiz_netinfo.sn, tmp_arr, 4); - sscanf(gw, "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1], &tmp_arr[2], &tmp_arr[3]); - char_arr_assign((uint8_t **)&wiz_netinfo.gw, tmp_arr, 4); - sscanf(dns, "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1], &tmp_arr[2], - &tmp_arr[3]); - char_arr_assign((uint8_t **)&wiz_netinfo.dns, tmp_arr, 4); - // set new netinfo + memcpy(&wiz_netinfo, &g_wiz_netinfo, sizeof(wiz_NetInfo)); + + int cur_arg_idx = 1; + + while (argv[cur_arg_idx] != NULL) { + if (argv[cur_arg_idx + 1] == NULL) { + KPrintf("[W5500] Network config %s requires value.\n", argv[cur_arg_idx]); + return; + } + uint32_t tmp_arr[4]; + sscanf(argv[cur_arg_idx + 1], "%d.%d.%d.%d", &tmp_arr[0], &tmp_arr[1], + &tmp_arr[2], &tmp_arr[3]); + if (memcmp(argv[cur_arg_idx], network_param_name[0], 2 * sizeof(char)) == + 0) { + char_arr_assign(wiz_netinfo.ip, tmp_arr, 4); + } else if (memcmp(argv[cur_arg_idx], network_param_name[1], + 2 * sizeof(char)) == 0) { + char_arr_assign(wiz_netinfo.sn, tmp_arr, 4); + } else if (memcmp(argv[cur_arg_idx], network_param_name[2], + 2 * sizeof(char)) == 0) { + char_arr_assign(wiz_netinfo.gw, tmp_arr, 4); + } else { + KPrintf("[W5500] Invalid network param.\n"); + } + cur_arg_idx += 2; + } + ctlnetwork(CN_SET_NETINFO, (void *)&wiz_netinfo); + KPrintf("[W5500] Network config success.\n", argv[cur_arg_idx]); ifconfig(); } -SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | - SHELL_CMD_PARAM_NUM(5), +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), config_w5500_network, config_w5500_network, set w5500 configurations); \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c index 0c7167441..33bf5bd75 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c @@ -50,6 +50,11 @@ static struct io_config IOCONFIG(BSP_LCD_RST_PIN, HS_GPIO(FPIOA_LCD_RST)), #endif +#ifdef BSP_USING_W5500 + IOCONFIG(BSP_WIZ_RST_PIN, HS_GPIO(WIZ_RST_PIN)), + IOCONFIG(BSP_WIZ_INT_PIN, HS_GPIO(WIZ_INT_PIN)), +#endif + #ifdef BSP_USING_SPI1 IOCONFIG(BSP_SPI1_CLK_PIN, FUNC_SPI1_SCLK), IOCONFIG(BSP_SPI1_D0_PIN, FUNC_SPI1_D0), diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h index 4c4f86972..2ff8356b0 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h @@ -47,7 +47,8 @@ enum HS_GPIO_CONFIG { SPI1_CS3_PIN, #endif #ifdef BSP_USING_W5500 - WIZ_RST_PIN, WIZ_INT_PIN, + WIZ_RST_PIN, + WIZ_INT_PIN, #endif GPIO_ALLOC_START /* index of gpio driver start */ } diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Kconfig index d1ebdeb3c..19f485458 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/spi/Kconfig @@ -12,13 +12,13 @@ if BSP_USING_SPI1 default "spi1_drv" config BSP_SPI1_CLK_PIN int "spi1 clk pin number" - default 6 + default 9 config BSP_SPI1_D0_PIN int "spi1 d0 pin number" - default 8 + default 11 config BSP_SPI1_D1_PIN int "spi1 d1 pin number" - default 7 + default 10 menuconfig BSP_SPI1_USING_SS0 bool "SPI1 Enable SS0" default y @@ -28,7 +28,7 @@ if BSP_USING_SPI1 default "spi1_dev0" config BSP_SPI1_SS0_PIN int "spi1 ss0 pin number" - default 9 + default 12 menuconfig RESOURCES_SPI_LORA bool "Using spi lora function" default n From 100fe8c2d014b29e3b711858901714fabf80ddde Mon Sep 17 00:00:00 2001 From: wuzheng Date: Tue, 29 Nov 2022 09:30:48 +0800 Subject: [PATCH 02/15] add w5500 test example --- APP_Framework/Applications/app_test/Kconfig | 4 + APP_Framework/Applications/app_test/Makefile | 6 +- .../Applications/app_test/test_loraE220.c | 4 +- .../Applications/app_test/test_w5500.c | 81 +++++++++++++++++++ .../transform_layer/xizi/transform.h | 5 ++ 5 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 APP_Framework/Applications/app_test/test_w5500.c diff --git a/APP_Framework/Applications/app_test/Kconfig b/APP_Framework/Applications/app_test/Kconfig index 1c2965bd2..e25b29155 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -192,6 +192,10 @@ menu "test app" bool "Config test lcd device" default n + config USER_TEST_W5500 + select BSP_USING_W5500 + bool "Config test W5500 only for edu-riscv64" + default n endif endmenu diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 68801066a..830c40916 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -83,7 +83,11 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y) ifeq ($(CONFIG_USER_TEST_CAMERA),y) SRC_FILES += test_camera.c - endif + endif + + ifeq ($(CONFIG_USER_TEST_W5500),y) + SRC_FILES += test_w5500.c + endif include $(KERNEL_ROOT)/compiler.mk endif diff --git a/APP_Framework/Applications/app_test/test_loraE220.c b/APP_Framework/Applications/app_test/test_loraE220.c index c4409dd21..78c27f305 100644 --- a/APP_Framework/Applications/app_test/test_loraE220.c +++ b/APP_Framework/Applications/app_test/test_loraE220.c @@ -67,7 +67,6 @@ void TestLora(int argc, char *argv[]) printf("pin configure success\n"); struct SerialDataCfg uart_cfg; - memset(&uart_cfg, 0, sizeof(struct SerialDataCfg)); // loraE220 support only 9600bps with 8N1 during initializing uart_cfg.serial_baud_rate = BAUD_RATE_9600; @@ -96,7 +95,8 @@ void TestLora(int argc, char *argv[]) printf("lora configure into sleep(configure) mode\n"); // send configure data, and receive the same length of data - char sendbuff[] = {0xC0, 0x00, 0x05, 0x19, 0x49, 0xE6, 0x00, 0x17}; // config as address 1949 CH17 36.8kps + // configure loraE220 as address 1949 CH17 36.8kps + char sendbuff[] = {0xC0, 0x00, 0x05, 0x19, 0x49, 0xE6, 0x00, 0x17}; PrivTaskDelay(2000); diff --git a/APP_Framework/Applications/app_test/test_w5500.c b/APP_Framework/Applications/app_test/test_w5500.c new file mode 100644 index 000000000..2a589171f --- /dev/null +++ b/APP_Framework/Applications/app_test/test_w5500.c @@ -0,0 +1,81 @@ +#include +#include +#include + +#include + +#define BUFF_SIZE 128 +#define RECV_SIZE 16 +#define TCP_PORT 12345 + +const static uint32_t sn = 0; +const static uint32_t socket_tcp = 0; + +static int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, + uint16_t port, enum TCP_OPTION opt) { + int32_t ret = 0; + uint16_t size = 0, sentsize = 0; + switch (getSn_SR(sn)) { + case SOCK_ESTABLISHED: + if (getSn_IR(sn) & Sn_IR_CON) { + printf("%d:Connected\r\n", sn); + setSn_IR(sn, Sn_IR_CON); + } + if (opt == SEND_DATA) { + uint32_t sent_size = 0; + memset(buf,0,buf_size); + strcpy(buf,"The message has been recved"); + ret = wiz_sock_send(socket_tcp, buf, buf_size); + if (ret < 0) { + wiz_sock_close(socket_tcp); + return ret; + } + } else if (opt == RECV_DATA) { + uint32_t size = 0; + if ((size = getSn_RX_RSR(sn)) > 0) { + if (size > buf_size) size = buf_size; + memset(buf,0,buf_size); + ret = wiz_sock_recv(sn, buf, size); + printf("Recv message: %s\n",buf); + return ret; + } + } + break; + case SOCK_CLOSE_WAIT: + printf("%d:CloseWait\r\n", sn); + if ((ret = wiz_sock_disconnect(sn)) != SOCK_OK) return ret; + printf("%d:Closed\r\n", sn); + break; + case SOCK_INIT: + printf("%d:Listen, port [%d]\r\n", sn, port); + if ((ret = wiz_sock_listen(sn)) != SOCK_OK) return ret; + break; + case SOCK_CLOSED: + printf("%d:LBTStart\r\n", sn); + if ((ret = wiz_socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret; + printf("%d:Opened\r\n", sn); + break; + default: + break; + } + return 0; +} + +void TestSocketInW5500(int argc, char *argv[]) +{ + x_err_t ret; + uint8_t buf[BUFF_SIZE] = {0}; + + while (1) { + ret = wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, RECV_DATA); + if (ret > 0) { + wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, SEND_DATA); + }; + } + + return ; + +} + + +PRIV_SHELL_CMD_FUNCTION(TestSocketInW5500, a w5500 test sample, PRIV_SHELL_CMD_MAIN_ATTR); \ No newline at end of file diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.h b/APP_Framework/Framework/transform_layer/xizi/transform.h index 7514d9297..9cb3be855 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.h +++ b/APP_Framework/Framework/transform_layer/xizi/transform.h @@ -227,6 +227,11 @@ struct RtcDrvConfigureParam time_t *time; }; +enum TCP_OPTION { + SEND_DATA = 0, + RECV_DATA, +}; + #define PRIV_SYSTICK_GET (CurrentTicksGain()) #define PRIV_LCD_DEV "/dev/lcd_dev" #define MY_DISP_HOR_RES BSP_LCD_Y_MAX From a782b53423571c67b1eca1666254618c1bb62c50 Mon Sep 17 00:00:00 2001 From: wuzheng Date: Thu, 1 Dec 2022 09:37:43 +0800 Subject: [PATCH 03/15] adapt qs-fs and qs-fx for edu-riscv64 --- .../sensor_app/winddirection_qs_fx.c | 11 +++- .../Applications/sensor_app/windspeed_qs_fs.c | 11 +++- .../Framework/sensor/winddirection/Kconfig | 8 +++ .../sensor/winddirection/qs-fx/qs-fx.c | 50 +++++++++++++++++-- .../Framework/sensor/windspeed/Kconfig | 10 +++- .../Framework/sensor/windspeed/qs-fs/qs-fs.c | 50 ++++++++++++++++++- .../third_party_driver/gpio/drv_io_config.c | 12 +++-- .../include/drv_io_config.h | 6 ++- 8 files changed, 143 insertions(+), 15 deletions(-) diff --git a/APP_Framework/Applications/sensor_app/winddirection_qs_fx.c b/APP_Framework/Applications/sensor_app/winddirection_qs_fx.c index 26d53601a..70c78f067 100644 --- a/APP_Framework/Applications/sensor_app/winddirection_qs_fx.c +++ b/APP_Framework/Applications/sensor_app/winddirection_qs_fx.c @@ -29,7 +29,14 @@ void WindDirectionQsFx(void) struct SensorQuantity *wind_direction = SensorQuantityFind(SENSOR_QUANTITY_QS_FX_WINDDIRECTION, SENSOR_QUANTITY_WINDDIRECTION); SensorQuantityOpen(wind_direction); PrivTaskDelay(2000); - uint16_t result = SensorQuantityReadValue(wind_direction); - printf("wind direction : %d degree\n", result); + int result = 0; + for(int i=0;i<2000;i++) + { + result = 0; + PrivTaskDelay(1000); + result = SensorQuantityReadValue(wind_direction); + if(result > 0) + printf("wind direction : %d degree\n", result); + } SensorQuantityClose(wind_direction); } diff --git a/APP_Framework/Applications/sensor_app/windspeed_qs_fs.c b/APP_Framework/Applications/sensor_app/windspeed_qs_fs.c index d9ec38f5f..b55f4e3ea 100644 --- a/APP_Framework/Applications/sensor_app/windspeed_qs_fs.c +++ b/APP_Framework/Applications/sensor_app/windspeed_qs_fs.c @@ -29,7 +29,14 @@ void WindSpeedQsFs(void) struct SensorQuantity *wind_speed = SensorQuantityFind(SENSOR_QUANTITY_QS_FS_WINDSPEED, SENSOR_QUANTITY_WINDSPEED); SensorQuantityOpen(wind_speed); PrivTaskDelay(2000); - uint16_t result = SensorQuantityReadValue(wind_speed); - printf("wind speed : %d.%d m/s\n", result/10, result%10); + int result = 0; + for(int i=0;i<2000;i++) + { + result = 0; + PrivTaskDelay(1000); + result = SensorQuantityReadValue(wind_speed); + if(result > 0) + printf("wind speed : %d.%d m/s\n", result/10, result%10); + } SensorQuantityClose(wind_speed); } diff --git a/APP_Framework/Framework/sensor/winddirection/Kconfig b/APP_Framework/Framework/sensor/winddirection/Kconfig index 726bfea8a..7fdbd7bd4 100644 --- a/APP_Framework/Framework/sensor/winddirection/Kconfig +++ b/APP_Framework/Framework/sensor/winddirection/Kconfig @@ -22,6 +22,14 @@ config SENSOR_QS_FX default "/dev/uart2_dev2" depends on !SENSOR_QS_FX_DRIVER_EXTUART + config SENSOR_DEVICE_QS_FX_PIN_DEV + string "qs-fx pin device name" + default "/dev/pin_dev" + + config SENSOR_DEVICE_QS_FX_PIN_NUMBER + int "qs-fx pin device number" + default 24 + if SENSOR_QS_FX_DRIVER_EXTUART config SENSOR_DEVICE_QS_FX_DEV string "qs-fx device extra uart path" diff --git a/APP_Framework/Framework/sensor/winddirection/qs-fx/qs-fx.c b/APP_Framework/Framework/sensor/winddirection/qs-fx/qs-fx.c index e521b9f7e..72cb4da02 100644 --- a/APP_Framework/Framework/sensor/winddirection/qs-fx/qs-fx.c +++ b/APP_Framework/Framework/sensor/winddirection/qs-fx/qs-fx.c @@ -53,6 +53,7 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) cfg.serial_parity_mode = PARITY_NONE; cfg.serial_bit_order = 0; cfg.serial_invert_mode = 0; + cfg.serial_timeout = 1000; cfg.is_ext_uart = 0; #ifdef SENSOR_QS_FX_DRIVER_EXTUART cfg.is_ext_uart = 1; @@ -66,7 +67,34 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) result = PrivIoctl(sdev->fd, OPE_INT, &ioctl_cfg); return result; -} +} + +static int PinOpen(void){ + int pin_fd = PrivOpen(SENSOR_DEVICE_QS_FX_PIN_DEV, O_RDWR); + if (pin_fd < 0) { + printf("open %s error\n", SENSOR_DEVICE_QS_FX_PIN_DEV); + return -1; + } + + //config led pin in board + struct PinParam pin_parameter; + memset(&pin_parameter, 0, sizeof(struct PinParam)); + pin_parameter.cmd = GPIO_CONFIG_MODE; + pin_parameter.pin = SENSOR_DEVICE_QS_FX_PIN_NUMBER; + pin_parameter.mode = GPIO_CFG_OUTPUT; + + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = PIN_TYPE; + ioctl_cfg.args = (void *)&pin_parameter; + + if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg)) { + printf("ioctl pin fd error %d\n", pin_fd); + PrivClose(pin_fd); + return -1; + } + + return pin_fd; +} /** * @description: Read sensor device @@ -76,12 +104,25 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) */ static int SensorDeviceRead(struct SensorDevice *sdev, size_t len) { + int pin_fd=PinOpen(); + struct PinStat pin_dir; + pin_dir.pin = SENSOR_DEVICE_QS_FX_PIN_NUMBER; + + pin_dir.val = GPIO_HIGH; + if (PrivWrite(pin_fd,&pin_dir,0) < 0) // pull-up pin to configure as tx mode + return -1; + PrivTaskDelay(20); if (PrivWrite(sdev->fd, instructions, sizeof(instructions)) < 0) return -1; + + PrivTaskDelay(20); + pin_dir.val = GPIO_LOW; + if (PrivWrite(pin_fd,&pin_dir,0) < 0) // pull-down pin to configure as rx mode + return -1; if (PrivRead(sdev->fd, sdev->buffer, len) < 0) return -1; - + PrivClose(pin_fd); return 0; } @@ -124,7 +165,10 @@ static int32_t ReadWindDirection(struct SensorQuantity *quant) short result; if (quant->sdev->done->read != NULL) { if (quant->sdev->status == SENSOR_DEVICE_PASSIVE) { - quant->sdev->done->read(quant->sdev, 6); + quant->sdev->done->read(quant->sdev, 7); + if(Crc16(quant->sdev->buffer,7)!=0x00){ + return -1; + } result = (quant->sdev->buffer[3] << 8) | quant->sdev->buffer[4]; return (int32_t)result; diff --git a/APP_Framework/Framework/sensor/windspeed/Kconfig b/APP_Framework/Framework/sensor/windspeed/Kconfig index 91bc1fb92..96dfabf27 100644 --- a/APP_Framework/Framework/sensor/windspeed/Kconfig +++ b/APP_Framework/Framework/sensor/windspeed/Kconfig @@ -19,9 +19,17 @@ config SENSOR_QS_FS config SENSOR_DEVICE_QS_FS_DEV string "qs-fx device name" - default "/dev/uart2_dev2" + default "/dev/uart1_dev1" depends on !SENSOR_QS_FS_DRIVER_EXTUART + config SENSOR_DEVICE_QS_FS_PIN_DEV + string "qs-fx pin device name" + default "/dev/pin_dev" + + config SENSOR_DEVICE_QS_FS_PIN_NUMBER + int "qs-fs pin device number" + default 24 + if SENSOR_QS_FS_DRIVER_EXTUART config SENSOR_DEVICE_QS_FS_DEV string "qs-fx device extra uart path" diff --git a/APP_Framework/Framework/sensor/windspeed/qs-fs/qs-fs.c b/APP_Framework/Framework/sensor/windspeed/qs-fs/qs-fs.c index 0ff9c6f18..025dc5d87 100644 --- a/APP_Framework/Framework/sensor/windspeed/qs-fs/qs-fs.c +++ b/APP_Framework/Framework/sensor/windspeed/qs-fs/qs-fs.c @@ -21,7 +21,7 @@ #include static struct SensorDevice qs_fs; -static const unsigned char instructions[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A}; +static const unsigned char instructions[] = {0x02,0x03,0x00,0x00,0x00,0x01,0x84,0x39}; static struct SensorProductInfo info = { @@ -68,6 +68,34 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) return result; } + +static int PinOpen(void){ + int pin_fd = PrivOpen(SENSOR_DEVICE_QS_FS_PIN_DEV, O_RDWR); + if (pin_fd < 0) { + printf("open %s error\n", SENSOR_DEVICE_QS_FS_PIN_DEV); + return -1; + } + + //config led pin in board + struct PinParam pin_parameter; + memset(&pin_parameter, 0, sizeof(struct PinParam)); + pin_parameter.cmd = GPIO_CONFIG_MODE; + pin_parameter.pin = SENSOR_DEVICE_QS_FS_PIN_NUMBER; + pin_parameter.mode = GPIO_CFG_OUTPUT; + + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = PIN_TYPE; + ioctl_cfg.args = (void *)&pin_parameter; + + if (0 != PrivIoctl(pin_fd, OPE_CFG, &ioctl_cfg)) { + printf("ioctl pin fd error %d\n", pin_fd); + PrivClose(pin_fd); + return -1; + } + + return pin_fd; +} + /** * @description: Read sensor device * @param sdev - sensor device pointer @@ -76,12 +104,27 @@ static int SensorDeviceOpen(struct SensorDevice *sdev) */ static int SensorDeviceRead(struct SensorDevice *sdev, size_t len) { + int pin_fd=PinOpen(); + struct PinStat pin_dir; + pin_dir.pin = SENSOR_DEVICE_QS_FS_PIN_NUMBER; + + pin_dir.val = GPIO_HIGH; + if (PrivWrite(pin_fd,&pin_dir,0) < 0) // pull-up pin to configure as tx mode + return -1; + PrivTaskDelay(20); if (PrivWrite(sdev->fd, instructions, sizeof(instructions)) < 0) return -1; + PrivTaskDelay(20); + + + pin_dir.val = GPIO_LOW; + if (PrivWrite(pin_fd,&pin_dir,0) < 0) // pull-down pin to configure as rx mode + return -1; if (PrivRead(sdev->fd, sdev->buffer, len) < 0) return -1; + PrivClose(pin_fd); return 0; } @@ -124,7 +167,10 @@ static int32_t ReadWindSpeed(struct SensorQuantity *quant) short result; if (quant->sdev->done->read != NULL) { if (quant->sdev->status == SENSOR_DEVICE_PASSIVE) { - quant->sdev->done->read(quant->sdev, 6); + quant->sdev->done->read(quant->sdev, 7); + if(Crc16(quant->sdev->buffer,7)!=0x00){ + return -1; + } result = (quant->sdev->buffer[3] << 8) | quant->sdev->buffer[4]; return (int32_t)result; diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c index 33bf5bd75..1e847c453 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/gpio/drv_io_config.c @@ -111,16 +111,20 @@ static struct io_config IOCONFIG(BSP_E220_M1_PIN, HS_GPIO(FUNC_GPIOHS11)), #endif -#ifdef BSP_USING_RS485 - IOCONFIG(BSP_485_DIR_PIN,HS_GPIO(FUNC_GPIOHS12)); +#ifdef USER_TEST_RS485 + IOCONFIG(BSP_485_DIR_PIN,HS_GPIO(FUNC_GPIOHS12)), +#elif defined SENSOR_QS_FX + IOCONFIG(BSP_485_DIR_PIN,HS_GPIO(FUNC_GPIOHS12)), +#elif defined SENSOR_QS_FS + IOCONFIG(BSP_485_DIR_PIN,HS_GPIO(FUNC_GPIOHS12)), #endif #ifdef BSP_USING_LED - IOCONFIG(BSP_LED_PIN,FUNC_GPIO5); + IOCONFIG(BSP_LED_PIN,FUNC_GPIO5), #endif #ifdef BSP_USING_KEY - IOCONFIG(BSP_KEY_PIN,FUNC_GPIO6); + IOCONFIG(BSP_KEY_PIN,FUNC_GPIO6), #endif }; diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h index 2ff8356b0..94257d4ed 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/drv_io_config.h @@ -98,7 +98,11 @@ enum HS_GPIO_CONFIG { #define BSP_E220_M1_PIN 33 #endif -#ifdef BSP_USING_RS485 +#ifdef USER_TEST_RS485 +#define BSP_485_DIR_PIN 24 +#elif defined SENSOR_QS_FX +#define BSP_485_DIR_PIN 24 +#elif defined SENSOR_QS_FS #define BSP_485_DIR_PIN 24 #endif From 6fa996d132301bef04497ead7bf811ce5e5eab47 Mon Sep 17 00:00:00 2001 From: wuzheng Date: Fri, 2 Dec 2022 11:04:46 +0800 Subject: [PATCH 04/15] add ethernet test fro edu-riscv64 --- APP_Framework/Applications/app_test/Kconfig | 19 +- APP_Framework/Applications/app_test/Makefile | 4 +- .../Applications/app_test/test_ethernet.c | 171 ++++++++++++++++++ .../Applications/app_test/test_w5500.c | 81 --------- 4 files changed, 189 insertions(+), 86 deletions(-) create mode 100644 APP_Framework/Applications/app_test/test_ethernet.c delete mode 100644 APP_Framework/Applications/app_test/test_w5500.c diff --git a/APP_Framework/Applications/app_test/Kconfig b/APP_Framework/Applications/app_test/Kconfig index e25b29155..12537ed19 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -192,10 +192,23 @@ menu "test app" bool "Config test lcd device" default n - config USER_TEST_W5500 - select BSP_USING_W5500 - bool "Config test W5500 only for edu-riscv64" + menuconfig USER_TEST_ETHERNET + bool "Config test ethernet only for edu-riscv64" default n + if USER_TEST_ETHERNET + if ADD_XIZI_FETURES + choice + prompt "set ethernet role as client or server" + default ETHERNET_AS_SERVER + + config ETHERNET_AS_SERVER + bool "test as server" + + config ETHERNET_AS_CLIENT + bool "test as client" + endchoice + endif + endif endif endmenu diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 830c40916..74d981eac 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -85,8 +85,8 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y) SRC_FILES += test_camera.c endif - ifeq ($(CONFIG_USER_TEST_W5500),y) - SRC_FILES += test_w5500.c + ifeq ($(CONFIG_USER_TEST_ETHERNET),y) + SRC_FILES += test_ethernet.c endif include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Applications/app_test/test_ethernet.c b/APP_Framework/Applications/app_test/test_ethernet.c new file mode 100644 index 000000000..5574d2fcb --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ethernet.c @@ -0,0 +1,171 @@ +#include +#include +#include + +#include + +#define BUFF_SIZE 128 +#define RECV_SIZE 16 +#define TCP_PORT 12345 + +const static uint32_t sn = 0; +const static uint32_t socket_tcp = 0; + +#ifdef ETHERNET_AS_SERVER +static int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, + uint16_t port, enum TCP_OPTION opt) { + int32_t ret = 0; + uint16_t size = 0, sentsize = 0; + switch (getSn_SR(sn)) { + case SOCK_ESTABLISHED: + if (getSn_IR(sn) & Sn_IR_CON) { + printf("%d:Connected\r\n", sn); + setSn_IR(sn, Sn_IR_CON); + } + if (opt == SEND_DATA) { + uint32_t sent_size = 0; + memset(buf,0,buf_size); + strcpy(buf,"The message has been recved"); + ret = wiz_sock_send(socket_tcp, buf, buf_size); + if (ret < 0) { + wiz_sock_close(socket_tcp); + return ret; + } + } else if (opt == RECV_DATA) { + uint32_t size = 0; + if ((size = getSn_RX_RSR(sn)) > 0) { + if (size > buf_size) size = buf_size; + memset(buf,0,buf_size); + ret = wiz_sock_recv(sn, buf, size); + printf("Recv message: %s\n",buf); + return ret; + } + } + break; + case SOCK_CLOSE_WAIT: + printf("%d:CloseWait\r\n", sn); + if ((ret = wiz_sock_disconnect(sn)) != SOCK_OK) return ret; + printf("%d:Closed\r\n", sn); + break; + case SOCK_INIT: + printf("%d:Listen, port [%d]\r\n", sn, port); + if ((ret = wiz_sock_listen(sn)) != SOCK_OK) return ret; + break; + case SOCK_CLOSED: + printf("%d:LBTStart\r\n", sn); + if ((ret = wiz_socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret; + printf("%d:Opened\r\n", sn); + break; + default: + break; + } + return 0; +} + +void TestSocketAsServer(int argc, char *argv[]) +{ + x_err_t ret; + uint8_t buf[BUFF_SIZE] = {0}; + + while (1) { + ret = wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, RECV_DATA); + if (ret > 0) { + wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, SEND_DATA); + }; + } + + return ; + +} + +PRIV_SHELL_CMD_FUNCTION(TestSocketAsServer, a w5500 server test sample, PRIV_SHELL_CMD_MAIN_ATTR); + +#elif defined ETHERNET_AS_CLIENT + +static uint32_t wiz_client_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, + uint8_t dst_ip[4], uint16_t dst_port, + enum TCP_OPTION opt) { + // assert(buf_size <= g_wiznet_buf_size); + int32_t ret; + switch (getSn_SR(socket_tcp)) { + case SOCK_CLOSE_WAIT: + wiz_sock_disconnect(socket_tcp); + break; + case SOCK_CLOSED: + wiz_socket(socket_tcp, Sn_MR_TCP, 5000, 0x00); + break; + case SOCK_INIT: + KPrintf("[SOCKET CLIENT] sock init.\n"); + wiz_sock_connect(socket_tcp, dst_ip, dst_port); + break; + case SOCK_ESTABLISHED: + if (getSn_IR(socket_tcp) & Sn_IR_CON) { + printf("[SOCKET CLIENT] %d:Connected\r\n", socket_tcp); + setSn_IR(socket_tcp, Sn_IR_CON); + } + if (opt == SEND_DATA) { + uint32_t sent_size = 0; + ret = wiz_sock_send(socket_tcp, buf, buf_size); + if (ret < 0) { + wiz_sock_close(socket_tcp); + return ret; + } + } else if (opt == RECV_DATA) { + uint32_t size = 0; + if ((size = getSn_RX_RSR(sn)) > 0) { + if (size > buf_size) size = buf_size; + ret = wiz_sock_recv(sn, buf, size); + if (ret <= 0) return ret; + } + } + break; + default: + break; + } +} + + +void TestSocketAsClient(int argc, char *argv[]) +{ + x_err_t ret; + uint8_t buf[BUFF_SIZE] = {0}; + uint32_t tmp_ip[4]; + uint32_t port; + const uint8_t client_sock = 2; + + if(argc<3){ + printf("Please enter command like TestSocketAsClient ip:port msg\n"); + } + + sscanf(argv[1],"%d.%d.%d.%d:%d",tmp_ip,tmp_ip+1,tmp_ip+2,tmp_ip+3,&port); + printf("Client to %d.%d.%d.%d:%d\n",tmp_ip[0],tmp_ip[1],tmp_ip[2],tmp_ip[3],port); + uint8_t destination_ip[4]={0}; + for(int i=0;i<4;i++){ + destination_ip[i]=tmp_ip[i]; + } + + while(1){ + ret = wiz_client_op(client_sock, argv[2], sizeof(argv[2]), destination_ip, port,SEND_DATA); + PrivTaskDelay(10); + if (ret > 0) { + ret=wiz_client_op(client_sock, buf, BUFF_SIZE, destination_ip, port, RECV_DATA); + printf("client recv msg successfully!\n"); + printf("%s\n",buf); + break; + }; + PrivTaskDelay(100); + } + + + + + return ; + +} + +PRIV_SHELL_CMD_FUNCTION(TestSocketAsClient, a w5500 client-ip-port-msg test sample, PRIV_SHELL_CMD_MAIN_ATTR); + + +#endif + + diff --git a/APP_Framework/Applications/app_test/test_w5500.c b/APP_Framework/Applications/app_test/test_w5500.c deleted file mode 100644 index 2a589171f..000000000 --- a/APP_Framework/Applications/app_test/test_w5500.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include - -#include - -#define BUFF_SIZE 128 -#define RECV_SIZE 16 -#define TCP_PORT 12345 - -const static uint32_t sn = 0; -const static uint32_t socket_tcp = 0; - -static int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, - uint16_t port, enum TCP_OPTION opt) { - int32_t ret = 0; - uint16_t size = 0, sentsize = 0; - switch (getSn_SR(sn)) { - case SOCK_ESTABLISHED: - if (getSn_IR(sn) & Sn_IR_CON) { - printf("%d:Connected\r\n", sn); - setSn_IR(sn, Sn_IR_CON); - } - if (opt == SEND_DATA) { - uint32_t sent_size = 0; - memset(buf,0,buf_size); - strcpy(buf,"The message has been recved"); - ret = wiz_sock_send(socket_tcp, buf, buf_size); - if (ret < 0) { - wiz_sock_close(socket_tcp); - return ret; - } - } else if (opt == RECV_DATA) { - uint32_t size = 0; - if ((size = getSn_RX_RSR(sn)) > 0) { - if (size > buf_size) size = buf_size; - memset(buf,0,buf_size); - ret = wiz_sock_recv(sn, buf, size); - printf("Recv message: %s\n",buf); - return ret; - } - } - break; - case SOCK_CLOSE_WAIT: - printf("%d:CloseWait\r\n", sn); - if ((ret = wiz_sock_disconnect(sn)) != SOCK_OK) return ret; - printf("%d:Closed\r\n", sn); - break; - case SOCK_INIT: - printf("%d:Listen, port [%d]\r\n", sn, port); - if ((ret = wiz_sock_listen(sn)) != SOCK_OK) return ret; - break; - case SOCK_CLOSED: - printf("%d:LBTStart\r\n", sn); - if ((ret = wiz_socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret; - printf("%d:Opened\r\n", sn); - break; - default: - break; - } - return 0; -} - -void TestSocketInW5500(int argc, char *argv[]) -{ - x_err_t ret; - uint8_t buf[BUFF_SIZE] = {0}; - - while (1) { - ret = wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, RECV_DATA); - if (ret > 0) { - wiz_server_op(0, buf, BUFF_SIZE, TCP_PORT, SEND_DATA); - }; - } - - return ; - -} - - -PRIV_SHELL_CMD_FUNCTION(TestSocketInW5500, a w5500 test sample, PRIV_SHELL_CMD_MAIN_ATTR); \ No newline at end of file From 2df54e7f41a0c3ebd916ca65c45c1c68a3d81384 Mon Sep 17 00:00:00 2001 From: wuzheng Date: Fri, 9 Dec 2022 13:57:01 +0800 Subject: [PATCH 05/15] fix some bugs for sd read --- .../kpu/k210_yolov2_detect_procedure/Kconfig | 4 + .../kpu/k210_yolov2_detect_procedure/Makefile | 4 + .../k210_yolov2_detect.h | 3 + .../Framework/knowing/kpu/yolov2/Makefile | 4 + .../knowing/kpu/yolov2/region_layer.c | 2 +- .../knowing/kpu/yolov2_json/Makefile | 4 + .../knowing/kpu/yolov2_json/json_parser.c | 7 +- .../user_api/posix_support/include/pthread.h | 6 + .../xizi/user_api/posix_support/pthread.c | 25 + .../XiZi_IIoT/board/edu-riscv64/board.c | 1 + .../edu-riscv64/third_party_driver/Kconfig | 10 +- .../edu-riscv64/third_party_driver/Makefile | 4 + .../third_party_driver/include/kpu.h | 930 ++++++++++ .../third_party_driver/kpu/Kconfig | 1 + .../third_party_driver/kpu/Makefile | 4 + .../edu-riscv64/third_party_driver/kpu/kpu.c | 1634 +++++++++++++++++ Ubiquitous/XiZi_IIoT/path_kernel.mk | 7 + .../resources/spi/sd_card_spi/sd_spi.c | 1 - 18 files changed, 2646 insertions(+), 5 deletions(-) create mode 100644 APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Makefile create mode 100644 APP_Framework/Framework/knowing/kpu/yolov2/Makefile create mode 100644 APP_Framework/Framework/knowing/kpu/yolov2_json/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/kpu.h create mode 100644 Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig create mode 100644 Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig index fa5819f4f..2d25a5710 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig @@ -3,5 +3,9 @@ menuconfig USING_K210_YOLOV2_DETECT depends on USING_KPU_PROCESSING default n +config CAMERA_DEV_DRIVER + string "Set camera dev path" + default "/dev/ov2640" + diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Makefile b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Makefile new file mode 100644 index 000000000..767322091 --- /dev/null +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := k210_yolov2_detect.c + +include $(KERNEL_ROOT)/compiler.mk + diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.h b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.h index 47427e734..935b23067 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.h +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.h @@ -1,7 +1,10 @@ #ifndef _K210_DETECT_H_ #define _K210_DETECT_H_ +#include +#include #include +#include "sleep.h" void k210_detect(char *json_file_path); diff --git a/APP_Framework/Framework/knowing/kpu/yolov2/Makefile b/APP_Framework/Framework/knowing/kpu/yolov2/Makefile new file mode 100644 index 000000000..6ebd0b800 --- /dev/null +++ b/APP_Framework/Framework/knowing/kpu/yolov2/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := region_layer.c + +include $(KERNEL_ROOT)/compiler.mk + diff --git a/APP_Framework/Framework/knowing/kpu/yolov2/region_layer.c b/APP_Framework/Framework/knowing/kpu/yolov2/region_layer.c index 255bf82a0..32a6a08dc 100644 --- a/APP_Framework/Framework/knowing/kpu/yolov2/region_layer.c +++ b/APP_Framework/Framework/knowing/kpu/yolov2/region_layer.c @@ -224,7 +224,7 @@ static void get_region_boxes(region_layer_t *rl, float *predictions, float **pro correct_region_boxes(rl, boxes); } -static int nms_comparator(void *pa, void *pb) +static int nms_comparator(const void *pa,const void *pb) { sortable_box_t a = *(sortable_box_t *)pa; sortable_box_t b = *(sortable_box_t *)pb; diff --git a/APP_Framework/Framework/knowing/kpu/yolov2_json/Makefile b/APP_Framework/Framework/knowing/kpu/yolov2_json/Makefile new file mode 100644 index 000000000..50b092a60 --- /dev/null +++ b/APP_Framework/Framework/knowing/kpu/yolov2_json/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := json_parser.c + +include $(KERNEL_ROOT)/compiler.mk + diff --git a/APP_Framework/Framework/knowing/kpu/yolov2_json/json_parser.c b/APP_Framework/Framework/knowing/kpu/yolov2_json/json_parser.c index 9a3167f64..ada573872 100644 --- a/APP_Framework/Framework/knowing/kpu/yolov2_json/json_parser.c +++ b/APP_Framework/Framework/knowing/kpu/yolov2_json/json_parser.c @@ -1,6 +1,9 @@ #include "json_parser.h" -#include +// #include +#include +#include +#include #include "cJSON.h" @@ -31,9 +34,9 @@ yolov2_params_t param_parse(char *json_file_path) } else { printf("Reading config from: %s\n", json_file_path); } + read(fin, buffer, sizeof(buffer)); close(fin); - // read json string json_obj = cJSON_Parse(buffer); // free(buffer); diff --git a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/include/pthread.h b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/include/pthread.h index efe995dc7..acebf067f 100644 --- a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/include/pthread.h +++ b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/include/pthread.h @@ -73,6 +73,12 @@ typedef int pid_t; int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)); int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); +int pthread_attr_init(pthread_attr_t *attr); +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size); +int pthread_attr_setschedparam(pthread_attr_t *attr,struct sched_param const *param); +int pthread_attr_setstack(pthread_attr_t *attr, + void *stack_base, + size_t stack_size); void pthread_exit(void *value_ptr); int pthread_detach(pthread_t thread); int pthread_join(pthread_t thread, void **retval); diff --git a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c index 3b8b170fd..ce33b259a 100644 --- a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c +++ b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c @@ -22,6 +22,10 @@ #include #include "include/pthread.h" +#define DEFAULT_STACK_SIZE 2048 +#define DEFAULT_PRIORITY (KTASK_PRIORITY_MAX/2 + KTASK_PRIORITY_MAX/4) + + int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) { @@ -55,6 +59,27 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr, } +int pthread_attr_init(pthread_attr_t *attr) +{ + return 0; +} + +int pthread_attr_setschedparam(pthread_attr_t *attr, + struct sched_param const *param) +{ + NULL_PARAM_CHECK(attr != NULL); + NULL_PARAM_CHECK(param != NULL); + + attr->schedparam.sched_priority = param->sched_priority; + + return 0; +} + +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size) +{ + return 0; +} + void pthread_exit(void *value_ptr){ //todo add exit value UserTaskQuit(); diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c index ad4ec5406..1a76f26c6 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c @@ -70,6 +70,7 @@ extern int HwLcdInit(void); extern int HwSpiInit(void); extern int HwSoftSPIInit(void); extern int HwWiznetInit(void); +extern int HwDvpInit(void); #include #ifdef MOUNT_USB diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Kconfig index f6322f544..31d42d085 100755 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Kconfig @@ -123,9 +123,17 @@ menuconfig BSP_USING_WIZCHIP menuconfig BSP_USING_CAMERA bool "Using camera device" - default y + default n select RESOURCES_CAMERA if BSP_USING_CAMERA source "$BSP_DIR/third_party_driver/dvp/Kconfig" endif +menuconfig BSP_USING_KPU + bool "Using kpu device" + default n + select RESOURCES_KPU + if BSP_USING_KPU + source "$BSP_DIR/third_party_driver/kpu/Kconfig" + endif + diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Makefile b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Makefile index 7c5f9ad84..51804af84 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/Makefile @@ -59,9 +59,13 @@ endif ifeq ($(CONFIG_BSP_USING_WIZCHIP),y) SRC_DIR += ethernet endif + ifeq ($(CONFIG_BSP_USING_CAMERA),y) SRC_DIR += dvp endif +ifeq ($(CONFIG_BSP_USING_KPU),y) + SRC_DIR += kpu +endif include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/kpu.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/kpu.h new file mode 100644 index 000000000..1bf683c90 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/kpu.h @@ -0,0 +1,930 @@ +/* Copyright 2018 Canaan Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _KPU_H +#define _KPU_H + +#include +#include +#include "dmac.h" + +#define kpu_matmul_begin kpu_conv2d_output + +typedef int (*plic_irq_callback_t)(void *ctx); + +typedef struct +{ + union + { + uint64_t reg; + struct + { + uint64_t int_en:1; + uint64_t ram_flag:1; + uint64_t full_add:1; + uint64_t depth_wise_layer:1; + uint64_t reserved:60; + } data; + } interrupt_enabe; + + union + { + uint64_t reg; + struct + { + uint64_t image_src_addr:15; + uint64_t reserved0:17; + uint64_t image_dst_addr:15; + uint64_t reserved1:17; + } data; + } image_addr; + + union + { + uint64_t reg; + struct + { + uint64_t i_ch_num:10; + uint64_t reserved0:22; + uint64_t o_ch_num:10; + uint64_t reserved1:6; + uint64_t o_ch_num_coef:10; + uint64_t reserved2:6; + } data; + } image_channel_num; + + union + { + uint64_t reg; + struct + { + uint64_t i_row_wid:10; + uint64_t i_col_high:9; + uint64_t reserved0:13; + uint64_t o_row_wid:10; + uint64_t o_col_high:9; + uint64_t reserved1:13; + } data; + } image_size; + + union + { + uint64_t reg; + struct + { + uint64_t kernel_type:3; + uint64_t pad_type:1; + uint64_t pool_type:4; + uint64_t first_stride:1; + uint64_t bypass_conv:1; + uint64_t load_para:1; + uint64_t reserved0:5; + uint64_t dma_burst_size:8; + uint64_t pad_value:8; + uint64_t bwsx_base_addr:32; + } data; + } kernel_pool_type_cfg; + + union + { + uint64_t reg; + struct + { + uint64_t load_coor:1; + uint64_t load_time:6; + uint64_t reserved0:8; + uint64_t para_size:17; + uint64_t para_start_addr:32; + } data; + } kernel_load_cfg; + + union + { + uint64_t reg; + struct + { + uint64_t coef_column_offset:4; + uint64_t coef_row_offset:12; + uint64_t reserved0:48; + } data; + } kernel_offset; + + union + { + uint64_t reg; + struct + { + uint64_t channel_switch_addr:15; + uint64_t reserved:1; + uint64_t row_switch_addr:4; + uint64_t coef_size:8; + uint64_t coef_group:3; + uint64_t load_act:1; + uint64_t active_addr:32; + } data; + } kernel_calc_type_cfg; + + union + { + uint64_t reg; + struct + { + uint64_t wb_channel_switch_addr:15; + uint64_t reserved0:1; + uint64_t wb_row_switch_addr:4; + uint64_t wb_group:3; + uint64_t reserved1:41; + } data; + } write_back_cfg; + + union + { + uint64_t reg; + struct + { + uint64_t shr_w:4; + uint64_t shr_x:4; + uint64_t arg_w:24; + uint64_t arg_x:24; + uint64_t reserved0:8; + } data; + } conv_value; + + union + { + uint64_t reg; + struct + { + uint64_t arg_add:40; + uint64_t reserved:24; + } data; + } conv_value2; + + union + { + uint64_t reg; + struct + { + uint64_t send_data_out:1; + uint64_t reserved:15; + uint64_t channel_byte_num:16; + uint64_t dma_total_byte:32; + } data; + } dma_parameter; +} kpu_layer_argument_t; + +typedef struct +{ + union + { + uint64_t reg; + struct + { + uint64_t shift_number:8; + uint64_t y_mul:16; + uint64_t x_start:36; + } data; + } activate_para[16]; + + union + { + uint64_t reg; + struct + { + uint8_t result_bias[8]; + } data; + } activate_para_bias0; + + union + { + uint64_t reg; + struct + { + uint8_t result_bias[8]; + } data; + } activate_para_bias1; +} kpu_activate_table_t; + +typedef struct +{ + union + { + uint64_t reg; + struct + { + uint64_t norm_mul:24; + uint64_t norm_add:32; + uint64_t norm_shift:4; + } data; + } batchnorm; +} kpu_batchnorm_argument_t; + + +typedef struct +{ + union + { + uint64_t reg; + struct + { + uint16_t weight[9]; + } data; + } weights; +} kpu_weights_kernel_16_3x3_t; + +typedef struct +{ + uint64_t calc_done_int:1; + uint64_t layer_cfg_almost_empty_int:1; + uint64_t layer_cfg_almost_full_int:1; + uint64_t reserved:61; +} kpu_config_interrupt_t; + +typedef struct +{ + uint64_t fifo_full_threshold:4; + uint64_t fifo_empty_threshold:4; + uint64_t reserved:56; +} kpu_config_fifo_threshold_t; + +typedef struct +{ + uint64_t dma_fifo_flush_n:1; + uint64_t gs_fifo_flush_n:1; + uint64_t cfg_fifo_flush_n:1; + uint64_t cmd_fifo_flush_n:1; + uint64_t resp_fifo_flush_n:1; + uint64_t reserved:59; +} kpu_config_fifo_ctrl_t; + +typedef struct +{ + uint64_t eight_bit_mode:1; + uint64_t reserved:63; +} kpu_config_eight_bit_mode_t; + + +typedef struct +{ + volatile uint64_t layer_argument_fifo; + + volatile union + { + uint64_t reg; + kpu_config_interrupt_t data; + } interrupt_status; + + volatile union + { + uint64_t reg; + kpu_config_interrupt_t data; + } interrupt_raw; + + volatile union { + uint64_t reg; + kpu_config_interrupt_t data; + } interrupt_mask; + + volatile union + { + uint64_t reg; + kpu_config_interrupt_t data; + } interrupt_clear; + + volatile union + { + uint64_t reg; + kpu_config_fifo_threshold_t data; + } fifo_threshold; + + volatile uint64_t fifo_data_out; + + volatile union + { + uint64_t reg; + kpu_config_fifo_ctrl_t data; + } fifo_ctrl; + + volatile union + { + uint64_t reg; + kpu_config_eight_bit_mode_t data; + } eight_bit_mode; +} kpu_config_t; + +typedef struct +{ + kpu_layer_argument_t *layers; + kpu_layer_argument_t *remain_layers; + plic_irq_callback_t callback; + void *ctx; + uint64_t *src; + uint64_t *dst; + uint32_t src_length; + uint32_t dst_length; + uint32_t layers_length; + uint32_t remain_layers_length; + dmac_channel_number_t dma_ch; + uint32_t eight_bit_mode; + float output_scale; + float output_bias; + float input_scale; + float input_bias; +} kpu_task_t; + +typedef struct +{ + uint32_t version; + uint32_t flags; + uint32_t arch; + uint32_t layers_length; + uint32_t max_start_address; + uint32_t main_mem_usage; + uint32_t output_count; +} kpu_kmodel_header_t; + +typedef struct +{ + uint32_t version; + uint32_t flags; + uint32_t layers_length; + uint32_t max_start_address; + uint32_t layers_argument_start; +} kpu_model_header_t; + +typedef struct +{ + uint32_t address; + uint32_t size; +} kpu_model_output_t; + +typedef enum +{ + KL_INVALID = 0, + KL_ADD, + KL_QUANTIZED_ADD, + KL_GLOBAL_MAX_POOL2D, + KL_QUANTIZED_GLOBAL_MAX_POOL2D, + KL_GLOBAL_AVERAGE_POOL2D, + KL_QUANTIZED_GLOBAL_AVERAGE_POOL2D, + KL_MAX_POOL2D, + KL_QUANTIZED_MAX_POOL2D, + KL_AVERAGE_POOL2D, + KL_QUANTIZED_AVERAGE_POOL2D, + KL_QUANTIZE, + KL_DEQUANTIZE, + KL_REQUANTIZE, + KL_L2_NORMALIZATION, + KL_SOFTMAX, + KL_CONCAT, + KL_QUANTIZED_CONCAT, + KL_FULLY_CONNECTED, + KL_QUANTIZED_FULLY_CONNECTED, + KL_TENSORFLOW_FLATTEN, + KL_QUANTIZED_TENSORFLOW_FLATTEN, + KL_RESIZE_NEAREST_NEIGHBOR, + KL_QUANTIZED_RESIZE_NEAREST_NEIGHBOR, + KL_CHANNELWISE_DEQUANTIZE, + KL_K210_CONV = 10240, + KL_K210_ADD_PADDING, + KL_K210_REMOVE_PADDING, + KL_K210_UPLOAD +} kpu_model_layer_type_t; + +typedef struct +{ + uint32_t type; + uint32_t body_size; +} kpu_model_layer_header_t; + +typedef enum +{ + KLF_NONE = 0, + KLF_MAIN_MEM_OUT = 1 +} kpu_model_layer_flags_t; + +typedef enum +{ + KLP_SAME = 0, + KLP_VALID = 1 +} kpu_model_padding_t; + +typedef enum +{ + KLA_LINEAR = 0, + KLA_RELU = 1, + KLA_RELU6 = 2 +} kpu_model_activation_t; + +typedef struct +{ + float scale; + float bias; +} kpu_model_quant_param_t; + +typedef struct +{ + uint32_t width; + uint32_t height; + uint32_t channels; +} kpu_model_shape_t; + +typedef struct +{ + uint32_t start; + uint32_t size; +} kpu_model_memory_range_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_out_address; + uint32_t layer_offset; + uint32_t weights_offset; + uint32_t bn_offset; + uint32_t act_offset; +} kpu_model_conv_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_a_address; + uint32_t main_mem_in_b_address; + uint32_t main_mem_out_address; + uint32_t count; +} kpu_model_add_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_a_address; + uint32_t main_mem_in_b_address; + uint32_t main_mem_out_address; + uint32_t count; + int32_t in_a_offset; + int32_t in_a_mul; + int32_t in_a_shift; + int32_t in_b_offset; + int32_t in_b_mul; + int32_t in_b_shift; + int32_t out_offset; + int32_t out_mul; + int32_t out_shift; +} kpu_model_quant_add_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t kernel_size; + uint32_t channels; +} kpu_model_gap2d_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + kpu_model_shape_t in_shape; + kpu_model_shape_t out_shape; + uint32_t kernel_width; + uint32_t kernel_height; + uint32_t stride_width; + uint32_t stride_height; + uint32_t padding_width; + uint32_t padding_height; +} kpu_model_quant_max_pool2d_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + kpu_model_shape_t in_shape; + kpu_model_shape_t out_shape; + uint32_t kernel_width; + uint32_t kernel_height; + uint32_t stride_width; + uint32_t stride_height; + uint32_t padding_width; + uint32_t padding_height; + kpu_model_activation_t act; +} kpu_model_ave_pool2d_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t mem_out_address; + uint32_t count; + kpu_model_quant_param_t quant_param; +} kpu_model_quantize_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t count; + kpu_model_quant_param_t quant_param; +} kpu_model_dequantize_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t count; + uint8_t table[256]; +} kpu_model_requantize_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t kpu_mem_out_address; + uint32_t channels; +} kpu_model_add_padding_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t channels; +} kpu_model_remove_padding_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t kpu_mem_out_address; + uint32_t width; + uint32_t height; + uint32_t channels; +} kpu_model_upload_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t channels; +} kpu_model_l2_norm_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t channels; +} kpu_model_softmax_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_out_address; + uint32_t input_count; + kpu_model_memory_range_t inputs_mem[0]; +} kpu_model_concat_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t in_channels; + uint32_t out_channels; + kpu_model_activation_t act; + float weights[0]; +} kpu_model_fully_connected_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + kpu_model_shape_t shape; +} kpu_model_tf_flatten_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + kpu_model_shape_t in_shape; + uint32_t out_width; + uint32_t out_height; + uint32_t align_corners; +} kpu_model_resize_nearest_neighbor_layer_argument_t; + +typedef struct +{ + uint32_t flags; + uint32_t main_mem_in_address; + uint32_t main_mem_out_address; + uint32_t channels; + uint32_t channel_size; + kpu_model_quant_param_t quant_params[0]; +} kpu_model_channelwise_dequant_argument_t; + +typedef void(*kpu_done_callback_t)(void* userdata); + +typedef struct +{ + const uint8_t *model_buffer; + uint8_t *main_buffer; + uint32_t output_count; + const kpu_model_output_t *outputs; + const kpu_model_layer_header_t *layer_headers; + const uint8_t *body_start; + uint32_t layers_length; + volatile uint32_t current_layer; + const uint8_t * volatile current_body; + dmac_channel_number_t dma_ch; + kpu_done_callback_t done_callback; + void *userdata; +} kpu_model_context_t; + +typedef struct +{ + uint32_t weigths_offset; + uint32_t bn_offset; + uint32_t act_offset; + float input_scale; + float input_bias; + float output_scale; + float output_bias; +} kpu_model_layer_metadata_t; + +typedef struct _quantize_param +{ + float scale; + float bias; +} quantize_param_t; + +extern volatile kpu_config_t *const kpu; + +/** + * @brief Modle complier init kpu handler + * + * @param[in] task Kpu handler + * + * @return Kpu handler + */ +extern kpu_task_t *kpu_task_init(kpu_task_t* task); + +/** + * @brief Kpu run for AI + * + * @param[in] task Kpu handler + * @param[in] dma_ch DMA for kpu + * @param[in] src The picture data + * @param[in] dest The result of kpu + * @param[in] callback The callback of kpu + * + * @return result + * - 0 Success + * - Other Fail.Kpu is busy. + */ +int kpu_run(kpu_task_t* task, dmac_channel_number_t dma_ch, const void *src, void* dest, plic_irq_callback_t callback); + +/** + * @brief Get kpu result buf + * + * @param[in] task Kpu handler + * + * @return Kpu result buf + */ +uint8_t *kpu_get_output_buf(kpu_task_t* task); + +/** + * @brief Release kpu output buf + * + * @param[in] output_buf Kpu output buf + * + */ +void kpu_release_output_buf(uint8_t *output_buf); + +/** + * @brief Kpu run for AI + * + * @param[in] task Kpu handler +* +* @return result +* - 0 Success +* - Other Fail.Kpu is busy. +*/ +int kpu_start(kpu_task_t *task); + +/** + * @brief Initialize kpu handler + * + * @param[in] task Kpu handler + * + * @return result + * - 0 Success + * - Other Fail. + */ +int kpu_single_task_init(kpu_task_t *task); + +/** + * @brief Uninitialize kpu handler + * + * @param[in] task Kpu handler + * + * @return result + * - 0 Success + * - Other Fail. + */ +int kpu_single_task_deinit(kpu_task_t *task); + +/** + * @brief Load kmodel and init kpu task + * + * @param[in] task Kpu handler + * @param[in] buffer Kmodel + * @param[in] meta Test data + * + * @return result + * - 0 Success + * - Other Fail. + */ +int kpu_model_load_from_buffer(kpu_task_t *task, uint8_t *buffer, kpu_model_layer_metadata_t **meta); + +/** + * @brief Kpu initialize + * + * @param[in] eight_bit_mode 0:16bit mode 1:8bit mode + * @param[in] callback Callback of kpu + * @param[in] userdata Data of callback + * + */ +void kpu_init(int eight_bit_mode, plic_irq_callback_t callback, void *userdata); + +/** + * @brief Kpu input data by dma + * + * @param[in] layer Kpu task layer + * @param[in] src Image data + * @param[in] dma_ch Dmac channel + * @param[in] callback Dmac complete callback + * @param[in] userdata Data of callback + * + */ +void kpu_input_dma(const kpu_layer_argument_t *layer, const uint8_t *src, dmac_channel_number_t dma_ch, plic_irq_callback_t callback, void *userdata); + +/** + * @brief Kpu input data by cpu + * + * @param[in] layer Kpu task layer + * @param[in] src Image data + * @param[in] width Image width + * @param[in] height Image heigth + * @param[in] channels Color channel, RGB is 3 + * + */ +void kpu_input_with_padding(kpu_layer_argument_t *layer, const uint8_t *src, int width, int height, int channels); + +/** + * @brief Kpu run only one layer + * + * @param[in] layer Kpu task layer + * + */ +void kpu_conv2d(kpu_layer_argument_t *layer); + +/** + * @brief Kpu run only one layer then get the result by dma + * + * @param[in] layer Kpu task layer + * @param[in] dma_ch Dmac channel + * @param[in] dest Result + * @param[in] callback Dmac complete callback + * @param[in] userdata Data of callback + * + */ +void kpu_conv2d_output(kpu_layer_argument_t *layer, dmac_channel_number_t dma_ch, uint8_t *dest, plic_irq_callback_t callback, void *userdata); + +/** + * @brief Kpu pooling + * + * @param[in] src Source + * @param[in] src_param Source param + * @param[in] kernel_size Kernel size, 7*7 is 49 + * @param[in] channels Channels + * @param[in] dest Dest + * @param[in] dest_param Dest param + * + */ +void kpu_global_average_pool(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, uint8_t *dest, const quantize_param_t *dest_param); + +/** + * @brief Kpu pooling + * + * @param[in] src Source + * @param[in] src_param Source param + * @param[in] kernel_size Kernel size, 7*7 is 49 + * @param[in] channels Channels + * @param[in] dest Dest + * + */ +void kpu_global_average_pool_float(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, float *dest); + +/** + * @brief Kpu fullly connected by cpu + * + * @param[in] src Source + * @param[in] weights Weight + * @param[in] biases Biases + * @param[in] dest Dest + * @param[in] input_channels Input channels + * @param[in] output_channels Output channels + * + */ +void kpu_fully_connected(const float *src, const float *weights, const float *biases, float *dest, int input_channels, int output_channels); + +/** + * @brief Kpu matrix multiplication + * + * @param[in] src Source + * @param[in] channels Channels + * @param[in] dest Dest + * @param[in] dest_param Dest param + * + */ +void kpu_matmul_end(const uint8_t *src, int channels, float *dest, const quantize_param_t *dest_param); + +/** + * @brief Kpu dequantize + * + * @param[in] src Source + * @param[in] src_param Source param + * @param[in] count Dequantize count + * @param[in] dest Dest + * + */ +void kpu_dequantize(const uint8_t *src, const quantize_param_t *src_param, size_t count, float *dest); + +/** + * @brief Kpu load kmodel + * + * @param[in] ctx Kmodel object + * @param[in] buffer Kmodel buffer + * + * @return result + * - 0 Success + * - Other Fail. + */ +int kpu_load_kmodel(kpu_model_context_t *ctx, const uint8_t *buffer); + +/** + * @brief Kpu free kmodel buffer + * + * @param[in] ctx kmodel object + * + */ +void kpu_model_free(kpu_model_context_t *ctx); + +/** + * @brief Kpu load kmodel + * + * @param[in] ctx Kmodel object + * @param[in] index Output index + * @param[in] data Output data + * @param[in] size Output data size + * + * @return result + * - 0 Success + * - Other Fail. + */ +int kpu_get_output(kpu_model_context_t *ctx, uint32_t index, uint8_t **data, size_t *size); + +/** + * @brief Kpu run kmodel + * + * @param[in] ctx Kmodel object + * @param[in] src Source data + * @param[in] dma_ch Dma channel + * @param[in] done_callback Kpu complete callback + * @param[in] userdata Data of callback + * + * @return result + * - 0 Success + * - Other Fail. + */ +int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_number_t dma_ch, kpu_done_callback_t done_callback, void *userdata); + +#endif diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig @@ -0,0 +1 @@ + diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile new file mode 100644 index 000000000..cedabd673 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := kpu.c + + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c new file mode 100644 index 000000000..4926c8d6a --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c @@ -0,0 +1,1634 @@ +#include "kpu.h" +#include +#include +#include +#include +#include +#include "printf.h" +#include "dmac.h" +#include +#include "bsp.h" +#include +#include + +#define LAYER_BURST_SIZE 12 + +#define KPU_DEBUG 0 +#define USE_CACHED_AI_RAM 0 + +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define ALIGN_UP(x, align) ((x + (align - 1)) & (~(align - 1))) + +static int ai_step(void *userdata); +static int kpu_kmodel_done(kpu_model_context_t *ctx); + +volatile kpu_config_t *const kpu = (volatile kpu_config_t *)AI_BASE_ADDR; +static volatile uint32_t kpu_status; + +typedef struct kpu_context +{ + kpu_task_t kpu_task; + uint32_t kpu_status; +} kpu_context_t; + +volatile kpu_context_t g_kpu_context; + +static int kpu_run_all_done(void* _task) +{ + atomic_swap(&g_kpu_context.kpu_status, 0); + kpu_task_t* task = (kpu_task_t*)_task; + task->callback(task); + return 0; +} + +int kpu_continue(void* _task) +{ + kpu_task_t* task = (kpu_task_t*)_task; + int layer_burst_size = 1; + + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int=1, + .layer_cfg_almost_empty_int=1, + .layer_cfg_almost_full_int=1 + }; + + if(task->remain_layers_length == 0) + { + return 0; + } + if(task->remain_layers_length <= layer_burst_size) + { + for(uint32_t i=0; iremain_layers_length; i++) + { + kpu->layer_argument_fifo = task->remain_layers[i].interrupt_enabe.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_addr.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_channel_num.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_size.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_pool_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_load_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_offset.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_calc_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].write_back_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value2.reg; + kpu->layer_argument_fifo = task->remain_layers[i].dma_parameter.reg; + } + task->remain_layers_length = 0; + } + else + { + for(uint32_t i=0; ilayer_argument_fifo = task->remain_layers[i].interrupt_enabe.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_addr.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_channel_num.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_size.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_pool_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_load_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_offset.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_calc_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].write_back_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value2.reg; + kpu->layer_argument_fifo = task->remain_layers[i].dma_parameter.reg; + } + task->remain_layers += layer_burst_size; + task->remain_layers_length -= layer_burst_size; + } + return 0; +} + +static int kpu_run_dma_output(uint32_t dma_ch, void* dst, uint32_t length, plic_irq_callback_t cb, void* _task) +{ + sysctl_dma_select(dma_ch, SYSCTL_DMA_SELECT_AI_RX_REQ); + dmac_irq_register(dma_ch, kpu_run_all_done, _task, 1); + dmac_set_single_mode(dma_ch, (void *)(&kpu->fifo_data_out), (void *)(dst), DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, (length+7)/8); + return 0; +} + +static int kpu_run_dma_input_done_push_layers(void* _task) +{ + kpu_task_t* task = (kpu_task_t*)_task; + kpu->interrupt_clear.reg = 7; + dmac->channel[task->dma_ch].intclear = 0xFFFFFFFF; + kpu->fifo_threshold.data = (kpu_config_fifo_threshold_t) + { + .fifo_full_threshold = 10, .fifo_empty_threshold=1 + }; + kpu->eight_bit_mode.data = (kpu_config_eight_bit_mode_t) + { + .eight_bit_mode=task->eight_bit_mode + }; + + kpu_layer_argument_t* last_layer = &task->layers[task->layers_length-1]; + + kpu_run_dma_output(task->dma_ch, task->dst, last_layer->dma_parameter.data.dma_total_byte+1, kpu_run_all_done, task); + + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int=0, + .layer_cfg_almost_empty_int=0, + .layer_cfg_almost_full_int=1 + }; + kpu_continue(task); + return 0; +} + +static void kpu_run_dma_input(uint32_t dma_ch, const void* src, plic_irq_callback_t cb, void* _task) +{ + kpu_task_t* task = _task; + kpu_layer_argument_t* first_layer = &task->layers[0]; + uint64_t input_size = first_layer->kernel_calc_type_cfg.data.channel_switch_addr * 64 * (first_layer->image_channel_num.data.i_ch_num+1); + void *v_src = ((uintptr_t)src > 0x80000000 && (uintptr_t)src < 0x80600000) ? (void *)(src - 0x40000000) : (void *)src; + dmac_irq_register(dma_ch, cb, _task, 1); + dmac_set_single_mode(dma_ch, (void *)v_src, (void *)(AI_IO_BASE_ADDR), DMAC_ADDR_INCREMENT, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_16, DMAC_TRANS_WIDTH_64, input_size / 8); +} + +int kpu_run(kpu_task_t* v_task, dmac_channel_number_t dma_ch, const void *src, void* dest, plic_irq_callback_t callback) +{ + if(atomic_cas(&g_kpu_context.kpu_status, 0, 1)) + return -1; + + memcpy((void *)&g_kpu_context.kpu_task, v_task, sizeof(kpu_task_t)); + kpu_task_t *task = (kpu_task_t *)&g_kpu_context.kpu_task; + + kpu_layer_argument_t* last_layer = &task->layers[task->layers_length-1]; + + uint64_t output_size = last_layer->dma_parameter.data.dma_total_byte+1; + + last_layer->dma_parameter.data.send_data_out = 1; + last_layer->interrupt_enabe.data.int_en = 1; + + task->dma_ch = dma_ch; + task->dst = dest; + task->dst_length = output_size; + task->callback = callback; + task->remain_layers_length = task->layers_length; + task->remain_layers = task->layers; + + plic_irq_enable(IRQN_AI_INTERRUPT); + plic_set_priority(IRQN_AI_INTERRUPT, 1); + plic_irq_register(IRQN_AI_INTERRUPT, kpu_continue, task); + + kpu_run_dma_input(dma_ch, src, kpu_run_dma_input_done_push_layers, task); + + return 0; +} + +uint8_t *kpu_get_output_buf(kpu_task_t* task) +{ + kpu_layer_argument_t* last_layer = &task->layers[task->layers_length-1]; + size_t output_size = ((last_layer->dma_parameter.data.dma_total_byte+1) + 7) / 8 * 8; + return malloc(output_size); +} + +void kpu_release_output_buf(uint8_t *output_buf) +{ + if(output_buf != NULL) + free(output_buf); +} + +static int kpu_done(void *ctx) +{ + atomic_swap(&kpu_status, 0); + kpu_task_t *task = (kpu_task_t *)ctx; + task->callback(task->ctx); + return 0; +} + +static int kpu_config_input(void *ctx) +{ + kpu_task_t *task = (kpu_task_t *)ctx; + kpu->interrupt_clear.reg = 7; + if (task->remain_layers_length <= LAYER_BURST_SIZE) + { + for (uint32_t i = 0; i < task->remain_layers_length; i++) + { + kpu->layer_argument_fifo = task->remain_layers[i].interrupt_enabe.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_addr.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_channel_num.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_size.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_pool_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_load_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_offset.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_calc_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].write_back_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value2.reg; + kpu->layer_argument_fifo = task->remain_layers[i].dma_parameter.reg; + } + task->remain_layers_length = 0; + kpu->interrupt_mask.reg = 7; + } + else + { + for (uint32_t i = 0; i < LAYER_BURST_SIZE; i++) + { + kpu->layer_argument_fifo = task->remain_layers[i].interrupt_enabe.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_addr.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_channel_num.reg; + kpu->layer_argument_fifo = task->remain_layers[i].image_size.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_pool_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_load_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_offset.reg; + kpu->layer_argument_fifo = task->remain_layers[i].kernel_calc_type_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].write_back_cfg.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value.reg; + kpu->layer_argument_fifo = task->remain_layers[i].conv_value2.reg; + kpu->layer_argument_fifo = task->remain_layers[i].dma_parameter.reg; + } + task->remain_layers += LAYER_BURST_SIZE; + task->remain_layers_length -= LAYER_BURST_SIZE; + } + return 0; +} + +static void kpu_data_output(kpu_task_t *task) +{ + sysctl_dma_select(task->dma_ch, SYSCTL_DMA_SELECT_AI_RX_REQ); + dmac_irq_register(task->dma_ch, kpu_done, task, 1); + dmac_set_single_mode(task->dma_ch, (void *)(&kpu->fifo_data_out), (void *)(task->dst), DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, task->dst_length); +} + +static int kpu_data_ready(void *ctx) +{ + kpu_task_t *task = (kpu_task_t *)ctx; + + dmac->channel[task->dma_ch].intclear = 0xFFFFFFFF; + kpu_data_output(task); + + kpu->eight_bit_mode.reg = task->eight_bit_mode; + kpu->interrupt_mask.reg = 7; + kpu->interrupt_clear.reg = 7; + kpu->fifo_threshold.data = (kpu_config_fifo_threshold_t) + { + .fifo_full_threshold = 12, .fifo_empty_threshold = 1 + }; + plic_irq_enable(IRQN_AI_INTERRUPT); + plic_set_priority(IRQN_AI_INTERRUPT, 2); + plic_irq_register(IRQN_AI_INTERRUPT, kpu_config_input, task); + kpu_config_input(task); + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 0, + .layer_cfg_almost_full_int = 1 + }; + return 0; +} + +static void kpu_data_input(kpu_task_t *task) +{ + if (task->src == NULL) + { + kpu_data_ready(task); + return; + } + void *v_src = ((uintptr_t)task->src > 0x80000000 && (uintptr_t)task->src < 0x80600000) ? (void *)((void *)task->src - 0x40000000) : (void *)task->src; + dmac_irq_register(task->dma_ch, kpu_data_ready, task, 1); + kpu_layer_argument_t *layer = &task->layers[0]; + dmac_set_single_mode(task->dma_ch, v_src, (void *)(uintptr_t)(AI_IO_BASE_ADDR + layer->image_addr.data.image_src_addr * 64), DMAC_ADDR_INCREMENT, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_16, DMAC_TRANS_WIDTH_64, task->src_length); +} + +int kpu_single_task_init(kpu_task_t *task) +{ + sysctl_clock_enable(SYSCTL_CLOCK_AI); + kpu_layer_argument_t *first_layer = &task->layers[0]; + kpu_layer_argument_t *last_layer = &task->layers[task->layers_length - 1]; + + last_layer->dma_parameter.data.send_data_out = 1; + last_layer->interrupt_enabe.data.int_en = 1; + task->src_length = first_layer->kernel_calc_type_cfg.data.channel_switch_addr * 64 * (first_layer->image_channel_num.data.i_ch_num + 1) / 8; + task->dst_length = ((last_layer->dma_parameter.data.dma_total_byte + 1) + 7) / 8; + task->dst = (uint64_t *)malloc(task->dst_length * 8); + memset(task->dst, 0, task->dst_length * 8); + if (task->dst == NULL) + return 1; + return 0; +} + +int kpu_single_task_deinit(kpu_task_t *task) +{ + free(task->dst); + return 0; +} + +int kpu_model_load_from_buffer(kpu_task_t *task, uint8_t *buffer, kpu_model_layer_metadata_t **meta) +{ + uintptr_t base_addr = (uintptr_t)buffer; + kpu_model_header_t *header = (kpu_model_header_t *)buffer; + kpu_model_layer_metadata_t *layer_meta = (kpu_model_layer_metadata_t *)(base_addr + sizeof(kpu_model_header_t)); + kpu_layer_argument_t *layers = (kpu_layer_argument_t *)(base_addr + header->layers_argument_start); + + if (header->version != 1) + return -1; + uint32_t layers_length = header->layers_length; + task->layers_length = layers_length; + task->eight_bit_mode = header->flags & 1; + task->layers = layers; + task->output_scale = layer_meta[layers_length - 1].output_scale; + task->output_bias = layer_meta[layers_length - 1].output_bias; + size_t i; + for (i = 0; i < layers_length; i++) + { + layers[i].kernel_load_cfg.data.para_start_addr = (uint64_t)(base_addr + layer_meta[i].weigths_offset); + layers[i].kernel_pool_type_cfg.data.bwsx_base_addr = (uint64_t)(base_addr + layer_meta[i].bn_offset); + layers[i].kernel_calc_type_cfg.data.active_addr = (uint64_t)(base_addr + layer_meta[i].act_offset); + } + + if (meta) + *meta = layer_meta; + return 0; +} + +int kpu_start(kpu_task_t *task) +{ + if (atomic_cas(&kpu_status, 0, 1)) + return -1; + + task->remain_layers_length = task->layers_length; + task->remain_layers = task->layers; + kpu_data_input(task); + return 0; +} + +static void kpu_send_layer(const kpu_layer_argument_t *layer) +{ + kpu->layer_argument_fifo = layer->interrupt_enabe.reg; + kpu->layer_argument_fifo = layer->image_addr.reg; + kpu->layer_argument_fifo = layer->image_channel_num.reg; + kpu->layer_argument_fifo = layer->image_size.reg; + kpu->layer_argument_fifo = layer->kernel_pool_type_cfg.reg; + kpu->layer_argument_fifo = layer->kernel_load_cfg.reg; + kpu->layer_argument_fifo = layer->kernel_offset.reg; + kpu->layer_argument_fifo = layer->kernel_calc_type_cfg.reg; + kpu->layer_argument_fifo = layer->write_back_cfg.reg; + kpu->layer_argument_fifo = layer->conv_value.reg; + kpu->layer_argument_fifo = layer->conv_value2.reg; + kpu->layer_argument_fifo = layer->dma_parameter.reg; +} + +void kpu_init(int eight_bit_mode, plic_irq_callback_t callback, void *userdata) +{ + kpu->interrupt_clear.reg = 7; + kpu->fifo_threshold.data = (kpu_config_fifo_threshold_t) + { + .fifo_full_threshold = 10, .fifo_empty_threshold = 1 + }; + kpu->eight_bit_mode.data = (kpu_config_eight_bit_mode_t) + { + .eight_bit_mode = eight_bit_mode + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 0, + .layer_cfg_almost_full_int = 1 + }; + + plic_irq_enable(IRQN_AI_INTERRUPT); + plic_set_priority(IRQN_AI_INTERRUPT, 1); + plic_irq_register(IRQN_AI_INTERRUPT, callback, userdata); +} + +#if 0 +void kpu_input_dma(kpu_layer_argument_t *layer, const uint8_t *src, dmac_channel_number_t dma_ch, plic_irq_callback_t callback, void *userdata) +{ + uint64_t input_size = layer->kernel_calc_type_cfg.data.channel_switch_addr * 64 * (layer->image_channel_num.data.i_ch_num + 1); + dmac_set_irq(dma_ch, callback, userdata, 1); + dmac_set_single_mode(dma_ch, (void *)src, (void *)(AI_IO_BASE_ADDR + layer->image_addr.data.image_src_addr * 64), DMAC_ADDR_INCREMENT, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_16, DMAC_TRANS_WIDTH_64, input_size / 8); +} +#endif + +void kpu_input_dma(const kpu_layer_argument_t *layer, const uint8_t *src, dmac_channel_number_t dma_ch, plic_irq_callback_t callback, void *userdata) +{ + uint64_t input_size = layer->kernel_calc_type_cfg.data.channel_switch_addr * 64 * (layer->image_channel_num.data.i_ch_num + 1); + void *v_src = ((uintptr_t)src > 0x80000000 && (uintptr_t)src < 0x80600000) ? (void *)(src - 0x40000000) : (void *)src; + dmac_set_irq(dma_ch, callback, userdata, 1); + dmac_set_single_mode(dma_ch, (void *)v_src, (void *)(uintptr_t)(AI_IO_BASE_ADDR + layer->image_addr.data.image_src_addr * 64), DMAC_ADDR_INCREMENT, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_16, DMAC_TRANS_WIDTH_64, input_size / 8); +} + +static void kpu_conv2d_core(kpu_layer_argument_t *layer) +{ + kpu_send_layer(layer); +} + +void kpu_conv2d(kpu_layer_argument_t *layer) +{ + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 0, + .layer_cfg_almost_full_int = 1 + }; + kpu_conv2d_core(layer); +} + +void kpu_conv2d_output(kpu_layer_argument_t *layer, dmac_channel_number_t dma_ch, uint8_t *dest, plic_irq_callback_t callback, void *userdata) +{ + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + layer->dma_parameter.data.send_data_out = 1; + sysctl_dma_select(dma_ch, SYSCTL_DMA_SELECT_AI_RX_REQ); + dmac_set_irq(dma_ch, callback, userdata, 1); + dmac_set_single_mode(dma_ch, (void *)(&kpu->fifo_data_out), dest, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, (layer->dma_parameter.data.dma_total_byte + 8) / 8); + kpu_conv2d_core(layer); +} + +void kpu_conv2d_output_full_add(kpu_layer_argument_t *layer, dmac_channel_number_t dma_ch, uint64_t *dest, plic_irq_callback_t callback, void *userdata) +{ + uint32_t channels = layer->image_channel_num.data.o_ch_num + 1; + layer->interrupt_enabe.data.full_add = 1; + + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + layer->dma_parameter.data.send_data_out = 1; + sysctl_dma_select(dma_ch, SYSCTL_DMA_SELECT_AI_RX_REQ); + dmac_set_irq(dma_ch, callback, userdata, 1); + dmac_set_single_mode(dma_ch, (void *)(&kpu->fifo_data_out), dest, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, channels); + kpu_conv2d_core(layer); +} + +void kpu_add(const uint8_t *src1, const quantize_param_t *src1_param, const uint8_t *src2, const quantize_param_t *src2_param, size_t count, uint8_t *dest, const quantize_param_t *dest_param) +{ + quantize_param_t q1 = *src1_param, q2 = *src2_param, q3 = *dest_param; + + size_t i; + for (i = 0; i < count; i++) + { + int value = ((*src1++ * q1.scale + q1.bias + *src2++ * q2.scale + q2.bias) - q3.bias) / q3.scale; + if (value < 0) value = 0; + if (value > 0xFF) value = 0xFF; + *dest++ = value; + } +} + +void kpu_global_average_pool(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, uint8_t *dest, const quantize_param_t *dest_param) +{ + quantize_param_t q1 = *src_param, q2 = *dest_param; + size_t oc, y, x; + + if (((uintptr_t)dest) >= AI_IO_BASE_ADDR && ((uintptr_t)dest) < AI_IO_BASE_ADDR + 2 * 1024 * 1024) + { + uint32_t row_padding = 16; + uint32_t row_group = 4; + uint32_t row_length = 1; + uint32_t height = 4; + + for (oc = 0; oc < channels; oc++) + { + uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding; + for (y = 0; y < 1; y++) + { + uint8_t *y_origin = channel_origin + y * row_length * 64; + for (x = 0; x < 1; x++) + { + int64_t sum = 0; + size_t i; + for (i = 0; i < kernel_size; i++) + sum += *src++; + + int value = ((sum * q1.scale + q1.bias) / kernel_size - q2.bias) / q2.scale; + if (value < 0) value = 0; + if (value > 0xFF) value = 0xFF; + y_origin[x] = value; + } + } + } + } + else + { + for (oc = 0; oc < channels; oc++) + { + int64_t sum = 0; + size_t i; + for (i = 0; i < kernel_size; i++) + sum += *src++; + + int value = ((sum * q1.scale + q1.bias) / kernel_size - q2.bias) / q2.scale; + if (value < 0) value = 0; + if (value > 0xFF) value = 0xFF; + dest[oc] = value; + } + } +} + +void kpu_global_average_pool_float(const uint8_t *src, const quantize_param_t *src_param, int kernel_size, int channels, float *dest) +{ + quantize_param_t q = *src_param; + size_t oc; + + for (oc = 0; oc < channels; oc++) + { + int64_t sum = 0; + size_t i; + for (i = 0; i < kernel_size; i++) + sum += *src++; + + float value = (sum * q.scale + q.bias) / kernel_size; + dest[oc] = value; + } +} + +void kpu_matmul_end(const uint8_t *src, int channels, float *dest, const quantize_param_t *dest_param) +{ + quantize_param_t q1 = *dest_param; + size_t i = 0; + for (i = 0; i < channels; i++) + *dest++ = src[i * 16] * q1.scale + q1.bias; +} + +void kpu_fully_connected(const float *src, const float *weights, const float *biases, float *dest, int input_channels, int output_channels) +{ + int ic, oc; + for (oc = 0; oc < output_channels; oc++) + { + const float *c_weights = weights + oc * input_channels; + + float sum = 0.0f; + for (ic = 0; ic < input_channels; ic++) + sum += src[ic] * c_weights[ic]; + dest[oc] = sum + biases[oc]; + } +} + +void kpu_dequantize(const uint8_t *src, const quantize_param_t *src_param, size_t count, float *dest) +{ + quantize_param_t q1 = *src_param; + size_t i = 0; + for (i = 0; i < count; i++) + *dest++ = src[i] * q1.scale + q1.bias; +} + + +void kpu_input_with_padding(kpu_layer_argument_t *layer, const uint8_t *src, int width, int height, int channels) +{ + uint8_t *dest = (uint8_t *)(uintptr_t)(AI_IO_BASE_ADDR + layer->image_addr.data.image_src_addr * 64); + size_t oc, y, x; + + uint32_t row_padding; + uint32_t row_group; + uint32_t row_length; + + if (width <= 16) + { + row_padding = 16; + row_group = 4; + row_length = 1; + } + else if (width <= 32) + { + row_padding = 32; + row_group = 2; + row_length = 1; + } + else + { + row_padding = 64; + row_group = 1; + row_length = (width + 63) / 64; + } + + for (oc = 0; oc < channels; oc++) + { + uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding; + for (y = 0; y < height; y++) + { + uint8_t *y_origin = channel_origin + y * row_length * 64; + for (x = 0; x < width; x++) + y_origin[x] = *src++; + } + } +} +#if USE_CACHED_AI_RAM +static void kpu_flush_cache(uint32_t addr, size_t lines) +{ + size_t line; + for (line = 0; line < lines; line++) + { + const uint64_t *src = (const uint64_t *)(AI_RAM_BASE_ADDR + (addr + line) * 64); + uint64_t *dest = (uint64_t *)(AI_IO_BASE_ADDR + (addr + line) * 64); + size_t i; + for (i = 0; i < 8; i++) + dest[i] = src[i]; + } +} +#endif +static int64_t kpu_carry_shift(int64_t value, uint32_t shift) +{ + if (shift > 0) + { + value >>= shift - 1; + if (value & 0x1) + { + if (value < 0) + value = (value >> 1) - 1; + else + value = (value >> 1) + 1; + } + else + { + value >>= 1; + } + } + + return value; +} +static void kpu_upload_core(size_t width, size_t height, size_t channels, const uint8_t *src, uint32_t kpu_addr) +{ + uint8_t *dest = (uint8_t *)(uintptr_t)(AI_IO_BASE_ADDR + kpu_addr * 64); + size_t oc, y, x; + uint32_t row_padding; + uint32_t row_group; + uint32_t row_length; + if (width <= 16) + { + row_padding = 16; + row_group = 4; + row_length = 1; + } + else if (width <= 32) + { + row_padding = 32; + row_group = 2; + row_length = 1; + } + else + { + row_padding = 64; + row_group = 1; + row_length = (width + 63) / 64; + } + + if ((uintptr_t)src % 8 == 0 && width % 8 == 0) + { +#define UPLOAD_BEGIN() \ + for (oc = 0; oc < channels; oc++) \ + { \ + uint8_t* channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding; \ + for (y = 0; y < height; y++) \ + { \ + uint64_t* y_origin = (uint64_t*)(channel_origin + y * row_length * 64); \ + +#define UPLOAD_END() \ + } \ + } + + width /= 8; + const uint64_t *u64_src = (const uint64_t *)src; + if (width == 1) + { + UPLOAD_BEGIN() + y_origin[0] = *u64_src++; + UPLOAD_END() + } + else if (width == 2) + { + UPLOAD_BEGIN() + { + y_origin[0] = *u64_src++; + y_origin[1] = *u64_src++; + } + UPLOAD_END() + } + else if (width == 4) + { + UPLOAD_BEGIN() + { + y_origin[0] = *u64_src++; + y_origin[1] = *u64_src++; + y_origin[2] = *u64_src++; + y_origin[3] = *u64_src++; + } + UPLOAD_END() + } + else + { + UPLOAD_BEGIN() + for (x = 0; x < width; x++) + y_origin[x] = *u64_src++; + UPLOAD_END() + } + } + else + { + for (oc = 0; oc < channels; oc++) + { + uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding; + for (y = 0; y < height; y++) + { + uint8_t *y_origin = channel_origin + y * row_length * 64; + for (x = 0; x < width; x++) + y_origin[x] = *src++; + } + } + } +} +static void kpu_kmodel_input_with_padding(const kpu_layer_argument_t *layer, const uint8_t *src) +{ + size_t width = layer->image_size.data.i_row_wid + 1; + size_t height = layer->image_size.data.i_col_high + 1; + size_t channels = layer->image_channel_num.data.i_ch_num + 1; + + kpu_upload_core(width, height, channels, src, layer->image_addr.data.image_src_addr); +} + +static void kpu_kmodel_add(const kpu_model_add_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src_a = (const float *)(ctx->main_buffer + arg->main_mem_in_a_address); + const float *src_b = (const float *)(ctx->main_buffer + arg->main_mem_in_b_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + size_t i, count = arg->count; + + for (i = 0; i < count; i++) + dest[i] = src_a[i] + src_b[i]; +} + +static void kpu_quantized_add(const kpu_model_quant_add_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src_a = (const uint8_t*)(ctx->main_buffer + arg->main_mem_in_a_address); + const uint8_t *src_b = (const uint8_t*)(ctx->main_buffer + arg->main_mem_in_b_address); + size_t count = ALIGN_UP(arg->count, 8) / 8; + int64_t off_a = arg->in_a_offset, mul_a = arg->in_a_mul, sh_a = arg->in_a_shift; + int64_t off_b = arg->in_b_offset, mul_b = arg->in_b_mul, sh_b = arg->in_b_shift; + int64_t off_o = arg->out_offset, mul_o = arg->out_mul, sh_o = arg->out_shift; + + uint8_t* dest = (uint8_t*)(ctx->main_buffer + arg->main_mem_out_address); + size_t i; + + if (sh_a == sh_b) + { +#define QADD_UNROLL_1(x) \ + int64_t a##x = *src_a++; \ + int64_t b##x = *src_b++; + +#define QADD_UNROLL_2(x) \ + a##x += off_a; \ + b##x += off_b; + +#define QADD_UNROLL_3(x) \ + a##x *= mul_a; \ + b##x *= mul_b; + +#define QADD_UNROLL_4(x) \ + int64_t v##x = a##x + b##x; + +#define QADD_UNROLL_5(x) \ + v##x >>= sh_a; + +#define QADD_UNROLL_6(x) \ + v##x *= mul_o; + +#define QADD_UNROLL_7(x) \ + v##x = kpu_carry_shift(v##x, sh_o); + +#define QADD_UNROLL_8(x) \ + v##x += off_o; + +#define QADD_UNROLL_9(x) \ + v##x = min(0xFF, max(0, v##x)); + +#define QADD_UNROLL_10(x) \ + *dest++ = v##x; + +#define QADD_UNROLL_S(x) \ + QADD_UNROLL_##x(0) \ + QADD_UNROLL_##x(1) \ + QADD_UNROLL_##x(2) \ + QADD_UNROLL_##x(3) \ + QADD_UNROLL_##x(4) \ + QADD_UNROLL_##x(5) \ + QADD_UNROLL_##x(6) \ + QADD_UNROLL_##x(7) + + for (i = 0; i < count; i++) + { + QADD_UNROLL_S(1); + QADD_UNROLL_S(2); + QADD_UNROLL_S(3); + QADD_UNROLL_S(4); + QADD_UNROLL_S(5); + QADD_UNROLL_S(6); + QADD_UNROLL_S(7); + QADD_UNROLL_S(8); + QADD_UNROLL_S(9); + QADD_UNROLL_S(10); + } + } + else + { +#undef QADD_UNROLL_1 +#define QADD_UNROLL_1(x) \ + int64_t a##x = *src_a++; \ + int64_t b##x = *src_b++; + +#undef QADD_UNROLL_2 +#define QADD_UNROLL_2(x) \ + a##x += off_a; \ + b##x += off_b; + +#undef QADD_UNROLL_3 +#define QADD_UNROLL_3(x) \ + a##x *= mul_a; \ + b##x *= mul_b; + +#undef QADD_UNROLL_4 +#define QADD_UNROLL_4(x) \ + a##x >>= sh_a; \ + b##x >>= sh_b; + +#undef QADD_UNROLL_5 +#define QADD_UNROLL_5(x) \ + int64_t v##x = a##x + b##x; + +#undef QADD_UNROLL_6 +#define QADD_UNROLL_6(x) \ + v##x *= mul_o; + +#undef QADD_UNROLL_7 +#define QADD_UNROLL_7(x) \ + v##x >>= sh_o; + +#undef QADD_UNROLL_8 +#define QADD_UNROLL_8(x) \ + v##x += off_o; + +#undef QADD_UNROLL_9 +#define QADD_UNROLL_9(x) \ + v##x = min(0xFF, max(0, v##x)); + +#undef QADD_UNROLL_10 +#define QADD_UNROLL_10(x) \ + *dest++ = v##x; + +#undef QADD_UNROLL_S +#define QADD_UNROLL_S(x) \ + QADD_UNROLL_##x(0) \ + QADD_UNROLL_##x(1) \ + QADD_UNROLL_##x(2) \ + QADD_UNROLL_##x(3) \ + QADD_UNROLL_##x(4) \ + QADD_UNROLL_##x(5) \ + QADD_UNROLL_##x(6) \ + QADD_UNROLL_##x(7) + + for (i = 0; i < count; i++) + { + QADD_UNROLL_S(1); + QADD_UNROLL_S(2); + QADD_UNROLL_S(3); + QADD_UNROLL_S(4); + QADD_UNROLL_S(5); + QADD_UNROLL_S(6); + QADD_UNROLL_S(7); + QADD_UNROLL_S(8); + QADD_UNROLL_S(9); + QADD_UNROLL_S(10); + } + } +} + +static void kpu_global_average_pool2d(const kpu_model_gap2d_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + size_t oc, channels = arg->channels, kernel_size = arg->kernel_size; + + for (oc = 0; oc < channels; oc++) + { + float sum = 0.f; + size_t i; + for (i = 0; i < kernel_size; i++) + sum += *src++; + + dest[oc] = sum / kernel_size; + } +} + +static void kpu_quantized_max_pool2d(const kpu_model_quant_max_pool2d_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address); + uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address); + kpu_model_shape_t in_shape = arg->in_shape, out_shape = arg->out_shape; + uint32_t kernel_width = arg->kernel_width, kernel_height = arg->kernel_height; + uint32_t stride_width = arg->stride_width, stride_height = arg->stride_height; + uint32_t padding_width = arg->padding_width, padding_height = arg->padding_height; + + uint32_t out_y, out_x, oc; + + for (oc = 0; oc < out_shape.channels; oc++) + { + const uint8_t *channel_src = src + in_shape.width * in_shape.height * oc; + for (out_y = 0; out_y < out_shape.height; out_y++) + { + for (out_x = 0; out_x < out_shape.width; out_x++) + { + int32_t in_x_origin = (int32_t)(out_x * stride_width) - padding_width; + int32_t in_y_origin = (int32_t)(out_y * stride_height) - padding_height; + int32_t kernel_x_start = max(0, -in_x_origin); + int32_t kernel_x_end = min(kernel_width, in_shape.width - in_x_origin); + int32_t kernel_y_start = max(0, -in_y_origin); + int32_t kernel_y_end = min(kernel_height, in_shape.height - in_y_origin); + uint8_t value = 0; + + int32_t kernel_y, kernel_x; + for (kernel_y = kernel_y_start; kernel_y < kernel_y_end; kernel_y++) + { + for (kernel_x = kernel_x_start; kernel_x < kernel_x_end; kernel_x++) + { + int32_t in_x = in_x_origin + kernel_x; + int32_t in_y = in_y_origin + kernel_y; + value = max(value, channel_src[in_y * in_shape.width + in_x]); + } + } + + *dest++ = value; + } + } + } +} + +static void kpu_average_pool2d(const kpu_model_ave_pool2d_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + kpu_model_shape_t in_shape = arg->in_shape, out_shape = arg->out_shape; + uint32_t kernel_width = arg->kernel_width, kernel_height = arg->kernel_height; + uint32_t stride_width = arg->stride_width, stride_height = arg->stride_height; + uint32_t padding_width = arg->padding_width, padding_height = arg->padding_height; + + uint32_t out_y, out_x, oc; + + for (oc = 0; oc < out_shape.channels; oc++) + { + const float *channel_src = src + in_shape.width * in_shape.height * oc; + for (out_y = 0; out_y < out_shape.height; out_y++) + { + for (out_x = 0; out_x < out_shape.width; out_x++) + { + int32_t in_x_origin = (int32_t)(out_x * stride_width) - padding_width; + int32_t in_y_origin = (int32_t)(out_y * stride_height) - padding_height; + int32_t kernel_x_start = max(0, -in_x_origin); + int32_t kernel_x_end = min(kernel_width, in_shape.width - in_x_origin); + int32_t kernel_y_start = max(0, -in_y_origin); + int32_t kernel_y_end = min(kernel_height, in_shape.height - in_y_origin); + float value = 0; + float kernel_count = 0; + + int32_t kernel_y, kernel_x; + for (kernel_y = kernel_y_start; kernel_y < kernel_y_end; kernel_y++) + { + for (kernel_x = kernel_x_start; kernel_x < kernel_x_end; kernel_x++) + { + int32_t in_x = in_x_origin + kernel_x; + int32_t in_y = in_y_origin + kernel_y; + value += channel_src[in_y * in_shape.width + in_x]; + kernel_count++; + } + } + + *dest++ = value / kernel_count; + } + } + } +} + +static void kpu_quantize(const kpu_model_quantize_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + size_t count = arg->count; + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address);; + const kpu_model_quant_param_t q = arg->quant_param; + float scale = 1.f / q.scale; + + uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->mem_out_address); + size_t i; + for (i = 0; i < count; i++) + { + int value = (*src++ - q.bias) * scale; + if (value < 0) value = 0; + if (value > 0xFF) value = 0xFF; + *dest++ = (uint8_t)value; + } +} + +static void kpu_kmodel_dequantize(const kpu_model_dequantize_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + size_t oc, count = arg->count; + const kpu_model_quant_param_t q = arg->quant_param; + + for (oc = 0; oc < count; oc++) + dest[oc] = *src++ * q.scale + q.bias; +} + +static void kpu_kmodel_channelwise_dequantize(const kpu_model_channelwise_dequant_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + size_t oc, i, channels = arg->channels, count = arg->channel_size; + + for (oc = 0; oc < channels; oc++) + { + const kpu_model_quant_param_t q = arg->quant_params[oc]; + + for (i = 0; i < count; i++) + *dest++ = *src++ * q.scale + q.bias; + } +} + +static void kpu_requantize(const kpu_model_requantize_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address); + uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address); + size_t oc, count = ALIGN_UP(arg->count, 8) / 8; + const uint8_t *table = arg->table; + + for (oc = 0; oc < count;) + { + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + dest[oc++] = table[*src++]; + } +} + +static void kpu_l2_normalization(const kpu_model_l2_norm_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + size_t oc, channels = arg->channels; + + float sum = 0.f; + const float epsilon = 1e-10f; + for (oc = 0; oc < channels; oc++) + sum += src[oc] * src[oc]; + if (sum < epsilon) + sum = epsilon; + sum = 1.f / sqrtf(sum); + for (oc = 0; oc < channels; oc++) + dest[oc] = src[oc] * sum; +} + +static void kpu_softmax(const kpu_model_softmax_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + size_t oc, channels = arg->channels; + + float max = FLT_MIN; + for (oc = 0; oc < channels; oc++) + max = fmaxf(max, src[oc]); + + float sum = 0.f; + for (oc = 0; oc < channels; oc++) + { + float value = expf(src[oc] - max); + sum += value; + dest[oc] = value; + } + + for (oc = 0; oc < channels; oc++) + dest[oc] /= sum; +} + +static void kpu_concat(const kpu_model_concat_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address); + uint32_t count = arg->input_count, i; + + for (i = 0; i < count; i++) + { + kpu_model_memory_range_t input = arg->inputs_mem[i]; + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + input.start); + memcpy(dest, src, input.size); + dest += input.size; + } +} + +static void kpu_kmodel_fully_connected(const kpu_model_fully_connected_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + uint32_t in_channels = arg->in_channels, out_channels = arg->out_channels, ic, oc; + const float *weights = arg->weights, *bias = arg->weights + in_channels * out_channels; + + if (in_channels % 8 == 0) + { +#define FC_UNROLL_1(x) \ + float i##x = *c_src++; \ + float w##x = *c_weights++; + +#define FC_UNROLL_2(x) \ + sum += i##x * w##x; + +#define FC_UNROLL_S(x) \ + FC_UNROLL_##x(0) \ + FC_UNROLL_##x(1) \ + FC_UNROLL_##x(2) \ + FC_UNROLL_##x(3) \ + FC_UNROLL_##x(4) \ + FC_UNROLL_##x(5) \ + FC_UNROLL_##x(6) \ + FC_UNROLL_##x(7) + + for (oc = 0; oc < out_channels; oc++) + { + const float *c_src = src; + const float *c_weights = weights + oc * in_channels; + + float sum = 0.0f; + for (ic = 0; ic < in_channels / 8; ic++) + { + FC_UNROLL_S(1); + FC_UNROLL_S(2); + } + + dest[oc] = sum + bias[oc]; + } + } + else + { + for (oc = 0; oc < out_channels; oc++) + { + const float *c_weights = weights + oc * in_channels; + + float sum = 0.0f; + for (ic = 0; ic < in_channels; ic++) + sum += src[ic] * c_weights[ic]; + dest[oc] = sum + bias[oc]; + } + } +} + +static void kpu_tf_flatten(const kpu_model_tf_flatten_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + kpu_model_shape_t in_shape = arg->shape; + uint32_t oc, oy, ox; + + for (oy = 0; oy < in_shape.height; oy++) + for (ox = 0; ox < in_shape.width; ox++) + for (oc = 0; oc < in_shape.channels; oc++) + *dest++ = src[(oc * in_shape.height + oy) * in_shape.width + ox]; +} + +static void kpu_resize_nearest_neighbor(const kpu_model_resize_nearest_neighbor_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const float *src = (const float *)(ctx->main_buffer + arg->main_mem_in_address); + float *dest = (float *)(ctx->main_buffer + arg->main_mem_out_address); + kpu_model_shape_t in_shape = arg->in_shape; + uint32_t out_width = arg->out_width, out_height = arg->out_height; + uint32_t oc, oy, ox; + + float height_scale = (float)in_shape.height / out_height; + float width_scale = (float)in_shape.width / out_width; + + for (oc = 0; oc < in_shape.channels; oc++) + { + const float *channel_src = src + in_shape.width * in_shape.height * oc; + for (oy = 0; oy model_buffer + arg->layer_offset); + layer.kernel_load_cfg.data.para_start_addr = (uintptr_t)(ctx->model_buffer + arg->weights_offset); + layer.kernel_pool_type_cfg.data.bwsx_base_addr = (uintptr_t)(ctx->model_buffer + arg->bn_offset); + layer.kernel_calc_type_cfg.data.active_addr = (uintptr_t)(ctx->model_buffer + arg->act_offset); + + if (arg->flags & KLF_MAIN_MEM_OUT) + { + dmac_channel_number_t dma_ch = ctx->dma_ch; + uint8_t *dest = ctx->main_buffer + arg->main_mem_out_address; + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + layer.dma_parameter.data.send_data_out = 1; + sysctl_dma_select(dma_ch, SYSCTL_DMA_SELECT_AI_RX_REQ); + if (ctx->current_layer != ctx->layers_length) + dmac_set_irq(dma_ch, ai_step, ctx, 1); + else + dmac_set_irq(dma_ch, (plic_irq_callback_t)kpu_kmodel_done, ctx, 1); + dmac_set_single_mode(dma_ch, (void *)(&kpu->fifo_data_out), dest, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT, + DMAC_MSIZE_8, DMAC_TRANS_WIDTH_64, (layer.dma_parameter.data.dma_total_byte + 8) / 8); + } + else + { + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 0, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + layer.interrupt_enabe.data.int_en = 1; + } + + kpu_send_layer((const kpu_layer_argument_t *)&layer); +} + +static void kpu_add_padding(const kpu_model_add_padding_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address); +#if USE_CACHED_AI_RAM + uint8_t *dest = (uint8_t *)(uintptr_t)(AI_RAM_BASE_ADDR + arg->kpu_mem_out_address * 64); +#else + uint8_t *dest = (uint8_t *)(uintptr_t)(AI_IO_BASE_ADDR + arg->kpu_mem_out_address * 64); +#endif + + uint32_t row_padding = 16; + uint32_t row_group = 4; + uint32_t row_length = 1; + uint32_t height = 4; + uint32_t oc, x, y, channels = arg->channels; + + for (oc = 0; oc < channels; oc++) + { + uint8_t *channel_origin = dest + oc / row_group * row_length * height * 64 + oc % row_group * row_padding; + for (y = 0; y < 1; y++) + { + uint8_t *y_origin = channel_origin + y * row_length * 64; + for (x = 0; x < 1; x++) + y_origin[x] = *src++; + } + } + +#if USE_CACHED_AI_RAM + uint32_t lines = row_length * height * channels / row_group; + kpu_flush_cache(arg->kpu_mem_out_address, lines); +#endif +} + +static void kpu_remove_padding(const kpu_model_remove_padding_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + const uint8_t *src = (const uint8_t *)(ctx->main_buffer + arg->main_mem_in_address); + uint8_t *dest = (uint8_t *)(ctx->main_buffer + arg->main_mem_out_address); + uint32_t oc, channels = arg->channels; + + for (oc = 0; oc < channels; oc++) + *dest++ = src[oc * 16]; +} + +static void kpu_upload(const kpu_model_upload_layer_argument_t *arg, kpu_model_context_t *ctx) +{ + size_t width = arg->width; + size_t height = arg->height; + size_t channels = arg->channels; + + kpu_upload_core(width, height, channels, ctx->main_buffer + arg->main_mem_in_address, arg->kpu_mem_out_address); +} + +int kpu_load_kmodel(kpu_model_context_t *ctx, const uint8_t *buffer) +{ + uintptr_t base_addr = (uintptr_t)buffer; + const kpu_kmodel_header_t *header = (const kpu_kmodel_header_t *)buffer; + printf("\nheader->version:%d,header->arch:%d\n",header->version,header->arch); + if (header->version == 3 && header->arch == 0) + { + ctx->model_buffer = buffer; + ctx->output_count = header->output_count; + ctx->outputs = (const kpu_model_output_t *)(base_addr + sizeof(kpu_kmodel_header_t)); + ctx->layer_headers = (const kpu_model_layer_header_t *)((uintptr_t)ctx->outputs + sizeof(kpu_model_output_t) * ctx->output_count); + ctx->layers_length = header->layers_length; + ctx->body_start = (const uint8_t *)((uintptr_t)ctx->layer_headers + sizeof(kpu_model_layer_header_t) * header->layers_length); + ctx->main_buffer = (uint8_t *)malloc(header->main_mem_usage); + if (!ctx->main_buffer) + return -1; + } + else + { + return -1; + } + + return 0; +} + +int kpu_get_output(kpu_model_context_t *ctx, uint32_t index, uint8_t **data, size_t *size) +{ + if (index >= ctx->output_count) + return -1; + + const kpu_model_output_t * output = ctx->outputs + index; + *data = ctx->main_buffer + output->address; + *size = output->size; + return 0; +} + +void kpu_model_free(kpu_model_context_t *ctx) +{ + free(ctx->main_buffer); + ctx->main_buffer = NULL; +} + +#if KPU_DEBUG +static uint64_t last_time; +static uint64_t total_time; +static uint64_t kpu_time; +static uint32_t last_layer_type; + +static const char *str_layer_type(uint32_t type) +{ + switch (type) + { + case KL_ADD: + return "Add"; + case KL_QUANTIZED_ADD: + return "QuantAdd"; + case KL_GLOBAL_AVERAGE_POOL2D: + return "GAP"; + case KL_QUANTIZED_MAX_POOL2D: + return "QuantMaxPool2d"; + case KL_AVERAGE_POOL2D: + return "AveragePool2d"; + case KL_QUANTIZE: + return "Quantize"; + case KL_DEQUANTIZE: + return "Dequantize"; + case KL_REQUANTIZE: + return "Requantize"; + case KL_L2_NORMALIZATION: + return "L2Norm"; + case KL_SOFTMAX: + return "Softmax"; + case KL_CONCAT: + return "Concat"; + case KL_QUANTIZED_CONCAT: + return "QuantConcat"; + case KL_FULLY_CONNECTED: + return "FullyConnected"; + case KL_TENSORFLOW_FLATTEN: + return "TFFlatten"; + case KL_RESIZE_NEAREST_NEIGHBOR: + return "ResizeNearestNeighbor"; + case KL_CHANNELWISE_DEQUANTIZE: + return "ChannelwiseDequantize"; + case KL_K210_CONV: + return "K210Conv"; + case KL_K210_ADD_PADDING: + return "K210AddPad"; + case KL_K210_REMOVE_PADDING: + return "K210RemovePad"; + case KL_K210_UPLOAD: + return "K210Upload"; + default: + return "Unknown"; + } +} +#endif + +static int kpu_kmodel_done(kpu_model_context_t *ctx) +{ + kpu->interrupt_clear.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 1, + .layer_cfg_almost_full_int = 1 + }; +#if KPU_DEBUG + uint32_t cnt_layer_id = ctx->current_layer - 1; + uint64_t time = sysctl_get_time_us(); + if (last_time != 0) + { + uint64_t layer_time = time - last_time; + printf("layer %d [%s]: %f ms\n", cnt_layer_id, str_layer_type(last_layer_type), layer_time / 1000.0); + total_time += layer_time; + if (last_layer_type == KL_K210_CONV) + kpu_time += layer_time; + } + + printf("KPU: %f ms\n", kpu_time / 1000.0); + printf("CPU: %f ms\n", (total_time - kpu_time) / 1000.0); + printf("Model: %f ms\n", total_time / 1000.0); +#endif + ctx->done_callback(ctx->userdata); + return 0; +} + +static int ai_step(void *userdata) +{ + kpu_model_context_t *ctx = (kpu_model_context_t *)userdata; + + uint32_t cnt_layer_id = ctx->current_layer++; + const uint8_t *layer_body = ctx->current_body; + const kpu_model_layer_header_t *cnt_layer_header = ctx->layer_headers + cnt_layer_id; + ctx->current_body += cnt_layer_header->body_size; + +#if KPU_DEBUG + uint64_t time = sysctl_get_time_us(); + if (last_time != 0) + { + uint64_t layer_time = time - last_time; + printf("layer %d [%s]: %f ms\n", cnt_layer_id - 1, str_layer_type(last_layer_type), layer_time / 1000.0); + total_time += layer_time; + if (last_layer_type == KL_K210_CONV) + kpu_time += layer_time; + } + + last_layer_type = cnt_layer_header->type; + last_time = sysctl_get_time_us(); +#endif + + switch (cnt_layer_header->type) + { + case KL_ADD: + kpu_kmodel_add((const kpu_model_add_layer_argument_t *)layer_body, ctx); + break; + case KL_QUANTIZED_ADD: + kpu_quantized_add((const kpu_model_quant_add_layer_argument_t *)layer_body, ctx); + break; + case KL_GLOBAL_AVERAGE_POOL2D: + kpu_global_average_pool2d((const kpu_model_gap2d_layer_argument_t *)layer_body, ctx); + break; + case KL_QUANTIZED_MAX_POOL2D: + kpu_quantized_max_pool2d((const kpu_model_quant_max_pool2d_layer_argument_t *)layer_body, ctx); + break; + case KL_AVERAGE_POOL2D: + kpu_average_pool2d((const kpu_model_ave_pool2d_layer_argument_t *)layer_body, ctx); + break; + case KL_QUANTIZE: + kpu_quantize((const kpu_model_quantize_layer_argument_t *)layer_body, ctx); + break; + case KL_DEQUANTIZE: + kpu_kmodel_dequantize((const kpu_model_dequantize_layer_argument_t *)layer_body, ctx); + break; + case KL_REQUANTIZE: + kpu_requantize((const kpu_model_requantize_layer_argument_t *)layer_body, ctx); + break; + case KL_L2_NORMALIZATION: + kpu_l2_normalization((const kpu_model_l2_norm_layer_argument_t *)layer_body, ctx); + break; + case KL_SOFTMAX: + kpu_softmax((const kpu_model_softmax_layer_argument_t *)layer_body, ctx); + break; + case KL_CONCAT: + case KL_QUANTIZED_CONCAT: + kpu_concat((const kpu_model_concat_layer_argument_t *)layer_body, ctx); + break; + case KL_FULLY_CONNECTED: + kpu_kmodel_fully_connected((const kpu_model_fully_connected_layer_argument_t *)layer_body, ctx); + break; + case KL_TENSORFLOW_FLATTEN: + kpu_tf_flatten((const kpu_model_tf_flatten_layer_argument_t *)layer_body, ctx); + break; + case KL_RESIZE_NEAREST_NEIGHBOR: + kpu_resize_nearest_neighbor((const kpu_model_resize_nearest_neighbor_layer_argument_t *)layer_body, ctx); + break; + case KL_CHANNELWISE_DEQUANTIZE: + kpu_kmodel_channelwise_dequantize((const kpu_model_channelwise_dequant_argument_t *)layer_body, ctx); + break; + case KL_K210_CONV: + kpu_conv((const kpu_model_conv_layer_argument_t *)layer_body, ctx); + return 0; + case KL_K210_ADD_PADDING: + kpu_add_padding((const kpu_model_add_padding_layer_argument_t *)layer_body, ctx); + break; + case KL_K210_REMOVE_PADDING: + kpu_remove_padding((const kpu_model_remove_padding_layer_argument_t *)layer_body, ctx); + break; + case KL_K210_UPLOAD: + kpu_upload((const kpu_model_upload_layer_argument_t *)layer_body, ctx); + break; + default: + assert(!"Layer is not supported."); + } + + if (cnt_layer_id != (ctx->layers_length - 1)) + ai_step(userdata); + else + kpu_kmodel_done(ctx); + return 0; +} + +static void ai_step_not_isr(void *userdata) +{ + sysctl_disable_irq(); + ai_step(userdata); + sysctl_enable_irq(); +} + +int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_number_t dma_ch, kpu_done_callback_t done_callback, void *userdata) +{ + ctx->dma_ch = dma_ch; + ctx->done_callback = done_callback; + ctx->userdata = userdata; + ctx->current_layer = 0; + ctx->current_body = ctx->body_start; +#if KPU_DEBUG + last_time = 0; + total_time = 0; + kpu_time = 0; +#endif + + kpu_kmodel_header_t *header = (kpu_kmodel_header_t *)ctx->model_buffer; + kpu->interrupt_clear.reg = 7; + kpu->fifo_threshold.data = (kpu_config_fifo_threshold_t) + { + .fifo_full_threshold = 10, .fifo_empty_threshold = 1 + }; + kpu->eight_bit_mode.data = (kpu_config_eight_bit_mode_t) + { + .eight_bit_mode = header->flags & 1 + }; + kpu->interrupt_mask.data = (kpu_config_interrupt_t) + { + .calc_done_int = 1, + .layer_cfg_almost_empty_int = 0, + .layer_cfg_almost_full_int = 1 + }; + + plic_irq_enable(IRQN_AI_INTERRUPT); + plic_set_priority(IRQN_AI_INTERRUPT, 1); + plic_irq_register(IRQN_AI_INTERRUPT, ai_step, ctx); + + const kpu_model_layer_header_t *first_layer_header = ctx->layer_headers; + if (first_layer_header->type != KL_K210_CONV) + return -1; + const kpu_model_conv_layer_argument_t *first_layer = (const kpu_model_conv_layer_argument_t *)ctx->body_start; + kpu_layer_argument_t layer_arg = *(volatile kpu_layer_argument_t *)(ctx->model_buffer + first_layer->layer_offset); + + if ((layer_arg.image_size.data.i_row_wid + 1) % 64 != 0) + { + kpu_kmodel_input_with_padding(&layer_arg, src); + ai_step_not_isr(ctx); + } + else + { + kpu_input_dma(&layer_arg, src, ctx->dma_ch, ai_step, ctx); + } + + return 0; +} + diff --git a/Ubiquitous/XiZi_IIoT/path_kernel.mk b/Ubiquitous/XiZi_IIoT/path_kernel.mk index 3731ae559..b9544200b 100755 --- a/Ubiquitous/XiZi_IIoT/path_kernel.mk +++ b/Ubiquitous/XiZi_IIoT/path_kernel.mk @@ -461,6 +461,9 @@ KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/tensorflow KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/tensorflow-lite/tensorflow-lite-for-mcu/source/third_party/gemmlowp # KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/tensorflow-lite/tensorflow-lite-for-mcu/source/third_party/flatbuffers/include # KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/tensorflow-lite/tensorflow-lite-for-mcu/source/third_party/ruy # +KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure # +KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/kpu/yolov2 # +KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/knowing/kpu/yolov2_json # endif ifeq ($(CONFIG_LIB_LV),y) @@ -479,6 +482,10 @@ KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protoc KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protocol/melsec # KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protocol/opcua # KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protocol/s7 # +endif + + +ifeq ($(CONFIG_LIB_USING_CJSON), y) KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/lib/cJSON endif diff --git a/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c b/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c index 6eba43464..e66e82166 100644 --- a/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c +++ b/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c @@ -850,7 +850,6 @@ static uint32 SdReadMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const uint do { - BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param); BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); SD_TIMEOUT(start_time, 10 * SPI_SD_TIMEOUT_NUM); From 04dc796f9582737efbbac89753d7aa69cb37c76a Mon Sep 17 00:00:00 2001 From: wuzheng Date: Mon, 12 Dec 2022 16:22:36 +0800 Subject: [PATCH 06/15] fix problems in client recv --- .../Applications/app_test/test_ethernet.c | 38 ++++++++++--------- .../ethernet/connect_w5500.c | 23 ++++++----- .../ethernet/connect_w5500.c | 23 ++++++----- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/APP_Framework/Applications/app_test/test_ethernet.c b/APP_Framework/Applications/app_test/test_ethernet.c index 5574d2fcb..6e551c004 100644 --- a/APP_Framework/Applications/app_test/test_ethernet.c +++ b/APP_Framework/Applications/app_test/test_ethernet.c @@ -9,7 +9,6 @@ #define TCP_PORT 12345 const static uint32_t sn = 0; -const static uint32_t socket_tcp = 0; #ifdef ETHERNET_AS_SERVER static int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, @@ -26,9 +25,9 @@ static int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, uint32_t sent_size = 0; memset(buf,0,buf_size); strcpy(buf,"The message has been recved"); - ret = wiz_sock_send(socket_tcp, buf, buf_size); + ret = wiz_sock_send(sn, buf, buf_size); if (ret < 0) { - wiz_sock_close(socket_tcp); + wiz_sock_close(sn); return ret; } } else if (opt == RECV_DATA) { @@ -87,27 +86,27 @@ static uint32_t wiz_client_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, enum TCP_OPTION opt) { // assert(buf_size <= g_wiznet_buf_size); int32_t ret; - switch (getSn_SR(socket_tcp)) { + switch (getSn_SR(sn)) { case SOCK_CLOSE_WAIT: - wiz_sock_disconnect(socket_tcp); + wiz_sock_disconnect(sn); break; case SOCK_CLOSED: - wiz_socket(socket_tcp, Sn_MR_TCP, 5000, 0x00); + wiz_socket(sn, Sn_MR_TCP, 5000, 0x00); break; case SOCK_INIT: KPrintf("[SOCKET CLIENT] sock init.\n"); - wiz_sock_connect(socket_tcp, dst_ip, dst_port); + wiz_sock_connect(sn, dst_ip, dst_port); break; case SOCK_ESTABLISHED: - if (getSn_IR(socket_tcp) & Sn_IR_CON) { - printf("[SOCKET CLIENT] %d:Connected\r\n", socket_tcp); - setSn_IR(socket_tcp, Sn_IR_CON); + if (getSn_IR(sn) & Sn_IR_CON) { + printf("[SOCKET CLIENT] %d:Connected\r\n", sn); + setSn_IR(sn, Sn_IR_CON); } if (opt == SEND_DATA) { uint32_t sent_size = 0; - ret = wiz_sock_send(socket_tcp, buf, buf_size); + ret = wiz_sock_send(sn, buf, buf_size); if (ret < 0) { - wiz_sock_close(socket_tcp); + wiz_sock_close(sn); return ret; } } else if (opt == RECV_DATA) { @@ -145,15 +144,18 @@ void TestSocketAsClient(int argc, char *argv[]) } while(1){ - ret = wiz_client_op(client_sock, argv[2], sizeof(argv[2]), destination_ip, port,SEND_DATA); - PrivTaskDelay(10); + ret = wiz_client_op(client_sock, argv[2], strlen(argv[2]), destination_ip, port,SEND_DATA); + printf("sizeof:%d\n",strlen(argv[2])); + PrivTaskDelay(1000); if (ret > 0) { ret=wiz_client_op(client_sock, buf, BUFF_SIZE, destination_ip, port, RECV_DATA); - printf("client recv msg successfully!\n"); - printf("%s\n",buf); - break; + printf("read ret is %d\n",ret); + if(ret>0){ + printf("client recv msg successfully!\n"); + printf("%s\n",buf); + } }; - PrivTaskDelay(100); + PrivTaskDelay(1000); } diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c index ba1e0b810..62ad935e7 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/ethernet/connect_w5500.c @@ -22,7 +22,6 @@ extern void spi_select_cs(void); extern void spi_deselete_cs(void); // global configurations for w5500 tcp connection -const uint32_t socket_tcp = 0; const uint32_t g_wiznet_buf_size = 2048; static wiz_NetInfo g_wiz_netinfo = {.mac = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11}, @@ -269,27 +268,27 @@ uint32_t wiz_client_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, enum TCP_OPTION opt) { // assert(buf_size <= g_wiznet_buf_size); int32_t ret; - switch (getSn_SR(socket_tcp)) { + switch (getSn_SR(sn)) { case SOCK_CLOSE_WAIT: - wiz_sock_disconnect(socket_tcp); + wiz_sock_disconnect(sn); break; case SOCK_CLOSED: - wiz_socket(socket_tcp, Sn_MR_TCP, 5000, 0x00); + wiz_socket(sn, Sn_MR_TCP, 5000, 0x00); break; case SOCK_INIT: KPrintf("[SOCKET CLIENT] sock init.\n"); - wiz_sock_connect(socket_tcp, dst_ip, dst_port); + wiz_sock_connect(sn, dst_ip, dst_port); break; case SOCK_ESTABLISHED: - if (getSn_IR(socket_tcp) & Sn_IR_CON) { - printf("[SOCKET CLIENT] %d:Connected\r\n", socket_tcp); - setSn_IR(socket_tcp, Sn_IR_CON); + if (getSn_IR(sn) & Sn_IR_CON) { + printf("[SOCKET CLIENT] %d:Connected\r\n", sn); + setSn_IR(sn, Sn_IR_CON); } if (opt == SEND_DATA) { uint32_t sent_size = 0; - ret = wiz_sock_send(socket_tcp, buf, buf_size); + ret = wiz_sock_send(sn, buf, buf_size); if (ret < 0) { - wiz_sock_close(socket_tcp); + wiz_sock_close(sn); return ret; } } else if (opt == RECV_DATA) { @@ -348,9 +347,9 @@ int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, } if (opt == SEND_DATA) { uint32_t sent_size = 0; - ret = wiz_sock_send(socket_tcp, buf, buf_size); + ret = wiz_sock_send(sn, buf, buf_size); if (ret < 0) { - wiz_sock_close(socket_tcp); + wiz_sock_close(sn); return ret; } } else if (opt == RECV_DATA) { diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-riscv64/third_party_driver/ethernet/connect_w5500.c b/Ubiquitous/XiZi_IIoT/board/xidatong-riscv64/third_party_driver/ethernet/connect_w5500.c index 22803ee9e..93fcba38c 100644 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-riscv64/third_party_driver/ethernet/connect_w5500.c +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-riscv64/third_party_driver/ethernet/connect_w5500.c @@ -22,7 +22,6 @@ extern void spi_select_cs(void); extern void spi_deselete_cs(void); // global configurations for w5500 tcp connection -const uint32_t socket_tcp = 0; const uint32_t g_wiznet_buf_size = 2048; static wiz_NetInfo g_wiz_netinfo = {.mac = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11}, @@ -269,27 +268,27 @@ uint32_t wiz_client_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, enum TCP_OPTION opt) { // assert(buf_size <= g_wiznet_buf_size); int32_t ret; - switch (getSn_SR(socket_tcp)) { + switch (getSn_SR(sn)) { case SOCK_CLOSE_WAIT: - wiz_sock_disconnect(socket_tcp); + wiz_sock_disconnect(sn); break; case SOCK_CLOSED: - wiz_socket(socket_tcp, Sn_MR_TCP, 5000, 0x00); + wiz_socket(sn, Sn_MR_TCP, 5000, 0x00); break; case SOCK_INIT: KPrintf("[SOCKET CLIENT] sock init.\n"); - wiz_sock_connect(socket_tcp, dst_ip, dst_port); + wiz_sock_connect(sn, dst_ip, dst_port); break; case SOCK_ESTABLISHED: - if (getSn_IR(socket_tcp) & Sn_IR_CON) { - printf("[SOCKET CLIENT] %d:Connected\r\n", socket_tcp); - setSn_IR(socket_tcp, Sn_IR_CON); + if (getSn_IR(sn) & Sn_IR_CON) { + printf("[SOCKET CLIENT] %d:Connected\r\n", sn); + setSn_IR(sn, Sn_IR_CON); } if (opt == SEND_DATA) { uint32_t sent_size = 0; - ret = wiz_sock_send(socket_tcp, buf, buf_size); + ret = wiz_sock_send(sn, buf, buf_size); if (ret < 0) { - wiz_sock_close(socket_tcp); + wiz_sock_close(sn); return ret; } } else if (opt == RECV_DATA) { @@ -348,9 +347,9 @@ int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size, } if (opt == SEND_DATA) { uint32_t sent_size = 0; - ret = wiz_sock_send(socket_tcp, buf, buf_size); + ret = wiz_sock_send(sn, buf, buf_size); if (ret < 0) { - wiz_sock_close(socket_tcp); + wiz_sock_close(sn); return ret; } } else if (opt == RECV_DATA) { From 6a89a12c492fd1123df3798b37ced2b08dd4a750 Mon Sep 17 00:00:00 2001 From: wuzheng Date: Mon, 12 Dec 2022 16:24:54 +0800 Subject: [PATCH 07/15] temporarily adapt kpu for XiZi --- .../Applications/app_test/test_camera.c | 9 - APP_Framework/Framework/knowing/Makefile | 2 +- APP_Framework/Framework/knowing/kpu/Makefile | 3 + .../kpu/k210_yolov2_detect_procedure/Kconfig | 5 +- .../k210_yolov2_detect.c | 218 ++++++++++-------- .../transform_layer/xizi/transform.c | 5 +- .../transform_layer/xizi/transform.h | 38 +++ .../xizi/user_api/posix_support/pthread.c | 1 + .../edu-riscv64/third_party_driver/dma/dmac.c | 18 +- .../third_party_driver/dvp/connect_dvp.c | 43 +++- .../third_party_driver/include/connect_dvp.h | 28 +++ .../edu-riscv64/third_party_driver/kpu/kpu.c | 32 +-- 12 files changed, 268 insertions(+), 134 deletions(-) create mode 100644 APP_Framework/Framework/knowing/kpu/Makefile diff --git a/APP_Framework/Applications/app_test/test_camera.c b/APP_Framework/Applications/app_test/test_camera.c index f414dd2ee..56f389ff1 100644 --- a/APP_Framework/Applications/app_test/test_camera.c +++ b/APP_Framework/Applications/app_test/test_camera.c @@ -2,15 +2,6 @@ #include #include -#define NULL_PARAMETER 0 - -#define DVP_INIT 0x00U -#define REG_SCCB_READ 0x12U -#define REG_SCCB_WRITE 0x13U -#define OUTPUT_CONFIG 0x20U -#define LCD_STRING_TYPE 0 -#define LCD_DOT_TYPE 1 -#define LCD_SIZE 320 static uint16_t image_buff[384000]; diff --git a/APP_Framework/Framework/knowing/Makefile b/APP_Framework/Framework/knowing/Makefile index d12b24374..62c998618 100644 --- a/APP_Framework/Framework/knowing/Makefile +++ b/APP_Framework/Framework/knowing/Makefile @@ -1,4 +1,4 @@ -SRC_DIR := tensorflow-lite +SRC_DIR := kpu tensorflow-lite include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/knowing/kpu/Makefile b/APP_Framework/Framework/knowing/kpu/Makefile new file mode 100644 index 000000000..ff538d7ef --- /dev/null +++ b/APP_Framework/Framework/knowing/kpu/Makefile @@ -0,0 +1,3 @@ +SRC_DIR := k210_yolov2_detect_procedure yolov2 yolov2_json + +include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig index 2d25a5710..a359ac926 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig @@ -4,8 +4,11 @@ menuconfig USING_K210_YOLOV2_DETECT default n config CAMERA_DEV_DRIVER - string "Set camera dev path" + string "Set camera dev path for kpu" default "/dev/ov2640" +config KPU_LCD_DEV_DRIVER + string "Set lcd dev path for kpu" + default "/dev/lcd_dev" diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c index 028784b2d..e2aa4d8ec 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c @@ -1,24 +1,26 @@ #include "k210_yolov2_detect.h" #include "cJSON.h" +#include "dvp.h" #ifdef USING_YOLOV2_JSONPARSER #include #endif #include "region_layer.h" #define STACK_SIZE (128 * 1024) -static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX; +static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX-1; +static _ioctl_shoot_para shoot_para_t = {0}; #define THREAD_PRIORITY_D (11) static pthread_t tid = 0; static void *thread_detect_entry(void *parameter); -static int g_fd = 0; +static int camera_fd = 0; static int kmodel_fd = 0; static int if_exit = 0; static unsigned char *showbuffer = NULL; static unsigned char *kpurgbbuffer = NULL; -static _ioctl_shoot_para shoot_para_t = {0}; + unsigned char *model_data = NULL; // kpu data load memory unsigned char *model_data_align = NULL; @@ -29,6 +31,8 @@ volatile uint32_t g_ai_done_flag; static void ai_done(void *ctx) { g_ai_done_flag = 1; } +#define ERROR_FLAG (1) + void k210_detect(char *json_file_path) { int ret = 0; @@ -36,50 +40,78 @@ void k210_detect(char *json_file_path) int size = 0; char kmodel_path[127] = {}; + // open and parse from json file yolov2_params_t detect_params = param_parse(json_file_path); if (!detect_params.is_valid) { return; } - - g_fd = open("/dev/ov2640", O_RDONLY); - if (g_fd < 0) { - printf("open ov2640 fail !!"); + printf("select camera device name:%s\n",CAMERA_DEV_DRIVER); + camera_fd = PrivOpen(CAMERA_DEV_DRIVER, O_RDONLY); + if (camera_fd < 0) { + printf("open %s fail !!",CAMERA_DEV_DRIVER); return; } + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = CAMERA_TYPE; + struct CameraCfg camera_init_cfg ={ + .gain_manu_enable = 0, + .gain = 0xFF, + .window_w = 800, + .window_h = 600, + .output_w = IMAGE_WIDTH, + .output_h = IMAGE_HEIGHT, + .window_xoffset = 0, + .window_yoffset = 0 + }; + ioctl_cfg.args = &camera_init_cfg; + if (0 != PrivIoctl(camera_fd, OPE_CFG, &ioctl_cfg)) + { + printf("camera pin fd error %d\n", camera_fd); + PrivClose(camera_fd); + } + + // configure the resolution of camera _ioctl_set_reso set_dvp_reso = {detect_params.sensor_output_size[1], detect_params.sensor_output_size[0]}; - ioctl(g_fd, IOCTRL_CAMERA_OUT_SIZE_RESO, &set_dvp_reso); - showbuffer = - (unsigned char *)rt_malloc_align(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2, 64); + struct PrivIoctlCfg camera_cfg; + camera_cfg.args = &set_dvp_reso; + camera_cfg.ioctl_driver_type = CAMERA_TYPE; + PrivIoctl(camera_fd, IOCTRL_CAMERA_OUT_SIZE_RESO, &camera_cfg); + + // alloc the memory for camera and kpu running + showbuffer = (unsigned char *)malloc(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); if (NULL == showbuffer) { - close(g_fd); + close(camera_fd); printf("showbuffer apply memory fail !!"); return; } - kpurgbbuffer = (unsigned char *)rt_malloc_align(detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3, 64); + kpurgbbuffer = (unsigned char *)malloc(detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3); if (NULL == kpurgbbuffer) { - close(g_fd); - rt_free_align(showbuffer); + close(camera_fd); + free(showbuffer); printf("kpurgbbuffer apply memory fail !!"); return; } model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); + printf("model address:%x->%x\n",model_data_align,model_data_align + detect_params.kmodel_size); if (NULL == model_data) { - rt_free_align(showbuffer); - rt_free_align(kpurgbbuffer); - close(g_fd); + free(showbuffer); + free(kpurgbbuffer); + close(camera_fd); printf("model_data apply memory fail !!"); return; } memset(model_data, 0, detect_params.kmodel_size + 255); memset(showbuffer, 0, detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); memset(kpurgbbuffer, 0, detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3); - shoot_para_t.pdata = (unsigned int *)(showbuffer); + shoot_para_t.pdata = (uintptr_t)(showbuffer); shoot_para_t.length = (size_t)(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); + /* load memory */ // kmodel path generate from json file path, *.json -> *.kmodel memcpy(kmodel_path, json_file_path, strlen(json_file_path)); + int idx_suffix_start = strlen(json_file_path) - 4; const char kmodel_suffix[7] = "kmodel"; int kmodel_suffix_len = 6; @@ -87,45 +119,56 @@ void k210_detect(char *json_file_path) kmodel_path[idx_suffix_start + 5 - kmodel_suffix_len] = kmodel_suffix[5 - kmodel_suffix_len]; } printf("kmodel path: %s\n", kmodel_path); - kmodel_fd = open(kmodel_path, O_RDONLY); + unsigned char *model_data_align = (unsigned char *)(((uintptr_t)model_data + 255) & (~255)); + kmodel_fd = PrivOpen(kmodel_path, O_RDONLY); + + memset(model_data,0,sizeof(model_data)); if (kmodel_fd < 0) { printf("open kmodel fail"); - close(g_fd); + close(camera_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); return; } else { - size = read(kmodel_fd, model_data, detect_params.kmodel_size); + size = read(kmodel_fd, model_data_align, detect_params.kmodel_size); if (size != detect_params.kmodel_size) { printf("read kmodel error size %d\n", size); - close(g_fd); + close(camera_fd); close(kmodel_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); return; - } else { + close(kmodel_fd); printf("read kmodel success \n"); } } - unsigned char *model_data_align = (unsigned char *)(((unsigned int)model_data + 255) & (~255)); - // dvp_set_ai_addr((uint32_t)kpurgbbuffer, - // (uint32_t)(kpurgbbuffer + detect_params.net_input_size[0] * detect_params.net_input_size[1]), - // (uint32_t)(kpurgbbuffer + detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2)); + +#ifdef ADD_RTTHREAD_FETURES dvp_set_ai_addr( - (uint32_t)(kpurgbbuffer + + (uintptr_t)(kpurgbbuffer + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0])), - (uint32_t)(kpurgbbuffer + + (uintptr_t)(kpurgbbuffer + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + detect_params.net_input_size[0] * detect_params.net_input_size[1]), - (uint32_t)(kpurgbbuffer + + (uintptr_t)(kpurgbbuffer + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2)); +#endif + // Set AI buff address of Camera + RgbAddress ai_address_preset; + ai_address_preset.r_addr = (uintptr_t)kpurgbbuffer + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]); + ai_address_preset.g_addr = ai_address_preset.r_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1]; + ai_address_preset.b_addr = ai_address_preset.g_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1]; + camera_cfg.args = &ai_address_preset; + PrivIoctl(camera_fd,SET_AI_ADDR,&camera_cfg); + + // Load kmodel into kpu task if (kpu_load_kmodel(&detect_task, model_data_align) != 0) { printf("\nmodel init error\n"); - close(g_fd); + close(camera_fd); close(kmodel_fd); free(showbuffer); free(kpurgbbuffer); @@ -137,8 +180,7 @@ void k210_detect(char *json_file_path) detect_rl.anchor = detect_params.anchor; detect_rl.nms_value = detect_params.nms_thresh; detect_rl.classes = detect_params.class_num; - result = - region_layer_init(&detect_rl, detect_params.net_output_shape[0], detect_params.net_output_shape[1], + result =region_layer_init(&detect_rl, detect_params.net_output_shape[0], detect_params.net_output_shape[1], detect_params.net_output_shape[2], detect_params.net_input_size[1], detect_params.net_input_size[0]); printf("region_layer_init result %d \n\r", result); for (int idx = 0; idx < detect_params.class_num; idx++) { @@ -159,7 +201,7 @@ void k210_detect(char *json_file_path) printf("thread_detect_entry successfully!\n"); } else { printf("thread_detect_entry failed! error code is %d\n", result); - close(g_fd); + close(camera_fd); } } // #ifdef __RT_THREAD_H__ @@ -168,22 +210,38 @@ void k210_detect(char *json_file_path) static void *thread_detect_entry(void *parameter) { +#ifdef BSP_USING_LCD + int lcd_fd = PrivOpen(KPU_LCD_DEV_DRIVER, O_RDWR); + if (lcd_fd < 0) + { + printf("open lcd fd error:%d\n", lcd_fd); + } + LcdWriteParam graph_param; + graph_param.type = LCD_DOT_TYPE; +#endif + yolov2_params_t detect_params = *(yolov2_params_t *)parameter; - extern void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t * ptr); + struct PrivIoctlCfg camera_cfg; + camera_cfg.ioctl_driver_type = CAMERA_TYPE; + printf("thread_detect_entry start!\n"); int ret = 0; - // sysctl_enable_irq(); while (1) { - // memset(showbuffer,0,320*240*2); g_ai_done_flag = 0; - ret = ioctl(g_fd, IOCTRL_CAMERA_START_SHOT, &shoot_para_t); - if (RT_ERROR == ret) { + + //get a graph map from camera + camera_cfg.args = &shoot_para_t; + ret = PrivIoctl(camera_fd, IOCTRL_CAMERA_START_SHOT, &camera_cfg); + if (ERROR_FLAG == ret) { printf("ov2640 can't wait event flag"); - rt_free(showbuffer); - close(g_fd); + free(showbuffer); + close(camera_fd); pthread_exit(NULL); return NULL; } + + +#ifdef ADD_RTTHREAD_FETURES if (dmalock_sync_take(&dma_ch, 2000)) { printf("Fail to take DMA channel"); } @@ -191,13 +249,19 @@ static void *thread_detect_entry(void *parameter) while (!g_ai_done_flag) ; dmalock_release(dma_ch); +#elif defined ADD_XIZI_FETURES + kpu_run_kmodel(&detect_task, kpurgbbuffer, dma_ch, ai_done, NULL); + while (!g_ai_done_flag) + ; +#endif + float *output; size_t output_size; kpu_get_output(&detect_task, 0, (uint8_t **)&output, &output_size); detect_rl.input = output; region_layer_run(&detect_rl, &detect_info); + printf("detect_info.obj_number:%d\n",detect_info.obj_number); /* display result */ - for (int cnt = 0; cnt < detect_info.obj_number; cnt++) { detect_info.obj[cnt].y1 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0])/2; detect_info.obj[cnt].y2 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0])/2; @@ -208,12 +272,27 @@ static void *thread_detect_entry(void *parameter) detect_info.obj[cnt].prob); } #ifdef BSP_USING_LCD - lcd_draw_picture(0, 0, (uint16_t)detect_params.sensor_output_size[1] - 1, - (uint16_t)detect_params.sensor_output_size[0] - 1, (uint32_t *)showbuffer); - // lcd_show_image(0, 0, (uint16_t)detect_params.sensor_output_size[1], (uint16_t)detect_params.sensor_output_size[0], - // (unsigned int *)showbuffer); + +#ifdef ADD_RTTHREAD_FETURES + extern void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t * ptr); + lcd_draw_picture(0, 0, (uint16_t)detect_params.sensor_output_size[1] - 1, + (uint16_t)detect_params.sensor_output_size[0] - 1, (uint32_t *)showbuffer); + // lcd_show_image(0, 0, (uint16_t)detect_params.sensor_output_size[1], (uint16_t)detect_params.sensor_output_size[0], + // (unsigned int *)showbuffer); +#else + //refresh the LCD using photo of camera + for (int i = 0; i < IMAGE_HEIGHT; i++) + { + graph_param.pixel_info.pixel_color = (uint16_t*)showbuffer + i * IMAGE_WIDTH; + graph_param.pixel_info.x_startpos = 0; + graph_param.pixel_info.y_startpos = i + (LCD_SIZE - IMAGE_HEIGHT) / 2; + graph_param.pixel_info.x_endpos = IMAGE_WIDTH - 1; + graph_param.pixel_info.y_endpos = i + (LCD_SIZE - IMAGE_HEIGHT) / 2; + PrivWrite(lcd_fd, &graph_param, NULL_PARAMETER); + } +#endif + #endif - usleep(500); if (1 == if_exit) { if_exit = 0; printf("thread_detect_entry exit"); @@ -226,7 +305,7 @@ void detect_delete() { if (showbuffer != NULL) { int ret = 0; - close(g_fd); + close(camera_fd); close(kmodel_fd); free(showbuffer); free(kpurgbbuffer); @@ -235,46 +314,3 @@ void detect_delete() if_exit = 1; } } -// #ifdef __RT_THREAD_H__ -// MSH_CMD_EXPORT(detect_delete, detect task delete); -// #endif - -// void kmodel_load(unsigned char *model_data) -// { -// int kmodel_fd = 0; -// int size = 0; -// char kmodel_path[127] = {}; -// // kmodel path generate from json file path, *.json -> *.kmodel -// memcpy(kmodel_path, json_file_path, strlen(json_file_path)); -// int idx_suffix_start = strlen(json_file_path) - 4; -// const char kmodel_suffix[5] = "kmodel"; -// int kmodel_suffix_len = 5; -// while (kmodel_suffix_len--) { -// kmodel_path[idx_suffix_start + 4 - kmodel_suffix_len] = kmodel_suffix[4 - kmodel_suffix_len]; -// } -// printf("Kmodel path: %s\n", kmodel_path); -// kmodel_fd = open(kmodel_path, O_RDONLY); - -// model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); -// if (NULL == model_data) { -// printf("model_data apply memory fail !!"); -// return; -// } -// memset(model_data, 0, detect_params.kmodel_size + 255); - -// if (kmodel_fd >= 0) { -// size = read(kmodel_fd, model_data, detect_params.kmodel_size); -// if (size != detect_params.kmodel_size) { -// printf("read kmodel error size %d\n", size); - -// } else { -// printf("read kmodel success"); -// } -// } else { -// free(model_data); -// printf("open kmodel fail"); -// } -// } -// #ifdef __RT_THREAD_H__ -// MSH_CMD_EXPORT(kmodel_load, kmodel load memory); -// #endif diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.c b/APP_Framework/Framework/transform_layer/xizi/transform.c index f2d53d155..3fb8c4ddc 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.c +++ b/APP_Framework/Framework/transform_layer/xizi/transform.c @@ -154,7 +154,6 @@ int PrivIoctl(int fd, int cmd, void *args) { int ret; struct PrivIoctlCfg *ioctl_cfg = (struct PrivIoctlCfg *)args; - switch (ioctl_cfg->ioctl_driver_type) { case SERIAL_TYPE: @@ -163,12 +162,10 @@ int PrivIoctl(int fd, int cmd, void *args) case PIN_TYPE: ret = PrivPinIoctl(fd, cmd, ioctl_cfg->args); break; - case I2C_TYPE: - ret = ioctl(fd, cmd, ioctl_cfg->args); - break; case LCD_TYPE: ret = PrivLcdIoctl(fd, cmd, ioctl_cfg->args); break; + case I2C_TYPE: case RTC_TYPE: case ADC_TYPE: case DAC_TYPE: diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.h b/APP_Framework/Framework/transform_layer/xizi/transform.h index 9cb3be855..54f2b6897 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.h +++ b/APP_Framework/Framework/transform_layer/xizi/transform.h @@ -227,6 +227,25 @@ struct RtcDrvConfigureParam time_t *time; }; +typedef struct +{ + uintptr_t pdata; + uint32_t length; +}_ioctl_shoot_para; + +typedef struct +{ + uint32_t width; // width The width of image + uint32_t height; // height The height of image +}_ioctl_set_reso; + +typedef struct +{ + uintptr_t r_addr; + uintptr_t g_addr; + uintptr_t b_addr; +}RgbAddress; + enum TCP_OPTION { SEND_DATA = 0, RECV_DATA, @@ -241,6 +260,25 @@ enum TCP_OPTION { #define MY_INDEV_X BSP_LCD_Y_MAX #define MY_INDEV_Y BSP_LCD_X_MAX +#define DVP_INIT 0x00U +#define REG_SCCB_READ 0x12U +#define REG_SCCB_WRITE 0x13U +#define OUTPUT_CONFIG 0x20U +#define LCD_STRING_TYPE 0 +#define LCD_DOT_TYPE 1 +#define LCD_SIZE 320 +#define IMAGE_HEIGHT 240 +#define IMAGE_WIDTH 320 +#define NULL_PARAMETER 0 + +#define REG_SCCB_READ 0x12U +#define REG_SCCB_WRITE 0x13U +#define SCCB_REG_LENGTH 0x08U +#define IOCTRL_CAMERA_START_SHOT (20) +#define SET_DISPLAY_ADDR (21) +#define SET_AI_ADDR (22) +#define IOCTRL_CAMERA_OUT_SIZE_RESO (23) + /*********************shell***********************/ //for int func(int argc, char *agrv[]) #define PRIV_SHELL_CMD_MAIN_ATTR (SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)) diff --git a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c index ce33b259a..b10b2d07f 100644 --- a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c +++ b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/pthread.c @@ -77,6 +77,7 @@ int pthread_attr_setschedparam(pthread_attr_t *attr, int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stack_size) { + attr->stacksize = stack_size; return 0; } diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dma/dmac.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dma/dmac.c index a899e44f2..3306e7524 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dma/dmac.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dma/dmac.c @@ -31,6 +31,7 @@ #include "utils.h" #include "plic.h" #include "stdlib.h" +#include volatile dmac_t *const dmac = (dmac_t *)DMAC_BASE_ADDR; @@ -172,6 +173,7 @@ void dmac_channel_disable(dmac_channel_number_t channel_num) } writeq(chen.data, &dmac->chen); + } int32_t dmac_check_channel_busy(dmac_channel_number_t channel_num) @@ -766,26 +768,30 @@ void dmac_set_src_dest_length(dmac_channel_number_t channel_num, const void *src dmac_channel_enable(channel_num); } -static int dmac_irq_callback(void *ctx) +static int dmac_irq_callback(int vector,void *ctx) { dmac_context_t *v_dmac_context = (dmac_context_t *)(ctx); dmac_channel_number_t v_dmac_channel = v_dmac_context->dmac_channel; dmac_chanel_interrupt_clear(v_dmac_channel); - if(v_dmac_context->callback != NULL) + if(v_dmac_context->callback != NULL){ v_dmac_context->callback(v_dmac_context->ctx); - + } return 0; } + + void dmac_irq_register(dmac_channel_number_t channel_num , plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority) { dmac_context[channel_num].dmac_channel = channel_num; dmac_context[channel_num].callback = dmac_callback; dmac_context[channel_num].ctx = ctx; dmac_enable_channel_interrupt(channel_num); - plic_set_priority(IRQN_DMA0_INTERRUPT + channel_num, priority); - plic_irq_enable(IRQN_DMA0_INTERRUPT + channel_num); - plic_irq_register(IRQN_DMA0_INTERRUPT + channel_num, dmac_irq_callback, &dmac_context[channel_num]); + // plic_set_priority(IRQN_DMA0_INTERRUPT + channel_num, priority); + // plic_irq_enable(IRQN_DMA0_INTERRUPT + channel_num); + // plic_irq_register(IRQN_DMA0_INTERRUPT + channel_num, dmac_irq_callback, &dmac_context[channel_num]); + isrManager.done->enableIrq(IRQN_DMA0_INTERRUPT + channel_num); + isrManager.done->registerIrq(IRQN_DMA0_INTERRUPT + channel_num, (IsrHandlerType)dmac_irq_callback, &dmac_context[channel_num]); } void __attribute__((weak, alias("dmac_irq_register"))) dmac_set_irq(dmac_channel_number_t channel_num , plic_irq_callback_t dmac_callback, void *ctx, uint32_t priority); diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c index 04463832b..116c2bd07 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c @@ -6,9 +6,11 @@ #include "plic.h" #include -#define REG_SCCB_READ 0x12U -#define REG_SCCB_WRITE 0x13U -#define SCCB_REG_LENGTH 0x08U +#define CONTINOUS_SHOOTS 1 +#define ONLY_ONE_SHOOT 2 +#define STOP_SHOOT 0 + +static int shoot_flag = 0; // shoot will close when shoot_flag == 0 // irq interrupt function static int on_irq_dvp(int irq, void *arg) @@ -17,11 +19,16 @@ static int on_irq_dvp(int irq, void *arg) { dvp_clear_interrupt(DVP_STS_FRAME_FINISH); } - else - { - dvp_start_convert(); + else{ + if(shoot_flag>0){ + dvp_start_convert(); + if(ONLY_ONE_SHOOT==shoot_flag){ + shoot_flag=STOP_SHOOT; + } + } dvp_clear_interrupt(DVP_STS_FRAME_START); } + return 0; } @@ -64,14 +71,14 @@ static uint32 DvpDrvInit(void) #endif #ifdef DVP_AI_OUTPUT dvp_set_output_enable(DVP_OUTPUT_AI, 1); - dvp_set_ai_addr((uint32_t)DVP_AI_RED_ADRESS, (uint32_t)DVP_AI_GREEN_ADRESS, (uint32_t)DVP_AI_BLUE_ADRESS); + // dvp_set_ai_addr((uint32_t)DVP_AI_RED_ADRESS, (uint32_t)DVP_AI_GREEN_ADRESS, (uint32_t)DVP_AI_BLUE_ADRESS); #endif #ifdef DVP_INTERRUPT_ENABLE dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 0); isrManager.done->registerIrq(IRQN_DVP_INTERRUPT, (IsrHandlerType)on_irq_dvp, NULL); isrManager.done->enableIrq(IRQN_DVP_INTERRUPT); dvp_clear_interrupt(DVP_STS_FRAME_START | DVP_STS_FRAME_FINISH); - dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 1); + dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 0); KPrintf("camera interrupt has open!\n"); #endif return ret; @@ -125,15 +132,33 @@ static uint32 DvpDrvConfigure(void *drv, struct BusConfigureInfo *args) int cmd_type = args->configure_cmd; struct CameraCfg* tmp_cfg; + RgbAddress* kpu_rgb_address; + _ioctl_shoot_para* pixel_cfg; switch (cmd_type) { case OPE_INT: break; case OPE_CFG: tmp_cfg = (struct CameraCfg *)args->private_data; - SensorConfigure(tmp_cfg); + memcpy(&sensor_config,tmp_cfg,sizeof(struct CameraCfg)); + SensorConfigure(&sensor_config); dvp_set_image_size(tmp_cfg->output_w, tmp_cfg->output_h); break; + case IOCTRL_CAMERA_START_SHOT: + pixel_cfg = (_ioctl_shoot_para*)args->private_data; + dvp_set_display_addr(pixel_cfg->pdata); + dvp_set_output_enable(DVP_OUTPUT_DISPLAY, 1); + dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 1); + shoot_flag=ONLY_ONE_SHOOT; + break; + case SET_AI_ADDR: + kpu_rgb_address = (RgbAddress*)args->private_data; + dvp_set_output_enable(DVP_OUTPUT_AI, 1); + dvp_set_ai_addr(kpu_rgb_address->r_addr,kpu_rgb_address->g_addr,kpu_rgb_address->b_addr); + break; + case IOCTRL_CAMERA_OUT_SIZE_RESO: + dvp_set_image_size(((uint32_t*)args->private_data)[0], ((uint32_t*)args->private_data)[1]); + break; case REG_SCCB_READ: ReadDvpReg(drv, (struct DvpRegConfigureInfo *)args->private_data); break; diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h index 178fc5ddd..14695c659 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h @@ -25,6 +25,34 @@ extern "C" { #endif +#define REG_SCCB_READ 0x12U +#define REG_SCCB_WRITE 0x13U +#define SCCB_REG_LENGTH 0x08U +#define IOCTRL_CAMERA_START_SHOT (20) +#define SET_DISPLAY_ADDR (21) +#define SET_AI_ADDR (22) +#define IOCTRL_CAMERA_OUT_SIZE_RESO (23) + + +typedef struct +{ + uintptr_t r_addr; + uintptr_t g_addr; + uintptr_t b_addr; +}RgbAddress; + +typedef struct +{ + uintptr_t pdata; + uint32_t length; +}_ioctl_shoot_para; + +typedef struct +{ + uint32_t width; // width The width of image + uint32_t height; // height The height of image +}_ioctl_set_reso; + int HwDvpInit(void); #ifdef __cplusplus diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c index 4926c8d6a..01e2d21b5 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/kpu.c @@ -10,6 +10,8 @@ #include "bsp.h" #include #include +#include "plic.h" +#include #define LAYER_BURST_SIZE 12 @@ -765,7 +767,6 @@ static void kpu_kmodel_input_with_padding(const kpu_layer_argument_t *layer, con size_t width = layer->image_size.data.i_row_wid + 1; size_t height = layer->image_size.data.i_col_high + 1; size_t channels = layer->image_channel_num.data.i_ch_num + 1; - kpu_upload_core(width, height, channels, src, layer->image_addr.data.image_src_addr); } @@ -1349,7 +1350,7 @@ int kpu_load_kmodel(kpu_model_context_t *ctx, const uint8_t *buffer) { uintptr_t base_addr = (uintptr_t)buffer; const kpu_kmodel_header_t *header = (const kpu_kmodel_header_t *)buffer; - printf("\nheader->version:%d,header->arch:%d\n",header->version,header->arch); + if (header->version == 3 && header->arch == 0) { ctx->model_buffer = buffer; @@ -1500,7 +1501,6 @@ static int ai_step(void *userdata) last_layer_type = cnt_layer_header->type; last_time = sysctl_get_time_us(); #endif - switch (cnt_layer_header->type) { case KL_ADD: @@ -1564,9 +1564,10 @@ static int ai_step(void *userdata) default: assert(!"Layer is not supported."); } - - if (cnt_layer_id != (ctx->layers_length - 1)) - ai_step(userdata); + if (cnt_layer_id != (ctx->layers_length - 1)){ + + ai_step(userdata); + } else kpu_kmodel_done(ctx); return 0; @@ -1579,6 +1580,11 @@ static void ai_step_not_isr(void *userdata) sysctl_enable_irq(); } +static void ai_my_step(int vector,void *userdata) +{ + ai_step(userdata); +} + int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_number_t dma_ch, kpu_done_callback_t done_callback, void *userdata) { ctx->dma_ch = dma_ch; @@ -1608,10 +1614,12 @@ int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_nu .layer_cfg_almost_empty_int = 0, .layer_cfg_almost_full_int = 1 }; - - plic_irq_enable(IRQN_AI_INTERRUPT); - plic_set_priority(IRQN_AI_INTERRUPT, 1); - plic_irq_register(IRQN_AI_INTERRUPT, ai_step, ctx); + isrManager.done->enableIrq(IRQN_AI_INTERRUPT); + isrManager.done->registerIrq(IRQN_AI_INTERRUPT, (IsrHandlerType)ai_my_step, ctx); + + // plic_irq_enable(IRQN_AI_INTERRUPT); + // plic_set_priority(IRQN_AI_INTERRUPT, 1); + // plic_irq_register(IRQN_AI_INTERRUPT, ai_step, ctx); const kpu_model_layer_header_t *first_layer_header = ctx->layer_headers; if (first_layer_header->type != KL_K210_CONV) @@ -1624,11 +1632,9 @@ int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_nu kpu_kmodel_input_with_padding(&layer_arg, src); ai_step_not_isr(ctx); } - else - { + else{ kpu_input_dma(&layer_arg, src, ctx->dma_ch, ai_step, ctx); } - return 0; } From 1864f39dd296a01e7098317b87616b3308c45eed Mon Sep 17 00:00:00 2001 From: WuZheng Date: Wed, 14 Dec 2022 17:35:10 +0800 Subject: [PATCH 08/15] fix bugs in multi-blocks read meeting '0xFE' CRCs --- .../resources/spi/sd_card_spi/sd_spi.c | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c b/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c index e66e82166..8c0854830 100644 --- a/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c +++ b/Ubiquitous/XiZi_IIoT/resources/spi/sd_card_spi/sd_spi.c @@ -28,7 +28,7 @@ static uint32 SdReady(SpiSdDeviceType spi_sd_dev) NULL_PARAM_CHECK(spi_sd_dev); uint8 data = 0xFF; - uint8 read; + uint8 read = 0x00; uint32 start_time; struct BusBlockWriteParam write_param; @@ -42,7 +42,7 @@ static uint32 SdReady(SpiSdDeviceType spi_sd_dev) start_time = 0; do { - BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param); + // BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param); BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); @@ -690,7 +690,7 @@ static uint32 SdHwReadCSD(SpiSdDeviceType spi_sd_dev) if (0xFE != g_sd_cmd_param.sd_respone_data[1]) { /*Step2 : SPI write data 0xFF until read 0xFE*/ uint8 data = 0xFF; - uint8 read_spi=0x00; + uint8 read_spi = 0x00; uint32 start_time; write_param.buffer = (void *)&data; @@ -702,7 +702,7 @@ static uint32 SdHwReadCSD(SpiSdDeviceType spi_sd_dev) do { - BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param); + // BusDevWriteData(&spi_sd_dev->spi_dev->haldev, &write_param); BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); SD_TIMEOUT(start_time, 10 * SPI_SD_TIMEOUT_NUM); }while(0xFE != read_spi); @@ -768,7 +768,7 @@ static uint32 SdReadSingleBlock(SpiSdDeviceType spi_sd_dev, uint32 id, uint8 *re /*Step2 : SPI read until 0xFE*/ uint8 data = 0xFF; - uint8 read[2]; + uint8 read[2]={0}; uint32 start_time; write_param.buffer = (void *)&data; @@ -837,7 +837,7 @@ static uint32 SdReadMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const uint /*Step2 : SPI write data 0xFF until read 0xFE*/ uint32 i = 0; uint8 data = 0xFF; - uint8 read[2]; + uint8 read[2] = {0}; uint32 start_time; for (i = 0 ; i < block_num ; i ++) { @@ -847,7 +847,7 @@ static uint32 SdReadMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const uint read_param.size = 1; start_time = 0; - + read[0] = 0; do { BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); @@ -859,12 +859,12 @@ static uint32 SdReadMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const uint read_param.buffer = (void *)((uint8 *)read_buffer + i * spi_sd_dev->sd_param.block_param.block_size); read_param.size = spi_sd_dev->sd_param.block_param.block_size; BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); - } - /*Step4 : SPI read 2 bytes CRC*/ - read_param.buffer = (void *)read; - read_param.size = 2; - BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); + /*Step4 : SPI read 2 bytes CRC*/ + read_param.buffer = (void *)read; + read_param.size = 2; + BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); + } /*Step5 : CMD12 stop read*/ g_sd_cmd_param.sd_cmd_type = SD_CMD_12; @@ -921,7 +921,7 @@ static uint32 SdWriteSingleBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const ui /*Step2 : SPI write data 0xFE*/ uint8 data = 0xFE; - uint8 read; + uint8 read = 0x00; uint8 write[2] = {0xFF, 0xFF}; write_param.buffer = (void *)&data; @@ -1034,7 +1034,7 @@ static uint32 SdWriteMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const voi /*Step3 : SPI write data 0xFC*/ uint32 i; uint8 data = 0xFC; - uint8 read; + uint8 read = 0x00; uint8 write[2] = {0xFF, 0xFF}; for (i = 0 ; i < block_num; i ++) { @@ -1057,6 +1057,7 @@ static uint32 SdWriteMultiBlock(SpiSdDeviceType spi_sd_dev, uint32 id, const voi read_param.size = 1; start_time = 0; + read = 0xFF; do { BusDevReadData(&spi_sd_dev->spi_dev->haldev, &read_param); @@ -1232,7 +1233,6 @@ uint32 SdRead(void *dev, struct BusBlockReadParam *read_param) KMutexAbandon(spi_sd_dev->spi_dev->haldev.owner_bus->bus_lock); return ERROR; } - /*Step2 : read SD block*/ if (1 == block_num) { ret = SdReadSingleBlock(spi_sd_dev, id, read_buffer); From 186790f5ec29737b5d3dc0ead8571a40606c515e Mon Sep 17 00:00:00 2001 From: WuZheng Date: Thu, 15 Dec 2022 10:36:56 +0800 Subject: [PATCH 09/15] fix bugs camera buff unstable --- .../k210_yolov2_detect.c | 160 +++++++++++------- .../transform_layer/xizi/transform.h | 1 + .../third_party_driver/dvp/connect_dvp.c | 3 + .../third_party_driver/include/connect_dvp.h | 1 + 4 files changed, 103 insertions(+), 62 deletions(-) diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c index e2aa4d8ec..99c51f6dc 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c @@ -8,7 +8,7 @@ #include "region_layer.h" #define STACK_SIZE (128 * 1024) -static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX-1; +static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX - 1; static _ioctl_shoot_para shoot_para_t = {0}; #define THREAD_PRIORITY_D (11) @@ -19,9 +19,10 @@ static int kmodel_fd = 0; static int if_exit = 0; static unsigned char *showbuffer = NULL; static unsigned char *kpurgbbuffer = NULL; +static int image_width = IMAGE_WIDTH; +static int image_height = IMAGE_HEIGHT; - -unsigned char *model_data = NULL; // kpu data load memory +unsigned char *model_data = NULL; // kpu data load memory unsigned char *model_data_align = NULL; kpu_model_context_t detect_task; @@ -42,18 +43,20 @@ void k210_detect(char *json_file_path) // open and parse from json file yolov2_params_t detect_params = param_parse(json_file_path); - if (!detect_params.is_valid) { + if (!detect_params.is_valid) + { return; } - printf("select camera device name:%s\n",CAMERA_DEV_DRIVER); + printf("select camera device name:%s\n", CAMERA_DEV_DRIVER); camera_fd = PrivOpen(CAMERA_DEV_DRIVER, O_RDONLY); - if (camera_fd < 0) { - printf("open %s fail !!",CAMERA_DEV_DRIVER); + if (camera_fd < 0) + { + printf("open %s fail !!", CAMERA_DEV_DRIVER); return; } struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = CAMERA_TYPE; - struct CameraCfg camera_init_cfg ={ + struct CameraCfg camera_init_cfg = { .gain_manu_enable = 0, .gain = 0xFF, .window_w = 800, @@ -61,39 +64,43 @@ void k210_detect(char *json_file_path) .output_w = IMAGE_WIDTH, .output_h = IMAGE_HEIGHT, .window_xoffset = 0, - .window_yoffset = 0 - }; + .window_yoffset = 0}; ioctl_cfg.args = &camera_init_cfg; if (0 != PrivIoctl(camera_fd, OPE_CFG, &ioctl_cfg)) { printf("camera pin fd error %d\n", camera_fd); PrivClose(camera_fd); } - + // configure the resolution of camera _ioctl_set_reso set_dvp_reso = {detect_params.sensor_output_size[1], detect_params.sensor_output_size[0]}; struct PrivIoctlCfg camera_cfg; camera_cfg.args = &set_dvp_reso; camera_cfg.ioctl_driver_type = CAMERA_TYPE; PrivIoctl(camera_fd, IOCTRL_CAMERA_OUT_SIZE_RESO, &camera_cfg); + image_height = set_dvp_reso.height; + image_width = set_dvp_reso.width; + model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); // alloc the memory for camera and kpu running showbuffer = (unsigned char *)malloc(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); - if (NULL == showbuffer) { + if (NULL == showbuffer) + { close(camera_fd); printf("showbuffer apply memory fail !!"); return; } kpurgbbuffer = (unsigned char *)malloc(detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3); - if (NULL == kpurgbbuffer) { + if (NULL == kpurgbbuffer) + { close(camera_fd); free(showbuffer); printf("kpurgbbuffer apply memory fail !!"); return; } - model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); - printf("model address:%x->%x\n",model_data_align,model_data_align + detect_params.kmodel_size); - if (NULL == model_data) { + + if (NULL == model_data) + { free(showbuffer); free(kpurgbbuffer); close(camera_fd); @@ -115,24 +122,30 @@ void k210_detect(char *json_file_path) int idx_suffix_start = strlen(json_file_path) - 4; const char kmodel_suffix[7] = "kmodel"; int kmodel_suffix_len = 6; - while (kmodel_suffix_len--) { + while (kmodel_suffix_len--) + { kmodel_path[idx_suffix_start + 5 - kmodel_suffix_len] = kmodel_suffix[5 - kmodel_suffix_len]; } printf("kmodel path: %s\n", kmodel_path); unsigned char *model_data_align = (unsigned char *)(((uintptr_t)model_data + 255) & (~255)); + printf("model address:%x->%x\n", model_data_align, model_data_align + detect_params.kmodel_size); + kmodel_fd = PrivOpen(kmodel_path, O_RDONLY); - memset(model_data,0,sizeof(model_data)); - if (kmodel_fd < 0) { + if (kmodel_fd < 0) + { printf("open kmodel fail"); close(camera_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); return; - } else { + } + else + { size = read(kmodel_fd, model_data_align, detect_params.kmodel_size); - if (size != detect_params.kmodel_size) { + if (size != detect_params.kmodel_size) + { printf("read kmodel error size %d\n", size); close(camera_fd); close(kmodel_fd); @@ -140,7 +153,9 @@ void k210_detect(char *json_file_path) free(kpurgbbuffer); free(model_data); return; - } else { + } + else + { close(kmodel_fd); printf("read kmodel success \n"); } @@ -149,24 +164,25 @@ void k210_detect(char *json_file_path) #ifdef ADD_RTTHREAD_FETURES dvp_set_ai_addr( (uintptr_t)(kpurgbbuffer + - detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0])), + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0])), (uintptr_t)(kpurgbbuffer + - detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + - detect_params.net_input_size[0] * detect_params.net_input_size[1]), + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + + detect_params.net_input_size[0] * detect_params.net_input_size[1]), (uintptr_t)(kpurgbbuffer + - detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + - detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2)); + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + + detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2)); #endif // Set AI buff address of Camera RgbAddress ai_address_preset; - ai_address_preset.r_addr = (uintptr_t)kpurgbbuffer + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]); + ai_address_preset.r_addr = (uintptr_t)kpurgbbuffer + detect_params.net_input_size[1]; ai_address_preset.g_addr = ai_address_preset.r_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1]; - ai_address_preset.b_addr = ai_address_preset.g_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1]; + ai_address_preset.b_addr = ai_address_preset.g_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1]; camera_cfg.args = &ai_address_preset; - PrivIoctl(camera_fd,SET_AI_ADDR,&camera_cfg); + PrivIoctl(camera_fd, SET_AI_ADDR, &camera_cfg); // Load kmodel into kpu task - if (kpu_load_kmodel(&detect_task, model_data_align) != 0) { + if (kpu_load_kmodel(&detect_task, model_data_align) != 0) + { printf("\nmodel init error\n"); close(camera_fd); close(kmodel_fd); @@ -180,10 +196,11 @@ void k210_detect(char *json_file_path) detect_rl.anchor = detect_params.anchor; detect_rl.nms_value = detect_params.nms_thresh; detect_rl.classes = detect_params.class_num; - result =region_layer_init(&detect_rl, detect_params.net_output_shape[0], detect_params.net_output_shape[1], - detect_params.net_output_shape[2], detect_params.net_input_size[1], detect_params.net_input_size[0]); + result = region_layer_init(&detect_rl, detect_params.net_output_shape[0], detect_params.net_output_shape[1], + detect_params.net_output_shape[2], detect_params.net_input_size[1], detect_params.net_input_size[0]); printf("region_layer_init result %d \n\r", result); - for (int idx = 0; idx < detect_params.class_num; idx++) { + for (int idx = 0; idx < detect_params.class_num; idx++) + { detect_rl.threshold[idx] = detect_params.obj_thresh[idx]; } @@ -197,9 +214,12 @@ void k210_detect(char *json_file_path) /* 创建线程 1, 属性为 attr,入口函数是 thread_entry,入口函数参数是 1 */ result = pthread_create(&tid, &attr, thread_detect_entry, &detect_params); - if (0 == result) { + if (0 == result) + { printf("thread_detect_entry successfully!\n"); - } else { + } + else + { printf("thread_detect_entry failed! error code is %d\n", result); close(camera_fd); } @@ -226,13 +246,15 @@ static void *thread_detect_entry(void *parameter) printf("thread_detect_entry start!\n"); int ret = 0; - while (1) { + while (1) + { g_ai_done_flag = 0; - //get a graph map from camera + // get a graph map from camera camera_cfg.args = &shoot_para_t; ret = PrivIoctl(camera_fd, IOCTRL_CAMERA_START_SHOT, &camera_cfg); - if (ERROR_FLAG == ret) { + if (ERROR_FLAG == ret) + { printf("ov2640 can't wait event flag"); free(showbuffer); close(camera_fd); @@ -240,9 +262,15 @@ static void *thread_detect_entry(void *parameter) return NULL; } + int shoot_flag = 0; + camera_cfg.args = (int *)&shoot_flag; + PrivIoctl(camera_fd, FLAG_CHECK, &camera_cfg); + while (shoot_flag == 2) + PrivIoctl(camera_fd, FLAG_CHECK, &camera_cfg); #ifdef ADD_RTTHREAD_FETURES - if (dmalock_sync_take(&dma_ch, 2000)) { + if (dmalock_sync_take(&dma_ch, 2000)) + { printf("Fail to take DMA channel"); } kpu_run_kmodel(&detect_task, kpurgbbuffer, DMAC_CHANNEL5, ai_done, NULL); @@ -252,7 +280,7 @@ static void *thread_detect_entry(void *parameter) #elif defined ADD_XIZI_FETURES kpu_run_kmodel(&detect_task, kpurgbbuffer, dma_ch, ai_done, NULL); while (!g_ai_done_flag) - ; + ; #endif float *output; @@ -260,11 +288,12 @@ static void *thread_detect_entry(void *parameter) kpu_get_output(&detect_task, 0, (uint8_t **)&output, &output_size); detect_rl.input = output; region_layer_run(&detect_rl, &detect_info); - printf("detect_info.obj_number:%d\n",detect_info.obj_number); + printf("detect_info.obj_number:%d\n", detect_info.obj_number); /* display result */ - for (int cnt = 0; cnt < detect_info.obj_number; cnt++) { - detect_info.obj[cnt].y1 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0])/2; - detect_info.obj[cnt].y2 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0])/2; + for (int cnt = 0; cnt < detect_info.obj_number; cnt++) + { + detect_info.obj[cnt].y1 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0]) / 2; + detect_info.obj[cnt].y2 += (detect_params.sensor_output_size[0] - detect_params.net_input_size[0]) / 2; draw_edge((uint32_t *)showbuffer, &detect_info, cnt, 0xF800, (uint16_t)detect_params.sensor_output_size[1], (uint16_t)detect_params.sensor_output_size[0]); printf("%d: (%d, %d, %d, %d) cls: %s conf: %f\t", cnt, detect_info.obj[cnt].x1, detect_info.obj[cnt].y1, @@ -274,26 +303,32 @@ static void *thread_detect_entry(void *parameter) #ifdef BSP_USING_LCD #ifdef ADD_RTTHREAD_FETURES - extern void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t * ptr); - lcd_draw_picture(0, 0, (uint16_t)detect_params.sensor_output_size[1] - 1, - (uint16_t)detect_params.sensor_output_size[0] - 1, (uint32_t *)showbuffer); - // lcd_show_image(0, 0, (uint16_t)detect_params.sensor_output_size[1], (uint16_t)detect_params.sensor_output_size[0], - // (unsigned int *)showbuffer); + extern void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t * ptr); + lcd_draw_picture(0, 0, (uint16_t)detect_params.sensor_output_size[1] - 1, + (uint16_t)detect_params.sensor_output_size[0] - 1, (uint32_t *)showbuffer); + // lcd_show_image(0, 0, (uint16_t)detect_params.sensor_output_size[1], (uint16_t)detect_params.sensor_output_size[0], + // (unsigned int *)showbuffer); #else - //refresh the LCD using photo of camera - for (int i = 0; i < IMAGE_HEIGHT; i++) - { - graph_param.pixel_info.pixel_color = (uint16_t*)showbuffer + i * IMAGE_WIDTH; - graph_param.pixel_info.x_startpos = 0; - graph_param.pixel_info.y_startpos = i + (LCD_SIZE - IMAGE_HEIGHT) / 2; - graph_param.pixel_info.x_endpos = IMAGE_WIDTH - 1; - graph_param.pixel_info.y_endpos = i + (LCD_SIZE - IMAGE_HEIGHT) / 2; - PrivWrite(lcd_fd, &graph_param, NULL_PARAMETER); - } + // refresh the LCD using photo of camera + for (int i = 0; i < image_height; i++) + { + graph_param.pixel_info.pixel_color = (uint16_t *)showbuffer + i * image_width; + graph_param.pixel_info.x_startpos = (LCD_SIZE - image_width) / 2; + graph_param.pixel_info.y_startpos = i + (LCD_SIZE - image_height) / 2; + graph_param.pixel_info.x_endpos = LCD_SIZE - 1 - (LCD_SIZE - image_width) / 2; + graph_param.pixel_info.y_endpos = graph_param.pixel_info.y_startpos; + // printf("refreshing screen: address[%08X] at row in %d\n",graph_param.pixel_info.pixel_color, graph_param.pixel_info.y_startpos); + // for(int j=0;jprivate_data) = shoot_flag; + break; case SET_AI_ADDR: kpu_rgb_address = (RgbAddress*)args->private_data; dvp_set_output_enable(DVP_OUTPUT_AI, 1); diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h index 14695c659..9970920db 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h @@ -32,6 +32,7 @@ extern "C" { #define SET_DISPLAY_ADDR (21) #define SET_AI_ADDR (22) #define IOCTRL_CAMERA_OUT_SIZE_RESO (23) +#define FLAG_CHECK (24) typedef struct From 5761bd09162e2539e8354dfa31c920bdc68b6691 Mon Sep 17 00:00:00 2001 From: WuZheng Date: Thu, 15 Dec 2022 15:51:46 +0800 Subject: [PATCH 10/15] primarily unify dvp APIs with rt --- .../k210_yolov2_detect.c | 33 +- .../transform_layer/xizi/transform.h | 26 +- .../third_party_driver/dvp/connect_dvp.c | 30 +- .../third_party_driver/dvp/ov2640.c | 402 +++++++++++++++++- .../third_party_driver/include/connect_dvp.h | 21 +- .../third_party_driver/include/ov2640.h | 12 + 6 files changed, 488 insertions(+), 36 deletions(-) diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c index 99c51f6dc..1261ba685 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c @@ -7,11 +7,11 @@ #endif #include "region_layer.h" #define STACK_SIZE (128 * 1024) +#define THREAD_PRIORITY_D (11) static dmac_channel_number_t dma_ch = DMAC_CHANNEL_MAX - 1; static _ioctl_shoot_para shoot_para_t = {0}; -#define THREAD_PRIORITY_D (11) static pthread_t tid = 0; static void *thread_detect_entry(void *parameter); static int camera_fd = 0; @@ -32,7 +32,6 @@ volatile uint32_t g_ai_done_flag; static void ai_done(void *ctx) { g_ai_done_flag = 1; } -#define ERROR_FLAG (1) void k210_detect(char *json_file_path) { @@ -47,6 +46,7 @@ void k210_detect(char *json_file_path) { return; } + printf("select camera device name:%s\n", CAMERA_DEV_DRIVER); camera_fd = PrivOpen(CAMERA_DEV_DRIVER, O_RDONLY); if (camera_fd < 0) @@ -54,6 +54,8 @@ void k210_detect(char *json_file_path) printf("open %s fail !!", CAMERA_DEV_DRIVER); return; } + +#ifdef ADD_XIZI_FETURES struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = CAMERA_TYPE; struct CameraCfg camera_init_cfg = { @@ -71,6 +73,7 @@ void k210_detect(char *json_file_path) printf("camera pin fd error %d\n", camera_fd); PrivClose(camera_fd); } +#endif // configure the resolution of camera _ioctl_set_reso set_dvp_reso = {detect_params.sensor_output_size[1], detect_params.sensor_output_size[0]}; @@ -81,8 +84,16 @@ void k210_detect(char *json_file_path) image_height = set_dvp_reso.height; image_width = set_dvp_reso.width; - model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); // alloc the memory for camera and kpu running + model_data = (unsigned char *)malloc(detect_params.kmodel_size + 255); + if (NULL == model_data) + { + free(showbuffer); + free(kpurgbbuffer); + close(camera_fd); + printf("model_data apply memory fail !!"); + return; + } showbuffer = (unsigned char *)malloc(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); if (NULL == showbuffer) { @@ -99,14 +110,7 @@ void k210_detect(char *json_file_path) return; } - if (NULL == model_data) - { - free(showbuffer); - free(kpurgbbuffer); - close(camera_fd); - printf("model_data apply memory fail !!"); - return; - } + memset(model_data, 0, detect_params.kmodel_size + 255); memset(showbuffer, 0, detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); memset(kpurgbbuffer, 0, detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3); @@ -171,7 +175,7 @@ void k210_detect(char *json_file_path) (uintptr_t)(kpurgbbuffer + detect_params.net_input_size[1] * (detect_params.net_input_size[0] - detect_params.sensor_output_size[0]) + detect_params.net_input_size[0] * detect_params.net_input_size[1] * 2)); -#endif +#else // Set AI buff address of Camera RgbAddress ai_address_preset; ai_address_preset.r_addr = (uintptr_t)kpurgbbuffer + detect_params.net_input_size[1]; @@ -179,6 +183,7 @@ void k210_detect(char *json_file_path) ai_address_preset.b_addr = ai_address_preset.g_addr + detect_params.net_input_size[0] * detect_params.net_input_size[1]; camera_cfg.args = &ai_address_preset; PrivIoctl(camera_fd, SET_AI_ADDR, &camera_cfg); +#endif // Load kmodel into kpu task if (kpu_load_kmodel(&detect_task, model_data_align) != 0) @@ -207,7 +212,7 @@ void k210_detect(char *json_file_path) size_t stack_size = STACK_SIZE; pthread_attr_t attr; /* 线程属性 */ struct sched_param prio; /* 线程优先级 */ - prio.sched_priority = 8; /* 优先级设置为 8 */ + prio.sched_priority = THREAD_PRIORITY_D; /* 优先级设置为 11 */ pthread_attr_init(&attr); /* 先使用默认值初始化属性 */ pthread_attr_setschedparam(&attr, &prio); /* 修改属性对应的优先级 */ pthread_attr_setstacksize(&attr, stack_size); @@ -253,7 +258,7 @@ static void *thread_detect_entry(void *parameter) // get a graph map from camera camera_cfg.args = &shoot_para_t; ret = PrivIoctl(camera_fd, IOCTRL_CAMERA_START_SHOT, &camera_cfg); - if (ERROR_FLAG == ret) + if (EOF == ret) { printf("ov2640 can't wait event flag"); free(showbuffer); diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.h b/APP_Framework/Framework/transform_layer/xizi/transform.h index c35dc5c01..c989c58dd 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.h +++ b/APP_Framework/Framework/transform_layer/xizi/transform.h @@ -260,10 +260,6 @@ enum TCP_OPTION { #define MY_INDEV_X BSP_LCD_Y_MAX #define MY_INDEV_Y BSP_LCD_X_MAX -#define DVP_INIT 0x00U -#define REG_SCCB_READ 0x12U -#define REG_SCCB_WRITE 0x13U -#define OUTPUT_CONFIG 0x20U #define LCD_STRING_TYPE 0 #define LCD_DOT_TYPE 1 #define LCD_SIZE 320 @@ -271,15 +267,23 @@ enum TCP_OPTION { #define IMAGE_WIDTH 320 #define NULL_PARAMETER 0 -#define REG_SCCB_READ 0x12U -#define REG_SCCB_WRITE 0x13U +#define REG_SCCB_READ 0xA2U +#define REG_SCCB_WRITE 0xA3U #define SCCB_REG_LENGTH 0x08U -#define IOCTRL_CAMERA_START_SHOT (20) -#define SET_DISPLAY_ADDR (21) -#define SET_AI_ADDR (22) -#define IOCTRL_CAMERA_OUT_SIZE_RESO (23) -#define FLAG_CHECK (24) +#define SET_DISPLAY_ADDR (0xD1) +#define SET_AI_ADDR (0xD2) +#define FLAG_CHECK (0xD4) + +#define IOCTRL_CAMERA_START_SHOT (22) // start shoot +#define IOCTRL_CAMERA_OUT_SIZE_RESO (23) +#define IOCTRL_CAMERA_SET_WINDOWS_SIZE (21) // user set specific windows outsize +#define IOCTRL_CAMERA_SET_LIGHT (24) //set light mode +#define IOCTRL_CAMERA_SET_COLOR (25) //set color saturation +#define IOCTRL_CAMERA_SET_BRIGHTNESS (26) //set color brightness +#define IOCTRL_CAMERA_SET_CONTRAST (27) //set contrast +#define IOCTRL_CAMERA_SET_EFFECT (28) //set effect +#define IOCTRL_CAMERA_SET_EXPOSURE (29) //set auto exposure /*********************shell***********************/ //for int func(int argc, char *agrv[]) #define PRIV_SHELL_CMD_MAIN_ATTR (SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)) diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c index 50b8d5386..983719e61 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c @@ -126,6 +126,10 @@ static uint32 DvpRead(void *dev, struct BusBlockReadParam *read_param) return ret; } +/** + * @brief configure api for dvp device + * TODO: unified APIs to keep consistent with RT-thread + */ static uint32 DvpDrvConfigure(void *drv, struct BusConfigureInfo *args) { x_err_t ret = EOK; @@ -134,6 +138,7 @@ static uint32 DvpDrvConfigure(void *drv, struct BusConfigureInfo *args) struct CameraCfg* tmp_cfg; RgbAddress* kpu_rgb_address; _ioctl_shoot_para* pixel_cfg; + int value = ((int*)args->private_data)[0]; switch (cmd_type) { case OPE_INT: @@ -151,6 +156,9 @@ static uint32 DvpDrvConfigure(void *drv, struct BusConfigureInfo *args) dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 1); shoot_flag=ONLY_ONE_SHOOT; break; + case IOCTRL_CAMERA_OUT_SIZE_RESO: + dvp_set_image_size(((uint32_t*)args->private_data)[0], ((uint32_t*)args->private_data)[1]); + break; case FLAG_CHECK: *((int*)args->private_data) = shoot_flag; break; @@ -159,9 +167,27 @@ static uint32 DvpDrvConfigure(void *drv, struct BusConfigureInfo *args) dvp_set_output_enable(DVP_OUTPUT_AI, 1); dvp_set_ai_addr(kpu_rgb_address->r_addr,kpu_rgb_address->g_addr,kpu_rgb_address->b_addr); break; - case IOCTRL_CAMERA_OUT_SIZE_RESO: - dvp_set_image_size(((uint32_t*)args->private_data)[0], ((uint32_t*)args->private_data)[1]); + + // make compatible for rt-fusion xizi + case IOCTRL_CAMERA_SET_LIGHT: + ov2640_set_light_mode(value); break; + case IOCTRL_CAMERA_SET_COLOR: + ov2640_set_color_saturation(value); + break; + case IOCTRL_CAMERA_SET_BRIGHTNESS: + ov2640_set_brightness(value); + break; + case IOCTRL_CAMERA_SET_CONTRAST: + ov2640_set_contrast(value); + break; + case IOCTRL_CAMERA_SET_EFFECT: + ov2640_set_special_effects(value); + break; + case IOCTRL_CAMERA_SET_EXPOSURE: + ov2640_set_auto_exposure(value); + break; + case REG_SCCB_READ: ReadDvpReg(drv, (struct DvpRegConfigureInfo *)args->private_data); break; diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/ov2640.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/ov2640.c index 991a8982a..9f4e00859 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/ov2640.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/ov2640.c @@ -399,8 +399,8 @@ const uint8_t ov2640_config[][2]= #else const uint8_t ov2640_config[][2]= { - {0x00,x00} -} + {0x00,0x00} +}; #endif @@ -447,7 +447,7 @@ int SensorConfigure(struct CameraCfg *cfg_info) //set reg mode to dsp dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x01); - + //configure dsp gain if(cfg_info->gain_manu_enable){ reg_tmp = dvp_sccb_receive_data(OV2640_ADDR, 0x13); @@ -461,3 +461,399 @@ int SensorConfigure(struct CameraCfg *cfg_info) return 1; } + +const uint8_t OV2640_AUTOEXPOSURE_LEVEL[5][8]= +{ + { + 0xFF,0x01, + 0x24,0x20, + 0x25,0x18, + 0x26,0x60, + }, + { + 0xFF,0x01, + 0x24,0x34, + 0x25,0x1c, + 0x26,0x00, + }, + { + 0xFF,0x01, + 0x24,0x3e, + 0x25,0x38, + 0x26,0x81, + }, + { + 0xFF,0x01, + 0x24,0x48, + 0x25,0x40, + 0x26,0x81, + }, + { + 0xFF,0x01, + 0x24,0x58, + 0x25,0x50, + 0x26,0x92, + }, +}; + +const uint8_t ov2640_yuv422_reg_tbl[][2] = +{ + {0xFF, 0x00}, + {0xDA, 0x10}, + {0xD7, 0x03}, + {0xDF, 0x00}, + {0x33, 0x80}, + {0x3C, 0x40}, + {0xe1, 0x77}, + {0x00, 0x00}, +}; + +const uint8_t ov2640_jpeg_reg_tbl[][2]= +{ + {0xff, 0x01}, + {0xe0, 0x14}, + {0xe1, 0x77}, + {0xe5, 0x1f}, + {0xd7, 0x03}, + {0xda, 0x10}, + {0xe0, 0x00}, +}; + +const uint8_t ov2640_rgb565_reg_tbl[][2]= +{ + {0xFF, 0x00}, + {0xDA, 0x08}, + {0xD7, 0x03}, + {0xDF, 0x02}, + {0x33, 0xa0}, + {0x3C, 0x00}, + {0xe1, 0x67}, + + {0xff, 0x01}, + {0xe0, 0x00}, + {0xe1, 0x00}, + {0xe5, 0x00}, + {0xd7, 0x00}, + {0xda, 0x00}, + {0xe0, 0x00}, +}; + + +/* change ov2640 to jpeg mode */ +void ov2640_jpeg_mode(void) +{ + uint16_t i=0; + /* set yun422 mode */ + for (i = 0; i < (sizeof(ov2640_yuv422_reg_tbl) / 2); i++) + { + dvp_sccb_send_data(OV2640_ADDR, ov2640_yuv422_reg_tbl[i][0],ov2640_yuv422_reg_tbl[i][1]); + } + + /* set jpeg mode */ + for(i=0;i<(sizeof(ov2640_jpeg_reg_tbl)/2);i++) + { + dvp_sccb_send_data(OV2640_ADDR, ov2640_jpeg_reg_tbl[i][0],ov2640_jpeg_reg_tbl[i][1]); + } +} + +/* change ov2640 to rgb565 mode */ +void ov2640_rgb565_mode(void) +{ + uint16_t i=0; + for (i = 0; i < (sizeof(ov2640_rgb565_reg_tbl) / 2); i++) + { + dvp_sccb_send_data(OV2640_ADDR, ov2640_rgb565_reg_tbl[i][0],ov2640_rgb565_reg_tbl[i][1]); + } +} + + + +/* set auto exposure level value must be 0 ~4 */ +void ov2640_set_auto_exposure(uint8_t level) +{ + uint8_t i = 0; + uint8_t *p = (uint8_t*)OV2640_AUTOEXPOSURE_LEVEL[level]; + for (i = 0; i < 4; i++) + { + dvp_sccb_send_data(OV2640_ADDR, p[i*2],p[i*2+1]); + } +} + +/* set light mode + * 0: auto + * 1: sunny + * 2: cloudy + * 3: office + * 4: home + * */ +void ov2640_set_light_mode(uint8_t mode) +{ + uint8_t regccval, regcdval, regceval; + + switch(mode) + { + case 0: + dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0xC7, 0x10); + return; + + case 2: + regccval = 0x65; + regcdval = 0x41; + regceval = 0x4F; + break; + + case 3: + regccval = 0x52; + regcdval = 0x41; + regceval = 0x66; + break; + + case 4: + regccval = 0x42; + regcdval = 0x3F; + regceval = 0x71; + break; + + default: + regccval = 0x5E; + regcdval = 0x41; + regceval = 0x54; + break; + } + + dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0xC7, 0x40); + dvp_sccb_send_data(OV2640_ADDR, 0xCC, regccval); + dvp_sccb_send_data(OV2640_ADDR, 0xCD, regcdval); + dvp_sccb_send_data(OV2640_ADDR, 0xCE, regceval); +} + +/* set color saturation + * 0: -2 + * 1: -1 + * 2: 0 + * 3: +1 + * 4: +2 + * */ +void ov2640_set_color_saturation(uint8_t sat) +{ + uint8_t reg7dval = ((sat+2)<<4) | 0x08; + dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0X00); + dvp_sccb_send_data(OV2640_ADDR, 0x7C, 0X00); + dvp_sccb_send_data(OV2640_ADDR, 0x7D, 0X02); + dvp_sccb_send_data(OV2640_ADDR, 0x7C, 0X03); + dvp_sccb_send_data(OV2640_ADDR, 0x7D, reg7dval); + dvp_sccb_send_data(OV2640_ADDR, 0x7D, reg7dval); +} + +/* set brightness + * 0: -2 + * 1: -1 + * 2: 0 + * 3: 1 + * 4: 2 + * */ +void ov2640_set_brightness(uint8_t bright) +{ + dvp_sccb_send_data(OV2640_ADDR, 0xff, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0x7c, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, 0x04); + dvp_sccb_send_data(OV2640_ADDR, 0x7c, 0x09); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, bright << 4); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, 0x00); +} + +/* set contrast + * 0: -2 + * 1: -1 + * 2: 0 + * 3: 1 + * 4: 2 + * */ +void ov2640_set_contrast(uint8_t contrast) +{ + uint8_t reg7d0val, reg7d1val; + + switch(contrast) + { + case 0: + reg7d0val = 0x18; + reg7d1val = 0x34; + break; + + case 1: + reg7d0val = 0x1C; + reg7d1val = 0x2A; + break; + + case 3: + reg7d0val = 0x24; + reg7d1val = 0x16; + break; + + case 4: + reg7d0val = 0x28; + reg7d1val = 0x0C; + break; + + default: + reg7d0val = 0x20; + reg7d1val = 0x20; + break; + } + dvp_sccb_send_data(OV2640_ADDR, 0xff, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0x7c, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, 0x04); + dvp_sccb_send_data(OV2640_ADDR, 0x7c, 0x07); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, 0x20); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, reg7d0val); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, reg7d1val); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, 0x06); +} + +/* set special effects + * 0: noraml + * 1: negative film + * 2: black-and-white + * 3: the red + * 4: the green + * 5: the blue + * 6: Retro +*/ +void ov2640_set_special_effects(uint8_t eft) +{ + uint8_t reg7d0val, reg7d1val, reg7d2val; + + switch(eft) + { + case 1: + reg7d0val = 0x40; + break; + case 2: + reg7d0val = 0x18; + break; + case 3: + reg7d0val = 0x18; + reg7d1val = 0x40; + reg7d2val = 0xC0; + break; + case 4: + reg7d0val = 0x18; + reg7d1val = 0x40; + reg7d2val = 0x40; + break; + case 5: + reg7d0val = 0x18; + reg7d1val = 0xA0; + reg7d2val = 0x40; + break; + case 6: + reg7d0val = 0x18; + reg7d1val = 0x40; + reg7d2val = 0xA6; + break; + default: + reg7d0val = 0x00; + reg7d1val = 0x80; + reg7d2val = 0x80; + break; + } + dvp_sccb_send_data(OV2640_ADDR, 0xff, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0x7c, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, reg7d0val); + dvp_sccb_send_data(OV2640_ADDR, 0x7c, 0x05); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, reg7d1val); + dvp_sccb_send_data(OV2640_ADDR, 0x7d, reg7d2val); +} + +/* set the image output window */ +void ov2640_set_window_size(uint16_t sx,uint16_t sy,uint16_t width,uint16_t height) +{ + uint16_t endx; + uint16_t endy; + uint8_t temp; + endx = sx + width / 2; + endy = sy + height / 2; + + dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x01); + temp = dvp_sccb_receive_data(OV2640_ADDR,0x03); + temp &= 0xF0; + temp |= ((endy & 0x03) << 2) | (sy & 0x03); + dvp_sccb_send_data(OV2640_ADDR, 0x03, temp); + dvp_sccb_send_data(OV2640_ADDR, 0x19, sy>>2); + dvp_sccb_send_data(OV2640_ADDR, 0x1A, endy>>2); + + temp = dvp_sccb_receive_data(OV2640_ADDR,0x32); + temp &= 0xC0; + temp |= ((endx & 0x07) << 3) | (sx & 0x07); + dvp_sccb_send_data(OV2640_ADDR, 0x32, temp); + dvp_sccb_send_data(OV2640_ADDR, 0x17, sx>>3); + dvp_sccb_send_data(OV2640_ADDR, 0x18, endx>>3); +} + +/* set the image output size */ +uint8_t ov2640_set_image_out_size(uint16_t width,uint16_t height) +{ + uint16_t outh, outw; + uint8_t temp; + + if(width%4)return 1; + if(height%4)return 2; + outw = width /4; + outh = height/4; + dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0xE0, 0x04); + dvp_sccb_send_data(OV2640_ADDR, 0x5A, outw & 0XFF); + dvp_sccb_send_data(OV2640_ADDR, 0x5B, outh & 0XFF); + temp = (outw >> 8) & 0x03; + temp |= (outh >> 6) & 0x04; + dvp_sccb_send_data(OV2640_ADDR, 0x5C, temp); + dvp_sccb_send_data(OV2640_ADDR, 0xE0, 0X00); + + return 1; +} + +/* set the image window size */ +uint8_t ov2640_set_image_window_size(uint16_t offx, uint16_t offy, uint16_t width, uint16_t height) +{ + uint16_t hsize, vsize; + uint8_t temp; + if ((width % 4) || (height%4)) + { + return EOF; + } + hsize = width /4; + vsize = height/4; + dvp_sccb_send_data(OV2640_ADDR, 0XFF,0X00); + dvp_sccb_send_data(OV2640_ADDR, 0XE0,0X04); + dvp_sccb_send_data(OV2640_ADDR, 0X51,hsize&0XFF); + dvp_sccb_send_data(OV2640_ADDR, 0X52,vsize&0XFF); + dvp_sccb_send_data(OV2640_ADDR, 0X53,offx&0XFF); + dvp_sccb_send_data(OV2640_ADDR, 0X54,offy&0XFF); + temp=(vsize>>1)&0X80; + temp|=(offy>>4)&0X70; + temp|=(hsize>>5)&0X08; + temp|=(offx>>8)&0X07; + dvp_sccb_send_data(OV2640_ADDR, 0X55,temp); // + dvp_sccb_send_data(OV2640_ADDR, 0X57,(hsize>>2)&0X80); // + dvp_sccb_send_data(OV2640_ADDR, 0XE0,0X00); + return 0; +} + +/* set output resolution */ +uint8_t ov2640_set_image_size(uint16_t width ,uint16_t height) +{ + uint8_t temp; + dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x00); + dvp_sccb_send_data(OV2640_ADDR, 0xE0, 0x04); + dvp_sccb_send_data(OV2640_ADDR, 0xC0, (width >>3) & 0xFF); + dvp_sccb_send_data(OV2640_ADDR, 0xC1, (height >> 3) & 0xFF); + temp = (width & 0x07) << 3; + temp |= height & 0x07; + temp |= (width >> 4) & 0x80; + dvp_sccb_send_data(OV2640_ADDR, 0x8C, temp); + dvp_sccb_send_data(OV2640_ADDR, 0xE0, 0x00); + + return 1; +} diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h index 9970920db..7e31c9aff 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_dvp.h @@ -25,14 +25,23 @@ extern "C" { #endif -#define REG_SCCB_READ 0x12U -#define REG_SCCB_WRITE 0x13U +#define REG_SCCB_READ 0xA2U +#define REG_SCCB_WRITE 0xA3U #define SCCB_REG_LENGTH 0x08U -#define IOCTRL_CAMERA_START_SHOT (20) -#define SET_DISPLAY_ADDR (21) -#define SET_AI_ADDR (22) + +#define SET_DISPLAY_ADDR (0xD1) +#define SET_AI_ADDR (0xD2) +#define FLAG_CHECK (0xD4) + +#define IOCTRL_CAMERA_START_SHOT (22) // start shoot #define IOCTRL_CAMERA_OUT_SIZE_RESO (23) -#define FLAG_CHECK (24) +#define IOCTRL_CAMERA_SET_WINDOWS_SIZE (21) // user set specific windows outsize +#define IOCTRL_CAMERA_SET_LIGHT (24) //set light mode +#define IOCTRL_CAMERA_SET_COLOR (25) //set color saturation +#define IOCTRL_CAMERA_SET_BRIGHTNESS (26) //set color brightness +#define IOCTRL_CAMERA_SET_CONTRAST (27) //set contrast +#define IOCTRL_CAMERA_SET_EFFECT (28) //set effect +#define IOCTRL_CAMERA_SET_EXPOSURE (29) //set auto exposure typedef struct diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/ov2640.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/ov2640.h index 4f1240b73..4451a8e33 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/ov2640.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/ov2640.h @@ -34,5 +34,17 @@ struct CameraCfg int ov2640_init(void); int ov2640_read_id(uint16_t *manuf_id, uint16_t *device_id); int SensorConfigure(struct CameraCfg* cfg_info); +void ov2640_jpeg_mode(void); +void ov2640_rgb565_mode(void); +void ov2640_set_auto_exposure(uint8_t level); +void ov2640_set_light_mode(uint8_t mode); +void ov2640_set_color_saturation(uint8_t sat); +void ov2640_set_brightness(uint8_t bright); +void ov2640_set_contrast(uint8_t contrast); +void ov2640_set_special_effects(uint8_t eft); +void ov2640_set_window_size(uint16_t sx,uint16_t sy,uint16_t width,uint16_t height); +uint8_t ov2640_set_image_out_size(uint16_t width,uint16_t height); +uint8_t ov2640_set_image_window_size(uint16_t offx, uint16_t offy, uint16_t width, uint16_t height); +uint8_t ov2640_set_image_size(uint16_t width ,uint16_t height); #endif /* _OV2640_H */ From 4e1bc3bf0422d7a80e68dec7a44e0563596e79cd Mon Sep 17 00:00:00 2001 From: WuZheng Date: Thu, 15 Dec 2022 16:17:31 +0800 Subject: [PATCH 11/15] add readme for yolo framework --- .../k210_yolov2_detect_procedure/Readme.md | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md new file mode 100644 index 000000000..7b04a9288 --- /dev/null +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md @@ -0,0 +1,34 @@ +# YOLO Framework for K210 KPU + +## Usage + +* Include all src and header there in menuconfig, and copy codes like below in *main.c* in folder *Application*. +* In board *edu-riscv64*, if all operations are right, the LCD should light and show the image from camera and YOLO inference. + +```C +#include +#include +// #include +#include + + +extern int FrameworkInit(); +extern void ApplicationOtaTaskInit(void); +extern void k210_detect(char *json_file_path); + +int main(void) +{ + printf("Hello, world! \n"); + FrameworkInit(); +#ifdef APPLICATION_OTA + ApplicationOtaTaskInit(); +#endif + k210_detect("instrusion.json"); + return 0; +} +``` + +## TODO + +* KPU drivers are still not completed, because it is undefined how to reisgter KPU's bus and device name in XIZI system. The framework is still directly using the SDK From Canaan Inc. But after the driver completed, it will be easy to adapt framework for the APIs. +* Camera and LCD drivers between RT and XIZI are not completely compatible. So there are some marcos like `ifdef` to make the framework compatible for both systems. From 38c4419ef911289f5b066a7998a75a5e18d256d7 Mon Sep 17 00:00:00 2001 From: WuZheng Date: Mon, 19 Dec 2022 14:13:54 +0800 Subject: [PATCH 12/15] add KPU driver and resource in XiZi for edu-riscv64 --- .../kpu/k210_yolov2_detect_procedure/Kconfig | 4 + .../k210_yolov2_detect.c | 113 ++++++---- .../transform_layer/xizi/transform.c | 1 + .../transform_layer/xizi/transform.h | 16 +- .../XiZi_IIoT/board/edu-riscv64/board.c | 5 + .../third_party_driver/include/connect_kpu.h | 41 ++++ .../third_party_driver/kpu/Kconfig | 14 ++ .../third_party_driver/kpu/Makefile | 2 +- .../third_party_driver/kpu/connect_kpu.c | 170 +++++++++++++++ Ubiquitous/XiZi_IIoT/resources/Kconfig | 6 + Ubiquitous/XiZi_IIoT/resources/Makefile | 4 + Ubiquitous/XiZi_IIoT/resources/include/bus.h | 3 + .../XiZi_IIoT/resources/include/bus_kpu.h | 69 ++++++ .../XiZi_IIoT/resources/include/dev_kpu.h | 69 ++++++ .../XiZi_IIoT/resources/include/device.h | 5 + Ubiquitous/XiZi_IIoT/resources/kpu/Makefile | 5 + Ubiquitous/XiZi_IIoT/resources/kpu/bus_kpu.c | 123 +++++++++++ Ubiquitous/XiZi_IIoT/resources/kpu/dev_kpu.c | 200 ++++++++++++++++++ Ubiquitous/XiZi_IIoT/resources/kpu/drv_kpu.c | 68 ++++++ 19 files changed, 870 insertions(+), 48 deletions(-) create mode 100644 Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_kpu.h create mode 100644 Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/connect_kpu.c create mode 100644 Ubiquitous/XiZi_IIoT/resources/include/bus_kpu.h create mode 100644 Ubiquitous/XiZi_IIoT/resources/include/dev_kpu.h create mode 100644 Ubiquitous/XiZi_IIoT/resources/kpu/Makefile create mode 100644 Ubiquitous/XiZi_IIoT/resources/kpu/bus_kpu.c create mode 100644 Ubiquitous/XiZi_IIoT/resources/kpu/dev_kpu.c create mode 100644 Ubiquitous/XiZi_IIoT/resources/kpu/drv_kpu.c diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig index a359ac926..185b1f6cb 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Kconfig @@ -3,6 +3,10 @@ menuconfig USING_K210_YOLOV2_DETECT depends on USING_KPU_PROCESSING default n +config KPU_DEV_DRIVER + string "Set kpu dev path" + default "/dev/kpu_dev" + config CAMERA_DEV_DRIVER string "Set camera dev path for kpu" default "/dev/ov2640" diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c index 1261ba685..aea9b553f 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/k210_yolov2_detect.c @@ -16,6 +16,7 @@ static pthread_t tid = 0; static void *thread_detect_entry(void *parameter); static int camera_fd = 0; static int kmodel_fd = 0; +static int kpu_fd = 0; static int if_exit = 0; static unsigned char *showbuffer = NULL; static unsigned char *kpurgbbuffer = NULL; @@ -46,7 +47,16 @@ void k210_detect(char *json_file_path) { return; } - + +#ifdef ADD_XIZI_FETURES + kpu_fd = PrivOpen(KPU_DEV_DRIVER, O_RDONLY); + if (camera_fd < 0) + { + printf("open %s fail !!", KPU_DEV_DRIVER); + return; + } +#endif + printf("select camera device name:%s\n", CAMERA_DEV_DRIVER); camera_fd = PrivOpen(CAMERA_DEV_DRIVER, O_RDONLY); if (camera_fd < 0) @@ -55,26 +65,6 @@ void k210_detect(char *json_file_path) return; } -#ifdef ADD_XIZI_FETURES - struct PrivIoctlCfg ioctl_cfg; - ioctl_cfg.ioctl_driver_type = CAMERA_TYPE; - struct CameraCfg camera_init_cfg = { - .gain_manu_enable = 0, - .gain = 0xFF, - .window_w = 800, - .window_h = 600, - .output_w = IMAGE_WIDTH, - .output_h = IMAGE_HEIGHT, - .window_xoffset = 0, - .window_yoffset = 0}; - ioctl_cfg.args = &camera_init_cfg; - if (0 != PrivIoctl(camera_fd, OPE_CFG, &ioctl_cfg)) - { - printf("camera pin fd error %d\n", camera_fd); - PrivClose(camera_fd); - } -#endif - // configure the resolution of camera _ioctl_set_reso set_dvp_reso = {detect_params.sensor_output_size[1], detect_params.sensor_output_size[0]}; struct PrivIoctlCfg camera_cfg; @@ -90,21 +80,21 @@ void k210_detect(char *json_file_path) { free(showbuffer); free(kpurgbbuffer); - close(camera_fd); + PrivClose(camera_fd); printf("model_data apply memory fail !!"); return; } showbuffer = (unsigned char *)malloc(detect_params.sensor_output_size[0] * detect_params.sensor_output_size[1] * 2); if (NULL == showbuffer) { - close(camera_fd); + PrivClose(camera_fd); printf("showbuffer apply memory fail !!"); return; } kpurgbbuffer = (unsigned char *)malloc(detect_params.net_input_size[0] * detect_params.net_input_size[1] * 3); if (NULL == kpurgbbuffer) { - close(camera_fd); + PrivClose(camera_fd); free(showbuffer); printf("kpurgbbuffer apply memory fail !!"); return; @@ -122,7 +112,6 @@ void k210_detect(char *json_file_path) */ // kmodel path generate from json file path, *.json -> *.kmodel memcpy(kmodel_path, json_file_path, strlen(json_file_path)); - int idx_suffix_start = strlen(json_file_path) - 4; const char kmodel_suffix[7] = "kmodel"; int kmodel_suffix_len = 6; @@ -139,7 +128,7 @@ void k210_detect(char *json_file_path) if (kmodel_fd < 0) { printf("open kmodel fail"); - close(camera_fd); + PrivClose(camera_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); @@ -147,12 +136,12 @@ void k210_detect(char *json_file_path) } else { - size = read(kmodel_fd, model_data_align, detect_params.kmodel_size); + size = PrivRead(kmodel_fd, model_data_align, detect_params.kmodel_size); if (size != detect_params.kmodel_size) { printf("read kmodel error size %d\n", size); - close(camera_fd); - close(kmodel_fd); + PrivClose(camera_fd); + PrivClose(kmodel_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); @@ -160,7 +149,7 @@ void k210_detect(char *json_file_path) } else { - close(kmodel_fd); + PrivClose(kmodel_fd); printf("read kmodel success \n"); } } @@ -186,16 +175,32 @@ void k210_detect(char *json_file_path) #endif // Load kmodel into kpu task +#ifdef ADD_RTTHREAD_FETURES if (kpu_load_kmodel(&detect_task, model_data_align) != 0) { printf("\nmodel init error\n"); - close(camera_fd); - close(kmodel_fd); + PrivClose(camera_fd); + PrivClose(kmodel_fd); free(showbuffer); free(kpurgbbuffer); free(model_data); return; } +#else + struct PrivIoctlCfg kpu_cfg; + kpu_cfg.args = model_data_align; + kpu_cfg.ioctl_driver_type = KPU_TYPE; + if (PrivIoctl(kpu_fd,LOAD_KMODEL,&kpu_cfg) != 0) + { + printf("\nmodel init error\n"); + PrivClose(camera_fd); + PrivClose(kmodel_fd); + free(showbuffer); + free(kpurgbbuffer); + free(model_data); + return; + } +#endif detect_rl.anchor_number = ANCHOR_NUM; detect_rl.anchor = detect_params.anchor; @@ -226,7 +231,7 @@ void k210_detect(char *json_file_path) else { printf("thread_detect_entry failed! error code is %d\n", result); - close(camera_fd); + PrivClose(camera_fd); } } // #ifdef __RT_THREAD_H__ @@ -243,6 +248,15 @@ static void *thread_detect_entry(void *parameter) } LcdWriteParam graph_param; graph_param.type = LCD_DOT_TYPE; + for (int i = 0; i < LCD_SIZE; i++) + { + graph_param.pixel_info.pixel_color = (uint16_t *)showbuffer; + graph_param.pixel_info.x_startpos = 0; + graph_param.pixel_info.y_startpos = i; + graph_param.pixel_info.x_endpos = LCD_SIZE - 1; + graph_param.pixel_info.y_endpos = graph_param.pixel_info.y_startpos; + PrivWrite(lcd_fd, &graph_param, NULL_PARAMETER); + } #endif yolov2_params_t detect_params = *(yolov2_params_t *)parameter; @@ -262,7 +276,7 @@ static void *thread_detect_entry(void *parameter) { printf("ov2640 can't wait event flag"); free(showbuffer); - close(camera_fd); + PrivClose(camera_fd); pthread_exit(NULL); return NULL; } @@ -283,15 +297,29 @@ static void *thread_detect_entry(void *parameter) ; dmalock_release(dma_ch); #elif defined ADD_XIZI_FETURES - kpu_run_kmodel(&detect_task, kpurgbbuffer, dma_ch, ai_done, NULL); - while (!g_ai_done_flag) - ; + struct PrivIoctlCfg kpu_cfg; + kpu_cfg.args = kpurgbbuffer; + kpu_cfg.ioctl_driver_type = KPU_TYPE; + PrivIoctl(kpu_fd,RUN_KMODEL,&kpu_cfg); + + int wait_flag=0; + kpu_cfg.args = &wait_flag; + while (0==wait_flag){ + PrivIoctl(kpu_fd,WAIT_FLAG,&kpu_cfg); + } #endif +#ifdef ADD_RTTHREAD_FETURES float *output; size_t output_size; kpu_get_output(&detect_task, 0, (uint8_t **)&output, &output_size); detect_rl.input = output; +#else + KpuOutputBuffer output_buffer; + kpu_cfg.args = &output_buffer; + PrivIoctl(kpu_fd,GET_OUTPUT,&kpu_cfg); + detect_rl.input = (float*)(output_buffer.buffer); +#endif region_layer_run(&detect_rl, &detect_info); printf("detect_info.obj_number:%d\n", detect_info.obj_number); /* display result */ @@ -317,16 +345,11 @@ static void *thread_detect_entry(void *parameter) // refresh the LCD using photo of camera for (int i = 0; i < image_height; i++) { - graph_param.pixel_info.pixel_color = (uint16_t *)showbuffer + i * image_width; + graph_param.pixel_info.pixel_color = (uint16_t *)showbuffer + (image_height-i-1) * image_width; graph_param.pixel_info.x_startpos = (LCD_SIZE - image_width) / 2; graph_param.pixel_info.y_startpos = i + (LCD_SIZE - image_height) / 2; graph_param.pixel_info.x_endpos = LCD_SIZE - 1 - (LCD_SIZE - image_width) / 2; graph_param.pixel_info.y_endpos = graph_param.pixel_info.y_startpos; - // printf("refreshing screen: address[%08X] at row in %d\n",graph_param.pixel_info.pixel_color, graph_param.pixel_info.y_startpos); - // for(int j=0;jargs); break; default: diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.h b/APP_Framework/Framework/transform_layer/xizi/transform.h index c989c58dd..692c8083b 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.h +++ b/APP_Framework/Framework/transform_layer/xizi/transform.h @@ -151,6 +151,7 @@ enum IoctlDriverType WDT_TYPE, RTC_TYPE, CAMERA_TYPE, + KPU_TYPE, DEFAULT_TYPE, }; @@ -247,10 +248,16 @@ typedef struct }RgbAddress; enum TCP_OPTION { - SEND_DATA = 0, - RECV_DATA, + SEND_DATA = 0, + RECV_DATA, }; +typedef struct +{ + uint8_t *buffer; + size_t length; +}KpuOutputBuffer; + #define PRIV_SYSTICK_GET (CurrentTicksGain()) #define PRIV_LCD_DEV "/dev/lcd_dev" #define MY_DISP_HOR_RES BSP_LCD_Y_MAX @@ -275,6 +282,11 @@ enum TCP_OPTION { #define SET_AI_ADDR (0xD2) #define FLAG_CHECK (0xD4) +#define LOAD_KMODEL 0xA0 +#define RUN_KMODEL 0xA1 +#define GET_OUTPUT 0xA2 +#define WAIT_FLAG 0xA3 + #define IOCTRL_CAMERA_START_SHOT (22) // start shoot #define IOCTRL_CAMERA_OUT_SIZE_RESO (23) #define IOCTRL_CAMERA_SET_WINDOWS_SIZE (21) // user set specific windows outsize diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c index 1a76f26c6..bfa49afc1 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/board.c @@ -48,6 +48,7 @@ Modification: #include "connect_w5500.h" #include "connect_wdt.h" #include "connect_dvp.h" +#include "connect_kpu.h" #include "dmac.h" #include "encoding.h" #include "fpioa.h" @@ -71,6 +72,7 @@ extern int HwSpiInit(void); extern int HwSoftSPIInit(void); extern int HwWiznetInit(void); extern int HwDvpInit(void); +extern int HwKpuInit(void); #include #ifdef MOUNT_USB @@ -221,6 +223,9 @@ struct InitSequenceDesc _board_init[] = { #endif #ifdef BSP_USING_CAMERA {"hw_camera", HwDvpInit }, +#endif +#ifdef BSP_USING_KPU + {"hw_kpu", HwKpuInit }, #endif { " NONE ",NONE }, }; diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_kpu.h b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_kpu.h new file mode 100644 index 000000000..6b4e828b2 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/include/connect_kpu.h @@ -0,0 +1,41 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file connect_dvp.h +* @brief define edu-riscv64-board DVP init function +* @version 2.0 +* @author AIIT XUOS Lab +* @date 2022-11-21 +*/ +#ifndef CONNECT_DVP_H +#define CONNECT_DVP_H +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + uint8_t *buffer; + size_t length; +}KpuOutputBuffer; + + +int HwKpuInit(void); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig index 8b1378917..279af3459 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Kconfig @@ -1 +1,15 @@ +if BSP_USING_KPU + config KPU_DMA_CH + int "KPU DMA channel number" + default 5 + config KPU_BUS_NAME + string "kpu bus name" + default "kpu" + config KPU_DRV_NAME + string "kpu driver name" + default "kpu_drv" + config KPU_DEVICE_NAME + string "kpu device name" + default "kpu_dev" +endif diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile index cedabd673..3d79cd367 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/Makefile @@ -1,4 +1,4 @@ -SRC_FILES := kpu.c +SRC_FILES := kpu.c connect_kpu.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/connect_kpu.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/connect_kpu.c new file mode 100644 index 000000000..dc3366059 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/kpu/connect_kpu.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include "bsp.h" + +#define LOAD_KMODEL 0xA0 +#define RUN_KMODEL 0xA1 +#define GET_OUTPUT 0xA2 +#define WAIT_FLAG 0xA3 + +static kpu_model_context_t kpu_task; +static int g_ai_done_flag = 0; + +// irq interrupt function +static void ai_done(void *ctx) +{ + g_ai_done_flag = 1; +} + +struct KpuRegConfigureInfo +{ + uint8_t device_addr; + uint16_t reg_addr; + uint8_t reg_value; +}; + +static uint32 KpuDrvInit(void) +{ + x_err_t ret = EOK; + return ret; +} + +static uint32 KpuOpen(void *dev) +{ + x_err_t ret = EOK; + KpuDrvInit(); + return ret; +} + +static uint32 KpuClose(void *dev) +{ + x_err_t ret = EOK; + return ret; +} + +static uint32 KpuDrvConfigure(void *drv, struct BusConfigureInfo *args) +{ + x_err_t ret = EOK; + int cmd_type = args->configure_cmd; + KpuOutputBuffer* output_data; + switch (cmd_type) + { + case OPE_INT: + break; + case OPE_CFG: + break; + case LOAD_KMODEL: + kpu_load_kmodel(&kpu_task, args->private_data); + break; + case RUN_KMODEL: + g_ai_done_flag=0; + kpu_run_kmodel(&kpu_task, args->private_data, KPU_DMA_CH, ai_done, NULL); + break; + case GET_OUTPUT: + output_data = (KpuOutputBuffer*)args->private_data; + kpu_get_output(&kpu_task, 0, (uint8_t **)&(output_data->buffer), &(output_data->length)); + break; + case WAIT_FLAG: + *((uint8_t*)(args->private_data)) = g_ai_done_flag; + break; + default: + break; + } + return ret; +} + +/*manage the kpu device operations*/ +static const struct KpuDevDone kpu_dev_done = +{ + .dev_open = KpuOpen, + .dev_close = KpuClose, + .dev_write = NONE, + .dev_read = NONE, +}; + +/*Init kpu bus*/ +static int BoardKpuBusInit(struct KpuBus *kpu_bus, struct KpuDriver *kpu_driver) +{ + x_err_t ret = EOK; + + /*Init the kpu bus */ + kpu_bus->private_data = (void *)&kpu_dev_done; + ret = KpuBusInit(kpu_bus, KPU_BUS_NAME); + if (EOK != ret) + { + KPrintf("board_kpu_init KpuBusInit error %d\n", ret); + return ERROR; + } + + /*Init the kpu driver*/ + kpu_driver->private_data = (void *)&kpu_dev_done; + ret = KpuDriverInit(kpu_driver, KPU_DRV_NAME); + if (EOK != ret) + { + KPrintf("board_kpu_init KpuDriverInit error %d\n", ret); + return ERROR; + } + + /*Attach the kpu driver to the kpu bus*/ + ret = KpuDriverAttachToBus(KPU_DRV_NAME, KPU_BUS_NAME); + if (EOK != ret) + { + KPrintf("board_kpu_init KpuDriverAttachToBus error %d\n", ret); + return ERROR; + } + + return ret; +} + +/*Attach the kpu device to the kpu bus*/ +static int BoardKpuDevBend(void) +{ + x_err_t ret = EOK; + static struct KpuHardwareDevice kpu_device; + memset(&kpu_device, 0, sizeof(struct KpuHardwareDevice)); + + kpu_device.kpu_dev_done = &kpu_dev_done; + + ret = KpuDeviceRegister(&kpu_device, NONE, KPU_DEVICE_NAME); + if (EOK != ret) + { + KPrintf("board_kpu_init KpuDeviceInit device %s error %d\n", KPU_DEVICE_NAME, ret); + return ERROR; + } + + ret = KpuDeviceAttachToBus(KPU_DEVICE_NAME, KPU_BUS_NAME); + if (EOK != ret) + { + KPrintf("board_kpu_init KpuDeviceAttachToBus device %s error %d\n", KPU_DEVICE_NAME, ret); + return ERROR; + } + + return ret; +} + +int HwKpuInit(void) +{ + x_err_t ret = EOK; + static struct KpuBus kpu_bus; + memset(&kpu_bus, 0, sizeof(struct KpuBus)); + + static struct KpuDriver kpu_driver; + memset(&kpu_driver, 0, sizeof(struct KpuDriver)); + + kpu_driver.configure = KpuDrvConfigure; + ret = BoardKpuBusInit(&kpu_bus, &kpu_driver); + if (EOK != ret) + { + KPrintf("board_kpu_Init error ret %u\n", ret); + return ERROR; + } + + ret = BoardKpuDevBend(); + if (EOK != ret) + { + KPrintf("board_kpu_Init error ret %u\n", ret); + return ERROR; + } + return ret; +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/resources/Kconfig b/Ubiquitous/XiZi_IIoT/resources/Kconfig index c8119869a..4e143e847 100644 --- a/Ubiquitous/XiZi_IIoT/resources/Kconfig +++ b/Ubiquitous/XiZi_IIoT/resources/Kconfig @@ -169,3 +169,9 @@ if BSP_USING_CAMERA bool "Using Camera bus drivers" default n endif + +if BSP_USING_KPU + config RESOURCES_KPU + bool "Using Kpu bus drivers" + default n +endif diff --git a/Ubiquitous/XiZi_IIoT/resources/Makefile b/Ubiquitous/XiZi_IIoT/resources/Makefile index 833c982f2..3ac83f7d5 100644 --- a/Ubiquitous/XiZi_IIoT/resources/Makefile +++ b/Ubiquitous/XiZi_IIoT/resources/Makefile @@ -69,4 +69,8 @@ ifeq ($(CONFIG_RESOURCES_CAMERA),y) SRC_DIR += camera endif +ifeq ($(CONFIG_RESOURCES_KPU),y) + SRC_DIR += kpu +endif + include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/resources/include/bus.h b/Ubiquitous/XiZi_IIoT/resources/include/bus.h index c0f65c4a7..557fb977c 100644 --- a/Ubiquitous/XiZi_IIoT/resources/include/bus.h +++ b/Ubiquitous/XiZi_IIoT/resources/include/bus.h @@ -55,6 +55,7 @@ enum BusType_e TYPE_ADC_BUS, TYPE_DAC_BUS, TYPE_CAMERA_BUS, + TYPE_KPU_BUS, TYPE_BUS_END, }; @@ -82,6 +83,7 @@ enum DevType TYPE_ADC_DEV, TYPE_DAC_DEV, TYPE_CAMERA_DEV, + TYPE_KPU_DEV, TYPE_DEV_END, }; @@ -109,6 +111,7 @@ enum DriverType_e TYPE_ADC_DRV, TYPE_DAC_DRV, TYPE_CAMERA_DRV, + TYPE_KPU_DRV, TYPE_DRV_END, }; diff --git a/Ubiquitous/XiZi_IIoT/resources/include/bus_kpu.h b/Ubiquitous/XiZi_IIoT/resources/include/bus_kpu.h new file mode 100644 index 000000000..1ce2e21e5 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/include/bus_kpu.h @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file bus_kpu.h +* @brief define kpu bus and drv function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-12-19 +*/ + +#ifndef BUS_KPU_H +#define BUS_KPU_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +struct KpuDriver +{ + struct Driver driver; + + uint32 (*configure) (void *drv, struct BusConfigureInfo *configure_info); + + void *private_data; +}; + +struct KpuBus +{ + struct Bus bus; + + void *private_data; +}; + +/*Register the KPU bus*/ +int KpuBusInit(struct KpuBus *kpu_bus, const char *bus_name); + +/*Register the KPU driver*/ +int KpuDriverInit(struct KpuDriver *kpu_driver, const char *driver_name); + +/*Release the KPU device*/ +int KpuReleaseBus(struct KpuBus *kpu_bus); + +/*Register the KPU driver to the KPU bus*/ +int KpuDriverAttachToBus(const char *drv_name, const char *bus_name); + +/*Register the driver, manage with the double linklist*/ +int KpuDriverRegister(struct Driver *driver); + +/*Find the register driver*/ +DriverType KpuDriverFind(const char *drv_name, enum DriverType_e drv_type); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/resources/include/dev_kpu.h b/Ubiquitous/XiZi_IIoT/resources/include/dev_kpu.h new file mode 100644 index 000000000..b6a4a895e --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/include/dev_kpu.h @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file dev_kpu.h +* @brief define kpu dev function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-12-19 +*/ + +#ifndef DEV_KPU_H +#define DEV_KPU_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +struct KpuDataStandard +{ + uint16 addr; + uint16 flags; + uint16 len; + uint16 retries; + uint8 *buf; + + struct KpuDataStandard *next; +}; + +struct KpuDevDone +{ + uint32 (*dev_open) (void *kpu_device); + uint32 (*dev_close) (void *kpu_device); + uint32 (*dev_write) (void *kpu_device, struct BusBlockWriteParam *msg); + uint32 (*dev_read) (void *kpu_device, struct BusBlockReadParam *msg); +}; + +struct KpuHardwareDevice +{ + struct HardwareDev haldev; + const struct KpuDevDone *kpu_dev_done; +}; + +/*Register the KPU device*/ +int KpuDeviceRegister(struct KpuHardwareDevice *kpu_device, void *kpu_param, const char *device_name); + +/*Register the KPU device to the KPU bus*/ +int KpuDeviceAttachToBus(const char *dev_name, const char *bus_name); + +/*Find the register KPU device*/ +HardwareDevType KpuDeviceFind(const char *dev_name, enum DevType dev_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Ubiquitous/XiZi_IIoT/resources/include/device.h b/Ubiquitous/XiZi_IIoT/resources/include/device.h index fc4540f75..a73e64bb4 100644 --- a/Ubiquitous/XiZi_IIoT/resources/include/device.h +++ b/Ubiquitous/XiZi_IIoT/resources/include/device.h @@ -111,4 +111,9 @@ HardwareDevType ObtainConsole(void); #include #endif +#ifdef RESOURCES_KPU +#include +#include +#endif + #endif diff --git a/Ubiquitous/XiZi_IIoT/resources/kpu/Makefile b/Ubiquitous/XiZi_IIoT/resources/kpu/Makefile new file mode 100644 index 000000000..a0905642c --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/kpu/Makefile @@ -0,0 +1,5 @@ +SRC_FILES += dev_kpu.c drv_kpu.c bus_kpu.c + + + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/resources/kpu/bus_kpu.c b/Ubiquitous/XiZi_IIoT/resources/kpu/bus_kpu.c new file mode 100644 index 000000000..58f2bef0e --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/kpu/bus_kpu.c @@ -0,0 +1,123 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file bus_kpu.c +* @brief register kpu bus function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-12-19 +*/ + +#include +#include + +/*Register the KPU BUS*/ +int KpuBusInit(struct KpuBus *kpu_bus, const char *bus_name) +{ + NULL_PARAM_CHECK(kpu_bus); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + if (BUS_INSTALL != kpu_bus->bus.bus_state) { + strncpy(kpu_bus->bus.bus_name, bus_name, NAME_NUM_MAX); + + kpu_bus->bus.bus_type = TYPE_KPU_BUS; + kpu_bus->bus.bus_state = BUS_INSTALL; + kpu_bus->bus.private_data = kpu_bus->private_data; + + ret = BusRegister(&kpu_bus->bus); + if (EOK != ret) { + KPrintf("KpuBusInit BusRegister error %u\n", ret); + return ret; + } + } else { + KPrintf("KpuBusInit BusRegister bus has been register state%u\n", kpu_bus->bus.bus_state); + } + + return ret; +} + +/*Register the KPU Driver*/ +int KpuDriverInit(struct KpuDriver *kpu_driver, const char *driver_name) +{ + NULL_PARAM_CHECK(kpu_driver); + NULL_PARAM_CHECK(driver_name); + + x_err_t ret = EOK; + + if (DRV_INSTALL != kpu_driver->driver.driver_state) { + kpu_driver->driver.driver_type = TYPE_KPU_DRV; + kpu_driver->driver.driver_state = DRV_INSTALL; + + strncpy(kpu_driver->driver.drv_name, driver_name, NAME_NUM_MAX); + + kpu_driver->driver.private_data = kpu_driver->private_data; + + kpu_driver->driver.configure = kpu_driver->configure; + + ret = KpuDriverRegister(&kpu_driver->driver); + if (EOK != ret) { + KPrintf("KpuDriverInit DriverRegister error %u\n", ret); + return ret; + } + } else { + KPrintf("KpuDriverInit DriverRegister driver has been register state%u\n", kpu_driver->driver.driver_state); + } + + return ret; +} + +/*Release the KPU device*/ +int KpuReleaseBus(struct KpuBus *kpu_bus) +{ + NULL_PARAM_CHECK(kpu_bus); + + return BusRelease(&kpu_bus->bus); +} + +/*Register the KPU Driver to the KPU BUS*/ +int KpuDriverAttachToBus(const char *drv_name, const char *bus_name) +{ + NULL_PARAM_CHECK(drv_name); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + struct Bus *bus; + struct Driver *driver; + + bus = BusFind(bus_name); + if (NONE == bus) { + KPrintf("KpuDriverAttachToBus find kpu bus error!name %s\n", bus_name); + return ERROR; + } + + if (TYPE_KPU_BUS == bus->bus_type) { + driver = KpuDriverFind(drv_name, TYPE_KPU_DRV); + if (NONE == driver) { + KPrintf("KpuDriverAttachToBus find kpu driver error!name %s\n", drv_name); + return ERROR; + } + + if (TYPE_KPU_DRV == driver->driver_type) { + ret = DriverRegisterToBus(bus, driver); + if (EOK != ret) { + KPrintf("KpuDriverAttachToBus DriverRegisterToBus error %u\n", ret); + return ERROR; + } + } + } + + return ret; +} diff --git a/Ubiquitous/XiZi_IIoT/resources/kpu/dev_kpu.c b/Ubiquitous/XiZi_IIoT/resources/kpu/dev_kpu.c new file mode 100644 index 000000000..acbe17909 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/kpu/dev_kpu.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2006-03-13 bernard first version + * 2012-05-15 lgnq modified according bernard's implementation. + * 2012-05-28 bernard code cleanup + * 2012-11-23 bernard fix compiler warning. + * 2013-02-20 bernard use RT_KPU_RB_BUFSZ to define + * the size of ring buffer. + * 2014-07-10 bernard rewrite kpu framework + * 2014-12-31 bernard use open_flag for poll_tx stream mode. + * 2015-05-19 Quintin fix DMA tx mod tx_dma->activated flag !=RT_FALSE BUG + * in open function. + * 2015-11-10 bernard fix the poll rx issue when there is no data. + * 2016-05-10 armink add fifo mode to DMA rx when kpu->config.bufsz != 0. + * 2017-01-19 aubr.cool prevent change kpu rx bufsz when kpu is opened. + * 2017-11-07 JasonJia fix data bits error issue when using tcsetattr. + * 2017-11-15 JasonJia fix poll rx issue when data is full. + * add TCFLSH and FIONREAD support. + * 2018-12-08 Ernest Chen add DMA choice + * 2020-09-14 WillianChan add a line feed to the carriage return character + * when using interrupt tx + */ + +/** +* @file dev_kpu.c +* @brief register kpu dev function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-12-19 +*/ + +/************************************************* +File name: dev_kpu.c +Description: support kpu dev INT and DMA configure、transfer data +Others: take RT-Thread v4.0.2/components/driver/kpu/kpu.c for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2021-04-24 +Author: AIIT XUOS Lab +Modification: +1. support kpu dev register, configure, write and read +2. add bus driver framework support, include INT and DMA mode +*************************************************/ + +#include +#include + +static DoubleLinklistType kpudev_linklist; + +static uint32 KpuDevOpen(void *dev) +{ + NULL_PARAM_CHECK(dev); + + x_err_t ret = EOK; + struct KpuHardwareDevice *kpu_dev = (struct KpuHardwareDevice *)dev; + + ret = kpu_dev->kpu_dev_done->dev_open(dev); + + return EOK; +} + +static uint32 KpuDevClose(void *dev) +{ + NULL_PARAM_CHECK(dev); + + x_err_t ret = EOK; + struct KpuHardwareDevice *kpu_dev = (struct KpuHardwareDevice *)dev; + + ret = kpu_dev->kpu_dev_done->dev_close(dev); + return EOK; +} + +static uint32 KpuDevWrite(void *dev, struct BusBlockWriteParam *write_param) +{ + NULL_PARAM_CHECK(dev); + NULL_PARAM_CHECK(write_param); + + x_err_t ret = EOK; + + struct KpuHardwareDevice *kpu_dev = (struct KpuHardwareDevice *)dev; + ret = kpu_dev->kpu_dev_done->dev_write(dev,write_param); + + return ret; +} + +static uint32 KpuDevRead(void *dev, struct BusBlockReadParam *read_param) +{ + NULL_PARAM_CHECK(dev); + NULL_PARAM_CHECK(read_param); + + x_err_t ret = EOK; + + struct KpuHardwareDevice *kpu_dev = (struct KpuHardwareDevice *)dev; + ret = kpu_dev->kpu_dev_done->dev_read(dev,read_param); + + return EOK; +} + + +static const struct HalDevDone dev_done = +{ + .open = KpuDevOpen, + .close = KpuDevClose, + .write = KpuDevWrite, + .read = KpuDevRead, +}; + +/*Create the kpu device linklist*/ +static void KpuDeviceLinkInit() +{ + InitDoubleLinkList(&kpudev_linklist); +} + +HardwareDevType KpuDeviceFind(const char *dev_name, enum DevType dev_type) +{ + NULL_PARAM_CHECK(dev_name); + + struct HardwareDev *device = NONE; + + DoubleLinklistType *node = NONE; + DoubleLinklistType *head = &kpudev_linklist; + + for (node = head->node_next; node != head; node = node->node_next) { + device = SYS_DOUBLE_LINKLIST_ENTRY(node, struct HardwareDev, dev_link); + if ((!strcmp(device->dev_name, dev_name)) && (dev_type == device->dev_type)) { + return device; + } + } + + KPrintf("KpuDeviceFind cannot find the %s device.return NULL\n", dev_name); + return NONE; +} + +int KpuDeviceRegister(struct KpuHardwareDevice *kpu_device, void *kpu_param, const char *device_name) +{ + NULL_PARAM_CHECK(kpu_device); + NULL_PARAM_CHECK(device_name); + + x_err_t ret = EOK; + static x_bool dev_link_flag = RET_FALSE; + + if (!dev_link_flag) { + KpuDeviceLinkInit(); + dev_link_flag = RET_TRUE; + } + + if (DEV_INSTALL != kpu_device->haldev.dev_state) { + strncpy(kpu_device->haldev.dev_name, device_name, NAME_NUM_MAX); + kpu_device->haldev.dev_type = TYPE_KPU_DEV; + kpu_device->haldev.dev_state = DEV_INSTALL; + kpu_device->haldev.dev_done = (struct HalDevDone *)&dev_done; + + + DoubleLinkListInsertNodeAfter(&kpudev_linklist, &(kpu_device->haldev.dev_link)); + } else { + KPrintf("KpuDeviceRegister device has been register state%u\n", kpu_device->haldev.dev_state); + } + + return ret; +} + +int KpuDeviceAttachToBus(const char *dev_name, const char *bus_name) +{ + NULL_PARAM_CHECK(dev_name); + NULL_PARAM_CHECK(bus_name); + + x_err_t ret = EOK; + + struct Bus *bus; + struct HardwareDev *device; + + bus = BusFind(bus_name); + if (NONE == bus) { + KPrintf("KpuDeviceAttachToBus find kpu bus error!name %s\n", bus_name); + return ERROR; + } + + if (TYPE_KPU_BUS == bus->bus_type) { + device = KpuDeviceFind(dev_name, TYPE_KPU_DEV); + if (NONE == device) { + KPrintf("KpuDeviceAttachToBus find kpu device error!name %s\n", dev_name); + return ERROR; + } + + if (TYPE_KPU_DEV == device->dev_type) { + ret = DeviceRegisterToBus(bus, device); + if (EOK != ret) { + KPrintf("KpuDeviceAttachToBus DeviceRegisterToBus error %u\n", ret); + return ERROR; + } + } + } + + return EOK; +} diff --git a/Ubiquitous/XiZi_IIoT/resources/kpu/drv_kpu.c b/Ubiquitous/XiZi_IIoT/resources/kpu/drv_kpu.c new file mode 100644 index 000000000..6ed1f0738 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/kpu/drv_kpu.c @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2020 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file drv_kpu.c +* @brief register kpu drv function using bus driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2021-12-19 +*/ + +#include +#include + +static DoubleLinklistType kpu_drv_linklist; + +/*Create the driver linklist*/ +static void KpuDrvLinkInit() +{ + InitDoubleLinkList(&kpu_drv_linklist); +} + +DriverType KpuDriverFind(const char *drv_name, enum DriverType_e drv_type) +{ + NULL_PARAM_CHECK(drv_name); + + struct Driver *driver = NONE; + + DoubleLinklistType *node = NONE; + DoubleLinklistType *head = &kpu_drv_linklist; + + for (node = head->node_next; node != head; node = node->node_next) { + driver = SYS_DOUBLE_LINKLIST_ENTRY(node, struct Driver, driver_link); + + if ((!strcmp(driver->drv_name, drv_name)) && (drv_type == driver->driver_type)) { + return driver; + } + } + + KPrintf("KpuDriverFind cannot find the %s driver.return NULL\n", drv_name); + return NONE; +} + +int KpuDriverRegister(struct Driver *driver) +{ + NULL_PARAM_CHECK(driver); + + x_err_t ret = EOK; + static x_bool driver_link_flag = RET_FALSE; + + if (!driver_link_flag) { + KpuDrvLinkInit(); + driver_link_flag = RET_TRUE; + } + + DoubleLinkListInsertNodeAfter(&kpu_drv_linklist, &(driver->driver_link)); + + return ret; +} From 27cc89bcef34678f72874d6400b34079aa14bdb4 Mon Sep 17 00:00:00 2001 From: WuZheng Date: Mon, 19 Dec 2022 14:24:35 +0800 Subject: [PATCH 13/15] update readme.md for know framwork --- .../knowing/kpu/k210_yolov2_detect_procedure/Readme.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md index 7b04a9288..3ca0ceec6 100644 --- a/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md +++ b/APP_Framework/Framework/knowing/kpu/k210_yolov2_detect_procedure/Readme.md @@ -30,5 +30,6 @@ int main(void) ## TODO -* KPU drivers are still not completed, because it is undefined how to reisgter KPU's bus and device name in XIZI system. The framework is still directly using the SDK From Canaan Inc. But after the driver completed, it will be easy to adapt framework for the APIs. -* Camera and LCD drivers between RT and XIZI are not completely compatible. So there are some marcos like `ifdef` to make the framework compatible for both systems. +* KPU drivers and frameworks are still not completed, because it is undefined how to reisgter KPU's bus and device name in rt-fusion system. The framework is still directly using the SDK with *ifdef* From Canaan Inc. But after the driver completed, it will be easy to adapt framework for the APIs. +* Camera and LCD drivers between RT and XIZI are not completely compatible. So there are some marcos like *ifdef* to make the framework compatible for both systems. +* After completed, all codes from kernel in knowing framework should be posix interfaces,like *PrivOpen*、*PrivIoctrl*、*PrivRead*. From 0b5c6b0f9fbb2274f10e14d259d2cbf433d51e2d Mon Sep 17 00:00:00 2001 From: WuZheng Date: Tue, 20 Dec 2022 15:15:35 +0800 Subject: [PATCH 14/15] fix bugs that e220 initialize death --- APP_Framework/Framework/connection/lora/e220/e220.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/APP_Framework/Framework/connection/lora/e220/e220.c b/APP_Framework/Framework/connection/lora/e220/e220.c index 7f3c4638c..201e9417f 100644 --- a/APP_Framework/Framework/connection/lora/e220/e220.c +++ b/APP_Framework/Framework/connection/lora/e220/e220.c @@ -263,7 +263,7 @@ static int E220SetRegisterParam(struct Adapter *adapter, uint16 address, uint8 c uint8 baud_rate_bit = E220BaudRateSwitch(baud_rate); E220LoraModeConfig(CONFIGURE_MODE_MODE); - PrivTaskDelay(30); + PrivTaskDelay(2000); buffer[0] = 0xC0; //write register order buffer[1] = 0x00; //register start-address @@ -286,6 +286,7 @@ static int E220SetRegisterParam(struct Adapter *adapter, uint16 address, uint8 c printf("E220SetRegisterParam send failed %d!\n", ret); } + PrivTaskDelay(2000); PrivRead(adapter->fd, buffer, 11); E220LoraModeConfig(DATA_TRANSFER_MODE); From 9f6419e5f63139d4aa23474d3f4795a36f35eb78 Mon Sep 17 00:00:00 2001 From: WuZheng Date: Fri, 23 Dec 2022 09:09:54 +0800 Subject: [PATCH 15/15] fix dvp-read problem caused by driver adaptation --- .../board/edu-riscv64/third_party_driver/dvp/connect_dvp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c index 983719e61..8bf2ab67e 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-riscv64/third_party_driver/dvp/connect_dvp.c @@ -122,6 +122,8 @@ static uint32 DvpRead(void *dev, struct BusBlockReadParam *read_param) dvp_set_output_enable(DVP_OUTPUT_DISPLAY, 0); dvp_set_display_addr((uintptr_t)read_param->buffer); dvp_set_output_enable(DVP_OUTPUT_DISPLAY, 1); + shoot_flag=CONTINOUS_SHOOTS; + dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 1); return ret; }