From 38c4419ef911289f5b066a7998a75a5e18d256d7 Mon Sep 17 00:00:00 2001 From: WuZheng Date: Mon, 19 Dec 2022 14:13:54 +0800 Subject: [PATCH] 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; +}