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

1621 lines
50 KiB
C
Raw Normal View History

2024-09-28 14:24:04 +08:00
#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"
2024-09-28 14:24:04 +08:00
#include "oem_tool_hw.h"
#include "iot_oem_struct_v1.h"
2024-09-28 14:24:04 +08:00
#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
#define OEM_FILE_MAX_SIZE (3000)
#define OEM_INFO_MAX_SIZE (8192)
2024-09-28 14:24:04 +08:00
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 {
2024-10-30 14:38:11 +08:00
uint8_t buf[OEM_INFO_MAX_SIZE];
2024-09-28 14:24:04 +08:00
uint16_t len_total;
uint16_t len_cut;
uint16_t last_offset;
uint16_t cut_flag;
2024-09-28 14:24:04 +08:00
} 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外设或内设的编号
2024-09-28 14:24:04 +08:00
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外设或内设的编号
2024-09-28 14:24:04 +08:00
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
2024-09-28 14:24:04 +08:00
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
2024-09-28 14:24:04 +08:00
uint8_t get_category_info(char *buf)
{
// 以 空格 分割字符串
2024-09-28 14:24:04 +08:00
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 则初始化一份配置表
2024-09-28 14:24:04 +08:00
category = CATEGORY_RC_HDR;
oem_debug_print("============= resource counter:%d =============\n",
oem_tool.rc_cnt);
// 一个 iot_board_info_v1_t 结构体即可包含所有的硬件配置
2024-09-28 14:24:04 +08:00
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 用途
2024-09-28 14:24:04 +08:00
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
2024-09-28 14:24:04 +08:00
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
2024-09-28 14:24:04 +08:00
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大于范围 则退出程序
2024-09-28 14:24:04 +08:00
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
2024-09-28 14:24:04 +08:00
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
2024-09-28 14:24:04 +08:00
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
2024-09-28 14:24:04 +08:00
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;
}
// 解析细节,差分模式是把之前的拷贝一份再把改动部分覆盖之前的
2024-09-28 14:24:04 +08:00
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用于区分芯片
2024-09-28 14:24:04 +08:00
oemcfg.board_id = atoi(str_ptr[1]);
} else if (!strcmp(str_ptr[0], "mid")) {
// 0:sta 1:cco 2:iic 3:3ps
2024-09-28 14:24:04 +08:00
oemcfg.base_cfg.module_type = atoi(str_ptr[1]);
} else if (!strcmp(str_ptr[0], "vid")) {
/* vid is text data, two characters */
// 芯片厂家缩写
2024-09-28 14:24:04 +08:00
oemcfg.misc_cfg.vendor_id = htons(*(uint16_t*)str_ptr[1]);
} else if (!strcmp(str_ptr[0], "fver")) {
// ?
2024-09-28 14:24:04 +08:00
oemcfg.board_cfg_ver = atoi(str_ptr[1]);
}
return 0;
} else if (category == CATEGORY_RC_HDR) {
if (!strcmp(str_ptr[0], "hw_ver")) {
// 硬件识别码
2024-09-28 14:24:04 +08:00
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 结构体
2024-09-28 14:24:04 +08:00
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);
}
// 把之前的复制一份
2024-09-28 14:24:04 +08:00
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
2024-09-28 14:24:04 +08:00
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
2024-09-28 14:24:04 +08:00
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;
}
2024-09-28 14:24:04 +08:00
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;
}
// 重新装填 rc_hdr
// index rc 结构体 的序号,have_next 是否有下一个buf_index 存放hdr的buf_index
static int rc_reflush_rc_hdr(int index, int have_next, int buf_index)
{
/* fill header information (crc and offset) */
oem_tool.rc_list[index]->hdr.have_next = have_next;
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 */
// 把修改过参数的rc_hdr 重新复制到buff中
memcpy(&oem_tool.buf.buf[buf_index],
&oem_tool.rc_list[index]->hdr, sizeof(iot_oem_rc_hdr_v1_t));
return 0;
}
2024-09-28 14:24:04 +08:00
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 */
// 不是差分模式 全部复制过来
2024-09-28 14:24:04 +08:00
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 8K, including image header(64 bytes) and an
2024-09-28 14:24:04 +08:00
* iot_oem_cfg_t structure. the remaining space holds differential data.
*/
if (oem_tool.buf.len_total > OEM_INFO_MAX_SIZE - sizeof(iot_oem_cfg_t) - 64) {
2024-09-28 14:24:04 +08:00
die("diff data length exceeded the limit\n");
}
/* fill header information (crc and offset) */
if (oem_tool.rc_list[index + 1] != 0) {
rc_reflush_rc_hdr(index, 1, buf_index_last);
2024-09-28 14:24:04 +08:00
} else {
rc_reflush_rc_hdr(index, 0, buf_index_last);
2024-09-28 14:24:04 +08:00
}
if (oem_tool.buf.len_total + sizeof(iot_oem_cfg_t) <= OEM_FILE_MAX_SIZE) {
// 更新截断位置
oem_tool.buf.len_cut = oem_tool.buf.len_total;
} else {
// 如果本次的数据导致尺寸超出了,则上一个数据需要修改 have_next = 0
if (oem_tool.buf.cut_flag == 0) {
rc_reflush_rc_hdr(index - 1, 0, oem_tool.buf.last_offset);
oem_tool.buf.cut_flag = 1;
}
}
oem_tool.buf.last_offset = buf_index_last;
2024-09-28 14:24:04 +08:00
}
/* 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);
}
static void save_ext_data_hw(const char *filename,const uint8_t *buff,uint32_t size)
{
FILE *fp;
fp = fopen(filename, "wb");
fwrite(buff, size, 1, fp);
fclose(fp);
}
2024-09-28 14:24:04 +08:00
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_cut) {
// oem_tool.buf中存储的是差分后的配置信息 每个差分都是原配置的一个副本修改差异值
oem_debug_print("find extra data, size=%d\n",oem_tool.buf.len_cut);
fwrite(oem_tool.buf.buf, sizeof(uint8_t), oem_tool.buf.len_cut, fp);
if (oem_tool.buf.len_total>oem_tool.buf.len_cut){
printf("have cut oem info, cut size=%ld, total size=%ld\n",
oem_tool.buf.len_cut+sizeof(iot_oem_cfg_t),oem_tool.buf.len_total+sizeof(iot_oem_cfg_t));
save_ext_data_hw("oem_ext.bin",&oem_tool.buf.buf[oem_tool.buf.len_cut],
oem_tool.buf.len_total-oem_tool.buf.len_cut);
}
2024-09-28 14:24:04 +08:00
}
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
2024-09-28 14:24:04 +08:00
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:
// 如果存在下一个的话,读取下一个
2024-09-28 14:24:04 +08:00
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中剩余的空间
2024-09-28 14:24:04 +08:00
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 */
// 这里可以支持多个差异二进制片段
2024-09-28 14:24:04 +08:00
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文件并解析
2024-09-28 14:24:04 +08:00
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数据
2024-09-28 14:24:04 +08:00
fread(oem_tool.buf.buf, sizeof(oem_tool.buf.buf), 1, fp);
/* not include image header information by default */
// 把第一个配置信息复制到oemcfg结构体
2024-09-28 14:24:04 +08:00
memcpy((void*)&oemcfg, oem_tool.buf.buf, sizeof(iot_oem_cfg_t));
// 修改当前指针为 iot_oem_cfg_t 结构体的长度
2024-09-28 14:24:04 +08:00
oem_tool.buf.len_total += sizeof(iot_oem_cfg_t);
// 计算 iot_oem_cfg_t 结构体的crc8 此结构体的第一个字节为crc值
2024-09-28 14:24:04 +08:00
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);
}