Files
kunlun/mfgtool/oem_tool/hw3/oem_tool_hw.c

1570 lines
48 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stddef.h>
#include <arpa/inet.h>
#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是从配置文件中读取的关键字
// 通过这个函数设置的gpiofunc都是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_tool.buf中存储的是差分后的配置信息 每个差分都是原配置的一个副本修改差异值
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);
// 计算 iot_board_info_v1_t 结构体除crc字段其他部分的crc32
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);
}
// 读取bin文件并解析
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 */
// 读取4k个字节的oem数据
fread(oem_tool.buf.buf, sizeof(oem_tool.buf.buf), 1, fp);
/* not include image header information by default */
// 把第一个配置信息复制到oemcfg结构体
memcpy((void*)&oemcfg, oem_tool.buf.buf, sizeof(iot_oem_cfg_t));
// 修改当前指针为 iot_oem_cfg_t 结构体的长度
oem_tool.buf.len_total += sizeof(iot_oem_cfg_t);
// 计算 iot_oem_cfg_t 结构体的crc8 此结构体的第一个字节为crc值
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);
}