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;
 | |
| }
 |