From 042e609cc9caa21d68dedc8b3e2707420a9a32e6 Mon Sep 17 00:00:00 2001 From: Dereck Hao Date: Wed, 17 Dec 2025 17:14:20 +0800 Subject: [PATCH] =?UTF-8?q?Feat:=20=E6=96=B0=E5=A2=9E=20KL520=20IP=20?= =?UTF-8?q?=E8=87=AA=E5=8B=95=E9=A9=97=E8=AD=89=E6=B8=AC=E8=A9=A6=E5=A5=97?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 實作 GPIO, SPI, I2C, PWM-ADC 功能驗證模組 - 新增互動式 Console 選單 (ip_test_all) 與 README 接線說明 --- .../solution_kdp2_evb_verify/main_ncpu/main.c | 33 + .../main_ncpu/model_ftr_table.c | 58 + .../main_ncpu/user_post_process.c | 466 +++++++ .../main_ncpu/user_pre_process.c | 52 + .../main_scpu/application_init.c | 94 ++ .../main_scpu/device_init.c | 25 + .../main_scpu/driver_init.c | 28 + .../main_scpu/hw_test_i2c.c | 140 ++ .../main_scpu/hw_test_pwm_adc.c | 127 ++ .../main_scpu/hw_test_spi.c | 141 ++ .../main_scpu/include/application_init.h | 31 + .../main_scpu/include/device_init.h | 29 + .../main_scpu/include/driver_init.h | 29 + .../main_scpu/include/ip_test_all.h | 6 + .../main_scpu/include/middleware_init.h | 29 + .../main_scpu/include/system_init.h | 28 + .../main_scpu/include/task_handler.h | 86 ++ .../main_scpu/ip_test_all.c | 113 ++ .../main_scpu/ip_test_gpio.c | 125 ++ .../solution_kdp2_evb_verify/main_scpu/main.c | 57 + .../main_scpu/middleware_init.c | 31 + .../main_scpu/system_init.c | 23 + .../sn52096/ncpu_keil/ncpu.sct | 19 + .../sn52096/ncpu_keil/ncpu.uvoptx | 576 ++++++++ .../sn52096/ncpu_keil/ncpu.uvprojx | 557 ++++++++ .../sn52096/ncpu_keil/post_build.bat | 10 + .../sn52096/proj.uvmpw | 20 + .../sn52096/project.h | 163 +++ .../sn52096/scpu_keil/kdp2_scpu_jlink.ini | 13 + .../sn52096/scpu_keil/post_build.bat | 12 + .../sn52096/scpu_keil/pre_build.bat | 1 + .../sn52096/scpu_keil/scpu.uvoptx | 1197 +++++++++++++++++ .../sn52096/scpu_keil/scpu.uvprojx | 898 +++++++++++++ utils/JLink_programmer/bin/fw_ncpu.bin | Bin 39908 -> 39868 bytes utils/JLink_programmer/bin/fw_scpu.bin | Bin 52568 -> 61860 bytes utils/bin_gen/flash_bin/fw_ncpu.bin | Bin 39908 -> 39868 bytes utils/bin_gen/flash_bin/fw_scpu.bin | Bin 52568 -> 61860 bytes 37 files changed, 5217 insertions(+) create mode 100644 build/solution_kdp2_evb_verify/main_ncpu/main.c create mode 100644 build/solution_kdp2_evb_verify/main_ncpu/model_ftr_table.c create mode 100644 build/solution_kdp2_evb_verify/main_ncpu/user_post_process.c create mode 100644 build/solution_kdp2_evb_verify/main_ncpu/user_pre_process.c create mode 100644 build/solution_kdp2_evb_verify/main_scpu/application_init.c create mode 100644 build/solution_kdp2_evb_verify/main_scpu/device_init.c create mode 100644 build/solution_kdp2_evb_verify/main_scpu/driver_init.c create mode 100644 build/solution_kdp2_evb_verify/main_scpu/hw_test_i2c.c create mode 100644 build/solution_kdp2_evb_verify/main_scpu/hw_test_pwm_adc.c create mode 100644 build/solution_kdp2_evb_verify/main_scpu/hw_test_spi.c create mode 100644 build/solution_kdp2_evb_verify/main_scpu/include/application_init.h create mode 100644 build/solution_kdp2_evb_verify/main_scpu/include/device_init.h create mode 100644 build/solution_kdp2_evb_verify/main_scpu/include/driver_init.h create mode 100644 build/solution_kdp2_evb_verify/main_scpu/include/ip_test_all.h create mode 100644 build/solution_kdp2_evb_verify/main_scpu/include/middleware_init.h create mode 100644 build/solution_kdp2_evb_verify/main_scpu/include/system_init.h create mode 100644 build/solution_kdp2_evb_verify/main_scpu/include/task_handler.h create mode 100644 build/solution_kdp2_evb_verify/main_scpu/ip_test_all.c create mode 100644 build/solution_kdp2_evb_verify/main_scpu/ip_test_gpio.c create mode 100644 build/solution_kdp2_evb_verify/main_scpu/main.c create mode 100644 build/solution_kdp2_evb_verify/main_scpu/middleware_init.c create mode 100644 build/solution_kdp2_evb_verify/main_scpu/system_init.c create mode 100644 build/solution_kdp2_evb_verify/sn52096/ncpu_keil/ncpu.sct create mode 100644 build/solution_kdp2_evb_verify/sn52096/ncpu_keil/ncpu.uvoptx create mode 100644 build/solution_kdp2_evb_verify/sn52096/ncpu_keil/ncpu.uvprojx create mode 100644 build/solution_kdp2_evb_verify/sn52096/ncpu_keil/post_build.bat create mode 100644 build/solution_kdp2_evb_verify/sn52096/proj.uvmpw create mode 100644 build/solution_kdp2_evb_verify/sn52096/project.h create mode 100644 build/solution_kdp2_evb_verify/sn52096/scpu_keil/kdp2_scpu_jlink.ini create mode 100644 build/solution_kdp2_evb_verify/sn52096/scpu_keil/post_build.bat create mode 100644 build/solution_kdp2_evb_verify/sn52096/scpu_keil/pre_build.bat create mode 100644 build/solution_kdp2_evb_verify/sn52096/scpu_keil/scpu.uvoptx create mode 100644 build/solution_kdp2_evb_verify/sn52096/scpu_keil/scpu.uvprojx diff --git a/build/solution_kdp2_evb_verify/main_ncpu/main.c b/build/solution_kdp2_evb_verify/main_ncpu/main.c new file mode 100644 index 0000000..fb0021a --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_ncpu/main.c @@ -0,0 +1,33 @@ +/* -------------------------------------------------------------------------- + * Copyright (c) 2018-2019 Kneron Inc. All rights reserved. + * + * Name: main.c + * Purpose: Kneron NCPU + * + *---------------------------------------------------------------------------*/ + + +#include "cmsis_os2.h" +#include "kdpio.h" + +extern void SystemCoreClockUpdate(void); + +/*---------------------------------------------------------------------------- + * Main: Initialize OS Kernel and NCPU SDK + *---------------------------------------------------------------------------*/ +int main(void) +{ + SystemCoreClockUpdate(); + osKernelInitialize(); + + /* init NCPU */ + kdpio_sdk_init(); + + if (osKernelGetState() == osKernelReady) + { + osKernelStart(); + } + + while (1) + ; +} diff --git a/build/solution_kdp2_evb_verify/main_ncpu/model_ftr_table.c b/build/solution_kdp2_evb_verify/main_ncpu/model_ftr_table.c new file mode 100644 index 0000000..18a3d31 --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_ncpu/model_ftr_table.c @@ -0,0 +1,58 @@ +/* -------------------------------------------------------------------------- + * Copyright (c) 2018-2020 Kneron Inc. All rights reserved. + * + * Name: ncpu_extend_ftr.c + * Purpose: Extend new features implementation + * + *---------------------------------------------------------------------------*/ + +#include "kdpio.h" +#include "model_type.h" +#include "model_ppp.h" + +extern int user_pre_yolo(struct kdp_image_s *image_p); +extern int user_post_yolo(struct kdp_image_s *image_p); + +/********************************************************************************* + Registered model pre-process features list + +only need to register functions for models that default builtin pre-proc can't support +*********************************************************************************/ +model_pre_post_func_t model_pre_proc_fns[MAX_MODEL_REGISTRATIONS] = { + /* < model type ID > < pre-process function > */ + /* -------------------------------------------------------------------------- */ + 0 // no pre-process function is specified + + /* Put customized pre-process functions below: */ + //demo only + //{ TINY_YOLO_V3_224_224_3, user_pre_yolo }, + + /* + { CUSTOMER_MODEL_1, preproc_customer_model_1 }, + { CUSTOMER_MODEL_2, preproc_customer_model_2 }, + { CUSTOMER_MODEL_3, preproc_customer_model_3 }, + */ +}; + +/********************************************************************************* + Registered model post-process features list +*********************************************************************************/ +model_pre_post_func_t model_post_proc_fns[MAX_MODEL_REGISTRATIONS] = { + /* < model type ID > < post-process function > */ + /* -------------------------------------------------------------------------- */ + + /* user post-process function example*/ + { TINY_YOLO_V3_224_224_3, user_post_yolo }, + + /* use builtin post-process function example*/ + //for face_detection and landmark here using Kneron app functions + { KNERON_FD_MASK_MBSSD_200_200_3, post_ssd_face_detection }, + { KNERON_LM_5PTS_ONET_56_56_3, post_face_landmark_onet_5p }, + + + /* Put customized post-process functions below:*/ + //{ CUSTOMER_MODEL_1, post_customer_model_1 }, + //{ CUSTOMER_MODEL_2, post_customer_model_2 }, + //{ CUSTOMER_MODEL_3, post_customer_model_3 }, +}; + diff --git a/build/solution_kdp2_evb_verify/main_ncpu/user_post_process.c b/build/solution_kdp2_evb_verify/main_ncpu/user_post_process.c new file mode 100644 index 0000000..6af9bb0 --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_ncpu/user_post_process.c @@ -0,0 +1,466 @@ +/* + * Kneron Example Post-Processing driver + * + * Copyright (C) 2018-2019 Kneron, Inc. All rights reserved. + * + */ + +#include +#include +#include +#include "base.h" +#include "model_res.h" +#include "post_processing.h" + +#define YOLO_CLASS_MAX 80 /* max result box number per class */ +#define YOLO_GOOD_BOX_MAX 80 /* max result box number for one time inference */ +#define YOLO_BOX_FIX_CH 5 /* x, y, w, h, confidence score */ + +#define YOLO_V3_GRID_W 14 /* max output feature map width */ +#define YOLO_V3_GRID_H 14 /* max output feature map higheit */ +#define YOLO_V3_GRID_MAX (YOLO_V3_GRID_W * YOLO_V3_GRID_H) /* max predict box number per channel */ +#define YOLO_V3_CELL_BOX_NUM 3 /* number of anchors on each output node */ +#define YOLO_V3_MAX_BOX_NUM MIN(500, YOLO_V3_GRID_MAX * YOLO_V3_CELL_BOX_NUM) + +#define KDP_COL_MIN 16 /* hardware 16 bytes alignment, i.e. 128 bits */ + +/* YOLO default parameters */ +const float ex_unpass_score = -999.0; // used as box filter + +const float ex_anchors_v0[3][2] = {{116 ,90}, {156, 198}, {373, 326}}; +const float ex_anchors_v1[3][2] = {{30, 61}, {62, 45}, {59, 119}}; +const float ex_anchors_v2[3][2] = {{10, 13}, {16, 30}, {33, 23}}; + +/* Output node layout */ +struct ex_output_node { + int8_t *base_ptr; + uint32_t ch; + uint32_t row; + uint32_t col; + uint32_t col_len; + uint32_t radix; + uint32_t scale; +}; + +/* Shared global variable area among models */ +struct ex_yolo_v3_post_globals_s { + float box_class_probs[YOLO_CLASS_MAX]; + struct bounding_box_s bboxes_v3[YOLO_V3_GRID_MAX * YOLO_V3_CELL_BOX_NUM]; + struct bounding_box_s result_tmp_s[YOLO_V3_MAX_BOX_NUM]; +}; + +/* Model globals */ +static struct ex_yolo_v3_post_globals_s *ex_yolov3_gp; + +void *get_gp(void **gp, size_t len); + +static inline struct ex_yolo_v3_post_globals_s *get_yolov3_gp(void) { + return (struct ex_yolo_v3_post_globals_s *)get_gp((void **)&ex_yolov3_gp, sizeof(struct ex_yolo_v3_post_globals_s)); +} + +/* Post-Processing utils functions */ +float ex_do_div_scale_optim(float v, float scale) { + return (v * scale); +} + +uint32_t ex_round_up(uint32_t num) { + return ((num + (KDP_COL_MIN - 1)) & ~(KDP_COL_MIN - 1)); +} + +float ex_sigmoid(float x) { + float exp_value; + float return_value; + + exp_value = expf(-x); + + return_value = 1 / (1 + exp_value); + + return return_value; +} + +int ex_float_comparator(float a, float b) { + float diff = a - b; + + if (diff < 0) + return 1; + else if (diff > 0) + return -1; + return 0; +} + +int ex_box_score_comparator(const void *pa, const void *pb) { + float a, b; + + a = ((struct bounding_box_s *) pa)->score; + b = ((struct bounding_box_s *) pb)->score; + + return ex_float_comparator(a, b); +} + +float ex_overlap(float l1, float r1, float l2, float r2) { + float left = l1 > l2 ? l1 : l2; + float right = r1 < r2 ? r1 : r2; + return right - left; +} + +float ex_box_intersection(struct bounding_box_s *a, struct bounding_box_s *b) { + float w, h, area; + + w = ex_overlap(a->x1, a->x2, b->x1, b->x2); + h = ex_overlap(a->y1, a->y2, b->y1, b->y2); + + if (w < 0 || h < 0) + return 0; + + area = w * h; + return area; +} + +float ex_box_union(struct bounding_box_s *a, struct bounding_box_s *b) { + float i, u; + + i = ex_box_intersection(a, b); + u = (a->y2 - a->y1) * (a->x2 - a->x1) + (b->y2 - b->y1) * (b->x2 - b->x1) - i; + + return u; +} + +float ex_box_iou(struct bounding_box_s *a, struct bounding_box_s *b) { + /* origin iou */ + + float c; + float intersection_a_b = ex_box_intersection(a, b); + float union_a_b = ex_box_union(a, b); + + c = intersection_a_b / union_a_b; + + return c; +} + +/* Get the output node information */ +void ex_get_output_node(struct ex_output_node *out_node, struct kdp_image_s *image_p, int node_num) { + struct out_node_s *out_p; + out_p = (struct out_node_s *)((kdp_size_t)POSTPROC_OUT_NODE(image_p) + node_num * sizeof(struct out_node_s)); + + out_node->base_ptr = (int8_t *)OUT_NODE_ADDR(out_p); + out_node->ch = OUT_NODE_CH(out_p); + out_node->row = OUT_NODE_ROW(out_p); + out_node->col = OUT_NODE_COL(out_p); + out_node->col_len = ex_round_up(out_node->col); + out_node->radix = OUT_NODE_RADIX(out_p); + out_node->scale = OUT_NODE_SCALE(out_p); +} + +/* Get the index corresponding to given channel, row, and column indices */ +uint32_t ex_get_index(struct ex_output_node node, uint32_t ch_idx, uint32_t row_idx, uint32_t col_idx) { + uint32_t index = row_idx * node.ch * node.col_len + ch_idx * node.col_len + col_idx; + return index; +} + +/* Get the data pointer corresponding to given channel, row, and column indices */ +int8_t *ex_get_data(struct ex_output_node node, uint32_t ch_idx, uint32_t row_idx, uint32_t col_idx) { + uint32_t index = ex_get_index(node, ch_idx, row_idx, col_idx); + return node.base_ptr + index; +} + +/* Performs NMS on the potential boxes */ +static int ex_nms_bbox_for_post_yolov3_no_sigmoid(struct bounding_box_s *potential_boxes, + struct bounding_box_s *temp_results, + int class_num, + int good_box_count, + int max_boxes, + int single_class_max_boxes, + struct bounding_box_s *results, + float score_thresh, + float iou_thresh) { + int good_result_count = 0; + + // check overlap between only boxes from same class + for (int i = 0; i < class_num; i++) { + int class_good_result_count = 0; + if (good_result_count == max_boxes) // break out of outer loop as well for future classes + break; + + int class_good_box_count = 0; + + // find all boxes of a specific class + for (int j = 0; j < good_box_count; j++) { + if (potential_boxes[j].class_num == i) { + memcpy(&temp_results[class_good_box_count], &potential_boxes[j], sizeof(struct bounding_box_s)); + class_good_box_count++; + } + } + + if (class_good_box_count == 1) { + memcpy(&results[good_result_count], temp_results, sizeof(struct bounding_box_s)); + good_result_count++; + } else if (class_good_box_count >= 2) { + // sort boxes based on the score + qsort(temp_results, class_good_box_count, sizeof(struct bounding_box_s), ex_box_score_comparator); + for (int j = 0; j < class_good_box_count; j++) { + // if the box score is too low or is already filtered by previous box + if (temp_results[j].score < score_thresh) + continue; + + // filter out overlapping, lower score boxes + for (int k = j + 1; k < class_good_box_count; k++) + if (ex_box_iou(&temp_results[j], &temp_results[k]) > iou_thresh) + temp_results[k].score = ex_unpass_score; + + // keep boxes with highest scores, up to a certain amount + if ((good_result_count == max_boxes) || (class_good_result_count == single_class_max_boxes)) + break; + memcpy(&results[good_result_count], &temp_results[j], sizeof(struct bounding_box_s)); + good_result_count++; + class_good_result_count++; + } + } + } + + return good_result_count; +} + +/** + * Update candidate bbox list, reserve top max_candidate_num candidate bbox. + */ +static int ex_update_candidate_bbox_list(struct bounding_box_s *new_candidate_bbox, + int max_candidate_num, + struct bounding_box_s *candidate_bbox_list, + int *candidate_bbox_num, + int *max_candidate_idx, + int *min_candidate_idx) { + + if ((NULL == new_candidate_bbox) || (NULL == candidate_bbox_list)) + return -1; + + int update_idx = -1; + + if (0 == *candidate_bbox_num) { + /** add 1-th bbox */ + *max_candidate_idx = 0; + *min_candidate_idx = 0; + update_idx = 0; + (*candidate_bbox_num)++; + memcpy(&candidate_bbox_list[update_idx], new_candidate_bbox, sizeof(struct bounding_box_s)); + } else { + if (max_candidate_num > *candidate_bbox_num) { + /** directly add bbox when the candidate bbox list is not filled */ + update_idx = *candidate_bbox_num; + + if (new_candidate_bbox->score > candidate_bbox_list[*max_candidate_idx].score) + *max_candidate_idx = update_idx; + else if (new_candidate_bbox->score < candidate_bbox_list[*min_candidate_idx].score) + *min_candidate_idx = update_idx; + + (*candidate_bbox_num)++; + + if (0 <= update_idx) + memcpy(&candidate_bbox_list[update_idx], new_candidate_bbox, sizeof(struct bounding_box_s)); + } else { + /** update candidate bbox list when candidate bbox list is filled */ + if (new_candidate_bbox->score >= candidate_bbox_list[*max_candidate_idx].score) { + /** update the largest score candidate index */ + update_idx = *min_candidate_idx; + *max_candidate_idx = *min_candidate_idx; + } else if (new_candidate_bbox->score > candidate_bbox_list[*min_candidate_idx].score) { + update_idx = *min_candidate_idx; + } + + if (0 <= update_idx) { + memcpy(&candidate_bbox_list[update_idx], new_candidate_bbox, sizeof(struct bounding_box_s)); + + for (int i = 0; i < *candidate_bbox_num; i++) { + /** update the smallest score candidate index */ + if (candidate_bbox_list[i].score < candidate_bbox_list[*min_candidate_idx].score) + *min_candidate_idx = i; + } + } + } + } + + return 0; +} + +/* Remap one bounding box to original image coordinates */ +void ex_remap_bbox(struct kdp_image_s *image_p, struct bounding_box_s *box, int need_scale) { + // original box values are percentages, scale to model sizes + if (need_scale) { + box->x1 *= DIM_INPUT_COL(image_p); + box->y1 *= DIM_INPUT_ROW(image_p); + box->x2 *= DIM_INPUT_COL(image_p); + box->y2 *= DIM_INPUT_ROW(image_p); + } + + // scale from model sizes to original input sizes + box->x1 = (box->x1 - RAW_PAD_LEFT(image_p)) * RAW_SCALE_WIDTH(image_p) + RAW_CROP_LEFT(image_p); + box->y1 = (box->y1 - RAW_PAD_TOP(image_p)) * RAW_SCALE_HEIGHT(image_p) + RAW_CROP_TOP(image_p); + box->x2 = (box->x2 - RAW_PAD_LEFT(image_p)) * RAW_SCALE_WIDTH(image_p) + RAW_CROP_LEFT(image_p); + box->y2 = (box->y2 - RAW_PAD_TOP(image_p)) * RAW_SCALE_HEIGHT(image_p) + RAW_CROP_TOP(image_p); + + // clip to boundaries of image + box->x1 = (int)((box->x1 < 0 ? 0 : box->x1) + (float)0.5); + box->y1 = (int)((box->y1 < 0 ? 0 : box->y1) + (float)0.5); + box->x2 = (int)((box->x2 > RAW_INPUT_COL(image_p) ? RAW_INPUT_COL(image_p) : box->x2) + (float)0.5); + box->y2 = (int)((box->y2 > RAW_INPUT_ROW(image_p) ? RAW_INPUT_ROW(image_p) : box->y2) + (float)0.5); +} + +/* YOLO parameters */ +static float iou_threshold = 0.45; +static float score_threshold = 0.6; +static uint32_t max_detection_box_num = YOLO_V3_MAX_BOX_NUM; +static uint32_t anchors[3][3][2] = {{{0}}}; + +/* User YOLO post processing */ +int user_post_yolo(struct kdp_image_s *image_p) +{ + /************************* Input parameters ******************************/ + host_od_post_params_t *pHostParam = (host_od_post_params_t *)POSTPROC_PARAMS_P(image_p); + + if (pHostParam->prob_thresh > 0) + score_threshold = pHostParam->prob_thresh; + + if (pHostParam->nms_thresh > 0) + iou_threshold = pHostParam->nms_thresh; + + if (pHostParam->max_detection_per_class > 0) + { + max_detection_box_num = pHostParam->max_detection_per_class; + if (max_detection_box_num > YOLO_V3_MAX_BOX_NUM) + max_detection_box_num = YOLO_V3_MAX_BOX_NUM; + } + + // use passed anchor table + uint32_t *p_anchors = (uint32_t *)pHostParam->data; + if (pHostParam->anchor_row * pHostParam->anchor_col > 0 && pHostParam->anchor_row <= 3 && pHostParam->anchor_col <= 6) + { + for (int i = 0; i < pHostParam->anchor_row; i++) + { + for (int j = 0; j < (pHostParam->anchor_col / 2); j++) + { + anchors[i][j][0] = *p_anchors++; + anchors[i][j][1] = *p_anchors++; + } + } + } + else + { + memcpy(anchors[0], ex_anchors_v0, sizeof(float) * 6); + memcpy(anchors[1], ex_anchors_v1, sizeof(float) * 6); + memcpy(anchors[2], ex_anchors_v2, sizeof(float) * 6); + } + + /*************************************************************************/ + + // get result buffer + struct yolo_result_s *result = (struct yolo_result_s *)(POSTPROC_RESULT_MEM_ADDR(image_p)); + struct ex_yolo_v3_post_globals_s *gp = get_yolov3_gp(); + struct bounding_box_s *bbox = gp->bboxes_v3; + struct ex_output_node node_yolo; + int good_box_count = 0; + int max_candidate_idx = 0; + int min_candidate_idx = 0; + + ex_get_output_node(&node_yolo, image_p, 0); + int class_num = node_yolo.ch / YOLO_V3_CELL_BOX_NUM - YOLO_BOX_FIX_CH; + result->class_count = class_num; + + for (int idx = 0; idx < POSTPROC_OUTPUT_NUM(image_p); idx++) { + // get output node parameters + ex_get_output_node(&node_yolo, image_p, idx); + + // get radix and scale for floating conversion + float div = pow(2, node_yolo.radix); + float scale = *(float *)&node_yolo.scale; + + // convert threshold to fp for fast comparison + int prob_thresh_yolov3_fp = floor(-log(1.f / score_threshold - 1.f) * div * scale); + scale = 1.0f / (div * scale); + + for (int ch = 0; ch < YOLO_V3_CELL_BOX_NUM; ch++) { + for (int row = 0; row < node_yolo.row; row++) { + for (int col = 0; col < node_yolo.col; col++) { + // check if the score (4th channel) better than threshold + int8_t box_confidence_fp = *ex_get_data(node_yolo, ch * (class_num + 5) + 4, row, col); + + // filter out small box score + if (box_confidence_fp <= prob_thresh_yolov3_fp) + continue; + + // find maximum score among all classes + // get the predicted class and score in fixed + int max_score_class = 0; + int8_t max_score_int = *ex_get_data(node_yolo, ch * (class_num + YOLO_BOX_FIX_CH) + 5, row, col); + for (int i = 1; i < class_num; i++) { + int8_t cur_score = *ex_get_data(node_yolo, ch * (class_num + YOLO_BOX_FIX_CH) + 5 + i, row, col); + if (cur_score > max_score_int) { + max_score_int = cur_score; + max_score_class = i; + } + } + + // filter out small class number + if (max_score_int <= prob_thresh_yolov3_fp) + continue; + + // get the confidence score in floating + float box_confidence = ex_sigmoid(ex_do_div_scale_optim(box_confidence_fp, scale)); + float max_score = ex_sigmoid(ex_do_div_scale_optim(max_score_int, scale)); + float score = max_score * box_confidence; + + // check if score is larger than threshold we set in floating + if (score > score_threshold) { + if ((YOLO_V3_MAX_BOX_NUM == good_box_count) && (score <= bbox[min_candidate_idx].score)) + continue; + float box_x = (float)*ex_get_data(node_yolo, ch * (class_num + YOLO_BOX_FIX_CH), row, col); + float box_y = (float)*ex_get_data(node_yolo, ch * (class_num + YOLO_BOX_FIX_CH) + 1, row, col); + float box_w = (float)*ex_get_data(node_yolo, ch * (class_num + YOLO_BOX_FIX_CH) + 2, row, col); + float box_h = (float)*ex_get_data(node_yolo, ch * (class_num + YOLO_BOX_FIX_CH) + 3, row, col); + + box_x = ex_do_div_scale_optim(box_x, scale); + box_y = ex_do_div_scale_optim(box_y, scale); + box_w = ex_do_div_scale_optim(box_w, scale); + box_h = ex_do_div_scale_optim(box_h, scale); + + box_x = (ex_sigmoid(box_x) + col) * (DIM_INPUT_COL(image_p) / node_yolo.col); + box_y = (ex_sigmoid(box_y) + row) * (DIM_INPUT_ROW(image_p) / node_yolo.row); + box_w = expf(box_w) * anchors[idx][ch][0]; + box_h = expf(box_h) * anchors[idx][ch][1]; + + struct bounding_box_s new_candidate_bbox = {0}; + new_candidate_bbox.x1 = (box_x - (box_w / 2)); + new_candidate_bbox.y1 = (box_y - (box_h / 2)); + new_candidate_bbox.x2 = (box_x + (box_w / 2)); + new_candidate_bbox.y2 = (box_y + (box_h / 2)); + + new_candidate_bbox.score = score; + new_candidate_bbox.class_num = max_score_class; + + ex_update_candidate_bbox_list(&new_candidate_bbox, + YOLO_V3_MAX_BOX_NUM, + bbox, + &good_box_count, + &max_candidate_idx, + &min_candidate_idx); + } + } + } + } + } + + // do NMS + result->box_count = ex_nms_bbox_for_post_yolov3_no_sigmoid(gp->bboxes_v3, + gp->result_tmp_s, + class_num, + good_box_count, + max_detection_box_num, + max_detection_box_num, + result->boxes, + 0, + iou_threshold); + + // remap boxes to original coordinates + for (int i = 0; i < result->box_count; i++) + ex_remap_bbox(image_p, &result->boxes[i], 0); + + return result->box_count; +} diff --git a/build/solution_kdp2_evb_verify/main_ncpu/user_pre_process.c b/build/solution_kdp2_evb_verify/main_ncpu/user_pre_process.c new file mode 100644 index 0000000..8e2ea1d --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_ncpu/user_pre_process.c @@ -0,0 +1,52 @@ +/* + * Kneron Example Pre-Processing driver + * + * Copyright (C) 2019 Kneron, Inc. All rights reserved. + * + */ + +#include +#include +#include +#include "base.h" +#include "kdpio.h" +#include "ipc.h" + +inline static int pad_up_16(int a) +{ + return ceil((float)a / 16) * 16; +} + +static void pre_proc_unsign_right_shift(uint8_t *src_p, uint8_t *dst_p, int row, int col, int bit_shift) +{ + int unit = 4; + unsigned int r; + int pad_col = pad_up_16(col); + + int len = pad_col * row * unit; + for (r = 0; r < len; r++) { + *(dst_p + r) = (*(src_p + r)) >> bit_shift; + } + return; +} + +// This function is to right-shift the input RGBA image (HeightxWidthxChannel: 224x224x4) for 1 bit +int user_pre_yolo(struct kdp_image_s *image_p) +{ + int out_row, out_col; + int input_radix, bit_shift; + uint8_t *src_p, *dst_p; + + out_row = DIM_INPUT_ROW(image_p); + out_col = DIM_INPUT_COL(image_p); + + input_radix = PREPROC_INPUT_RADIX(image_p); + bit_shift = 8 - input_radix; // 1 byte (8 bits) for every R/G/B/A data + + src_p = (uint8_t *)RAW_IMAGE_MEM_ADDR(image_p); + dst_p = (uint8_t *)PREPROC_INPUT_MEM_ADDR(image_p); + pre_proc_unsign_right_shift(src_p, dst_p, out_row, out_col, bit_shift); + + return 0; +} + diff --git a/build/solution_kdp2_evb_verify/main_scpu/application_init.c b/build/solution_kdp2_evb_verify/main_scpu/application_init.c new file mode 100644 index 0000000..db6df5c --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_scpu/application_init.c @@ -0,0 +1,94 @@ +/* + * Kneron Application initialization + * + * Copyright (C) 2022 Kneron, Inc. All rights reserved. + * + */ + +#include +#include "cmsis_os2.h" + +// power manager +#include "kmdw_power_manager.h" + +// inference core +#include "kp_struct.h" +#include "kmdw_console.h" +#include "kmdw_inference_app.h" + +// inference app +#include "kdp2_inf_app_yolo.h" +#include "demo_customize_inf_single_model.h" +#include "demo_customize_inf_multiple_models.h" + +// inference client +#include "kdp2_usb_companion.h" + +#include "ip_test_all.h" + +#define MAX_IMAGE_COUNT 10 /**< MAX inference input queue slot count */ +#define MAX_RESULT_COUNT 10 /**< MAX inference output queue slot count */ + + +/** + * @brief To register AI applications + * @param[in] num_input_buf number of data inputs in list + * @param[in] inf_input_buf_list list of data input for inference task + * @return N/A + * @note Add a switch case item for a new inf_app application + */ +static void _app_func(int num_input_buf, void** inf_input_buf_list); + + +void _app_func(int num_input_buf, void** inf_input_buf_list) +{ + // check header stamp + if (0 >= num_input_buf) { + kmdw_printf("No input buffer for app function\n"); + return; + } + + kp_inference_header_stamp_t *header_stamp = (kp_inference_header_stamp_t *)inf_input_buf_list[0]; + uint32_t job_id = header_stamp->job_id; + + switch (job_id) + { + case KDP2_INF_ID_APP_YOLO: + kdp2_app_yolo_inference(job_id, num_input_buf, inf_input_buf_list); + break; + case KDP2_JOB_ID_APP_YOLO_CONFIG_POST_PROC: + kdp2_app_yolo_config_post_process_parameters(job_id, num_input_buf, inf_input_buf_list); + break; + case DEMO_KL520_CUSTOMIZE_INF_SINGLE_MODEL_JOB_ID: // a demo code implementation in SCPU for user-defined/customized infernece from one model + demo_customize_inf_single_model(job_id, num_input_buf, inf_input_buf_list); + break; + case DEMO_KL520_CUSTOMIZE_INF_MULTIPLE_MODEL_JOB_ID: // a demo code implementation in SCPU for user-defined/customized infernece from two models + demo_customize_inf_multiple_models(job_id, num_input_buf, inf_input_buf_list); + break; + default: + kmdw_inference_app_send_status_code(job_id, KP_FW_ERROR_UNKNOWN_APP); + break; + } +} + + +void app_initialize(void) +{ + info_msg(">> Start running KL520 KDP2 companion mode ...\n"); + + /* for shutdown command */ + kmdw_power_manager_init(); + + /* initialize inference app */ + /* register APP functions */ + /* specify depth of inference queues */ + kmdw_inference_app_init(_app_func, MAX_IMAGE_COUNT, MAX_RESULT_COUNT); + + /* companion mode init */ + kdp2_usb_companion_init(); + + /* IP verification tests */ + ip_test_all_init(); + + return; +} diff --git a/build/solution_kdp2_evb_verify/main_scpu/device_init.c b/build/solution_kdp2_evb_verify/main_scpu/device_init.c new file mode 100644 index 0000000..bbfa991 --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_scpu/device_init.c @@ -0,0 +1,25 @@ +/******************************************************************** + * Copyright (c) 2020 Kneron, Inc. All Rights Reserved. + * + * The information contained herein is property of Kneron, Inc. + * Terms and conditions of usage are described in detail in Kneron + * STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. + * NO WARRANTY of ANY KIND is provided. This heading must NOT be removed + * from the file. + ********************************************************************/ + //Include +#include "project.h" +#if defined(FLASH_TYPE) && (FLASH_TYPE == FLASH_TYPE_NULL) +#include "kdev_flash_null.h" +#else +#include "kdev_flash.h" +#endif + +//Function +void dev_initialize(void) +{ + kdev_flash_initialize(); +} + diff --git a/build/solution_kdp2_evb_verify/main_scpu/driver_init.c b/build/solution_kdp2_evb_verify/main_scpu/driver_init.c new file mode 100644 index 0000000..481a97b --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_scpu/driver_init.c @@ -0,0 +1,28 @@ +/******************************************************************** + * Copyright (c) 2020 Kneron, Inc. All Rights Reserved. + * + * The information contained herein is property of Kneron, Inc. + * Terms and conditions of usage are described in detail in Kneron + * STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. + * NO WARRANTY of ANY KIND is provided. This heading must NOT be removed + * from the file. + ********************************************************************/ + +#include "project.h" + +#include "kdrv_uart.h" +#include "kdrv_ddr.h" +#include "kdrv_pinmux.h" +//#include "kdrv_power.h" + +static uint32_t pinmux_array[PIN_NUM] = PINMUX_ARRAY; + +void drv_initialize(void) +{ + kdrv_uart_initialize(); + kdrv_pinmux_initialize(PIN_NUM, pinmux_array); + kdrv_ddr_system_init(DDR_INIT_ALL); // TODO, not 720 style +} + diff --git a/build/solution_kdp2_evb_verify/main_scpu/hw_test_i2c.c b/build/solution_kdp2_evb_verify/main_scpu/hw_test_i2c.c new file mode 100644 index 0000000..3b6b501 --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_scpu/hw_test_i2c.c @@ -0,0 +1,140 @@ +/* + * Kneron Hardware Test: I2C + * + * Copyright (C) 2023 Kneron, Inc. All rights reserved. + */ + +#include "cmsis_os2.h" +#include "kdrv_i2c.h" +#include "kdrv_pinmux.h" +#include "kmdw_console.h" + +// OV5647 Sensor specific defines +#define OV5647_I2C_ADDR 0x36 +#define OV5647_CHIP_ID_H_REG 0x300A +#define OV5647_CHIP_ID_L_REG 0x300B +#define OV5647_SYS_CTRL0_REG 0x0100 +#define OV5647_SW_RESET_REG 0x0103 + +// VEYE-MIPI-IMX462 Sensor specific defines +#define VEYE_IMX462_I2C_ADDR 0x3B + +int hw_test_i2c_run(void) +{ + kdrv_status_t status; + uint8_t found_devices = 0; + int result = -1; + + kmdw_printf("Starting I2C Bus Scan Test...\n"); + + // 1. Configure Pinmux for I2C0 + kmdw_printf("Configuring pins for I2C0...\n"); + kdrv_pinmux_config(KDRV_PIN_I2C0_SCL, PIN_MODE_0, PIN_PULL_NONE, PIN_DRIVING_8MA); + kdrv_pinmux_config(KDRV_PIN_I2C0_SDA, PIN_MODE_0, PIN_PULL_NONE, PIN_DRIVING_8MA); + + // 2. Initialize I2C0 + kmdw_printf("Initializing I2C0 at 100kHz...\n"); + status = kdrv_i2c_initialize(KDRV_I2C_CTRL_0, KDRV_I2C_SPEED_100K); + if (status != KDRV_STATUS_OK) { + kmdw_printf("I2C initialization failed. Status: %d\n", status); + return -1; + } + + // kmdw_printf("=========================================================\n"); + // kmdw_printf("Scanning I2C bus (addresses 0x01 to 0x7F)...\n"); + // kmdw_printf("=========================================================\n"); + + // for (uint16_t addr = 1; addr < 128; addr++) { + // // 3. Try to write a single null byte to probe the address. + // // The kdrv_i2c_write_register function is a bit complex for a simple probe. + // // A simpler `kdrv_i2c_master_write` or `kdrv_i2c_probe` would be ideal. + // // Let's try to use kdrv_i2c_write_register with a dummy write. + // // We send 0 bytes of data, but the address is sent on the bus. + // status = kdrv_i2c_write_register(KDRV_I2C_CTRL_0, addr, 0, 0, 0, NULL); + + // if (status == KDRV_STATUS_OK) { + // kmdw_printf("Found I2C device at address: 0x%02X\n", addr); + // found_devices++; + // } + + // // A short delay between probes + // osDelay(10); + // } + + // kmdw_printf("=========================================================\n"); + // kmdw_printf("I2C Bus Scan Summary:\n"); + // kmdw_printf(" Found %d device(s).\n", found_devices); + + kmdw_printf("=========================================================\n"); + kmdw_printf("Checking for OV5647 sensor at address 0x%02X...\n", OV5647_I2C_ADDR); + + uint8_t chip_id_h, chip_id_l; + uint16_t chip_id; + + // Read Chip ID High Byte + status = kdrv_i2c_read_register(KDRV_I2C_CTRL_0, OV5647_I2C_ADDR, OV5647_CHIP_ID_H_REG, 2, 1, &chip_id_h); + if (status != KDRV_STATUS_OK) { + kmdw_printf("Failed to communicate with device at 0x%02X. It might not be an OV5647 or is not connected.\n", OV5647_I2C_ADDR); + } else { + // Read Chip ID Low Byte + kdrv_i2c_read_register(KDRV_I2C_CTRL_0, OV5647_I2C_ADDR, OV5647_CHIP_ID_L_REG, 2, 1, &chip_id_l); + chip_id = ((uint16_t)chip_id_h << 8) | chip_id_l; + kmdw_printf(" Read Chip ID: 0x%04X\n", chip_id); + + if (chip_id == 0x5647) { + kmdw_printf(" OV5647 sensor detected successfully!\n"); + + result = 0; // Passed + // --- Additional Status Checks --- + // 1. Check System Status (Standby/Streaming) + uint8_t sys_status; + status = kdrv_i2c_read_register(KDRV_I2C_CTRL_0, OV5647_I2C_ADDR, OV5647_SYS_CTRL0_REG, 2, 1, &sys_status); + if (status == KDRV_STATUS_OK) { + kmdw_printf(" System Status (0x0100): 0x%02X -> %s\n", sys_status, (sys_status == 0x01) ? "Streaming" : "Standby"); + } else { + kmdw_printf(" Failed to read system status register (0x0100).\n"); + } + + // 2. Perform Software Reset and re-check ID + kmdw_printf(" Performing software reset...\n"); + uint8_t reset_val = 0x01; + status = kdrv_i2c_write_register(KDRV_I2C_CTRL_0, OV5647_I2C_ADDR, OV5647_SW_RESET_REG, 2, 1, &reset_val); + if (status != KDRV_STATUS_OK) { + kmdw_printf(" Failed to write software reset command.\n"); + } else { + osDelay(100); // Wait for the sensor to reset + status = kdrv_i2c_read_register(KDRV_I2C_CTRL_0, OV5647_I2C_ADDR, OV5647_CHIP_ID_H_REG, 2, 1, &chip_id_h); + if (status == KDRV_STATUS_OK) { + kmdw_printf(" Sensor responded after reset. -> PASSED\n"); + } else { + kmdw_printf(" Sensor did NOT respond after reset. -> FAILED\n"); + } + } + + } else { + kmdw_printf(" Device at 0x%02X is not an OV5647 (unexpected chip ID).\n", OV5647_I2C_ADDR); + } + } + +// kmdw_printf("---------------------------------------------------------\n"); +// kmdw_printf("Checking for VEYE-MIPI-IMX462 sensor at address 0x%02X...\n", VEYE_IMX462_I2C_ADDR); + +// // Probe for VEYE-MIPI-IMX462 +// // We use a 0-length write to check if the device ACKs the address. +// status = kdrv_i2c_write_register(KDRV_I2C_CTRL_0, VEYE_IMX462_I2C_ADDR, 0, 0, 0, NULL); + +// if (status == KDRV_STATUS_OK) { +// kmdw_printf(" VEYE-MIPI-IMX462 detected at 0x%02X! -> PASSED\n", VEYE_IMX462_I2C_ADDR); +// result = 0; // Passed if at least one supported sensor is found +// } else { +// kmdw_printf(" No response at 0x%02X. (Not connected or different address)\n", VEYE_IMX462_I2C_ADDR); +// } + + kmdw_printf("=========================================================\n"); + kmdw_printf("Test finished. Returning to main menu...\n"); + + // Uninitialize I2C controller + kdrv_i2c_uninitialize(KDRV_I2C_CTRL_0); + + return result; +} diff --git a/build/solution_kdp2_evb_verify/main_scpu/hw_test_pwm_adc.c b/build/solution_kdp2_evb_verify/main_scpu/hw_test_pwm_adc.c new file mode 100644 index 0000000..4199da4 --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_scpu/hw_test_pwm_adc.c @@ -0,0 +1,127 @@ +#include "cmsis_os2.h" +#include "kdrv_gpio.h" +#include +#include "kdrv_uart.h" +#include "base.h" +#include "kmdw_console.h" +#include "kdrv_pinmux.h" +#include "kdrv_pwm.h" +#include "kdrv_adc.h" +#include "kdrv_timer.h" + +/*************************************************************************************************/ +/* Macro-Definitions */ +/*************************************************************************************************/ +/* + * !! Please modify the following definitions according to your hardware design !! + * You must use a jumper to actually connect the pins corresponding to PWM_PIN and ADC_PIN. + */ + +// 1. Select the physical PIN to use (refer to kdrv_pinmux.h for pin names) +#define PWM_PIN (KDRV_PIN_LC_DATA_12) // FIXME: Please replace with your actual PWM output pin + +// 2. Select PIN_MODE for the required function (refer to kdrv_pinmux.h or chip datasheet) +#define PWM_PIN_MODE (PIN_MODE_2) // FIXME: Please replace with the PWM mode corresponding to your selected pin + +// 3. Find the PWM channel and ADC channel corresponding to the selected PIN +#define PWM_CHANNEL (PWMTIMER6) // FIXME: Please replace with the corresponding PWM timer channel +#define ADC_CHANNEL (3) // FIXME: Please replace with the corresponding ADC channel + +// 4. Test parameters +#define PWM_FREQUENCY_HZ (1000) // PWM Frequency (Hz) +#define PWM_POLARITY (PWM_POLARITY_INVERSED) // 0 for active-high, 1 for active-low + +#define ADC_MAX_VALUE (1023) // ADC max value (e.g., 4095 for 12-bit, 1023 for 10-bit) +#define TEST_VOLTAGE_TOLERANCE (50) // Allowed ADC reading tolerance (e.g., allow 50 error within 0-4095 range) + +/*************************************************************************************************/ +/* Function Declarations */ +/*************************************************************************************************/ + +/** + * @brief Initialize hardware components, including Pinmux, UART, ADC, and PWM. + */ +static void hw_test_initialize(void) +{ + // Initialize UART for debug output + // kmdw_console_init() is usually called at system startup, so it is not repeated here + kmdw_printf("\n[ADC-PWM Loopback Test] Initializing...\n"); + + // -- Key Step: Configure Pin Function -- + // Configure PWM pin + kdrv_pinmux_config(PWM_PIN, PWM_PIN_MODE, PIN_PULL_NONE, PIN_DRIVING_8MA); + kmdw_printf("Pinmux configured: PWM on pin %d (mode %d)\n", PWM_PIN, PWM_PIN_MODE); + + // Initialize ADC peripheral + if (kdrv_adc_initialize() != KDRV_STATUS_OK) { + kmdw_printf("Error: ADC peripheral initialization failed!\n"); + while(1); + } + kmdw_printf("ADC Initialized\n"); + + kmdw_printf("Initialization complete. Please connect pin P29 to pin ADC3 with a jumper wire.\n"); + osDelay(3000); // Give user time to read message and connect wires +} + +/** + * @brief Run PWM to ADC loopback test + */ +int hw_test_pwm_adc_run(void) +{ + hw_test_initialize(); + + const uint32_t duty_cycles[] = {10, 40, 70, 90}; + const uint32_t num_steps = sizeof(duty_cycles) / sizeof(duty_cycles[0]); + uint32_t pass_count = 0, adc_value = 0; + + // Calculate period based on expected frequency (Unit: 10ns) + // Period (10ns) = (1 / Frequency Hz) / (1 / System Clock Hz) / 10ns + // = 1,000,000,000 ns / Frequency Hz / 10ns + const uint32_t period_10ns = 100000000 / PWM_FREQUENCY_HZ; + + kmdw_printf("\n======== Starting PWM-ADC Loopback Test ========\n"); + + for (int i = 0; i < num_steps; i++) { + uint32_t duty_percentage = duty_cycles[i]; + + // Calculate duty cycle (Unit: 10ns) + uint32_t duty_10ns = (period_10ns * duty_percentage) / 100; + + // 1. Configure PWM output + kdrv_pwm_config(PWM_CHANNEL, PWM_POLARITY, duty_10ns, period_10ns, 0); + + // Enable PWM channel + kdrv_pwm_enable(PWM_CHANNEL); + + // Delay to wait for voltage stability + osDelay(200); + + // 2. Read ADC value + adc_value = kdrv_adc_read(ADC_CHANNEL); + // 3. Compare with expected value + // Note: 100% duty cycle might not produce ADC_MAX_VALUE, depending on whether Vref is the same. This is an approximation. + uint32_t expected_value = (ADC_MAX_VALUE * duty_percentage) / 100; + int32_t diff = abs((int)adc_value - (int)expected_value); + + kmdw_printf("Test [Duty %3u%%]: Expected ADC ~%4u, Got ADC = %4u, Diff = %3d ... ", + duty_percentage, expected_value, adc_value, diff); + + if (diff <= TEST_VOLTAGE_TOLERANCE) { + kmdw_printf("PASS\n"); + pass_count++; + } else { + kmdw_printf("FAIL\n"); + } + kdrv_pwm_disable(PWM_CHANNEL); + osDelay(200); + } + + kmdw_printf("======== Test Cycle Complete ========\n"); + if (pass_count == num_steps) { + kmdw_printf("Result: ALL TESTS PASSED.\n"); + return 0; + } else { + kmdw_printf("Result: %u/%u tests FAILED. Check hardware connection/functionality.\n", num_steps - pass_count, num_steps); + return -1; + } +} diff --git a/build/solution_kdp2_evb_verify/main_scpu/hw_test_spi.c b/build/solution_kdp2_evb_verify/main_scpu/hw_test_spi.c new file mode 100644 index 0000000..22622d9 --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_scpu/hw_test_spi.c @@ -0,0 +1,141 @@ +/* + * Kneron Hardware Test: SPI Loopback + * + * Copyright (C) 2023 Kneron, Inc. All rights reserved. + */ + +#include "cmsis_os2.h" +#include "kdrv_ssp.h" +#include "kdrv_pinmux.h" +#include "kdrv_clock.h" +#include "kdrv_gpio.h" +#include "kmdw_console.h" +#include + +#define SPI_PORT SSP_SPI_PORT0 +#define SPI_TEST_DATA_SIZE 16 + +extern struct st_ssp_spi driver_ssp_master_ctx; + +uint8_t kmdw_ssp_api_spi_init(kdrv_ssp_spi_dev_id_t handle, enum e_spi edata) +{ + if( kdrv_ssp_statemachine( handle, &driver_ssp_master_ctx, edata, NULL ) == e_spi_ret_init_done ){ + return 1; + } + return 0; +} +uint8_t kmdw_ssp_api_spi_transfer(kdrv_ssp_spi_dev_id_t handle) +{ + if( kdrv_ssp_statemachine( handle, &driver_ssp_master_ctx, e_spi_tx, NULL ) == e_spi_ret_txbusy ){ + return 1; //rx data correct + } + else{ + return 0; //rx data fail + } +} + +uint8_t kmdw_ssp_api_spi_transfer_checks(kdrv_ssp_spi_dev_id_t handle) +{ + if( kdrv_ssp_statemachine( handle, &driver_ssp_master_ctx, e_spi_tx_status_check, NULL ) == e_spi_ret_txbusy ) + { + return 0; + } + else + { + return 1; + } +} + +void kmdw_ssp_api_spi_write_tx_buff( uint8_t *src, uint16_t nlen ) +{ + kdrv_ssp_write_buff( &driver_ssp_master_ctx, src, nlen ); +} +/** + * @brief SPI Master thread to send data and verify the loopback data. + */ +int hw_test_spi_run(void) +{ + uint8_t tx_data[SPI_TEST_DATA_SIZE]; + uint8_t rx_data[SPI_TEST_DATA_SIZE]; + int result = -1; + + kmdw_printf("[SPI TEST] External Loopback Test Thread started.\n"); + osDelay(10); + + kmdw_printf("Configuring pins for SPI0 Loopback...\n"); + kmdw_printf("Please connect pins: LC_DATA_6 (MOSI) <-> LC_DATA_7 (MISO)\n"); + + // 1. Enable SSP clocks. This is crucial for the SPI peripheral to work. + kdrv_clock_enable(CLK_SSP0_0_SSPCLK); + kdrv_clock_enable(CLK_SSP0_1_SSPCLK); + + kdrv_clock_enable(CLK_SSP1_0_SSPCLK); + kdrv_clock_enable(CLK_SSP1_1_SSPCLK); + + // 2. Configure Pinmux for SSP0. + kdrv_pinmux_config(KDRV_PIN_LC_DATA_4, PIN_MODE_4, PIN_PULL_NONE, PIN_DRIVING_8MA); // SSP0_CLK + kdrv_pinmux_config(KDRV_PIN_LC_DATA_5, PIN_MODE_4, PIN_PULL_NONE, PIN_DRIVING_8MA); // SSP0_CS + kdrv_pinmux_config(KDRV_PIN_LC_DATA_6, PIN_MODE_4, PIN_PULL_NONE, PIN_DRIVING_8MA); // SSP0_MOSI + kdrv_pinmux_config(KDRV_PIN_LC_DATA_7, PIN_MODE_4, PIN_PULL_UP, PIN_DRIVING_8MA); // SSP0_MISO + + // 1. Prepare test data + for (int i = 0; i < SPI_TEST_DATA_SIZE; i++) { + tx_data[i] = (uint8_t)(0xA0 + i); + } + memset(rx_data, 0, SPI_TEST_DATA_SIZE); + + // 2. Initialize SSP in master mode + kmdw_printf("[SPI TEST] Initializing SSP0 in master mode...\n"); + if (kmdw_ssp_api_spi_init(SPI_PORT, e_spi_init_master) != 1) { + kmdw_printf("[SPI TEST] SSP0 initialization failed.\n"); + return -1; + } + + // 3. Perform transfer + kmdw_printf("[SPI TEST] Transferring data...\n"); + kmdw_ssp_api_spi_write_tx_buff(tx_data, SPI_TEST_DATA_SIZE); + + kdrv_ssp_spi_CS_set(KDRV_PIN_LC_DATA_5, SPI_CS_LOW); + kmdw_ssp_api_spi_transfer(SPI_PORT); + + uint32_t timeout = 1000; // 1000ms timeout + while (!kmdw_ssp_api_spi_transfer_checks(SPI_PORT) && timeout > 0) { + osDelay(1); + timeout--; + } + if (timeout == 0) { + kmdw_printf("[SPI TEST] Error: Transfer timed out!\n"); + } + + // Add a robust check to ensure the SPI bus is no longer busy. + // while (kdrv_ssp_busy(SPI_PORT)); + + kdrv_ssp_spi_CS_set(KDRV_PIN_LC_DATA_5, SPI_CS_HI); + + // 4. Read received data from FIFO + uint8_t nsize = kdrv_ssp_rxfifo_valid_entries(driver_ssp_master_ctx.port_no); + if (nsize) { + driver_ssp_master_ctx.Rx_buffer_index = 0; + kdrv_ssp_rx_polling_receive_all(&driver_ssp_master_ctx); + memcpy(rx_data, (void *)driver_ssp_master_ctx.Rx_buffer, nsize); + } + + // 5. Compare results + if (memcmp(tx_data, rx_data, SPI_TEST_DATA_SIZE) == 0) { + kmdw_printf("-> SPI Loopback Test PASSED\n"); + result = 0; + } else { + kmdw_printf("-> SPI Loopback Test FAILED\n"); + kmdw_printf(" TX Data: "); + for(int i=0; i +#include +#include +#include "cmsis_os2.h" +#include "kmdw_console.h" + +extern int hw_test_gpio_run(void); +extern int hw_test_spi_run(void); +extern int hw_test_i2c_run(void); +extern int hw_test_pwm_adc_run(void); + +void ip_test_all_thread(void *arg) { + int res_gpio, res_spi, res_i2c, res_pwm_adc; + + osDelay(1000); + + kmdw_printf("\n\n"); + kmdw_printf("************************************************\n"); + kmdw_printf("* KL520 IP Verification Auto-Test *\n"); + kmdw_printf("************************************************\n"); + kmdw_printf("Please ensure all loopback jumpers are connected:\n"); + kmdw_printf("1. GPIO Loopbacks (P37-P36, P34-P32, P27-P26, P35-P38)\n"); + kmdw_printf("2. SPI0 Loopback (MOSI - MISO)\n"); + kmdw_printf("3. PWM-ADC Loopback (P29 - ADC3)\n"); + kmdw_printf("4. I2C Sensor connected (OV5647)\n"); + kmdw_printf("Test starting in 3 seconds...\n"); + osDelay(3000); + + kmdw_printf("\n>>> Running GPIO Test...\n"); + res_gpio = hw_test_gpio_run(); + + kmdw_printf("\n>>> Running SPI Test...\n"); + osDelay(10); + res_spi = hw_test_spi_run(); + + kmdw_printf("\n>>> Running I2C Test...\n"); + osDelay(10); + res_i2c = hw_test_i2c_run(); + + kmdw_printf("\n>>> Running PWM-ADC Test...\n"); + osDelay(10); + res_pwm_adc = hw_test_pwm_adc_run(); + + kmdw_printf("\n\n"); + kmdw_printf("================================================\n"); + kmdw_printf(" Auto-Test Summary \n"); + kmdw_printf("================================================\n"); + kmdw_printf(" GPIO Test : %s\n", res_gpio == 0 ? "PASS" : "FAIL"); + kmdw_printf(" SPI Test : %s\n", res_spi == 0 ? "PASS" : "FAIL"); + kmdw_printf(" I2C Test : %s\n", res_i2c == 0 ? "PASS" : "FAIL"); + kmdw_printf(" PWM-ADC Test : %s\n", res_pwm_adc == 0 ? "PASS" : "FAIL"); + kmdw_printf("================================================\n"); + osDelay(10); + while (1) { + kmdw_printf("\n"); + kmdw_printf("--------------------------------\n"); + kmdw_printf(" IP Verification Menu \n"); + kmdw_printf("--------------------------------\n"); + kmdw_printf(" [1] GPIO Test\n"); + kmdw_printf(" [2] SPI Test\n"); + kmdw_printf(" [3] I2C Test\n"); + kmdw_printf(" [4] PWM-ADC Test\n"); + kmdw_printf(" [5] Run All Auto-Test Again\n"); + kmdw_printf("--------------------------------\n"); + kmdw_printf("Select test: "); + osDelay(10); + + char buf[64]; + int ch = 0; + + memset(buf, 0, sizeof(buf)); + kmdw_console_echo_gets(buf, sizeof(buf)); + + char *token = strtok(buf, " \r\n\t"); + if (token) ch = atoi(token); + + switch (ch) { + case 1: hw_test_gpio_run(); break; + case 2: hw_test_spi_run(); break; + case 3: hw_test_i2c_run(); break; + case 4: hw_test_pwm_adc_run(); break; + case 5: + kmdw_printf("\n>>> Running GPIO Test...\n"); + res_gpio = hw_test_gpio_run(); + kmdw_printf("\n>>> Running SPI Test...\n"); + res_spi = hw_test_spi_run(); + kmdw_printf("\n>>> Running I2C Test...\n"); + res_i2c = hw_test_i2c_run(); + kmdw_printf("\n>>> Running PWM-ADC Test...\n"); + res_pwm_adc = hw_test_pwm_adc_run(); + + kmdw_printf("================================================\n"); + kmdw_printf(" GPIO: %s | SPI: %s | I2C: %s | PWM-ADC: %s\n", + res_gpio == 0 ? "PASS" : "FAIL", + res_spi == 0 ? "PASS" : "FAIL", + res_i2c == 0 ? "PASS" : "FAIL", + res_pwm_adc == 0 ? "PASS" : "FAIL"); + break; + default: kmdw_printf("Invalid selection.\n"); break; + } + osDelay(500); + } +} + +void ip_test_all_init(void) { + + const osThreadAttr_t attr = { + .name = "IP_Test_All", + .stack_size = 2048, + .priority = osPriorityNormal, + }; + osThreadNew(ip_test_all_thread, NULL, &attr); +} diff --git a/build/solution_kdp2_evb_verify/main_scpu/ip_test_gpio.c b/build/solution_kdp2_evb_verify/main_scpu/ip_test_gpio.c new file mode 100644 index 0000000..35137c2 --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_scpu/ip_test_gpio.c @@ -0,0 +1,125 @@ +/* + * Kneron Hardware Test: GPIO + * + * Copyright (C) 2023 Kneron, Inc. All rights reserved. + */ + +#include "cmsis_os2.h" +#include "kdrv_pinmux.h" +#include "kdrv_gpio.h" +#include "kmdw_console.h" + +// Define a structure to hold a pair of GPIO pins for loopback testing. +typedef struct { + uint32_t pin_a_num; + const char* pin_a_name; + uint32_t pin_b_num; + const char* pin_b_name; +} gpio_pair_t; + +// Centralize all GPIO test pairs in one array. +static const gpio_pair_t gpio_test_pairs[] = { + {GPIO_PIN_25, "P37", GPIO_PIN_26, "P36"}, + {GPIO_PIN_23, "P34", GPIO_PIN_4, "P32"}, + {GPIO_PIN_21, "P27", GPIO_PIN_20, "P26"}, + {GPIO_PIN_27, "P35", GPIO_PIN_24, "P38"} +}; +static const int num_pairs = sizeof(gpio_test_pairs) / sizeof(gpio_test_pairs[0]); + +// Helper function to run a single test case. +static void run_gpio_test_case(uint32_t output_pin_num, const char* output_pin_name, uint32_t input_pin_num, const char* input_pin_name, bool output_val, uint32_t *pass_count, uint32_t *fail_count) +{ + kdrv_gpio_write_pin((kdrv_gpio_pin_t)output_pin_num, output_val); + kmdw_printf("Set %-3s output to: %s, ", output_pin_name, output_val ? "High" : "Low"); + osDelay(10); // Short delay to ensure signal stability. + + uint32_t input_val = 0; + + kdrv_gpio_read_pin((kdrv_gpio_pin_t)input_pin_num, (bool *)&input_val); + + bool passed = ((bool)input_val == output_val); + kmdw_printf("Read %-3s input as: %s -> %s\n", input_pin_name, input_val ? "High" : "Low", passed ? "PASSED" : "FAILED"); + + if (passed) { + (*pass_count)++; + } else { + (*fail_count)++; + } +} + +int hw_test_gpio_run(void) +{ + // 1. Configure Pinmux + // Note: The comments for GPIO numbers seem to be copy-paste errors and may not be accurate. + // It's recommended to verify them against the hardware documentation. + kdrv_pinmux_config(KDRV_PIN_SD_DAT_1, PIN_MODE_3, PIN_PULL_NONE, PIN_DRIVING_8MA); + kdrv_pinmux_config(KDRV_PIN_SD_DAT_2, PIN_MODE_3, PIN_PULL_UP, PIN_DRIVING_8MA); + kdrv_pinmux_config(KDRV_PIN_SD_CMD, PIN_MODE_3, PIN_PULL_NONE, PIN_DRIVING_8MA); + kdrv_pinmux_config(KDRV_PIN_LC_DATA_15, PIN_MODE_3, PIN_PULL_UP, PIN_DRIVING_8MA); + kdrv_pinmux_config(KDRV_PIN_LC_DATA_10, PIN_MODE_3, PIN_PULL_NONE, PIN_DRIVING_8MA); + kdrv_pinmux_config(KDRV_PIN_LC_DATA_9, PIN_MODE_3, PIN_PULL_UP, PIN_DRIVING_8MA); + kdrv_pinmux_config(KDRV_PIN_SD_DAT_3, PIN_MODE_3, PIN_PULL_NONE, PIN_DRIVING_8MA); + kdrv_pinmux_config(KDRV_PIN_SD_DAT_0, PIN_MODE_3, PIN_PULL_UP, PIN_DRIVING_8MA); + + // 2. Initialize GPIO controller + kdrv_gpio_initialize(); + + kmdw_printf("\n"); + kmdw_printf("=========================================================\n"); + kmdw_printf("Please connect GPIO pairs for loopback test:\n"); + kmdw_printf("P37-P36, P34-P32, P27-P26, P35-P38\n"); + kmdw_printf("The test will start in 1 seconds...\n"); + kmdw_printf("=========================================================\n"); + osDelay(1000); + + uint32_t pass_count = 0; + uint32_t fail_count = 0; + + // 3. First pass: Pin A is output, Pin B is input + kmdw_printf("--- Test Pass 1: A->B ---\n"); + for (int i = 0; i < num_pairs; i++) { + kdrv_gpio_set_attribute((kdrv_gpio_pin_t)gpio_test_pairs[i].pin_a_num, GPIO_DIR_OUTPUT); + kdrv_gpio_set_attribute((kdrv_gpio_pin_t)gpio_test_pairs[i].pin_b_num, GPIO_DIR_INPUT); + } + + for (int i = 0; i < num_pairs; i++) { + const gpio_pair_t* pair = &gpio_test_pairs[i]; + run_gpio_test_case(pair->pin_a_num, pair->pin_a_name, pair->pin_b_num, pair->pin_b_name, false, &pass_count, &fail_count); // Test Low + run_gpio_test_case(pair->pin_a_num, pair->pin_a_name, pair->pin_b_num, pair->pin_b_name, true, &pass_count, &fail_count); // Test High + kmdw_printf("\n"); + osDelay(50); + } + + kmdw_printf("=========================================================\n"); + kmdw_printf("Now swapping input/output roles and testing again...\n"); + kmdw_printf("=========================================================\n"); + osDelay(1000); + + // 4. Second pass: Pin B is output, Pin A is input (roles swapped) + kmdw_printf("--- Test Pass 2: B->A ---\n"); + for (int i = 0; i < num_pairs; i++) { + kdrv_gpio_set_attribute((kdrv_gpio_pin_t)gpio_test_pairs[i].pin_a_num, GPIO_DIR_INPUT); + kdrv_gpio_set_attribute((kdrv_gpio_pin_t)gpio_test_pairs[i].pin_b_num, GPIO_DIR_OUTPUT); + } + + for (int i = 0; i < num_pairs; i++) { + const gpio_pair_t* pair = &gpio_test_pairs[i]; + run_gpio_test_case(pair->pin_b_num, pair->pin_b_name, pair->pin_a_num, pair->pin_a_name, false, &pass_count, &fail_count); // Test Low + run_gpio_test_case(pair->pin_b_num, pair->pin_b_name, pair->pin_a_num, pair->pin_a_name, true, &pass_count, &fail_count); // Test High + kmdw_printf("\n"); + osDelay(50); + } + + kmdw_printf("=========================================================\n"); + kmdw_printf("GPIO Test Summary:\n"); + kmdw_printf(" PASSED: %d\n", pass_count); + kmdw_printf(" FAILED: %d\n", fail_count); + kmdw_printf("=========================================================\n"); + kmdw_printf("Test finished. Returning to main menu...\n"); + osDelay(1000); + if (fail_count == 0) { + return 0; + } else { + return -1; + } +} diff --git a/build/solution_kdp2_evb_verify/main_scpu/main.c b/build/solution_kdp2_evb_verify/main_scpu/main.c new file mode 100644 index 0000000..60e1db3 --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_scpu/main.c @@ -0,0 +1,57 @@ +/* + * Kneron Main Entry driver + * + * Copyright (C) 2020 Kneron, Inc. All rights reserved. + * + */ + +#include +#include "cmsis_os2.h" // ARM::CMSIS:RTOS2:Keil RTX5 + +#include "project.h" +#include "version.h" + +// Customized configration and implimentation +#include "system_init.h" +#include "driver_init.h" +#include "device_init.h" +#include "middleware_init.h" +#include "application_init.h" + +#include "kmdw_console.h" + +extern void task_initialize(void); + +/** + * @brief main, main function + */ +int main(void) +{ + osKernelInitialize(); // Initialize CMSIS-RTOS + sys_initialize(); + drv_initialize(); /* customize driver initialization, see driver_init.c */ + dev_initialize(); /* customize device initialization, see device_init.c */ + mdw_initialize(); /* customize middleware initialization, see middlewre_init.c */ + + + printf("SDK v%u.%u.%u-:build.%03u\n", + (uint8_t)(IMG_FW_MAJOR), + (uint8_t)(IMG_FW_MINOR), + (uint8_t)(IMG_FW_UPDATE), + (uint32_t)(IMG_FW_BUILD)); + + app_initialize(); /* customize application initialization, see application_init.c */ + + /* New task threads */ + task_initialize(); + + /* Start RTOS Kernel */ + if (osKernelGetState() == osKernelReady) + { + osKernelStart(); + } + + while (1) + { + } +} diff --git a/build/solution_kdp2_evb_verify/main_scpu/middleware_init.c b/build/solution_kdp2_evb_verify/main_scpu/middleware_init.c new file mode 100644 index 0000000..fcdb7b3 --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_scpu/middleware_init.c @@ -0,0 +1,31 @@ +/******************************************************************** + * Copyright (c) 2020 Kneron, Inc. All Rights Reserved. + * + * The information contained herein is property of Kneron, Inc. + * Terms and conditions of usage are described in detail in Kneron + * STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. + * NO WARRANTY of ANY KIND is provided. This heading must NOT be removed + * from the file. + ********************************************************************/ + +#include "project.h" + +#include "kmdw_memory.h" +#include "kmdw_model.h" +#include "kmdw_dfu.h" +#include "kmdw_console.h" + +void mdw_initialize(void) +{ + kmdw_ddr_init(DDR_HEAP_BEGIN, DDR_HEAP_END); + kmdw_ddr_store_system_reserve(DDR_SYSTEM_RESERVED_BEGIN, DDR_SYSTEM_RESERVED_END); + kmdw_uart_console_init(MSG_PORT, MSG_PORT_BAUDRATE); // uart console + kmdw_dfu_init(NULL, NULL); + kmdw_model_init(); + + // FW is loaded by fw_loader + //load_ncpu_fw(1/*reset_flag*/); // (kmdw_system.h) load ncpu fw from flash +} + diff --git a/build/solution_kdp2_evb_verify/main_scpu/system_init.c b/build/solution_kdp2_evb_verify/main_scpu/system_init.c new file mode 100644 index 0000000..a89c8f3 --- /dev/null +++ b/build/solution_kdp2_evb_verify/main_scpu/system_init.c @@ -0,0 +1,23 @@ +/******************************************************************** + * Copyright (c) 2020 Kneron, Inc. All Rights Reserved. + * + * The information contained herein is property of Kneron, Inc. + * Terms and conditions of usage are described in detail in Kneron + * STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. + * NO WARRANTY of ANY KIND is provided. This heading must NOT be removed + * from the file. + ********************************************************************/ + //Include +//#include "project.h" +#include "kdrv_system.h" + + + //Function +void sys_initialize(void) +{ + /* SDK main init for companion mode */ + kdrv_system_init(); + kdrv_system_init_ncpu(); +} diff --git a/build/solution_kdp2_evb_verify/sn52096/ncpu_keil/ncpu.sct b/build/solution_kdp2_evb_verify/sn52096/ncpu_keil/ncpu.sct new file mode 100644 index 0000000..0260f1e --- /dev/null +++ b/build/solution_kdp2_evb_verify/sn52096/ncpu_keil/ncpu.sct @@ -0,0 +1,19 @@ +#!armcc -E +#define DRAM_START 0x0FFF0000 +#define DRAM_SIZE 0x00010000 + +LR_IROM1 0x00000000 0x00010000 { ; load region size_region + ER_IROM1 0x00000000 0x00010000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 DRAM_START DRAM_SIZE-8 { ; RW data + .ANY (+RW +ZI) + } + + RW_IRAM2 AlignExpr(+0,8) { + .ANY (misc_data) + } +} + diff --git a/build/solution_kdp2_evb_verify/sn52096/ncpu_keil/ncpu.uvoptx b/build/solution_kdp2_evb_verify/sn52096/ncpu_keil/ncpu.uvoptx new file mode 100644 index 0000000..1ad4186 --- /dev/null +++ b/build/solution_kdp2_evb_verify/sn52096/ncpu_keil/ncpu.uvoptx @@ -0,0 +1,576 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + ncpu + 0x4 + ARM-ADS + + 250000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\Listings\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 7 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 4 + + + + + + + + + + + Segger\JL2CM3.dll + + + + 0 + DLGUARM + + + + 0 + DLGDARM + (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0) + + + 0 + ULP2CM3 + -UAny -O905 -S0 -C0 -P00 -N00("ARM CoreSight JTAG-DP") -D00(4BA00477) -L00(4) -N01("ARM CoreSight JTAG-DP") -D01(4BA00477) -L01(4) -TO18 -TC10000000 -TP18 -TDX0 -TDD0 -TDS8000 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO3 -FD20000000 -FC1000 -FN0 + + + 0 + ARMRTXEVENTFLAGS + -L70 -Z18 -C0 -M0 -T1 + + + 0 + DLGTARM + (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0) + + + 0 + ARMDBGFLAGS + -T0 + + + 0 + JL2CM3 + -U63610859 -O1 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST1 -N00("ARM CoreSight JTAG-DP") -D00(4BA00477) -L00(4) -N01("ARM CoreSight JTAG-DP") -D01(4BA00477) -L01(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO1 -FD20000000 -FC1000 -FN0 + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000) + + + + + 0 + 0 + 169 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + D:\3_code\mozart_sw_kdp2.git\scpu\project\companion_kdp2\main\main.c + + +
+
+ + + 1 + 2 + 0x30ff0140 + 0 + + + + + 2 + 2 + 0x61000000 + 0 + + + + + 3 + 2 + 0xa0000000 + 0 + + + + + 4 + 2 + 0 + 0 + + + + 0 + + + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + +
+
+ + + main + 1 + 0 + 0 + 0 + + 1 + 1 + 1 + 0 + 0 + 0 + ..\..\main_ncpu\main.c + main.c + 0 + 0 + + + 1 + 2 + 1 + 0 + 0 + 0 + ..\..\main_ncpu\user_pre_process.c + user_pre_process.c + 0 + 0 + + + 1 + 3 + 1 + 0 + 0 + 0 + ..\..\main_ncpu\user_post_process.c + user_post_process.c + 0 + 0 + + + 1 + 4 + 1 + 0 + 0 + 0 + ..\..\main_ncpu\model_ftr_table.c + model_ftr_table.c + 0 + 0 + + + + + libs + 1 + 0 + 0 + 0 + + 2 + 5 + 4 + 0 + 0 + 0 + ..\..\..\..\lib\kdp2_ncpu_sdk.lib + kdp2_ncpu_sdk.lib + 0 + 0 + + + 2 + 6 + 4 + 0 + 0 + 0 + ..\..\..\..\lib\kdp2_ncpu_model_ppp.lib + kdp2_ncpu_model_ppp.lib + 0 + 0 + + + + + rtx + 0 + 0 + 0 + 0 + + 3 + 7 + 2 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\irq_cm4f.s + irq_cm4f.s + 0 + 0 + + + 3 + 8 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\os_systick.c + os_systick.c + 0 + 0 + + + 3 + 9 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\RTX_Config.c + RTX_Config.c + 0 + 0 + + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_delay.c + rtx_delay.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_evflags.c + rtx_evflags.c + 0 + 0 + + + 3 + 12 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_evr.c + rtx_evr.c + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_kernel.c + rtx_kernel.c + 0 + 0 + + + 3 + 14 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_lib.c + rtx_lib.c + 0 + 0 + + + 3 + 15 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_memory.c + rtx_memory.c + 0 + 0 + + + 3 + 16 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_mempool.c + rtx_mempool.c + 0 + 0 + + + 3 + 17 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_msgqueue.c + rtx_msgqueue.c + 0 + 0 + + + 3 + 18 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_mutex.c + rtx_mutex.c + 0 + 0 + + + 3 + 19 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_semaphore.c + rtx_semaphore.c + 0 + 0 + + + 3 + 20 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_system.c + rtx_system.c + 0 + 0 + + + 3 + 21 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_thread.c + rtx_thread.c + 0 + 0 + + + 3 + 22 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_timer.c + rtx_timer.c + 0 + 0 + + + + + startup + 1 + 0 + 0 + 0 + + 4 + 23 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\startup\startup.c + startup.c + 0 + 0 + + + 4 + 24 + 2 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\ncpu\startup\startup_asm.s + startup_asm.s + 0 + 0 + + + +
diff --git a/build/solution_kdp2_evb_verify/sn52096/ncpu_keil/ncpu.uvprojx b/build/solution_kdp2_evb_verify/sn52096/ncpu_keil/ncpu.uvprojx new file mode 100644 index 0000000..dad3df7 --- /dev/null +++ b/build/solution_kdp2_evb_verify/sn52096/ncpu_keil/ncpu.uvprojx @@ -0,0 +1,557 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + ncpu + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::ARMCC + 0 + + + ARMCM4_FP + ARM + ARM.CMSIS.5.6.0 + http://www.keil.com/pack/ + IRAM(0x20000000,0x00020000) IROM(0x00000000,0x00040000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ESEL ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000) + 0 + $$Device:ARMCM4_FP$Device\ARM\ARMCM4\Include\ARMCM4_FP.h + + + + + + + + + + $$Device:ARMCM4$Device\ARM\SVD\ARMCM4.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\Objects\ + Mozart_ncpu + 1 + 0 + 0 + 1 + 1 + .\Listings\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 1 + fromelf.exe --bin "!L" --output ".\Objects\fw_ncpu.bin" + post_build.bat fw_ncpu.bin + 0 + 0 + 0 + 0 + + 1 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 8 + 1 + 1 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x0 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x10000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0xfff0000 + 0x10000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + ARM_MATH_CM4, TARGET_NCPU, LOG_ENABLE, KL520 + + ..\..\..\..\platform\kl520\common;..\..\..\..\platform\kl520\ncpu\rtos\rtx\include;..\..\..\..\platform\kl520\ncpu\drv\include;..\..\..\..\platform\kl520\ncpu\model_ppp\include;..\..\..\..\include + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + --cpreproc + + + ..\..\..\..\include + + + + 0 + 0 + 0 + 0 + 0 + 0 + 0x00000000 + 0x20000000 + + ..\..\..\..\platform\kl520\ncpu\mozart_ncpu.sct + + + + + + + + + + + main + + + main.c + 1 + ..\..\main_ncpu\main.c + + + user_pre_process.c + 1 + ..\..\main_ncpu\user_pre_process.c + + + user_post_process.c + 1 + ..\..\main_ncpu\user_post_process.c + + + model_ftr_table.c + 1 + ..\..\main_ncpu\model_ftr_table.c + + + + + libs + + + kdp2_ncpu_sdk.lib + 4 + ..\..\..\..\lib\kdp2_ncpu_sdk.lib + + + kdp2_ncpu_model_ppp.lib + 4 + ..\..\..\..\lib\kdp2_ncpu_model_ppp.lib + + + + + rtx + + + irq_cm4f.s + 2 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\irq_cm4f.s + + + os_systick.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\os_systick.c + + + RTX_Config.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\RTX_Config.c + + + rtx_delay.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_delay.c + + + rtx_evflags.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_evflags.c + + + rtx_evr.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_evr.c + + + rtx_kernel.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_kernel.c + + + rtx_lib.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_lib.c + + + rtx_memory.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_memory.c + + + rtx_mempool.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_mempool.c + + + rtx_msgqueue.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_msgqueue.c + + + rtx_mutex.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_mutex.c + + + rtx_semaphore.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_semaphore.c + + + rtx_system.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_system.c + + + rtx_thread.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_thread.c + + + rtx_timer.c + 1 + ..\..\..\..\platform\kl520\ncpu\rtos\rtx\rtx_timer.c + + + + + startup + + + startup.c + 1 + ..\..\..\..\platform\kl520\ncpu\startup\startup.c + + + startup_asm.s + 2 + ..\..\..\..\platform\kl520\ncpu\startup\startup_asm.s + + + + + + + + + + + + + RTE\CMSIS\RTX_Config.c + + + + + + RTE\CMSIS\RTX_Config.h + + + + + + RTE\Device\ARMCM4_FP\startup_ARMCM4.s + + + + + + RTE\Device\ARMCM4_FP\system_ARMCM4.c + + + + + + + +
diff --git a/build/solution_kdp2_evb_verify/sn52096/ncpu_keil/post_build.bat b/build/solution_kdp2_evb_verify/sn52096/ncpu_keil/post_build.bat new file mode 100644 index 0000000..1ac5a9c --- /dev/null +++ b/build/solution_kdp2_evb_verify/sn52096/ncpu_keil/post_build.bat @@ -0,0 +1,10 @@ +@ECHO OFF +REM SET BIN_IN=%1 +REM SET BIN_OUT=fw_ncpu.bin + +SET BIN_OUT=%1 + +SET UTILS_PATH=..\..\..\..\utils + +copy .\Objects\%BIN_OUT% %UTILS_PATH%\JLink_programmer\bin\ +copy .\Objects\%BIN_OUT% %UTILS_PATH%\bin_gen\flash_bin\ diff --git a/build/solution_kdp2_evb_verify/sn52096/proj.uvmpw b/build/solution_kdp2_evb_verify/sn52096/proj.uvmpw new file mode 100644 index 0000000..c38cafd --- /dev/null +++ b/build/solution_kdp2_evb_verify/sn52096/proj.uvmpw @@ -0,0 +1,20 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + WorkSpace + + + + .\scpu_keil\scpu.uvprojx + 1 + + + + .\ncpu_keil\ncpu.uvprojx + + +
diff --git a/build/solution_kdp2_evb_verify/sn52096/project.h b/build/solution_kdp2_evb_verify/sn52096/project.h new file mode 100644 index 0000000..b677458 --- /dev/null +++ b/build/solution_kdp2_evb_verify/sn52096/project.h @@ -0,0 +1,163 @@ +/* Copyright (c) 2020 Kneron, Inc. All Rights Reserved. + * + * The information contained herein is property of Kneron, Inc. + * Terms and conditions of usage are described in detail in Kneron + * STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. + * NO WARRANTY of ANY KIND is provided. This heading must NOT be removed + * from the file. + */ + +/****************************************************************************** +* Filename: +* --------- +* project.h +* +* Description: +* ------------ +* +* +******************************************************************************/ + +#ifndef _PROJECT_H_ +#define _PROJECT_H_ + + +/*============================================================================= +asic setting +=============================================================================*/ +#include "membase.h" + +/*============================================================================= +board setting +=============================================================================*/ +#include "board.h" + +#define FLASH_TYPE FLASH_TYPE_WINBOND_NOR +#define FLASH_SIZE FLASH_SIZE_256MBIT +#define FLASH_COMM FLASH_COMM_SPEED_25MHZ +#define FLASH_DRV FLASH_DRV_NORMAL_MODE + +/*============================================================================= +COMM setting +=============================================================================*/ +#define UART_NUM 1 +#define MSG_PORT COMM_PORT_ID_0 +#define MSG_PORT_BAUDRATE COMM_UART_BAUDRATE_115200 + +/*============================================================================= +Pinmux setting +=============================================================================*/ +#define PIN_NUM 38 +#define KDRV_PIN_SPI_WP_N_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_12MA << 6) //0x00000080 +#define KDRV_PIN_SPI_HOLD_N_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_12MA << 6) //0x00000080 +#define KDRV_PIN_JTAG_TRST_N_REG PIN_MODE_0 | (PIN_PULL_DOWN << 3) | (PIN_DRIVING_12MA << 6) //0x00000090 +#define KDRV_PIN_JTAG_TDI_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_12MA << 6) //0x00000080 +#define KDRV_PIN_JTAG_SWDITMS_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_12MA << 6) //0x00000080 +#define KDRV_PIN_JTAG_SWCLKTCK_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_12MA << 6) //0x00000080 +#define KDRV_PIN_JTAG_TDO_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_12MA << 6) //0x00000080 +#define KDRV_PIN_LC_PCLK_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_4MA << 6) //0x00000000 +#define KDRV_PIN_LC_VS_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_HS_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DE_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_0_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_4MA << 6) //0x00000000 +#define KDRV_PIN_LC_DATA_1_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_4MA << 6) //0x00000000 +#define KDRV_PIN_LC_DATA_2_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_4MA << 6) //0x00000000 +#define KDRV_PIN_LC_DATA_3_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_4_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_5_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_6_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_7_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_8_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_9_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_10_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_11_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_12_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_13_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_14_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_LC_DATA_15_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_8MA << 6) //0x00000040 +#define KDRV_PIN_SD_CLK_REG PIN_MODE_1 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_12MA << 6) //0x00000081 +#define KDRV_PIN_SD_CMD_REG PIN_MODE_1 | (PIN_PULL_UP << 3) | (PIN_DRIVING_12MA << 6) //0x00000089 +#define KDRV_PIN_SD_DAT_0_REG PIN_MODE_0 | (PIN_PULL_UP << 3) | (PIN_DRIVING_4MA << 6) //0x00000008 +#define KDRV_PIN_SD_DAT_1_REG PIN_MODE_0 | (PIN_PULL_UP << 3) | (PIN_DRIVING_4MA << 6) //0x00000008 +#define KDRV_PIN_SD_DAT_2_REG PIN_MODE_0 | (PIN_PULL_UP << 3) | (PIN_DRIVING_4MA << 6) //0x00000008 +#define KDRV_PIN_SD_DAT_3_REG PIN_MODE_0 | (PIN_PULL_UP << 3) | (PIN_DRIVING_4MA << 6) //0x00000008 +#define KDRV_PIN_UART0_RX_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_12MA << 6) //0x00000080 +#define KDRV_PIN_UART0_TX_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_12MA << 6) //0x00000080 +#define KDRV_PIN_I2C0_SCL_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_4MA << 6) //0x00000000 +#define KDRV_PIN_I2C0_SDA_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_4MA << 6) //0x00000000 +#define KDRV_PIN_PWM0_REG PIN_MODE_0 | (PIN_PULL_NONE << 3) | (PIN_DRIVING_12MA << 6) //0x00000080 +#define PINMUX_ARRAY {KDRV_PIN_SPI_WP_N_REG, KDRV_PIN_SPI_HOLD_N_REG, KDRV_PIN_JTAG_TRST_N_REG, KDRV_PIN_JTAG_TDI_REG, KDRV_PIN_JTAG_SWDITMS_REG,\ + KDRV_PIN_JTAG_SWCLKTCK_REG, KDRV_PIN_JTAG_TDO_REG, KDRV_PIN_LC_PCLK_REG, KDRV_PIN_LC_VS_REG, KDRV_PIN_LC_HS_REG,\ + KDRV_PIN_LC_DE_REG, KDRV_PIN_LC_DATA_0_REG, KDRV_PIN_LC_DATA_1_REG, KDRV_PIN_LC_DATA_2_REG, KDRV_PIN_LC_DATA_3_REG,\ + KDRV_PIN_LC_DATA_4_REG, KDRV_PIN_LC_DATA_5_REG, KDRV_PIN_LC_DATA_6_REG, KDRV_PIN_LC_DATA_7_REG, KDRV_PIN_LC_DATA_8_REG,\ + KDRV_PIN_LC_DATA_9_REG, KDRV_PIN_LC_DATA_10_REG, KDRV_PIN_LC_DATA_11_REG, KDRV_PIN_LC_DATA_12_REG, KDRV_PIN_LC_DATA_13_REG,\ + KDRV_PIN_LC_DATA_14_REG, KDRV_PIN_LC_DATA_15_REG, KDRV_PIN_SD_CLK_REG, KDRV_PIN_SD_CMD_REG, KDRV_PIN_SD_DAT_0_REG,\ + KDRV_PIN_SD_DAT_1_REG, KDRV_PIN_SD_DAT_2_REG, KDRV_PIN_SD_DAT_3_REG, KDRV_PIN_UART0_RX_REG, KDRV_PIN_UART0_TX_REG,\ + KDRV_PIN_I2C0_SCL_REG, KDRV_PIN_I2C0_SDA_REG, KDRV_PIN_PWM0_REG}; + + +/*============================================================================= +fw setting +=============================================================================*/ +#define OS_DYNAMIC_MEM_SIZE (1024*32) /**< available memory size in RTX*/ + +/*============================================================================= +DDR configuration +=============================================================================*/ +/* DDR table */ +#define DDR_BEGIN DDR_MEM_BASE /**< = 0x60000000, definded in regbase.h*/ +#define DDR_END (DDR_MEM_BASE + DDR_MEM_SIZE - 1) /**< DDR end address */ + +/** Reserve for all_models.bin */ +#define DDR_MODEL_RESERVED_BEGIN KDP_DDR_BASE /**< space head for model data */ +#define DDR_MODEL_RESERVED_END 0x613FFFFF /**< space end for model data(initial boundary) */ + +/** Resseve for DDR heap. Allocation direction from END to BEGIN */ +#define DDR_HEAP_BEGIN 0x61400000 /**< space head for HEAP (initial boundary) */ +#define DDR_HEAP_END 0x63FCFFFF /**< space end for HEAP */ + +/** Reserve for system information, 188KB */ +#define DDR_SYSTEM_RESERVED_BEGIN 0x63FD0000 /**< space head for system info */ +#define DDR_SYSTEM_RESERVED_END 0x63FFEFFF /**< space end for system info */ + +/** Definition of snapshot image address and size, for kdrv_lcdc debug only*/ +#define KDP_DDR_SNAPSHOT_RGB_IMG_SIZE 0x96000 /* 640x480x2(RGB565) */ +#define KDP_DDR_SNAPSHOT_NIR_IMG_SIZE 0x4B000 /* 480x640x1(RAW8) */ +#define KDP_DDR_SNAPSHOT_RGB_IMG_ADDR DDR_MODEL_RESERVED_END +#define KDP_DDR_SNAPSHOT_NIR_IMG_ADDR (DDR_MODEL_RESERVED_END + KDP_DDR_SNAPSHOT_RGB_IMG_SIZE ) + +/*============================================================================= +Flash configuration +=============================================================================*/ +/* Flash table */ +#define FLASH_FW_SCPU0_ADDR 0x00002000 /**< fw_scpu.bin */ +#define FLASH_FW_NCPU0_ADDR 0x00018000 /**< fw_ncpu.bin */ +#define FLASH_FW_CFG0_ADDR 0x00028000 /**< boot_cfg0.bin */ +#define FLASH_FW_SCPU1_ADDR 0x00041000 /**< fw_scpu1.bin */ +#define FLASH_FW_NCPU1_ADDR 0x00057000 /**< fw_ncpu1.bin */ +#define FLASH_FW_CFG1_ADDR 0x00067000 /**< boot_cfg1.bin */ +#define FLASH_MODEL_FW_INFO_ADDR 0x00300000 /**< fw_info.bin */ +#define FLASH_MODEL_ALL_ADDR 0x00301000 /**< all_models.bin */ +#define FLASH_END_ADDR 0x01FFFFFF /**< end addr of 32MB flash */ + +#define FLASH_MINI_BLOCK_SIZE (4 * 1024) + +/*============================================================================= +mdw setting +=============================================================================*/ +/* scpu/ncpu image size */ +#define SCPU_IMAGE_SIZE (SiRAM_MEM_SIZE - 0x2000) +#define NCPU_IMAGE_SIZE NiRAM_MEM_SIZE + +/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +-->critical setting<-- +Below setting is for RD tuning or testing. +**Don't touch anything if you don't know what you are doing** +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + + + + +#endif //_PROJECT_H_ diff --git a/build/solution_kdp2_evb_verify/sn52096/scpu_keil/kdp2_scpu_jlink.ini b/build/solution_kdp2_evb_verify/sn52096/scpu_keil/kdp2_scpu_jlink.ini new file mode 100644 index 0000000..d4099c3 --- /dev/null +++ b/build/solution_kdp2_evb_verify/sn52096/scpu_keil/kdp2_scpu_jlink.ini @@ -0,0 +1,13 @@ +MEMSET(0x10200000, 0x18000, 0) +MEMSET(0x10210000, 0x08000, 0) + +// to let USB know this is running in JTAG mode +MEMSET(0x10100000, 1, 0x01) +MEMSET(0x10100001, 1, 0xBA) +MEMSET(0x10100002, 1, 0xDC) +MEMSET(0x10100003, 1, 0xFE) + +_WDWORD(0xE000ED08, 0x10102000); +SP=_RDWORD(0x10104000) // Set Stack Pointer +PC=_RDWORD(0x10104004) // Set Program Counter = Reset_Handler +BS main \ No newline at end of file diff --git a/build/solution_kdp2_evb_verify/sn52096/scpu_keil/post_build.bat b/build/solution_kdp2_evb_verify/sn52096/scpu_keil/post_build.bat new file mode 100644 index 0000000..f839167 --- /dev/null +++ b/build/solution_kdp2_evb_verify/sn52096/scpu_keil/post_build.bat @@ -0,0 +1,12 @@ +@ECHO OFF +REM SET BIN_IN=%1 +REM SET BIN_OUT=fw_scpu.bin + +SET BIN_OUT=%1 + +SET UTILS_PATH=..\..\..\..\utils + +copy .\Objects\%BIN_OUT% %UTILS_PATH%\JLink_programmer\bin\ +copy .\Objects\%BIN_OUT% %UTILS_PATH%\bin_gen\flash_bin\ + + diff --git a/build/solution_kdp2_evb_verify/sn52096/scpu_keil/pre_build.bat b/build/solution_kdp2_evb_verify/sn52096/scpu_keil/pre_build.bat new file mode 100644 index 0000000..dba1dc6 --- /dev/null +++ b/build/solution_kdp2_evb_verify/sn52096/scpu_keil/pre_build.bat @@ -0,0 +1 @@ +REM "prebuild script" diff --git a/build/solution_kdp2_evb_verify/sn52096/scpu_keil/scpu.uvoptx b/build/solution_kdp2_evb_verify/sn52096/scpu_keil/scpu.uvoptx new file mode 100644 index 0000000..260c18d --- /dev/null +++ b/build/solution_kdp2_evb_verify/sn52096/scpu_keil/scpu.uvoptx @@ -0,0 +1,1197 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc; *.md + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + dev + 0x4 + ARM-ADS + + 200000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\Listings\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 7 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 4 + + + + + + + + + + .\kdp2_scpu_jlink.ini + Segger\JL2CM3.dll + + + + 0 + DLGUARM + + + + 0 + ARMRTXEVENTFLAGS + -L70 -Z18 -C0 -M0 -T1 + + + 0 + DLGTARM + (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0) + + + 0 + ARMDBGFLAGS + + + + 0 + JL2CM3 + -U59700618 -O64 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO5 -FD20000000 -FC1000 -FN0 + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000) + + + + + + 1 + 2 + 0 + 0 + + + + + 2 + 2 + 0x61000000 + 0 + + + + + 3 + 2 + 0xa0000000 + 0 + + + + + 4 + 2 + 0 + 0 + + + + 0 + + + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + main + 1 + 0 + 0 + 0 + + 1 + 1 + 1 + 0 + 0 + 0 + ..\..\main_scpu\main.c + main.c + 0 + 0 + + + 1 + 2 + 5 + 0 + 0 + 0 + ..\project.h + project.h + 0 + 0 + + + 1 + 3 + 5 + 0 + 0 + 0 + ..\..\main_scpu\include\task_handler.h + task_handler.h + 0 + 0 + + + 1 + 4 + 1 + 0 + 0 + 0 + ..\..\main_scpu\application_init.c + application_init.c + 0 + 0 + + + 1 + 5 + 1 + 0 + 0 + 0 + ..\..\main_scpu\system_init.c + system_init.c + 0 + 0 + + + 1 + 6 + 1 + 0 + 0 + 0 + ..\..\main_scpu\device_init.c + device_init.c + 0 + 0 + + + 1 + 7 + 1 + 0 + 0 + 0 + ..\..\main_scpu\driver_init.c + driver_init.c + 0 + 0 + + + 1 + 8 + 1 + 0 + 0 + 0 + ..\..\main_scpu\middleware_init.c + middleware_init.c + 0 + 0 + + + + + ip_verify + 1 + 0 + 0 + 0 + + 2 + 9 + 1 + 0 + 0 + 0 + ..\..\main_scpu\hw_test_i2c.c + hw_test_i2c.c + 0 + 0 + + + 2 + 10 + 1 + 0 + 0 + 0 + ..\..\main_scpu\hw_test_pwm_adc.c + hw_test_pwm_adc.c + 0 + 0 + + + 2 + 11 + 1 + 0 + 0 + 0 + ..\..\main_scpu\hw_test_spi.c + hw_test_spi.c + 0 + 0 + + + 2 + 12 + 1 + 0 + 0 + 0 + ..\..\main_scpu\ip_test_all.c + ip_test_all.c + 0 + 0 + + + 2 + 13 + 1 + 0 + 0 + 0 + ..\..\main_scpu\ip_test_gpio.c + ip_test_gpio.c + 0 + 0 + + + + + inf_app + 0 + 0 + 0 + 0 + + 3 + 14 + 1 + 0 + 0 + 0 + ..\..\..\..\app\demo_customize_inf_single_model.c + demo_customize_inf_single_model.c + 0 + 0 + + + 3 + 15 + 1 + 0 + 0 + 0 + ..\..\..\..\app\demo_customize_inf_multiple_models.c + demo_customize_inf_multiple_models.c + 0 + 0 + + + 3 + 16 + 1 + 0 + 0 + 0 + ..\..\..\..\app\kdp2_inf_app_yolo.c + kdp2_inf_app_yolo.c + 0 + 0 + + + + + inf_client + 1 + 0 + 0 + 0 + + 4 + 17 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\usb_companion\kdp2_cmd_handler_520.c + kdp2_cmd_handler_520.c + 0 + 0 + + + 4 + 18 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\usb_companion\kdp2_usb_companion.c + kdp2_usb_companion.c + 0 + 0 + + + 4 + 19 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\usb_companion\usbd_hal_520.c + usbd_hal_520.c + 0 + 0 + + + 4 + 20 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\usb_companion\kdp2_usb_log.c + kdp2_usb_log.c + 0 + 0 + + + + + middleware + 1 + 0 + 0 + 0 + + 5 + 21 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\memory\kmdw_memory.c + kmdw_memory.c + 0 + 0 + + + 5 + 22 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\flash\kmdw_memxfer.c + kmdw_memxfer.c + 0 + 0 + + + 5 + 23 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\console\kmdw_console.c + kmdw_console.c + 0 + 0 + + + 5 + 24 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\power\kmdw_power_manager.c + kmdw_power_manager.c + 0 + 0 + + + 5 + 25 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\dfu\kmdw_dfu.c + kmdw_dfu.c + 0 + 0 + + + 5 + 26 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\utils\kmdw_utils_crc.c + kdp_crc.c + 0 + 0 + + + 5 + 27 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\system\kmdw_system.c + kmdw_system.c + 0 + 0 + + + 5 + 28 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\ipc\kmdw_ipc.c + kmdw_ipc.c + 0 + 0 + + + 5 + 29 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\model\kmdw_model.c + kmdw_model.c + 0 + 0 + + + 5 + 30 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\inference\dual_fifo2.c + dual_fifo2.c + 0 + 0 + + + 5 + 31 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\inference\kdp2_inf_generic_raw.c + kdp2_inf_generic_raw.c + 0 + 0 + + + 5 + 32 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\inference\kmdw_inference_520.c + kmdw_inference_520.c + 0 + 0 + + + 5 + 33 + 1 + 0 + 0 + 0 + ..\..\..\..\mdw\inference\kmdw_fifoq_manager.c + kmdw_fifoq_manager.c + 0 + 0 + + + 5 + 34 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_i2c.c + kdrv_i2c.c + 0 + 0 + + + 5 + 35 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_adc.c + kdrv_adc.c + 0 + 0 + + + 5 + 36 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_ssp.c + kdrv_ssp.c + 0 + 0 + + + + + device + 0 + 0 + 0 + 0 + + 6 + 37 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\dev\flash\kdev_flash_winbond.c + kdev_flash_winbond.c + 0 + 0 + + + + + driver + 0 + 0 + 0 + 0 + + 7 + 38 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_pinmux.c + kdrv_pinmux.c + 0 + 0 + + + 7 + 39 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_gpio.c + kdrv_gpio.c + 0 + 0 + + + 7 + 40 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_spif.c + kdrv_spif.c + 0 + 0 + + + 7 + 41 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_uart.c + kdrv_uart.c + 0 + 0 + + + 7 + 42 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_ipc.c + kdrv_ipc.c + 0 + 0 + + + 7 + 43 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_ncpu.c + kdrv_ncpu.c + 0 + 0 + + + 7 + 44 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_usbd2.c + kdrv_usbd2.c + 0 + 0 + + + 7 + 45 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_usbd2v.c + kdrv_usbd2v.c + 0 + 0 + + + 7 + 46 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_clock.c + kdrv_clock.c + 0 + 0 + + + 7 + 47 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_mpu.c + kdrv_mpu.c + 0 + 0 + + + 7 + 48 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_ddr.c + kdrv_ddr.c + 0 + 0 + + + 7 + 49 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_power.c + kdrv_power.c + 0 + 0 + + + 7 + 50 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_system.c + kdrv_system.c + 0 + 0 + + + 7 + 51 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_wdt.c + kdrv_wdt.c + 0 + 0 + + + 7 + 52 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_gdma.c + kdrv_gdma.c + 0 + 0 + + + 7 + 53 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\rtc.c + rtc.c + 0 + 0 + + + 7 + 54 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_pwm.c + kdrv_pwm.c + 0 + 0 + + + + + rtx + 0 + 0 + 0 + 0 + + 8 + 55 + 2 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\irq_cm4f.s + irq_cm4f.s + 0 + 0 + + + 8 + 56 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\os_systick.c + os_systick.c + 0 + 0 + + + 8 + 57 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\RTX_Config.c + RTX_Config.c + 0 + 0 + + + 8 + 58 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_delay.c + rtx_delay.c + 0 + 0 + + + 8 + 59 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_evflags.c + rtx_evflags.c + 0 + 0 + + + 8 + 60 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_evr.c + rtx_evr.c + 0 + 0 + + + 8 + 61 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_kernel.c + rtx_kernel.c + 0 + 0 + + + 8 + 62 + 1 + 1 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_lib.c + rtx_lib.c + 0 + 0 + + + 8 + 63 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_memory.c + rtx_memory.c + 0 + 0 + + + 8 + 64 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_mempool.c + rtx_mempool.c + 0 + 0 + + + 8 + 65 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_msgqueue.c + rtx_msgqueue.c + 0 + 0 + + + 8 + 66 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_mutex.c + rtx_mutex.c + 0 + 0 + + + 8 + 67 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_semaphore.c + rtx_semaphore.c + 0 + 0 + + + 8 + 68 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_system.c + rtx_system.c + 0 + 0 + + + 8 + 69 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_thread.c + rtx_thread.c + 0 + 0 + + + 8 + 70 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_timer.c + rtx_timer.c + 0 + 0 + + + 8 + 71 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\task_handler.c + task_handler.c + 0 + 0 + + + + + startup + 0 + 0 + 0 + 0 + + 9 + 72 + 1 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\startup\startup.c + startup.c + 0 + 0 + + + 9 + 73 + 2 + 0 + 0 + 0 + ..\..\..\..\platform\kl520\scpu\startup\startup_asm.s + startup_asm.s + 0 + 0 + + + + + libs + 0 + 0 + 0 + 0 + + 10 + 74 + 4 + 0 + 0 + 0 + ..\..\..\..\lib\system_520.lib + system_520.lib + 0 + 0 + + + +
diff --git a/build/solution_kdp2_evb_verify/sn52096/scpu_keil/scpu.uvprojx b/build/solution_kdp2_evb_verify/sn52096/scpu_keil/scpu.uvprojx new file mode 100644 index 0000000..e9de7c0 --- /dev/null +++ b/build/solution_kdp2_evb_verify/sn52096/scpu_keil/scpu.uvprojx @@ -0,0 +1,898 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + dev + 0x4 + ARM-ADS + 5060960::V5.06 update 7 (build 960)::.\ARMCC + 0 + + + ARMCM4_FP + ARM + ARM.CMSIS.5.7.0 + http://www.keil.com/pack/ + IRAM(0x20000000,0x00020000) IROM(0x00000000,0x00040000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ESEL ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000) + 0 + $$Device:ARMCM4_FP$Device\ARM\ARMCM4\Include\ARMCM4_FP.h + + + + + + + + + + $$Device:ARMCM4_FP$Device\ARM\SVD\ARMCM4.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\Objects\ + scpu_fw + 1 + 0 + 0 + 1 + 1 + .\Listings\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + pre_build.bat + + 0 + 0 + 0 + 0 + + + 1 + 1 + fromelf.exe --bin "!L" --output ".\Objects\fw_scpu.bin" + post_build.bat fw_scpu.bin + 0 + 0 + 0 + 0 + + 1 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 0 + 1 + 4099 + + 0 + Segger\JL2CM3.dll + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 8 + 1 + 1 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x20000 + + + 1 + 0x0 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x10102000 + 0x16000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x10200000 + 0x16000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + --gnu + ARM_MATH_CM4, KL520, TARGET_SCPU, LOG_ENABLE + + ..\..\..\..\include;..\..\..\..\platform\kl520\common;..\..\..\..\platform\kl520\scpu\drv\include;..\..\..\..\platform\kl520\scpu\rtos\rtx\include;..\..\..\..\platform\board\board_sn52096;..\..\..\..\platform\dev\include;..\..\..\..\mdw\include;..\..\..\..\mdw\inference;..\..\..\..\app;..\..\main_scpu\include;..\;..\..\..\lib\system_520\main_scpu\include + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + --cpreproc + + + ..\..\sn52096;..\..\..\..\include;..\..\..\..\platform\kl520\common;..\..\..\..\platform\board\board_sn52096 + + + + 0 + 0 + 0 + 0 + 0 + 0 + 0x10100000 + 0x10200000 + + ..\..\..\..\platform\kl520\scpu\scatter_load.sct + + + + + + + + + + + main + + + main.c + 1 + ..\..\main_scpu\main.c + + + project.h + 5 + ..\project.h + + + task_handler.h + 5 + ..\..\main_scpu\include\task_handler.h + + + application_init.c + 1 + ..\..\main_scpu\application_init.c + + + system_init.c + 1 + ..\..\main_scpu\system_init.c + + + device_init.c + 1 + ..\..\main_scpu\device_init.c + + + driver_init.c + 1 + ..\..\main_scpu\driver_init.c + + + middleware_init.c + 1 + ..\..\main_scpu\middleware_init.c + + + + + ip_verify + + + hw_test_i2c.c + 1 + ..\..\main_scpu\hw_test_i2c.c + + + hw_test_pwm_adc.c + 1 + ..\..\main_scpu\hw_test_pwm_adc.c + + + hw_test_spi.c + 1 + ..\..\main_scpu\hw_test_spi.c + + + ip_test_all.c + 1 + ..\..\main_scpu\ip_test_all.c + + + ip_test_gpio.c + 1 + ..\..\main_scpu\ip_test_gpio.c + + + + + inf_app + + + demo_customize_inf_single_model.c + 1 + ..\..\..\..\app\demo_customize_inf_single_model.c + + + demo_customize_inf_multiple_models.c + 1 + ..\..\..\..\app\demo_customize_inf_multiple_models.c + + + kdp2_inf_app_yolo.c + 1 + ..\..\..\..\app\kdp2_inf_app_yolo.c + + + + + inf_client + + + kdp2_cmd_handler_520.c + 1 + ..\..\..\..\mdw\usb_companion\kdp2_cmd_handler_520.c + + + kdp2_usb_companion.c + 1 + ..\..\..\..\mdw\usb_companion\kdp2_usb_companion.c + + + usbd_hal_520.c + 1 + ..\..\..\..\mdw\usb_companion\usbd_hal_520.c + + + kdp2_usb_log.c + 1 + ..\..\..\..\mdw\usb_companion\kdp2_usb_log.c + + + + + middleware + + + kmdw_memory.c + 1 + ..\..\..\..\mdw\memory\kmdw_memory.c + + + kmdw_memxfer.c + 1 + ..\..\..\..\mdw\flash\kmdw_memxfer.c + + + kmdw_console.c + 1 + ..\..\..\..\mdw\console\kmdw_console.c + + + kmdw_power_manager.c + 1 + ..\..\..\..\mdw\power\kmdw_power_manager.c + + + kmdw_dfu.c + 1 + ..\..\..\..\mdw\dfu\kmdw_dfu.c + + + kdp_crc.c + 1 + ..\..\..\..\mdw\utils\kmdw_utils_crc.c + + + kmdw_system.c + 1 + ..\..\..\..\mdw\system\kmdw_system.c + + + kmdw_ipc.c + 1 + ..\..\..\..\mdw\ipc\kmdw_ipc.c + + + kmdw_model.c + 1 + ..\..\..\..\mdw\model\kmdw_model.c + + + dual_fifo2.c + 1 + ..\..\..\..\mdw\inference\dual_fifo2.c + + + kdp2_inf_generic_raw.c + 1 + ..\..\..\..\mdw\inference\kdp2_inf_generic_raw.c + + + kmdw_inference_520.c + 1 + ..\..\..\..\mdw\inference\kmdw_inference_520.c + + + kmdw_fifoq_manager.c + 1 + ..\..\..\..\mdw\inference\kmdw_fifoq_manager.c + + + kdrv_i2c.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_i2c.c + + + kdrv_adc.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_adc.c + + + kdrv_ssp.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_ssp.c + + + + + device + + + kdev_flash_winbond.c + 1 + ..\..\..\..\platform\dev\flash\kdev_flash_winbond.c + + + + + driver + + + kdrv_pinmux.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_pinmux.c + + + kdrv_gpio.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_gpio.c + + + kdrv_spif.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_spif.c + + + kdrv_uart.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_uart.c + + + kdrv_ipc.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_ipc.c + + + kdrv_ncpu.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_ncpu.c + + + 2 + 0 + 0 + 0 + 0 + 0 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + + + kdrv_usbd2.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_usbd2.c + + + kdrv_usbd2v.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_usbd2v.c + + + kdrv_clock.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_clock.c + + + kdrv_mpu.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_mpu.c + + + kdrv_ddr.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_ddr.c + + + kdrv_power.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_power.c + + + kdrv_system.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_system.c + + + kdrv_wdt.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_wdt.c + + + kdrv_gdma.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_gdma.c + + + rtc.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\rtc.c + + + kdrv_pwm.c + 1 + ..\..\..\..\platform\kl520\scpu\drv\kdrv_pwm.c + + + + + rtx + + + irq_cm4f.s + 2 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\irq_cm4f.s + + + os_systick.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\os_systick.c + + + RTX_Config.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\RTX_Config.c + + + rtx_delay.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_delay.c + + + rtx_evflags.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_evflags.c + + + rtx_evr.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_evr.c + + + rtx_kernel.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_kernel.c + + + rtx_lib.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_lib.c + + + rtx_memory.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_memory.c + + + rtx_mempool.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_mempool.c + + + rtx_msgqueue.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_msgqueue.c + + + rtx_mutex.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_mutex.c + + + rtx_semaphore.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_semaphore.c + + + rtx_system.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_system.c + + + rtx_thread.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_thread.c + + + rtx_timer.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\rtx_timer.c + + + task_handler.c + 1 + ..\..\..\..\platform\kl520\scpu\rtos\rtx\task_handler.c + + + + + startup + + + startup.c + 1 + ..\..\..\..\platform\kl520\scpu\startup\startup.c + + + startup_asm.s + 2 + ..\..\..\..\platform\kl520\scpu\startup\startup_asm.s + + + + + libs + + + system_520.lib + 4 + ..\..\..\..\lib\system_520.lib + + + + + + + + + + + + + RTE\CMSIS\RTX_Config.c + + + + + + RTE\CMSIS\RTX_Config.h + + + + + + RTE\Device\ARMCM4_FP\startup_ARMCM4.s + + + + + + RTE\Device\ARMCM4_FP\system_ARMCM4.c + + + + + + + + + + + scpu + 1 + + + + +
diff --git a/utils/JLink_programmer/bin/fw_ncpu.bin b/utils/JLink_programmer/bin/fw_ncpu.bin index 6cc6d9278b77e379db4fc2e5f8c605af2aafb6ee..95def3b2e609a6bc11c9c98c67681160ff527859 100644 GIT binary patch delta 7415 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 Xr?+YLcDa1qYpRmcoqx8%h2j4JJ7^(R delta 7370 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 diff --git a/utils/JLink_programmer/bin/fw_scpu.bin b/utils/JLink_programmer/bin/fw_scpu.bin index 07082a14684f934b20574fb823eea84a639069b1..fb3fd4c42c84480b8e7a78586b48d938b333b715 100644 GIT binary patch delta 28315 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 O;;ww{T03d?3jYNbk1V4A delta 19056 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 $}H&X<5XzWioZH0C`eDuukZ{?6&LVTMy`J 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 U?GFO==Dh)Sd17AC)3ne355H=Kv;Y7A diff --git a/utils/bin_gen/flash_bin/fw_ncpu.bin b/utils/bin_gen/flash_bin/fw_ncpu.bin index 6cc6d9278b77e379db4fc2e5f8c605af2aafb6ee..95def3b2e609a6bc11c9c98c67681160ff527859 100644 GIT binary patch delta 7415 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 Xr?+YLcDa1qYpRmcoqx8%h2j4JJ7^(R delta 7370 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 diff --git a/utils/bin_gen/flash_bin/fw_scpu.bin b/utils/bin_gen/flash_bin/fw_scpu.bin index 07082a14684f934b20574fb823eea84a639069b1..fb3fd4c42c84480b8e7a78586b48d938b333b715 100644 GIT binary patch delta 28315 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 O;;ww{T03d?3jYNbk1V4A delta 19056 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 $}H&X<5XzWioZH0C`eDuukZ{?6&LVTMy`J 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 U?GFO==Dh)Sd17AC)3ne355H=Kv;Y7A