1621 lines
50 KiB
C
1621 lines
50 KiB
C
#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"
|
||
#include "iot_oem_struct_v1.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
|
||
|
||
#define OEM_FILE_MAX_SIZE (3000)
|
||
#define OEM_INFO_MAX_SIZE (8192)
|
||
|
||
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[OEM_INFO_MAX_SIZE];
|
||
uint16_t len_total;
|
||
uint16_t len_cut;
|
||
uint16_t last_offset;
|
||
uint16_t cut_flag;
|
||
} 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;
|
||
}
|
||
|
||
|
||
|
||
// 重新装填 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;
|
||
}
|
||
|
||
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 8K, including image header(64 bytes) and an
|
||
* 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) {
|
||
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);
|
||
} else {
|
||
rc_reflush_rc_hdr(index, 0, buf_index_last);
|
||
}
|
||
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;
|
||
}
|
||
|
||
/* 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);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
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);
|
||
}
|
||
|