/* * Kneron NPU driver for KDP520 * * Copyright (C) 2022 Kneron, Inc. All rights reserved. * */ #include #include "io.h" #include "kmdw_memory.h" #include "ipc.h" #include "kdrv_ipc.h" #include "kmdw_ipc.h" #include "kmdw_console.h" #include "kmdw_model.h" #include "base.h" #include "kdrv_cmsis_core.h" #include "kmdw_console.h" #define NCPU_IRQ 51 #define INPROC_ARRAY_MAX_SIZE 1000 /* 1000 uint32*/ #define IMAGE_PREPROCESS_BUF_SIZE 0x200000 ipc_handler_t ipc_handler_cb; scpu_to_ncpu_t *out_comm_p; ncpu_to_scpu_result_t *in_comm_p; #ifndef KL520 extern osThreadId_t logger_tid; extern logger_mgt_t logger_mgt; #endif static bool bDSPBusy; /** * @brief Weak function for user to implement the specific functions\n * Ex: Start to flash LED or start to evaluate NCPU running time * @return IPC struct */ __WEAK void hook_ncpu_start(void) { } /** * @brief Weak function for user to implement the specific functions\n * Ex: Stop to flash LED or stop to evaluate NCPU running time * @return IPC struct */ __WEAK void hook_ncpu_stop(void) { } void kmdw_ipc_trigger_int(int ipc_cmd) { while(bDSPBusy == true) { osDelay(10); } hook_ncpu_start(); if(ipc_cmd == CMD_RUN_NPU) { ncpu_to_scpu_req_img_t *req_img_p = &in_comm_p->req_img; dbg_msg("DSP> %d, %d (sts %d)\n", in_comm_p->bHandledByScpu, req_img_p->bHandledByScpu, in_comm_p->sts); } else { // standalone cases will not require parallel processing ncpu_to_scpu_req_img_t *req_img_p = &in_comm_p->req_img; req_img_p->bHandledByScpu = true; } out_comm_p->cmd = ipc_cmd; out_comm_p->bNcpuReceived = 0; kdrv_ipc_trigger_to_ncpu_int(); while(!out_comm_p->bNcpuReceived) { // osDelay(1); //delay 1ms } } static void NCPU_IRQHandler(void) { ncpu_to_scpu_req_img_t *req_img_p = &in_comm_p->req_img; struct kdp_img_raw_s *p_raw_image; // kp inference debug code if(in_comm_p->kp_dbg_status == 0xAA) // FIXME: workaround for dbg flow { ipc_handler_cb(p_raw_image, 0x999); goto irq_out; } #ifndef KL520 if(in_comm_p->print_log) { osThreadFlagsSet(logger_tid, FLAG_LOGGER_NCPU_IN); in_comm_p->print_log = false; goto irq_out; } #endif if (in_comm_p->sts != NCPU_STS_READY) { dbg_msg("Note: DSP IRQ (%d, %d) %d %d %d\n", in_comm_p->bHandledByScpu, req_img_p->bHandledByScpu, in_comm_p->sts, in_comm_p->ipc_type, in_comm_p->out_type); bDSPBusy = true; goto irq_out; } bDSPBusy = false; handle_irqs: if (!in_comm_p->bHandledByScpu) { if((in_comm_p->out_type < NCPU_POSTPROC_RESULT) || (in_comm_p->out_type >= NCPU_RESULT_TYPE_MAX)){ kmdw_printf("[DSP IRQ: wrong out_type] (%d, %d) %d %d %d\n", in_comm_p->bHandledByScpu, req_img_p->bHandledByScpu, in_comm_p->sts, in_comm_p->ipc_type, in_comm_p->out_type); goto irq_out; } if(in_comm_p->out_type == NCPU_POSTPROC_RESULT) { int img_idx = in_comm_p->result.postproc.img_result.seq_num; p_raw_image = &out_comm_p->raw_images[img_idx]; ipc_handler_cb(p_raw_image, IMAGE_STATE_RECEIVING); } if(in_comm_p->out_type == NCPU_JPEG_ENC_RESULT) { ipc_handler_cb(p_raw_image, IMAGE_STATE_JPEG_ENC_DONE); } if(in_comm_p->out_type == NCPU_JPEG_DEC_RESULT) { ipc_handler_cb(p_raw_image, IMAGE_STATE_JPEG_DEC_DONE); } if(in_comm_p->out_type == NCPU_TOF_DEC_RESULT) { ipc_handler_cb(p_raw_image, IMAGE_STATE_TOF_DEC_DONE); } in_comm_p->bHandledByScpu = true; } if (!req_img_p->bHandledByScpu) { req_img_p->bHandledByScpu = true; ipc_handler_cb(NULL, IMAGE_STATE_ACTIVE); } irq_out: hook_ncpu_stop(); kdrv_ipc_clear_from_ncpu_int(); NVIC_ClearPendingIRQ((IRQn_Type)NCPU_IRQ); if((!in_comm_p->bHandledByScpu || !req_img_p->bHandledByScpu) && (in_comm_p->out_type == NCPU_POSTPROC_RESULT)){ kmdw_printf("[dsp irq] (%d, %d) %d %d %d\n", in_comm_p->bHandledByScpu, req_img_p->bHandledByScpu, in_comm_p->sts, in_comm_p->ipc_type, in_comm_p->out_type); goto handle_irqs; } } /* ############################ * ## Public Functions ## * ############################ */ void kmdw_ipc_set_image_active(uint32_t n_index) { #ifdef KL520 out_comm_p->active_img_index = n_index; #endif out_comm_p->pRawimg = &out_comm_p->raw_images[n_index]; } void kmdw_ipc_set_model_active(uint32_t n_index) { out_comm_p->model_slot_index = n_index; } void kmdw_ipc_set_model(struct kdp_model_s *model_info_addr, uint32_t info_idx, int32_t slot_idx) { if (slot_idx >= MULTI_MODEL_MAX) { dbg_msg("[ERR] too many active model is set\n"); return; } struct kdp_model_s * info = model_info_addr + info_idx; out_comm_p->models[slot_idx] = *(info); out_comm_p->models_type[slot_idx] = info->model_type; dbg_msg("[%s] idx [%u], slot [%d]\n" "in addr [0x%x], len [%u], out addr [0x%x], len [%u]\n", __func__, info_idx, slot_idx, info->input_mem_addr, info->input_mem_len, info->output_mem_addr, info->output_mem_len); dbg_msg("buf addr [0x%x], len [%u], cmd addr [0x%x], len [%u]\n" "weight addr [0x%x], len [%u], setup addr [0x%x], len [%u]\n", info->buf_addr, info->buf_len, info->cmd_mem_addr, info->cmd_mem_len, info->weight_mem_addr, info->weight_mem_len, info->setup_mem_addr, info->setup_mem_len); if (slot_idx + 1 > out_comm_p->num_models) { out_comm_p->num_models = slot_idx + 1; } } void kmdw_ipc_initialize(ipc_handler_t ipc_handler) { #ifndef KL520 uint32_t nExtBufInSize, nExtBufOutSize; #endif out_comm_p = (scpu_to_ncpu_t *)SCPU_IPC_MEM_ADDR; in_comm_p = (ncpu_to_scpu_result_t *)SCPU_IPC_MEM_ADDR2; memset(out_comm_p, 0, sizeof(scpu_to_ncpu_t)); memset(in_comm_p, 0, sizeof(ncpu_to_scpu_result_t)); out_comm_p->id = SCPU2NCPU_ID; in_comm_p->id = NCPU2SCPU_ID; kmdw_console_set_log_level_scpu(LOG_ERROR); kmdw_console_set_log_level_ncpu(LOG_ERROR); NVIC_SetVector((IRQn_Type)NCPU_IRQ, (uint32_t)NCPU_IRQHandler); NVIC_EnableIRQ((IRQn_Type)NCPU_IRQ); uint32_t mem_len2 = IMAGE_PREPROCESS_BUF_SIZE; uint8_t *mem_addr2 = (uint8_t*)kmdw_ddr_reserve(sizeof(uint8_t)*mem_len2); if(mem_addr2 == 0) { critical_msg("Error: failed to malloc IPC mem_addr2\n"); return; } out_comm_p->input_mem_addr2 = (uint32_t)mem_addr2; out_comm_p->input_mem_len2 = mem_len2; out_comm_p->ncpu_img_req_msg_addr = (uint32_t)&in_comm_p->req_img; out_comm_p->kp_dbg_checkpoinots = 0x0; #ifdef KL520 //allocate the space for inproc array out_comm_p->inproc_mem_addr = kmdw_ddr_reserve(sizeof(uint32_t)*INPROC_ARRAY_MAX_SIZE); #else /* for jpeg enc/dec or tof dec use */ nExtBufInSize = MAX(sizeof(tof_decode_params_t), MAX(sizeof(jpeg_encode_params_t), sizeof(jpeg_decode_params_t))); nExtBufOutSize = MAX(sizeof(tof_decode_result_t), MAX(sizeof(jpeg_encode_result_t), sizeof(jpeg_decode_result_t))); out_comm_p->pExtInParam = (void *)kmdw_ddr_reserve(nExtBufInSize); if(out_comm_p->pExtInParam == 0) { critical_msg("Error: failed to malloc IPC out_comm_p->pExtInParam\n"); return; } out_comm_p->pExtOutRslt = (void *)kmdw_ddr_reserve(nExtBufOutSize); if(out_comm_p->pExtOutRslt == 0) { critical_msg("Error: failed to malloc IPC out_comm_p->pExtOutRslt\n"); return; } in_comm_p->p_log_buf_base = (uint8_t *)&logger_mgt; #endif ipc_handler_cb = ipc_handler; bDSPBusy = false; kdrv_ipc_enable_to_ncpu_int(); } struct scpu_to_ncpu_s* kmdw_ipc_get_output(void) { return out_comm_p; } ncpu_to_scpu_result_t* kmdw_ipc_get_input(void) { return in_comm_p; } void kdrv_ncpu_set_scpu_debug_lvl(uint32_t lvl) { out_comm_p->debug_flags = (out_comm_p->debug_flags & ~0x000F0000) | (((lvl) << 16) & 0x000F0000); } void kdrv_ncpu_set_ncpu_debug_lvl(uint32_t lvl) { out_comm_p->debug_flags = (out_comm_p->debug_flags & ~0x0000000F) | ((lvl)&0x0000000F); }