#include #include #include #include #include #include #include #include "../../../inc/hw/reg/riscv3/2/gpio_mtx_sig.h" #include "oem_common.h" #include "oem_tool_hw.h" #define RC_TOTAL_GPIO 128 #define RC_TOTAL_UART IOT_UART_MAX_NUM_V1 #define RC_TOTAL_PWM IOT_PWM_MAX_NUM_V1 #define RC_TOTAL_ADC IOT_ADC_MAX_NUM_V1 #define RC_TOTAL_LEDC IOT_LEDC_MAX_NUM_V1 #define RC_TOTAL_SPI IOT_SPI_MAX_NUM_V1 #define RC_TOTAL_I2C IOT_I2C_MAX_NUM_V1 #define RC_TOTAL_SPINLOCK IOT_SPINLOCK_MAX_NUM_V1 #define RC_TOTAL_DMA IOT_DMA_MAX_NUM_V1 #define RC_TOTAL_GPTIMER IOT_GPTIMER_MAX_NUM_V1 #define RC_TOTAL_MAILBOX IOT_MAILBOX_MAX_NUM_V1 #define RC_TOTAL_WDG IOT_WDG_MAX_NUM_V1 #define RC_TOTAL_ZC 3 //3 phase #define RC_TOTAL_PA 3 //3 phase #define OEM_TOOL_DEBUG_EB 0 #if OEM_TOOL_DEBUG_EB #define oem_debug_print(fmt, ...) printf(fmt, ##__VA_ARGS__) #else #define oem_debug_print(fmt, ...) #endif typedef enum _category_type_t { CATEGORY_GENERAL = 0, CATEGORY_RC_HDR, /* external reosurce */ CATEGORY_GPIO, CATEGORY_UART, CATEGORY_PWM, CATEGORY_ADC, CATEGORY_LEDC, CATEGORY_SPI, CATEGORY_I2C, /* internal resource */ CATEGORY_SPINLOCK, CATEGORY_DMA, CATEGORY_GPTIMER, CATEGORY_MAILBOX, CATEGORY_WDG, /* special resources, only one zc\pa\rf module, * only binding signal are required, resource allocation is not required. */ CATEGORY_ZC, CATEGORY_PA, CATEGORY_MAX = 0xff, } category_type_t; typedef enum _peripheral_signal_type_t { SIGNAL_UART_TX = 0, SIGNAL_UART_RX, SIGNAL_UART_RTS, SIGNAL_UART_CTS, SIGNAL_SPI_CS, SIGNAL_SPI_CLK, SIGNAL_SPI_MISO, SIGNAL_SPI_MOSI, SIGNAL_I2C_SDA, SIGNAL_I2C_SCL, /* PWM complementary output */ SIGNAL_PWM_A_OUT, SIGNAL_PWM_B_OUT, SIGNAL_LEDC_OUT, SIGNAL_ZC_UP, SIGNAL_ZC_DOWN, SIGNAL_PA_TX_EN, SIGNAL_PA_RX_EN, SIGNAL_PA_GAIN, SIGNAL_MAX = 0xff, } peripheral_signal_type_t; typedef struct _current_rc_info_t { uint8_t device_last; uint8_t core_last; uint8_t pin_idx; iot_board_info_v1_t *rc_ptr; } current_rc_info_t; typedef struct _diff_data_buffer_t { uint8_t buf[4096]; uint16_t len_total; } diff_data_buffer_t; typedef struct _oem_tool_info_t { uint32_t line_num; /* source file(*.ini file) line number */ uint8_t rc_cnt; iot_board_info_v1_t *rc_list[128]; current_rc_info_t rc; diff_data_buffer_t buf; } oem_tool_info_t; oem_tool_info_t oem_tool = {0}; /* The order is the same as category_type_t */ char *g_category_string[] = { "general", "rc_header", "gpio", "uart", "pwm", "adc", "ledc", "spi", "i2c", "spinlock", "dma", "gptimer", "mailbox", "wdg", "zc", "pa", }; /* The order is the same as peripheral_signal_type_t */ char *g_signal_string[] = { "uart_tx", "uart_rx", "uart_rts", "uart_cts", "spi_cs", "spi_clk", "spi_miso", "spi_mosi", "i2c_sda", "i2c_scl", "pwma", "pwmb", "ledc_out", "zc_up", "zc_down", "pa_tx_en", "pa_rx_en", "pa_gain", }; uint8_t gpio_func_sel(uint8_t gpio) { return 0; } // 输出inid // sig_type gpio信号的类型 number,外设或内设的编号 uint8_t get_matrix_signal_inid(uint8_t sig_type, uint8_t number) { uint8_t inid = 0xff; switch (sig_type) { case SIGNAL_UART_RX: switch (number) { case 0: inid = GPIO_MTX_UART0_RXD_IN; break; case 1: inid = GPIO_MTX_UART1_RXD_IN; break; case 2: inid = GPIO_MTX_UART2_RXD_IN; break; case 3: inid = GPIO_MTX_UART3_RXD_IN; break; case 4: inid = GPIO_MTX_UART4_RXD_IN; break; case 5: inid = GPIO_MTX_UART5_RXD_IN; break; case 6: inid = GPIO_MTX_UART6_RXD_IN; break; case 7: inid = GPIO_MTX_UART7_RXD_IN; break; default: break; } break; case SIGNAL_UART_CTS: switch (number) { case 0: inid = GPIO_MTX_UART0_CTS_IN; break; case 1: inid = GPIO_MTX_UART1_CTS_IN; break; case 2: inid = GPIO_MTX_UART2_CTS_IN; break; case 3: inid = GPIO_MTX_UART3_CTS_IN; break; case 4: inid = GPIO_MTX_UART4_CTS_IN; break; case 5: inid = GPIO_MTX_UART5_CTS_IN; break; case 6: inid = GPIO_MTX_UART6_CTS_IN; break; case 7: inid = GPIO_MTX_UART7_CTS_IN; break; default: break; } break; case SIGNAL_SPI_MISO: switch (number) { case 0: inid = GPIO_MTX_SPI_M0_SI_IN; break; case 1: inid = GPIO_MTX_SPI_M1_SI_IN; break; case 2: inid = GPIO_MTX_SPI_M2_SI_IN; break; case 3: inid = GPIO_MTX_SPI_M3_SI_IN; break; default: break; } break; case SIGNAL_I2C_SDA: switch (number) { case 0: inid = GPIO_MTX_I2C0_SDA_IN; break; case 1: inid = GPIO_MTX_I2C1_SDA_IN; break; case 2: inid = GPIO_MTX_I2C2_SDA_IN; break; case 3: inid = GPIO_MTX_I2C3_SDA_IN; break; default: break; } break; case SIGNAL_ZC_UP: switch (number) { case 0: inid = GPIO_MTX_MAC_ZC_UP_PHASE_0; break; case 1: inid = GPIO_MTX_MAC_ZC_UP_PHASE_1; break; case 2: inid = GPIO_MTX_MAC_ZC_UP_PHASE_2; break; } break; case SIGNAL_ZC_DOWN: switch (number) { case 0: inid = GPIO_MTX_MAC_ZC_DOWN_PHASE_0; break; case 1: inid = GPIO_MTX_MAC_ZC_DOWN_PHASE_1; break; case 2: inid = GPIO_MTX_MAC_ZC_DOWN_PHASE_2; break; } break; default: break; } return inid; } // 输出outid // sig_type gpio信号的类型 number,外设或内设的编号 uint8_t get_matrix_signal_outid(uint8_t sig_type, uint8_t number) { uint8_t outid = 0xff; switch (sig_type) { case SIGNAL_UART_TX: switch (number) { case 0: outid = GPIO_MTX_UART0_TXD_OUT; break; case 1: outid = GPIO_MTX_UART1_TXD_OUT; break; case 2: outid = GPIO_MTX_UART2_TXD_OUT; break; case 3: outid = GPIO_MTX_UART3_TXD_OUT; break; case 4: outid = GPIO_MTX_UART4_TXD_OUT; break; case 5: outid = GPIO_MTX_UART5_TXD_OUT; break; case 6: outid = GPIO_MTX_UART6_TXD_OUT; break; case 7: outid = GPIO_MTX_UART7_TXD_OUT; break; default: break; } break; case SIGNAL_UART_RTS: switch (number) { case 0: outid = GPIO_MTX_UART0_RTS_OUT; break; case 1: outid = GPIO_MTX_UART1_RTS_OUT; break; case 2: outid = GPIO_MTX_UART2_RTS_OUT; break; case 3: outid = GPIO_MTX_UART3_RTS_OUT; break; case 4: outid = GPIO_MTX_UART4_RTS_OUT; break; case 5: outid = GPIO_MTX_UART5_RTS_OUT; break; case 6: outid = GPIO_MTX_UART6_RTS_OUT; break; case 7: outid = GPIO_MTX_UART7_RTS_OUT; break; default: break; } break; case SIGNAL_SPI_CS: switch (number) { case 0: outid = GPIO_MTX_SPI_M0_CS_OUT; break; case 1: outid = GPIO_MTX_SPI_M1_CS_OUT; break; case 2: outid = GPIO_MTX_SPI_M2_CS_OUT; break; case 3: outid = GPIO_MTX_SPI_M3_CS_OUT; break; default: break; } break; case SIGNAL_SPI_CLK: switch (number) { case 0: outid = GPIO_MTX_SPI_M0_CLK_OUT; break; case 1: outid = GPIO_MTX_SPI_M1_CLK_OUT; break; case 2: outid = GPIO_MTX_SPI_M2_CLK_OUT; break; case 3: outid = GPIO_MTX_SPI_M3_CLK_OUT; break; default: break; } break; case SIGNAL_SPI_MOSI: switch (number) { case 0: outid = GPIO_MTX_SPI_M0_SO_OUT; break; case 1: outid = GPIO_MTX_SPI_M1_SO_OUT; break; case 2: outid = GPIO_MTX_SPI_M2_SO_OUT; break; case 3: outid = GPIO_MTX_SPI_M3_SO_OUT; break; default: break; } break; case SIGNAL_I2C_SCL: switch (number) { case 0: outid = GPIO_MTX_I2C0_SCL_OUT; break; case 1: outid = GPIO_MTX_I2C1_SCL_OUT; break; case 2: outid = GPIO_MTX_I2C2_SCL_OUT; break; case 3: outid = GPIO_MTX_I2C3_SCL_OUT; break; default: break; } break; case SIGNAL_I2C_SDA: switch (number) { case 0: outid = GPIO_MTX_I2C0_SDA_OUT; break; case 1: outid = GPIO_MTX_I2C1_SDA_OUT; break; case 2: outid = GPIO_MTX_I2C2_SDA_OUT; break; case 3: outid = GPIO_MTX_I2C3_SDA_OUT; break; default: break; } break; case SIGNAL_PWM_A_OUT: switch (number) { case 0: outid = GPIO_MTX_PWM0A_OUT; break; case 1: outid = GPIO_MTX_PWM1A_OUT; break; case 2: outid = GPIO_MTX_PWM2A_OUT; break; case 3: outid = GPIO_MTX_PWM3A_OUT; break; case 4: outid = GPIO_MTX_PWM4A_OUT; break; case 5: outid = GPIO_MTX_PWM5A_OUT; break; default: break; } break; case SIGNAL_PWM_B_OUT: switch (number) { case 0: outid = GPIO_MTX_PWM0B_OUT; break; case 1: outid = GPIO_MTX_PWM1B_OUT; break; case 2: outid = GPIO_MTX_PWM2B_OUT; break; case 3: outid = GPIO_MTX_PWM3B_OUT; break; case 4: outid = GPIO_MTX_PWM4B_OUT; break; case 5: outid = GPIO_MTX_PWM5B_OUT; break; default: break; } break; case SIGNAL_LEDC_OUT: outid = GPIO_MTX_LED0_OUT + number; break; case SIGNAL_PA_TX_EN: switch (number) { case 0: outid = GPIO_MTX_TX_EN_A; break; case 1: outid = GPIO_MTX_TX_EN_B; break; case 2: outid = GPIO_MTX_TX_EN_C; break; } break; case SIGNAL_PA_RX_EN: switch (number) { case 0: outid = GPIO_MTX_RX_EN_A; break; case 1: outid = GPIO_MTX_RX_EN_B; break; case 2: outid = GPIO_MTX_RX_EN_C; break; } break; case SIGNAL_PA_GAIN: switch (number) { case 0: outid = GPIO_MTX_RX_GLNA_0; break; case 1: outid = GPIO_MTX_RX_GLNA_1; break; case 2: outid = GPIO_MTX_RX_GLNA_2; break; } break; default: break; } return outid; } // 如果buf中的字符全是空白或者以 # 开头则返回1 uint8_t is_comments_and_blankline(char *buf) { char *ptr = buf; if (is_whitespace(ptr)) { return 1; } /* the # at the beginning of the line indicates a comment */ while (*ptr && isspace(*ptr)) { ptr++; } if (*ptr == '#') { return 1; } return 0; } // buf 是一行字符 如果这行字符在几种类型之中,返回类型代码,否则返回0xff uint8_t get_category_info(char *buf) { // 以 空格 分割字符串 char *start = strtok(buf, " "); category_type_t category = CATEGORY_MAX; while (*start && isspace(*start)) { start++; } if (!strcmp(start, "general")) { category = CATEGORY_GENERAL; } else if(!strcmp(start, "rc_hdr")) { // 如果类型为 rc_hdr 则初始化一份配置表 category = CATEGORY_RC_HDR; oem_debug_print("============= resource counter:%d =============\n", oem_tool.rc_cnt); // 一个 iot_board_info_v1_t 结构体即可包含所有的硬件配置 void *temp = malloc(sizeof(iot_board_info_v1_t)); if (temp == NULL) { die("not enough memory"); } memset(temp, 0xff, sizeof(iot_board_info_v1_t)); oem_tool.rc_list[oem_tool.rc_cnt] = (iot_board_info_v1_t *)temp; oem_tool.rc.rc_ptr = oem_tool.rc_list[oem_tool.rc_cnt]; oem_tool.rc.device_last = 0; oem_tool.rc.pin_idx = 0; oem_tool.rc.core_last = 0; oem_tool.rc_cnt++; } else if (!strcmp(start, "gpio")) { category = CATEGORY_GPIO; } else if(!strcmp(start, "uart")) { category = CATEGORY_UART; } else if(!strcmp(start, "pwm")) { category = CATEGORY_PWM; } else if(!strcmp(start, "adc")) { category = CATEGORY_ADC; } else if(!strcmp(start, "ledc")) { category = CATEGORY_LEDC; } else if(!strcmp(start, "spi")) { category = CATEGORY_SPI; } else if(!strcmp(start, "i2c")) { category = CATEGORY_I2C; } else if(!strcmp(start, "spinlock")) { category = CATEGORY_SPINLOCK; } else if(!strcmp(start, "dma")) { category = CATEGORY_DMA; } else if(!strcmp(start, "gptimer")) { category = CATEGORY_GPTIMER; } else if(!strcmp(start, "mailbox")) { category = CATEGORY_MAILBOX; } else if(!strcmp(start, "wdg")) { category = CATEGORY_WDG; } else if(!strcmp(start, "zc")) { category = CATEGORY_ZC; } else if(!strcmp(start, "pa")) { category = CATEGORY_PA; } else { oem_debug_print("get category info fail, buf:%s\n", buf); return category; } oem_debug_print(" category info, buf:%s, result:%s\n", start, g_category_string[category]); return category; } // 把配置写入 iot_board_info_v1_t 结构体中 // category 类型, number 外设或内设的编号, core 使用的核心, purpose 用途 uint8_t set_peripheral_allot(uint8_t category, uint8_t number, uint8_t core, uint8_t purpose) { switch (category) { case CATEGORY_GPIO: for (uint8_t i = 0; i < IOT_PIN_MAX_NUM_V1; i++) { // 如果找到已配置的编号相同的gpio或者找到一个未配置的gpio,返回其在数组中的index if (oem_tool.rc.rc_ptr->pin[i].gpio == number || oem_tool.rc.rc_ptr->pin[i].gpio == 0xff) { oem_tool.rc.pin_idx = i; break; } if (i == IOT_PIN_MAX_NUM_V1 - 1) { die("not enough structural space, line:%d", oem_tool.line_num); } } oem_debug_print("pin array current index:%d\n", oem_tool.rc.pin_idx); /* gpio index maybe greater than IOT_PIN_MAX_NUM_V1 */ // 配置这个gpio oem_tool.rc.rc_ptr->pin[oem_tool.rc.pin_idx].gpio = number; oem_tool.rc.rc_ptr->pin[oem_tool.rc.pin_idx].core = core; oem_tool.rc.rc_ptr->pin[oem_tool.rc.pin_idx].purpose = purpose; if (oem_tool.rc.rc_ptr->hdr.mode) { /* clear the peripheral signals that may be bound */ oem_tool.rc.rc_ptr->pin[oem_tool.rc.pin_idx].inid = 0xff; oem_tool.rc.rc_ptr->pin[oem_tool.rc.pin_idx].outid = 0xff; oem_tool.rc.rc_ptr->pin[oem_tool.rc.pin_idx].func = 0xff; } break; case CATEGORY_UART: oem_tool.rc.rc_ptr->uart[number].core = core; oem_tool.rc.rc_ptr->uart[number].purpose = purpose; break; case CATEGORY_PWM: oem_tool.rc.rc_ptr->pwm[number].core = core; oem_tool.rc.rc_ptr->pwm[number].purpose = purpose; break; case CATEGORY_ADC: oem_tool.rc.rc_ptr->adc[number].core = core; oem_tool.rc.rc_ptr->adc[number].purpose = purpose; break; case CATEGORY_LEDC: oem_tool.rc.rc_ptr->ledc[number].core = core; oem_tool.rc.rc_ptr->ledc[number].purpose = purpose; break; case CATEGORY_SPI: oem_tool.rc.rc_ptr->spi[number].core = core; oem_tool.rc.rc_ptr->spi[number].purpose = purpose; break; case CATEGORY_I2C: oem_tool.rc.rc_ptr->i2c[number].core = core; oem_tool.rc.rc_ptr->i2c[number].purpose = purpose; break; case CATEGORY_SPINLOCK: oem_tool.rc.rc_ptr->spinlock[number].core = core; oem_tool.rc.rc_ptr->spinlock[number].purpose = purpose; break; case CATEGORY_DMA: oem_tool.rc.rc_ptr->dma[number].core = core; oem_tool.rc.rc_ptr->dma[number].purpose = purpose; break; case CATEGORY_GPTIMER: oem_tool.rc.rc_ptr->gptimer[number].core = core; oem_tool.rc.rc_ptr->gptimer[number].purpose = purpose; break; case CATEGORY_MAILBOX: oem_tool.rc.rc_ptr->mailbox[number].core = core; oem_tool.rc.rc_ptr->mailbox[number].purpose = purpose; break; case CATEGORY_WDG: oem_tool.rc.rc_ptr->wdg[number].core = core; oem_tool.rc.rc_ptr->wdg[number].purpose = purpose; break; default: break; } oem_debug_print(" peripheral allot, category:%s, number:%d, core:%d, " "purpose:%d\n", g_category_string[category], number, core, purpose); return 0; } // 如果外设或内设编号number大于范围 则退出程序 void rc_quantity_boundary_check(uint8_t category, uint8_t number) { uint8_t out_of_bounds = 0; switch (category) { case CATEGORY_GPIO: out_of_bounds = (number >= RC_TOTAL_GPIO); break; case CATEGORY_UART: out_of_bounds = (number >= RC_TOTAL_UART); break; case CATEGORY_PWM: out_of_bounds = (number >= RC_TOTAL_PWM); break; case CATEGORY_ADC: out_of_bounds = (number >= RC_TOTAL_ADC); break; case CATEGORY_LEDC: out_of_bounds = (number >= RC_TOTAL_LEDC); break; case CATEGORY_SPI: out_of_bounds = (number >= RC_TOTAL_SPI); break; case CATEGORY_I2C: out_of_bounds = (number >= RC_TOTAL_I2C); break; case CATEGORY_SPINLOCK: out_of_bounds = (number >= RC_TOTAL_SPINLOCK); break; case CATEGORY_DMA: out_of_bounds = (number >= RC_TOTAL_DMA); break; case CATEGORY_GPTIMER: out_of_bounds = (number >= RC_TOTAL_GPTIMER); break; case CATEGORY_MAILBOX: out_of_bounds = (number >= RC_TOTAL_MAILBOX); break; case CATEGORY_WDG: out_of_bounds = (number >= RC_TOTAL_WDG); break; case CATEGORY_ZC: out_of_bounds = (number >= RC_TOTAL_ZC); break; case CATEGORY_PA: out_of_bounds = (number >= RC_TOTAL_PA); break; } if (out_of_bounds) { die("device number exceeds maximum, device:%s, number:%d\n", g_category_string[category], number); } oem_debug_print("====== %s, number:%d, out:%d\n", g_category_string[category], number, out_of_bounds); } // 设置gpio的参数到 iot_board_info_v1_t 结构体中,str是从配置文件中读取的关键字 // 通过这个函数设置的gpio,func都是0 uint8_t set_gpio_matrix_signal(uint8_t category, uint8_t number, char *str, uint8_t gpio, uint8_t core) { uint8_t sig_type = SIGNAL_MAX; uint8_t inid = 0xff, outid = 0xff; // func好像没用到 都是返回0 uint8_t func = gpio_func_sel(gpio); if (!strcmp(str, "tx")) { if (category == CATEGORY_UART) { sig_type = SIGNAL_UART_TX; } } else if (!strcmp(str, "rx")) { if (category == CATEGORY_UART) { sig_type = SIGNAL_UART_RX; } } else if (!strcmp(str, "rts")) { if (category == CATEGORY_UART) { sig_type = SIGNAL_UART_RTS; } } else if (!strcmp(str, "cts")) { if (category == CATEGORY_UART) { sig_type = SIGNAL_UART_CTS; } } else if (!strcmp(str, "cs")) { if (category == CATEGORY_SPI) { sig_type = SIGNAL_SPI_CS; } } else if (!strcmp(str, "clk")) { if (category == CATEGORY_SPI) { sig_type = SIGNAL_SPI_CLK; } } else if (!strcmp(str, "miso")) { if (category == CATEGORY_SPI) { sig_type = SIGNAL_SPI_MISO; } } else if (!strcmp(str, "mosi")) { if (category == CATEGORY_SPI) { sig_type = SIGNAL_SPI_MOSI; } } else if (!strcmp(str, "sda")) { if (category == CATEGORY_I2C) { sig_type = SIGNAL_I2C_SDA; } } else if (!strcmp(str, "scl")) { if (category == CATEGORY_I2C) { sig_type = SIGNAL_I2C_SCL; } } else if (!strcmp(str, "pwma")) { if (category == CATEGORY_PWM) { sig_type = SIGNAL_PWM_A_OUT; } } else if (!strcmp(str, "pwmb")) { if (category == CATEGORY_PWM) { sig_type = SIGNAL_PWM_B_OUT; } } else if (!strcmp(str, "ledout")) { if (category == CATEGORY_LEDC) { sig_type = SIGNAL_LEDC_OUT; } } else if (starts_with(str, "up_")) { if (category == CATEGORY_ZC) { sig_type = SIGNAL_ZC_UP; number = atoi(&str[iot_strlen("up_")]); rc_quantity_boundary_check(category, number); } } else if (starts_with(str, "down_")) { if (category == CATEGORY_ZC) { sig_type = SIGNAL_ZC_DOWN; number = atoi(&str[iot_strlen("down_")]); rc_quantity_boundary_check(category, number); } } else if (starts_with(str, "tx_en_")) { if (category == CATEGORY_PA) { sig_type = SIGNAL_PA_TX_EN; number = atoi(&str[iot_strlen("tx_en_")]); rc_quantity_boundary_check(category, number); } } else if (starts_with(str, "rx_en_")) { if (category == CATEGORY_PA) { sig_type = SIGNAL_PA_RX_EN; number = atoi(&str[iot_strlen("rx_en_")]); rc_quantity_boundary_check(category, number); } } else if (starts_with(str, "gain_")) { if (category == CATEGORY_PA) { sig_type = SIGNAL_PA_GAIN; number = atoi(&str[iot_strlen("gain_")]); rc_quantity_boundary_check(category, number); } } if (sig_type == SIGNAL_MAX) { die("signal type error, category:%s, signal str:%s\n", g_category_string[category], str); } outid = get_matrix_signal_outid(sig_type, number); inid = get_matrix_signal_inid(sig_type, number); // 找到gpio在结数组中的index for (uint8_t i = 0; i < IOT_PIN_MAX_NUM_V1; i++) { if (oem_tool.rc.rc_ptr->pin[i].gpio == gpio || oem_tool.rc.rc_ptr->pin[i].gpio == 0xff) { oem_tool.rc.pin_idx = i; break; } if (i == IOT_PIN_MAX_NUM_V1 - 1) { die("not enough structural space, line:%d", oem_tool.line_num); } } oem_debug_print("pin array current index:%d\n", oem_tool.rc.pin_idx); /* gpio index maybe greater than IOT_PIN_MAX_NUM_V1 */ oem_tool.rc.rc_ptr->pin[oem_tool.rc.pin_idx].gpio = gpio; oem_tool.rc.rc_ptr->pin[oem_tool.rc.pin_idx].func = func; /* gpio绑定多个信号 */ if (inid != 0xff) { oem_tool.rc.rc_ptr->pin[oem_tool.rc.pin_idx].inid = inid; } if (outid != 0xff) { oem_tool.rc.rc_ptr->pin[oem_tool.rc.pin_idx].outid = outid; } oem_debug_print(" signal matrix info, buf:%s, category:%s, signal:%s, " "number:%d, gpio:%d, core:%d, inid:%d, outid:%d\n", str, g_category_string[category], g_signal_string[sig_type], number, gpio, core, inid, outid); return 0; } // 解析细节,差分模式是把之前的拷贝一份再把改动部分覆盖之前的 uint8_t get_detail_info(char *buf, uint8_t category) { char *str_ptr[3] = {0}; char *split_str = " "; uint8_t is_peripheral_gpio_map = 1; /* split string */ str_ptr[0] = strtok(buf, split_str); str_ptr[1] = strtok(NULL, split_str); str_ptr[2] = strtok(NULL, split_str); /* special category */ if (category == CATEGORY_GENERAL) { if (!strcmp(str_ptr[0], "bid")) { // board_id 可以用于区分模块用途 是sta iic 3ps还是cco // 比subid 更详细 subid用于区分芯片 oemcfg.board_id = atoi(str_ptr[1]); } else if (!strcmp(str_ptr[0], "mid")) { // 0:sta 1:cco 2:iic 3:3ps oemcfg.base_cfg.module_type = atoi(str_ptr[1]); } else if (!strcmp(str_ptr[0], "vid")) { /* vid is text data, two characters */ // 芯片厂家缩写 oemcfg.misc_cfg.vendor_id = htons(*(uint16_t*)str_ptr[1]); } else if (!strcmp(str_ptr[0], "fver")) { // ? oemcfg.board_cfg_ver = atoi(str_ptr[1]); } return 0; } else if (category == CATEGORY_RC_HDR) { if (!strcmp(str_ptr[0], "hw_ver")) { // 硬件识别码 oem_tool.rc.rc_ptr->hdr.hw_version = oem_atoi(str_ptr[1]); } else if (!strcmp(str_ptr[0], "mode")) { oem_tool.rc.rc_ptr->hdr.mode = atoi(str_ptr[1]) ? 1 : 0; #if 0 /* currently, only differential mode is supported */ if ((oem_tool.rc_cnt != 1) && (!oem_tool.rc.rc_ptr->hdr.mode)) { die("not diff mode, line:%d", oem_tool.line_num); } #endif } else if (!strcmp(str_ptr[0], "d_hw_ver")) { uint32_t diff_hw_ver = oem_atoi(str_ptr[1]); oem_tool.rc.rc_ptr->hdr.diff_hw_ver = diff_hw_ver; if (oem_tool.rc.rc_ptr->hdr.mode) { uint8_t i; uint8_t len_hdr = sizeof(iot_oem_rc_hdr_v1_t); // 找到 diff_hw_ver 所在的 iot_board_info_v1_t 结构体 for (i = 0; i < oem_tool.rc_cnt; i++) { if (oem_tool.rc_list[i]->hdr.hw_version == diff_hw_ver) { break; } } if (i == oem_tool.rc_cnt) { die("diff hw version not match, line:%d", oem_tool.line_num); } // 把之前的复制一份 memcpy((uint8_t *)oem_tool.rc.rc_ptr + len_hdr, (uint8_t *)oem_tool.rc_list[i] + len_hdr, sizeof(iot_board_info_v1_t) - len_hdr); } } return 0; } /* peripheral category */ if (isdigit(*str_ptr[0])) { is_peripheral_gpio_map = 0; } if (is_peripheral_gpio_map) { // 通过外设来设置gpio uint8_t gpio = atoi(str_ptr[1]); if (set_gpio_matrix_signal(category, oem_tool.rc.device_last, str_ptr[0], gpio, oem_tool.rc.core_last)) { die("signal info error, line:%d", oem_tool.line_num); } } else { // 配置gpio uint8_t number = atoi(str_ptr[0]); uint8_t core = atoi(str_ptr[1]); uint8_t purpose = atoi(str_ptr[2]); rc_quantity_boundary_check(category, number); set_peripheral_allot(category, number, core, purpose); oem_tool.rc.device_last = number; oem_tool.rc.core_last = core; } return 0; } uint8_t genereate_diff_content(iot_board_info_v1_t *rc, iot_board_info_v1_t *rc_d) { uint16_t i, j, idx_0, idx_1, idx_d; uint8_t len_hdr = sizeof(iot_oem_rc_hdr_v1_t); uint32_t len_rc = sizeof(iot_board_info_v1_t); uint8_t len_diff = sizeof(iot_oem_rc_diff_v1_t); uint8_t *p_rc = (uint8_t *)rc; uint8_t *p_rc_d = (uint8_t *)rc_d; iot_oem_rc_diff_v1_t *diff; /* save header info */ memcpy(&oem_tool.buf.buf[oem_tool.buf.len_total], &rc->hdr, len_hdr); oem_tool.buf.len_total += len_hdr; for (i = len_hdr; i < len_rc; i++) { /* If the interval between two adjacent differential data is less than * 4 bytes, the space used to save the data together is smaller. */ if (p_rc[i] != p_rc_d[i]) { idx_0 = i; idx_1 = idx_0 + 1; //prevents the last byte from being unequal again: for (j = i + 1; j < len_rc; j++) { if (p_rc[j] != p_rc_d[j]) { if (j - i > 4) { //store the two sections separately for (j = i + 1; j < len_rc; j++) { if (p_rc[j] == p_rc_d[j]) { idx_1 = j; break; } } } else { //store the two sections together i = j; goto again; } break; } else { if (j == len_rc - 1) { //the last unequal block for (j = i + 1; j < len_rc; j++) { if (p_rc[j] == p_rc_d[j]) { idx_1 = j; break; } } break; } } } i = idx_1; idx_d = idx_1 - idx_0; diff = (iot_oem_rc_diff_v1_t *)&oem_tool.buf.buf[\ oem_tool.buf.len_total]; oem_tool.buf.len_total += len_diff; diff->offset = idx_0; diff->length = idx_d; memcpy(&oem_tool.buf.buf[oem_tool.buf.len_total], &p_rc[idx_0], idx_d); oem_tool.buf.len_total += idx_d; oem_debug_print("find diff data, offset:%d, length:%d, buf offset:%d\n", diff->offset, diff->length, oem_tool.buf.len_total); oem_debug_print(" curr data: "); for (uint16_t m = 0; m < diff->length; m++) { oem_debug_print("%02x ", p_rc[diff->offset + m]); } oem_debug_print("\n"); oem_debug_print(" diff data: "); for (uint16_t m = 0; m < diff->length; m++) { oem_debug_print("%02x ", p_rc_d[diff->offset + m]); } oem_debug_print("\n"); } } return 0; } uint8_t rc_data_merge() { uint16_t buf_index_last; uint8_t index, diff_index; for (index = 0; index < oem_tool.rc_cnt; index++) { buf_index_last = oem_tool.buf.len_total; if (oem_tool.rc_list[index]->hdr.mode == 0) { if (index != 0) { /* save the complete resource table */ oem_debug_print("save complete rc data\n"); memcpy(&oem_tool.buf.buf[oem_tool.buf.len_total], &oem_tool.rc_list[index]->hdr, sizeof(iot_board_info_v1_t)); oem_tool.buf.len_total += sizeof(iot_board_info_v1_t); } oem_tool.rc_list[index]->hdr.length = sizeof(iot_board_info_v1_t) - sizeof(iot_oem_rc_hdr_v1_t); } else { for (diff_index = 0; diff_index < oem_tool.rc_cnt; diff_index++) { if (oem_tool.rc_list[diff_index]->hdr.hw_version == oem_tool.rc_list[index]->hdr.diff_hw_ver) { break; } } if (diff_index == oem_tool.rc_cnt) { die("diff hw version(0x%08x) not match\n", oem_tool.rc_list[index]->hdr.diff_hw_ver); } /* save the difference data */ oem_debug_print("save difference data\n"); genereate_diff_content(oem_tool.rc_list[index], oem_tool.rc_list[diff_index]); oem_tool.rc_list[index]->hdr.length = oem_tool.buf.len_total - buf_index_last - sizeof(iot_oem_rc_hdr_v1_t); oem_debug_print("genereate diff data succeed, len:%d,(%d - %d)\n", oem_tool.rc_list[index]->hdr.length, oem_tool.buf.len_total, buf_index_last); } /* oem partition size is 4K, including image header(64 bytes) and an * iot_oem_cfg_t structure. the remaining space holds differential data. */ if (oem_tool.buf.len_total > 4096 - sizeof(iot_oem_cfg_t) - 64) { die("diff data length exceeded the limit\n"); } /* fill header information (crc and offset) */ if (oem_tool.rc_list[index + 1] != 0) { oem_tool.rc_list[index]->hdr.have_next = 1; } else { oem_tool.rc_list[index]->hdr.have_next = 0; } oem_tool.rc_list[index]->hdr.crc = \ iot_getcrc32((uint8_t *)&oem_tool.rc_list[index]->hdr + sizeof(uint32_t), sizeof(iot_board_info_v1_t) - sizeof(uint32_t)); /* copy header info again */ memcpy(&oem_tool.buf.buf[buf_index_last], &oem_tool.rc_list[index]->hdr, sizeof(iot_oem_rc_hdr_v1_t)); } /* The first resource is put into the OEM architecture */ memcpy(&oemcfg.board_cfg_v1, oem_tool.rc_list[0], sizeof(iot_board_info_v1_t)); return 0; } void load_database_hw(const char *filename) { FILE *fp; char buf[2048]; category_type_t category; fp = fopen(filename, "r"); if (fp == NULL) { die ("error opening %s: %s", filename, strerror (errno)); } memset(oem_tool.buf.buf, 0xff, sizeof(oem_tool.buf.buf)); while (fgets(buf, sizeof(buf), fp) != NULL) { oem_tool.line_num++; if (is_comments_and_blankline(buf)) { continue; } oem_debug_print("--> line data:%s", buf); chomp_trailing_whitespace(buf); if (!isspace(buf[0])){ category = get_category_info(buf); if (category == CATEGORY_MAX) { die("ini file category data error, lines:%d", oem_tool.line_num); } } else { get_detail_info(buf, category); } } rc_data_merge(); fclose (fp); } void save_database_hw(const char *filename) { FILE *fp; uint8_t *buf = (uint8_t*)&oemcfg; if (filename == NULL) { fp = fopen("oem.bin", "wb"); } else { fp = fopen(filename, "wb"); } //printf("oem len:%d\n", (uint32_t)sizeof(iot_oem_cfg_t)); oemcfg.base_cfg.oem_crc = iot_getcrc8(buf + sizeof(uint8_t), sizeof(iot_oem_cfg_t) - sizeof(uint8_t)); if (fp == NULL) die ("error write oem.bin: %s", strerror(errno)); fwrite(buf, sizeof(iot_oem_cfg_t), 1, fp); if (oem_tool.buf.len_total) { oem_debug_print("find diff data, write to file\n"); fwrite(oem_tool.buf.buf, sizeof(uint8_t), oem_tool.buf.len_total, fp); } fclose(fp); } void oem_resource_info_dump(iot_board_info_v1_t *ptr_rc) { uint8_t i; uint32_t crc; printf("resource info, crc:0x%08x, hw_version:0x%08x, mode:%d, " "diff hw_ver:0x%08x, length:%d, have next:%d\n", ptr_rc->hdr.crc, ptr_rc->hdr.hw_version, ptr_rc->hdr.mode, ptr_rc->hdr.diff_hw_ver, ptr_rc->hdr.length, ptr_rc->hdr.have_next); crc = iot_getcrc32((uint8_t *)&ptr_rc->hdr + sizeof(uint32_t), sizeof(iot_board_info_v1_t) - sizeof(uint32_t)); if (crc != ptr_rc->hdr.crc) { die("crc error, hdr:0x%08x, cal:0x%08x", ptr_rc->hdr.crc, crc); } else { printf("resource crc check pass\n"); } for (i = 0; i < IOT_PIN_MAX_NUM_V1; i++) { if (ptr_rc->pin[i].gpio == 0xff) { continue; } printf("pin info, index:%d, gpio:%d, core:%d, func:%d, inid:%d, outid:%d," " purpose:%d\n", i, ptr_rc->pin[i].gpio, ptr_rc->pin[i].core, ptr_rc->pin[i].func, ptr_rc->pin[i].inid, ptr_rc->pin[i].outid, ptr_rc->pin[i].purpose); } for (i = 0; i < IOT_UART_MAX_NUM_V1; i++) { if (ptr_rc->uart[i].core == 0xff) { continue; } printf("uart info, index:%d, core:%d, purpose:%d\n", i, ptr_rc->uart[i].core, ptr_rc->uart[i].purpose); } for (i = 0; i < IOT_PWM_MAX_NUM_V1; i++) { if (ptr_rc->pwm[i].core == 0xff) { continue; } printf("pwm info, index:%d, core:%d, purpose:%d\n", i, ptr_rc->pwm[i].core, ptr_rc->pwm[i].purpose); } for (i = 0; i < IOT_ADC_MAX_NUM_V1; i++) { if (ptr_rc->adc[i].core == 0xff) { continue; } printf("adc info, index:%d, core:%d, purpose:%d\n", i, ptr_rc->adc[i].core, ptr_rc->adc[i].purpose); } for (i = 0; i < IOT_LEDC_MAX_NUM_V1; i++) { if (ptr_rc->ledc[i].core == 0xff) { continue; } printf("ledc info, index:%d, core:%d, purpose:%d\n", i, ptr_rc->ledc[i].core, ptr_rc->ledc[i].purpose); } for (i = 0; i < IOT_SPI_MAX_NUM_V1; i++) { if (ptr_rc->spi[i].core == 0xff) { continue; } printf("spi info, index:%d, core:%d, purpose:%d\n", i, ptr_rc->spi[i].core, ptr_rc->spi[i].purpose); } for (i = 0; i < IOT_I2C_MAX_NUM_V1; i++) { if (ptr_rc->i2c[i].core == 0xff) { continue; } printf("i2c info, index:%d, core:%d, purpose:%d\n", i, ptr_rc->i2c[i].core, ptr_rc->i2c[i].purpose); } for (i = 0; i < IOT_SPINLOCK_MAX_NUM_V1; i++) { if (ptr_rc->spinlock[i].core == 0xff) { continue; } printf("spinlock info, index:%d, core:%d, purpose:%d\n", i, ptr_rc->spinlock[i].core, ptr_rc->spinlock[i].purpose); } for (i = 0; i < IOT_DMA_MAX_NUM_V1; i++) { if (ptr_rc->dma[i].core == 0xff) { continue; } printf("dma info, index:%d, core:%d, purpose:%d\n", i, ptr_rc->dma[i].core, ptr_rc->dma[i].purpose); } for (i = 0; i < IOT_GPTIMER_MAX_NUM_V1; i++) { if (ptr_rc->gptimer[i].core == 0xff) { continue; } printf("gptimer info, index:%d, core:%d, purpose:%d\n", i, ptr_rc->gptimer[i].core, ptr_rc->gptimer[i].purpose); } for (i = 0; i < IOT_MAILBOX_MAX_NUM_V1; i++) { if (ptr_rc->mailbox[i].core == 0xff) { continue; } printf("mailbox info, index:%d, core:%d, purpose:%d\n", i, ptr_rc->mailbox[i].core, ptr_rc->mailbox[i].purpose); } for (i = 0; i < IOT_WDG_MAX_NUM_V1; i++) { if (ptr_rc->wdg[i].core == 0xff) { continue; } printf("wdg info, index:%d, core:%d, purpose:%d\n", i, ptr_rc->wdg[i].core, ptr_rc->wdg[i].purpose); } printf("\n"); } void oem_bin_file_parse_hw_all() { uint8_t i; uint8_t len_hdr = sizeof(iot_oem_rc_hdr_v1_t); uint8_t diff_buf[sizeof(iot_board_info_v1_t)]; uint8_t diff_idx; uint16_t diff_data_len; uint32_t diff_hw_ver; iot_oem_rc_hdr_v1_t *hdr_ptr; /* get all resource */ oem_tool.rc_list[oem_tool.rc_cnt] = &oemcfg.board_cfg_v1; again: // 如果存在下一个的话,读取下一个 if (oem_tool.rc_list[oem_tool.rc_cnt]->hdr.have_next) { printf("find next rc, offset:%d\n", oem_tool.buf.len_total); oem_tool.rc_cnt++; void *temp = malloc(sizeof(iot_board_info_v1_t)); if (temp == NULL) { die("not enough memory"); } oem_tool.rc_list[oem_tool.rc_cnt] = (iot_board_info_v1_t *)temp; // 读取buf中剩余的空间 hdr_ptr = (iot_oem_rc_hdr_v1_t *)&oem_tool.buf.buf[oem_tool.buf.len_total]; if (hdr_ptr->mode == 0) { printf("full resource table\n"); memcpy(temp, &oem_tool.buf.buf[oem_tool.buf.len_total], sizeof(iot_board_info_v1_t)); oem_tool.buf.len_total += sizeof(iot_board_info_v1_t); goto again; } printf("differential resource table\n"); /* copy header */ memcpy(temp, &oem_tool.buf.buf[oem_tool.buf.len_total], len_hdr); oem_tool.buf.len_total += len_hdr; diff_hw_ver = oem_tool.rc_list[oem_tool.rc_cnt]->hdr.diff_hw_ver; for (diff_idx = 0; diff_idx < oem_tool.rc_cnt; diff_idx++) { if (oem_tool.rc_list[diff_idx]->hdr.hw_version == diff_hw_ver) { break; } } if (diff_idx >= oem_tool.rc_cnt) { die("diff hw version(0x%08x) not match, current rc cnt:%d\n", diff_hw_ver, oem_tool.rc_cnt); } /* copy diff source data */ memcpy((uint8_t *)oem_tool.rc_list[oem_tool.rc_cnt] + len_hdr, (uint8_t *)oem_tool.rc_list[diff_idx] + len_hdr, sizeof(iot_board_info_v1_t) - len_hdr); /* copy diff data */ diff_data_len = oem_tool.rc_list[oem_tool.rc_cnt]->hdr.length; memcpy(diff_buf, &oem_tool.buf.buf[oem_tool.buf.len_total], diff_data_len); oem_tool.buf.len_total += diff_data_len; /* restore differential data */ i = 0; while (i < diff_data_len) { iot_oem_rc_diff_v1_t *diff_temp = (iot_oem_rc_diff_v1_t *)&diff_buf[i]; uint16_t len_temp = diff_temp->length; uint16_t offset_temp = diff_temp->offset; memcpy((uint8_t *)oem_tool.rc_list[oem_tool.rc_cnt] + offset_temp, diff_temp->data, len_temp); i += sizeof(iot_oem_rc_diff_v1_t) + len_temp; } goto again; } printf("total of %d resource table\n", oem_tool.rc_cnt + 1); for (uint8_t cnt = 0; cnt < oem_tool.rc_cnt + 1; cnt++) { iot_board_info_v1_t *ptr_rc = oem_tool.rc_list[cnt]; /* dump board resource info */ printf("============= resource counter:%d =============\n", cnt); oem_resource_info_dump(ptr_rc); } } void oem_bin_file_parse_hw_specific(uint8_t *buf, uint32_t hw_ver) { int i = 0; iot_board_info_v1_t *ptr_rc; iot_oem_rc_hdr_v1_t *ptr_hdr; uint32_t hw_ver_rc, hw_ver_cal; uint8_t cnt_rc = 1; uint16_t offset = 0; uint16_t *offset_array; uint8_t *diff_idx_array; iot_board_info_v1_t rc_info = {0}; uint8_t buf_oem[4096 - sizeof(iot_oem_cfg_t) - 64] = {0}; iot_oem_cfg_t *oem_cfg; printf("parse hw version:0x%08x\n", hw_ver); oem_cfg = (iot_oem_cfg_t *)buf; ptr_rc = &oem_cfg->board_cfg_v1; memcpy(&rc_info, ptr_rc, sizeof(iot_board_info_v1_t)); memcpy(buf_oem, buf + sizeof(iot_oem_cfg_t), sizeof(buf_oem)); hw_ver_cal = hw_ver; ptr_hdr = &ptr_rc->hdr; hw_ver_rc = ptr_hdr->hw_version; /* fund the matching resource table */ hdr_check: if (hw_ver_cal != hw_ver_rc) { if (ptr_hdr->have_next == 0) { die("resource does not match but no other resource\n"); } cnt_rc++; ptr_hdr = (iot_oem_rc_hdr_v1_t *)&buf_oem[offset]; offset += ptr_hdr->length + sizeof(iot_oem_rc_hdr_v1_t); hw_ver_rc = ptr_hdr->hw_version; goto hdr_check; } printf("match resource counter:%d\n", cnt_rc); /* gets information about all matched headers */ if (cnt_rc >= 2) { uint8_t cnt_diff_deep = 0; /* Not differential mode */ if (ptr_hdr->mode == 0) { memcpy(&rc_info, ptr_hdr, sizeof(iot_board_info_v1_t)); goto dump; } /* differential mode */ offset_array = (uint16_t *)malloc(sizeof(uint16_t) * cnt_rc); diff_idx_array = (uint8_t *)malloc(sizeof(uint8_t) * cnt_rc); if (offset_array == NULL || diff_idx_array == NULL) { die("malloc memory failed\n"); } offset = 0; /* get resource header information offset in diff data buffer */ for (i = 1; i < cnt_rc; i++) { //skip the first full resource table offset_array[i] = offset; ptr_hdr = (iot_oem_rc_hdr_v1_t *)&buf_oem[offset]; offset += ptr_hdr->length + sizeof(iot_oem_rc_hdr_v1_t); } /* get the difference mapping table */ for (i = cnt_rc - 1; i > 0;) { uint8_t j; uint32_t hw_ver_diff; ptr_hdr = (iot_oem_rc_hdr_v1_t *)&buf_oem[offset_array[i]]; hw_ver_diff = ptr_hdr->diff_hw_ver; diff_idx_array[cnt_diff_deep] = i; cnt_diff_deep++; for (j = i - 1; j > 0; j--) { ptr_hdr = (iot_oem_rc_hdr_v1_t *)&buf_oem[offset_array[j]]; if (ptr_hdr->hw_version == hw_ver_diff) { i = j; oem_debug_print("find father rc table, index:%d\n", i); if (ptr_hdr->mode == 0) { oem_debug_print("father is full rc table\n"); memcpy(&rc_info, ptr_hdr, sizeof(iot_board_info_v1_t)); j = 0; } break; } } if (j == 0) { oem_debug_print("find full rc table, as root\n"); break; } } printf("get diff deep:%d, array:", cnt_diff_deep); for (i = 0; i < cnt_diff_deep; i++) { printf("%d, ", diff_idx_array[i]); } printf("\n"); /* get diff resource table information */ for (i = cnt_diff_deep - 1; i >= 0; i--) { uint16_t offset_temp; iot_oem_rc_diff_v1_t *ptr_diff; uint8_t diff_idx = diff_idx_array[i]; ptr_hdr = (iot_oem_rc_hdr_v1_t *)&buf_oem[offset_array[diff_idx]]; /* copy header info */ memcpy(&rc_info, ptr_hdr, sizeof(iot_oem_rc_hdr_v1_t)); /* replace diff data */ offset = offset_array[diff_idx] + sizeof(iot_oem_rc_hdr_v1_t); offset_temp = offset; while (offset_temp < offset + ptr_hdr->length) { ptr_diff = (iot_oem_rc_diff_v1_t *)&buf_oem[offset_temp]; memcpy((uint8_t *)&rc_info + ptr_diff->offset, ptr_diff->data, ptr_diff->length); offset_temp += sizeof(iot_oem_rc_diff_v1_t) + ptr_diff->length; } } } dump: printf("============= resource hw version:0x%08x =============\n", hw_ver); oem_resource_info_dump(&rc_info); } void oem_bin_file_parse_hw(const char *filename) { FILE *fp; uint8_t crc; if (filename == NULL) { fp = fopen("oem.bin", "rb"); } else { fp = fopen (filename, "rb"); } if (fp == NULL) { die("open oem bin file(%s) failed, %s", filename, strerror(errno)); } printf("open oem bin file(%s) succeed\n", filename); /* read oem bin file all data */ fread(oem_tool.buf.buf, sizeof(oem_tool.buf.buf), 1, fp); /* not include image header information by default */ memcpy((void*)&oemcfg, oem_tool.buf.buf, sizeof(iot_oem_cfg_t)); oem_tool.buf.len_total += sizeof(iot_oem_cfg_t); crc = iot_getcrc8((uint8_t*)&oemcfg + sizeof(uint8_t), sizeof(iot_oem_cfg_t) - sizeof(uint8_t)); if (crc != oemcfg.base_cfg.oem_crc) { die("oem bin file crc check error, cal:0x%x, file:0x%x", crc, oemcfg.base_cfg.oem_crc); } /* general information */ printf("board id:%d\n", oemcfg.board_id); printf("module type:%d\n", oemcfg.base_cfg.module_type); /* [TODO]: vendor id need byte order conversion and limited two characters */ printf("vendor id:%s\n", (char*)&oemcfg.misc_cfg.vendor_id); printf("resource version:%d\n", oemcfg.board_cfg_ver); oem_bin_file_parse_hw_all(); oem_bin_file_parse_hw_specific(oem_tool.buf.buf, 0x2); fclose(fp); }