407 lines
10 KiB
C
407 lines
10 KiB
C
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
****************************************************************************/
|
|
#include "chip_reg_base.h"
|
|
#include "hw_reg_api.h"
|
|
#include "iot_bitops.h"
|
|
#include "flash.h"
|
|
#include "os_lock.h"
|
|
#include "iot_config.h"
|
|
#include "ahb_rf.h"
|
|
#include "ahb.h"
|
|
#include "clk.h"
|
|
#include "sfc.h"
|
|
#include "sec_glb.h"
|
|
#include "dbg_io.h"
|
|
#include "iot_io.h"
|
|
#include "iot_errno_api.h"
|
|
|
|
#include "gp_timer.h"
|
|
#include "flash.h"
|
|
#include "os_mem_api.h"
|
|
#include "iot_crc.h"
|
|
#include "iot_cal_data.h"
|
|
#include "uart.h"
|
|
#include "iot_string.h"
|
|
|
|
#define PPM_VERSION "V1.0"
|
|
extern struct uart_ctrl uart_e_ctrl;
|
|
iot_cal_data_cfg_t g_calc_data;
|
|
|
|
uint8_t gbuf[256];
|
|
|
|
int ppm_tool_atoi(uint8_t * str)
|
|
{
|
|
int value = 0;
|
|
int sign = 1;
|
|
int radix;
|
|
|
|
|
|
if(*str == '-')
|
|
{
|
|
sign = -1;
|
|
str++;
|
|
}
|
|
if(*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
|
|
{
|
|
radix = 16;
|
|
str += 2;
|
|
} else {
|
|
radix = 10;
|
|
}
|
|
while(*str)
|
|
{
|
|
if(radix == 16)
|
|
{
|
|
if(*str >= '0' && *str <= '9')
|
|
{
|
|
value = value * radix + *str - '0';
|
|
}
|
|
else if(*str >= 'A' && *str <= 'F')
|
|
{
|
|
value = value * radix + *str - 'A' + 10;
|
|
}
|
|
else if(*str >= 'a' && *str <= 'f')
|
|
{
|
|
value = value * radix + *str - 'a' + 10;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else if(radix == 8)
|
|
{
|
|
if(*str >= '0' && *str <= '7')
|
|
{
|
|
value = value * radix + *str - '0';
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(*str >= '0' && *str <= '9')
|
|
{
|
|
value = value * radix + *str - '0';
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
str ++;
|
|
}
|
|
return sign*value;
|
|
}
|
|
|
|
/*
|
|
* String = "#PPM=-120,ptver=0x00880000,crc8=0x65#"
|
|
* crc8 protect "#PPM=-120,ptver=0x88880000,"
|
|
*/
|
|
const char input_str[] = "#PPM=+128,ptver=0x56789012,crc8=0xc0#";
|
|
uint32_t ppm_tool_uart_param_get(uint32_t *p_out_ptver, int8_t *p_out_ppm, uint32_t tm_ms)
|
|
{
|
|
uint8_t *p_w_pos = gbuf, *p_ppm, *p_ptver, *p_crc, buf[12], crc;
|
|
int8_t ppm;
|
|
uint32_t tm_start, tm_delta, ch, ptver;
|
|
|
|
tm_start = gp_timer_get_current_val(0);
|
|
tm_delta = tm_ms * 1000;
|
|
os_mem_set(gbuf, 0, sizeof(gbuf));
|
|
|
|
do {
|
|
while (uart_e_ctrl.rx_fifo_cnt(0) > 0) {
|
|
ch = uart_e_ctrl.getc(0);
|
|
*p_w_pos++ = ch & 0xFF;
|
|
}
|
|
|
|
if (sizeof(input_str) - 1 <= (p_w_pos - gbuf)) {
|
|
break;
|
|
}
|
|
} while (tm_delta > gp_timer_get_current_val(0) - tm_start);
|
|
|
|
p_w_pos = '\0';
|
|
|
|
/* Find PPM */
|
|
if (NULL == (p_ppm = (uint8_t *)iot_strstr ((char *)gbuf, "#PPM"))
|
|
|| ',' != p_ppm[9]) {
|
|
return ERR_FAIL;
|
|
}
|
|
os_mem_set(buf, 0x0, sizeof(buf));
|
|
os_mem_cpy(buf, &p_ppm[6], 3);
|
|
ppm = ppm_tool_atoi(buf);
|
|
ppm = ('-' == p_ppm[5]) ? (0 - ppm) : ppm;
|
|
|
|
/* Find ptver */
|
|
if (NULL == (p_ptver = (uint8_t *)iot_strstr ((char *)gbuf, "ptver"))
|
|
|| ',' != p_ptver[16]) {
|
|
return ERR_FAIL;
|
|
}
|
|
os_mem_set(buf, 0x0, sizeof(buf));
|
|
os_mem_cpy(buf, &p_ptver[6], 10);
|
|
ptver = (uint32_t)ppm_tool_atoi(buf);
|
|
|
|
/* Find crc8 */
|
|
if (NULL == (p_crc = (uint8_t *)iot_strstr ((char *)gbuf, "crc8"))
|
|
|| '#' != p_crc[9]) {
|
|
return ERR_FAIL;
|
|
}
|
|
os_mem_set(buf, 0x0, sizeof(buf));
|
|
os_mem_cpy(buf, &p_crc[5], 4);
|
|
crc = (uint8_t)ppm_tool_atoi(buf);
|
|
|
|
if (crc != iot_getcrc8(p_ppm, p_crc - p_ppm)) {
|
|
iot_printf("crc 0x%x != 0x%x\n", crc, iot_getcrc8(p_ppm, p_crc - p_ppm));
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
*p_out_ptver = ptver;
|
|
*p_out_ppm = 0 - ppm;
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
void ppm_tool_uart_rx_clear(void)
|
|
{
|
|
uint32_t cnt = 256;
|
|
|
|
do {
|
|
(void)uart_e_ctrl.getc(0);
|
|
} while (uart_e_ctrl.rx_fifo_cnt(0) > 0 && cnt-- > 0);
|
|
|
|
return;
|
|
}
|
|
|
|
uint32_t ppm_tool_uart_param_put(uint32_t ptver, int8_t ppm)
|
|
{
|
|
uint32_t s_len, fin_ppm;
|
|
uint8_t crc;
|
|
|
|
/* Not need to check ppm && version. */
|
|
if (0 >= ppm) {
|
|
fin_ppm = 0 - ppm;
|
|
/* Change the SIGN of ppm to uart. */
|
|
s_len = iot_sprintf((char *)gbuf, "#PPM=+%03d,ptver=0x%08x,", fin_ppm, ptver);
|
|
} else {
|
|
fin_ppm = ppm;
|
|
/* Change the SIGN of ppm to uart. */
|
|
s_len = iot_sprintf((char *)gbuf, "#PPM=-%03d,ptver=0x%08x,", fin_ppm, ptver);
|
|
}
|
|
|
|
crc = iot_getcrc8(gbuf, s_len);
|
|
|
|
iot_sprintf((char *)(gbuf + s_len), "crc8=0x%02x#", crc);
|
|
|
|
iot_printf("%s", gbuf);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint32_t ppm_tool_uart_errcode_put(uint32_t err_code)
|
|
{
|
|
iot_printf("#DONE=0x%08x#", err_code);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint32_t ppm_tool_flash_part_offset_get (void)
|
|
{
|
|
uint32_t f_size, p_offset;
|
|
f_size = flash_get_dev_size();
|
|
|
|
switch (f_size) {
|
|
case FLASH_SIZE_2MB:
|
|
/* 2m cal part start addr 0x001FF000 */
|
|
p_offset = 0x001FF000;
|
|
break;
|
|
default:
|
|
p_offset = 0x001FF000;
|
|
break;
|
|
}
|
|
|
|
return p_offset;
|
|
}
|
|
|
|
uint32_t ppm_tool_flash_data_read (iot_cal_data_cfg_t *p_cal)
|
|
{
|
|
uint32_t offset = ppm_tool_flash_part_offset_get();
|
|
|
|
if (HAL_OK != flash_read(p_cal, offset, sizeof(*p_cal), MOD_SFC_READ_QUAD_IO_FAST)) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint32_t ppm_tool_flash_data_write (iot_cal_data_cfg_t *p_cal)
|
|
{
|
|
uint32_t offset = ppm_tool_flash_part_offset_get();
|
|
|
|
flash_write_param_t w_param = {
|
|
.read_mode = MOD_SFC_READ_QUAD_IO_FAST,
|
|
.write_mode = MOD_SFC_PROG_QUAD,
|
|
.is_erase = 1,
|
|
.sw_mode = MOD_SW_MODE_DIS,
|
|
.erase_mode = MODE_ERASE_SECTOR
|
|
};
|
|
|
|
if (HAL_OK != flash_write(p_cal, offset, sizeof(*p_cal), &w_param)) {
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
void gp_timer_delay()
|
|
{
|
|
uint32_t timer_val = 0;
|
|
gp_timer_init();
|
|
gp_timer_set(0, -1, 0);
|
|
gp_timer_start(0);
|
|
while(1) {
|
|
timer_val = gp_timer_get_current_val(0);
|
|
if (timer_val > 100000) break;
|
|
}
|
|
}
|
|
|
|
void ppm_tool_hw_init (void)
|
|
{
|
|
|
|
gp_timer_delay();
|
|
|
|
dbg_uart_init();
|
|
|
|
flash_init(1);
|
|
|
|
clk_core_freq_set(CPU_FREQ_150M);
|
|
/* The basic frequency of SFC is 75m, 0 represents no frequency division */
|
|
sfc_clk_div_set(1);
|
|
|
|
return;
|
|
}
|
|
|
|
void ppm_tool_dump_version(void)
|
|
{
|
|
iot_printf("\r\n#PPM tool ver:%s %s %s#\n", PPM_VERSION, __DATE__, __TIME__);
|
|
}
|
|
|
|
void ppm_tool (void)
|
|
{
|
|
uint8_t crc8;
|
|
int8_t param_ppm = 0;
|
|
uint32_t pt_ver = 0, param_pt_ver = 0, err_code = 0;
|
|
|
|
/* Read calibration data from flash. */
|
|
if (ERR_OK != ppm_tool_flash_data_read(&g_calc_data)) {
|
|
/* Read flash failed. */
|
|
err_code = 1;
|
|
goto error_out;
|
|
}
|
|
|
|
ppm_tool_uart_rx_clear();
|
|
|
|
/* Write org ppm & pt_ver to uart. */
|
|
ppm_tool_uart_param_put(g_calc_data.halphy_cfg.pt_fw_ver, g_calc_data.halphy_cfg.ppm);
|
|
|
|
/* Read new ppm & pt_ver from uart */
|
|
if (ERR_OK != ppm_tool_uart_param_get(¶m_pt_ver, ¶m_ppm, 10000)) {
|
|
err_code = 2;
|
|
goto error_out;
|
|
}
|
|
|
|
/* -15 ≤ ppm ≤ 15*/
|
|
if (param_ppm > 15 || param_ppm < -15) {
|
|
err_code = 3;
|
|
goto error_out;
|
|
}
|
|
|
|
pt_ver = g_calc_data.halphy_cfg.pt_fw_ver;
|
|
|
|
/* Check the top structure by crc8, only 'halphy_cfg' section. */
|
|
crc8 = iot_getcrc8((uint8_t *)&g_calc_data.halphy_cfg, sizeof(g_calc_data.halphy_cfg));
|
|
if (g_calc_data.crc == crc8) {
|
|
if (IOT_OEM_PHY_MAGIC_NUM == g_calc_data.halphy_cfg.magic) {
|
|
if (pt_ver && 0xFFFFFFFF != pt_ver) {
|
|
//iot_printf("Exist ptver:0x%08x\n", pt_ver);
|
|
if (pt_ver != param_pt_ver) {
|
|
err_code = 4;
|
|
goto error_out;
|
|
}
|
|
} else {
|
|
g_calc_data.halphy_cfg.pt_fw_ver = param_pt_ver;
|
|
g_calc_data.halphy_cfg.mask |= (1 << IOT_PHY_CFG_MASK_PT_VER);
|
|
}
|
|
|
|
/* pt_ver && halphy_cfg are OK. Just change ppm. */
|
|
g_calc_data.halphy_cfg.ppm = param_ppm;
|
|
g_calc_data.halphy_cfg.mask |= (1 << IOT_PHY_CFG_MASK_PPM);
|
|
} else {
|
|
/* Structure broken, do nothing, return ERROR. */
|
|
err_code = 5;
|
|
goto error_out;
|
|
}
|
|
} else if (0xFF == g_calc_data.crc && 0xFFFFFFFF == g_calc_data.halphy_cfg.magic) {
|
|
/* Top structure is NULL, update the data. */
|
|
g_calc_data.halphy_cfg.magic = IOT_OEM_PHY_MAGIC_NUM;
|
|
g_calc_data.halphy_cfg.pt_fw_ver = param_pt_ver;
|
|
g_calc_data.halphy_cfg.ppm = param_ppm;
|
|
g_calc_data.halphy_cfg.mask = (1 << IOT_PHY_CFG_MASK_PPM) | (1 << IOT_PHY_CFG_MASK_PT_VER);
|
|
/* Init hw version as 0. */
|
|
g_calc_data.halphy_cfg.hw_ver_major = 0;
|
|
g_calc_data.halphy_cfg.hw_ver_minor = 0;
|
|
} else {
|
|
/* Top structuer is broken, return error. */
|
|
err_code = 6;
|
|
goto error_out;
|
|
}
|
|
|
|
/* Write the whole new structure. */
|
|
g_calc_data.crc = iot_getcrc8((uint8_t *)&g_calc_data.halphy_cfg, sizeof(g_calc_data.halphy_cfg));
|
|
if (ERR_OK != ppm_tool_flash_data_write(&g_calc_data)) {
|
|
/* Read flash failed. */
|
|
err_code = 7;
|
|
goto error_out;
|
|
}
|
|
|
|
/* Read back the structure. */
|
|
if (ERR_OK != ppm_tool_flash_data_read(&g_calc_data)) {
|
|
/* Read flash failed. */
|
|
err_code = 8;
|
|
goto error_out;
|
|
}
|
|
|
|
/* Write new ppm & pt_ver to uart. */
|
|
ppm_tool_uart_param_put(g_calc_data.halphy_cfg.pt_fw_ver, g_calc_data.halphy_cfg.ppm);
|
|
|
|
error_out:
|
|
|
|
/* Handle error condition : 1. print error code to uart. */
|
|
ppm_tool_uart_errcode_put(err_code);
|
|
|
|
return;
|
|
}
|
|
|
|
int main(void) {
|
|
ppm_tool_hw_init();
|
|
ppm_tool();
|
|
ppm_tool_dump_version();
|
|
|
|
while(1);
|
|
|
|
return 0;
|
|
}
|