sdk-hwV1.3/lichee/xr806/appos/src/efpg/efpg.c

284 lines
8.6 KiB
C
Executable File

/*
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CONFIG_BOOTLOADER
#include "efpg_i.h"
#include "efpg_debug.h"
#include "efpg/efpg.h"
#include "driver/chip/hal_uart.h"
#include "driver/chip/hal_efuse.h"
static void efpg_task(void *arg)
{
uint8_t *buf;
int32_t recv_len;
efpg_priv_t *efpg = arg;
efpg_state_t state = EFPG_STATE_NUM;
if (efpg->start_cb) {
efpg->start_cb();
}
efpg_reset:
efpg->is_cmd = 1;
efpg->ext_cmd = EFPG_NORMAL_CMD;
efpg->expt_len = EFPG_CMD_FRAME_LEN;
efpg->recv_len = 0;
efpg->op = EFPG_OP_NUM;
efpg->field = EFPG_FIELD_NUM;
efpg->start_bit_addr = 0;
efpg->bit_length = 0;
while (1) {
efpg_continue:
if (efpg->is_cmd) {
if (efpg->ext_cmd == EFPG_EXT_CMD) {
buf = efpg->ext_cmd_frame;
} else {
buf = efpg->cmd_frame;
}
} else {
buf = efpg->data_frame;
}
recv_len = 0;
while (recv_len == 0) {
recv_len = HAL_UART_Receive_IT(efpg->uart_id, buf, efpg->expt_len, EFPG_RECV_TIMEOUT_MS);
}
if (recv_len == -1) {
EFPG_ERR("UART receive failed\n");
goto efpg_stop;
}
if ((uint16_t)recv_len != efpg->expt_len) {
EFPG_WARN("%s(), %d, recv len %d, expt len %d\n",
__func__, __LINE__, recv_len, efpg->expt_len);
goto efpg_reset;
}
efpg->recv_len = (uint16_t)recv_len;
if (efpg->is_cmd) {
state = efpg_cmd_frame_process(efpg);
} else {
state = efpg_data_frame_process(efpg);
}
switch (state) {
case EFPG_STATE_CONTINUE:
goto efpg_continue;
case EFPG_STATE_RESET:
goto efpg_reset;
case EFPG_STATE_STOP:
goto efpg_stop;
default:
EFPG_ERR("invalid state %d\n", state);
goto efpg_stop;
}
}
efpg_stop:
if (efpg->stop_cb) {
efpg->stop_cb();
}
if (efpg) {
efpg_free(efpg);
}
OS_ThreadDelete(NULL);
}
/**
* @brief Start communicating with the OEM programming tool
* @param[in] key Pointer to the key
* @param[in] key_len The length of the key
* @param[in] uart_id ID of the specified UART used to communication
* @param[in] start_cb Function called when start communication
* @param[in] stop_cb Function called when stop communication
* @return 0 on success, -1 on failure
*
* @note Just for OEM programming tool to entry eFuse programming mode.
*/
int efpg_start(uint8_t *key, uint8_t key_len, UART_ID uart_id, efpg_cb_t start_cb, efpg_cb_t stop_cb)
{
efpg_priv_t *efpg;
OS_Thread_t thread;
if ((key == NULL) || (key_len == 0) || (key_len > EFPG_KEY_LEN_MAX) || (uart_id >= UART_NUM)) {
EFPG_ERR("key %p, key len %d, uart id %d\n", key, key_len, uart_id);
return -1;
}
efpg = efpg_malloc(sizeof(efpg_priv_t));
if (efpg == NULL) {
EFPG_ERR("malloc failed\n");
return -1;
}
efpg->uart_id = uart_id;
efpg->start_cb = start_cb;
efpg->stop_cb = stop_cb;
efpg_memcpy(efpg->key, key, key_len);
efpg->key_len = key_len;
OS_ThreadSetInvalid(&thread);
if (OS_ThreadCreate(&thread,
"efpg",
efpg_task,
efpg,
OS_THREAD_PRIO_CONSOLE,
EFPG_THREAD_STACK_SIZE) != OS_OK) {
EFPG_ERR("create efpg task failed\n");
return -1;
}
return 0;
}
/**
* @brief Read data from the specified field in eFuse
* @param[in] field The filed in eFuse
* @param[in] data Pointer to the data buffer
* @return 0 on success, -1 on failure
*
* @note The rest bit(s) in data will be cleared to 0.
*/
int efpg_read(efpg_field_t field, uint8_t *data)
{
if (data == NULL) {
EFPG_ERR("data %p\n", data);
return -1;
}
uint16_t ack = efpg_read_field(field, data, 0, 0);
if (ack != EFPG_ACK_OK) {
EFPG_WARN("%s(), field %d, ack %d\n", __func__, field, ack);
return -1;
}
return 0;
}
/**
* @brief Read data from user area (OEM reserved field) on EFUSE
* @param[in] start The first bit to be read in user area (OEM reserved field)
* @param[in] num Number of bits to be read
* @param[in] data Pointer to the data buffer
* @return 0 on success, -1 on failure
*
* @note The rest bit(s) in data will be cleared to be 0.
*/
int efpg_read_ua(uint32_t start, uint32_t num, uint8_t *data)
{
if (data == NULL) {
EFPG_ERR("data %p\n", data);
return -1;
}
if (efpg_read_field(EFPG_FIELD_UA, data, start, num) != EFPG_ACK_OK) {
return -1;
}
return 0;
}
/**
* @brief Read data from all areas on EFUSE
* @param[in] start The first bit to be read on EFUSE
* @param[in] num Number of bits to be read
* @param[in] data Pointer to the data buffer
* @return 0 on success, -1 on failure
*
* @note The rest bit(s) in data will be cleared to be 0.
*/
int efpg_read_all(uint32_t start, uint32_t num, uint8_t *data)
{
if (data == NULL) {
EFPG_ERR("data %p\n", data);
return -1;
}
if (efpg_read_field(EFPG_FIELD_ALL, data, start, num) != EFPG_ACK_OK) {
return -1;
}
return 0;
}
#if (CONFIG_CHIP_ARCH_VER == 3)
/**
* @brief Print EFUSE layout
*/
void efpg_layout(void)
{
printf("--------------- EFUSE layout ---------------\n");
printf("********* HOSC type *********\n");
printf("HOSC_TYPE_START:%d bit\n", EFPG_HOSC_TYPE_START);
printf("HOSC_TYPE_TOTAL_LEN:%d bit\n", EFPG_HOSC_TYPE_NUM);
printf("********* SECURE BOOT *********\n");
printf("SECURE_BOOT_START:%d bit\n", EFPG_BOOT_FLAG_START);
printf("SECURE_BOOT_TOTAL_LEN:%d bit\n", EFPG_MAC_ADDRESS_FLAG_START - EFPG_BOOT_FLAG_START);
printf("********* MAC address *********\n");
printf("MAC_ADDR_START:%d bit\n", EFPG_MAC_ADDRESS_FLAG_START);
printf("MAC_ADDR_NUM:%d\n", EFPG_MAC_ADDRESS_FLAG_NUM);
printf("MAC_ADDR_TOTAL_LEN:%d bit\n", (EFPG_MAC_ADDRESS_FLAG_NUM + EFPG_MAC_ADDRESS_NUM));
printf("********* WLAN MAC address *********\n");
printf("MAC_WLAN_ADDR_START:%d bit\n", EFPG_MAC_WLAN_ADDR_FLAG_START);
printf("MAC_WLAN_ADDR_NUM:%d\n", EFPG_MAC_WLAN_ADDR_NUM);
printf("MAC_WLAN_ADDR_TOTAL_LEN:%d bit\n", EFPG_MAC_WLAN_ADDR_NUM * (1 + EFPG_MAC_WLAN_ADDR_LEN));
printf("********* BT MAC address *********\n");
printf("MAC_BT_ADDR_START:%d bit\n", EFPG_MAC_BT_ADDR_FLAG_START);
printf("MAC_BT_ADDR_NUM:%d\n", EFPG_MAC_BT_ADDR_NUM);
printf("MAC_BT_ADDR_TOTAL_LEN:%d bit\n", EFPG_MAC_BT_ADDR_NUM * (1 + EFPG_MAC_BT_ADDR_LEN));
printf("********* DCXO TRIM *********\n");
printf("DCXO_TRIM_START:%d bit\n", EFPG_DCXO_TRIM_FLAG_START);
printf("DCXO_TRIM_NUM:%d\n", EFPG_DCXO_TRIM_NUM);
printf("DCXO_TRIM_TOTAL_LEN:%d bit\n", EFPG_DCXO_TRIM_NUM * (1 + EFPG_DCXO_TRIM_LEN));
printf("********* POUT CAL *********\n");
printf("POUT_CAL_START:%d bit\n", EFPG_POUT_CAL_FLAG_START);
printf("POUT_CAL_NUM:%d\n", EFPG_POUT_CAL_NUM);
printf("POUT_CAL_TOTAL_LEN:%d bit\n", EFPG_POUT_CAL_NUM * (1 + EFPG_POUT_CAL_LEN));
printf("********* BT POUT CAL *********\n");
printf("POUT_BT_CAL_START:%d bit\n", EFPG_BT_POUT_CAL_FLAG_START);
printf("POUT_BT_CAL_NUM:%d\n", EFPG_BT_POUT_CAL_NUM);
printf("POUT_BT_CAL_TOTAL_LEN:%d bit\n", EFPG_BT_POUT_CAL_NUM * (1 + EFPG_BT_POUT_CAL_LEN));
printf("********* USER area *********\n");
printf("USER_AREA_START:%d bit\n", EFPG_USER_AREA_START);
printf("USER_AREA_LEN:%d bit\n", EFPG_USER_AREA_NUM);
printf("-----------------------------------------\n");
}
void efpg_update_all(void)
{
HAL_EFUSE_UpdateAll();
}
#endif
#endif /* CONFIG_BOOTLOADER */