256 lines
8.0 KiB
C
256 lines
8.0 KiB
C
|
/**
|
||
|
*****************************************************************************
|
||
|
* @file cmem7_efuse.c
|
||
|
*
|
||
|
* @brief CMEM7 EFUSE source file
|
||
|
*
|
||
|
*
|
||
|
* @version V1.0
|
||
|
* @date 3. September 2013
|
||
|
*
|
||
|
* @note
|
||
|
*
|
||
|
*****************************************************************************
|
||
|
* @attention
|
||
|
*
|
||
|
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||
|
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||
|
* TIME. AS A RESULT, CAPITAL-MICRO SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
|
||
|
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||
|
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||
|
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||
|
*
|
||
|
* <h2><center>© COPYRIGHT 2013 Capital-micro </center></h2>
|
||
|
*****************************************************************************
|
||
|
*/
|
||
|
|
||
|
#include "cmem7_efuse.h"
|
||
|
|
||
|
static void efuse_SetClock(uint8_t dividor) {
|
||
|
if (dividor <= 2) {
|
||
|
GLOBAL_CTRL->CLK_SEL_1_b.EFUSE_CLK = 0;
|
||
|
} else if (dividor <= 4) {
|
||
|
GLOBAL_CTRL->CLK_SEL_1_b.EFUSE_CLK = 1;
|
||
|
} else if (dividor <= 8) {
|
||
|
GLOBAL_CTRL->CLK_SEL_1_b.EFUSE_CLK = 2;
|
||
|
} else {
|
||
|
GLOBAL_CTRL->CLK_SEL_1_b.EFUSE_CLK = 3;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static uint32_t efuse_GetClock() {
|
||
|
return SYSTEM_CLOCK_FREQ / (1 << (GLOBAL_CTRL->CLK_SEL_1_b.EFUSE_CLK + 1));
|
||
|
}
|
||
|
|
||
|
// static uint8_t efuse_Crc8Bit(uint8_t data, uint8_t crc) {
|
||
|
// uint8_t newCrc;
|
||
|
// uint8_t d[8], c[8], i;
|
||
|
//
|
||
|
// for (i = 0; i < 8; i++) {
|
||
|
// d[i] = (data >> i) & 0x01;
|
||
|
// c[i] = (crc >> i) & 0x01;
|
||
|
// }
|
||
|
//
|
||
|
// newCrc = d[7] ^ d[6] ^ d[0] ^ c[0] ^ c[6] ^ c[7];
|
||
|
// newCrc |= (d[6] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[6]) << 1;
|
||
|
// newCrc |= (d[6] ^ d[2] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[2] ^ c[6]) << 2;
|
||
|
// newCrc |= (d[7] ^ d[3] ^ d[2] ^ d[1] ^ c[1] ^ c[2] ^ c[3] ^ c[7]) << 3;
|
||
|
// newCrc |= (d[4] ^ d[3] ^ d[2] ^ c[2] ^ c[3] ^ c[4]) << 4;
|
||
|
// newCrc |= (d[5] ^ d[4] ^ d[3] ^ c[3] ^ c[4] ^ c[5]) << 5;
|
||
|
// newCrc |= (d[6] ^ d[5] ^ d[4] ^ c[4] ^ c[5] ^ c[6]) << 6;
|
||
|
// newCrc |= (d[7] ^ d[6] ^ d[5] ^ c[5] ^ c[6] ^ c[7]) << 1;
|
||
|
//
|
||
|
// return newCrc;
|
||
|
// }
|
||
|
|
||
|
// static uint8_t efuse_Crc(EFUSE_AesKey* key, uint8_t lock, BOOL isLowRegion) {
|
||
|
// uint8_t crc = 0;
|
||
|
//
|
||
|
// if (isLowRegion) {
|
||
|
// crc = efuse_Crc8Bit(key->key0, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key0 >> 8, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key0 >> 16, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key0 >> 24, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key1, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key1 >> 8, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key1 >> 16, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key1 >> 24, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key2, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key2 >> 8, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key2 >> 16, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key2 >> 24, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key3, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key3 >> 8, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key3 >> 16, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key3 >> 24, crc);
|
||
|
// crc = efuse_Crc8Bit(lock, crc);
|
||
|
// crc = efuse_Crc8Bit(0x0, crc);
|
||
|
// crc = efuse_Crc8Bit(0x0, crc);
|
||
|
// } else {
|
||
|
// crc = efuse_Crc8Bit(key->key4, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key4 >> 8, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key4 >> 16, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key4 >> 24, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key5, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key5 >> 8, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key5 >> 16, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key5 >> 24, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key6, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key6 >> 8, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key6 >> 16, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key6 >> 24, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key7, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key7 >> 8, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key7 >> 16, crc);
|
||
|
// crc = efuse_Crc8Bit(key->key7 >> 24, crc);
|
||
|
// crc = efuse_Crc8Bit(lock, crc);
|
||
|
// crc = efuse_Crc8Bit(0x0, crc);
|
||
|
// crc = efuse_Crc8Bit(0x0, crc);
|
||
|
// }
|
||
|
//
|
||
|
// return crc;
|
||
|
// }
|
||
|
|
||
|
void EFUSE_Init(EFUSE_InitTypeDef* init) {
|
||
|
assert_param(init);
|
||
|
assert_param(IS_EFUSE_TMRF(init->EFUSE_TMRF));
|
||
|
|
||
|
efuse_SetClock(init->EFUSE_ClockDividor);
|
||
|
EFUSE->USER_CTRL_LOW_b.TMRF = init->EFUSE_TMRF;
|
||
|
EFUSE->USER_CTRL_HI_b.TMRF = init->EFUSE_TMRF;
|
||
|
if (init->timing) {
|
||
|
uint32_t value;
|
||
|
|
||
|
value = (init->timing->EFUSE_Tpwph * (efuse_GetClock() / 1000000) / 1000);
|
||
|
value = (value == 0) ? 1 : value;
|
||
|
EFUSE->TIMING_0_b.TPWPH = value >> 2;
|
||
|
EFUSE->TIMING_1_b.TPWPH = value & 0x00000003;
|
||
|
|
||
|
value = (init->timing->EFUSE_Trac * (efuse_GetClock() / 1000000) / 1000);
|
||
|
value = (value == 0) ? 1 : value;
|
||
|
EFUSE->TIMING_0_b.TRAC = value;
|
||
|
|
||
|
value = (init->timing->EFUSE_Trah * (efuse_GetClock() / 1000000) / 1000);
|
||
|
value = (value == 0) ? 1 : value;
|
||
|
EFUSE->TIMING_0_b.TRAH = value;
|
||
|
|
||
|
value = (init->timing->EFUSE_Trpw * (efuse_GetClock() / 1000000) / 1000);
|
||
|
value = (value == 0) ? 1 : value;
|
||
|
EFUSE->TIMING_0_b.TRPW = value;
|
||
|
|
||
|
value = (init->timing->EFUSE_Trc * (efuse_GetClock() / 1000000) / 1000);
|
||
|
value = (value == 0) ? 1 : value;
|
||
|
EFUSE->TIMING_0_b.TRC = value;
|
||
|
|
||
|
value = (init->timing->EFUSE_Tesr * (efuse_GetClock() / 1000000) / 1000);
|
||
|
value = (value == 0) ? 1 : value;
|
||
|
EFUSE->TIMING_0_b.TESR = value;
|
||
|
|
||
|
value = (init->timing->EFUSE_Tprs * (efuse_GetClock() / 1000000) / 1000);
|
||
|
value = (value == 0) ? 1 : value;
|
||
|
EFUSE->TIMING_0_b.TPRS = value;
|
||
|
|
||
|
value = (init->timing->EFUSE_Tpi * (efuse_GetClock() / 1000000) / 1000);
|
||
|
value = (value == 0) ? 1 : value;
|
||
|
EFUSE->TIMING_1_b.TPIT = value;
|
||
|
|
||
|
value = (init->timing->EFUSE_Tpp * (efuse_GetClock() / 1000000) / 1000);
|
||
|
value = (value == 0) ? 1 : value;
|
||
|
EFUSE->TIMING_1_b.TPP = value;
|
||
|
|
||
|
value = (init->timing->EFUSE_Teps * (efuse_GetClock() / 1000000) / 1000);
|
||
|
value = (value == 0) ? 1 : value;
|
||
|
EFUSE->TIMING_1_b.TEPS = value;
|
||
|
|
||
|
value = (init->timing->EFUSE_Teps * (efuse_GetClock() / 1000000) / 1000);
|
||
|
value = (value == 0) ? 1 : value;
|
||
|
EFUSE->TIMING_1_b.TPWPS = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* It only can be written once */
|
||
|
// BOOL EFUSE_Write(EFUSE_AesKey* key) {
|
||
|
// assert_param(key);
|
||
|
//
|
||
|
// if ((EFUSE->USER_CTRL_LOW_b.LOCK || EFUSE->USER_CTRL_LOW_b.BUSY) ||
|
||
|
// (EFUSE->USER_CTRL_HI_b.LOCK || EFUSE->USER_CTRL_HI_b.BUSY)) {
|
||
|
// return FALSE;
|
||
|
// }
|
||
|
//
|
||
|
// // write low region
|
||
|
// EFUSE->USER_DATA0_LOW = key->key0;
|
||
|
// EFUSE->USER_DATA1_LOW = key->key1;
|
||
|
// EFUSE->USER_DATA2_LOW = key->key2;
|
||
|
// EFUSE->USER_DATA3_LOW = key->key3;
|
||
|
// EFUSE->USER_DATA4_LOW_b.CRC = efuse_Crc(key, 0x1, TRUE);
|
||
|
// EFUSE->USER_DATA4_LOW_b.LOCK = 1;
|
||
|
// EFUSE->USER_CTRL_LOW_b.WR_EN = FALSE;
|
||
|
// EFUSE->USER_CTRL_LOW_b.WR_EN = TRUE;
|
||
|
//
|
||
|
// udelay(1000);
|
||
|
// while (EFUSE->USER_CTRL_LOW_b.BUSY) ;
|
||
|
//
|
||
|
// if (EFUSE->USER_CTRL_LOW_b.WR_CRC_ERR) {
|
||
|
// return FALSE;
|
||
|
// }
|
||
|
//
|
||
|
// // write high region
|
||
|
// EFUSE->USER_DATA0_HI = key->key4;
|
||
|
// EFUSE->USER_DATA1_HI = key->key5;
|
||
|
// EFUSE->USER_DATA2_HI = key->key6;
|
||
|
// EFUSE->USER_DATA3_HI = key->key7;
|
||
|
// EFUSE->USER_DATA4_HI_b.CRC = efuse_Crc(key, 0x1, FALSE);
|
||
|
// EFUSE->USER_DATA4_HI_b.LOCK = 1;
|
||
|
// EFUSE->USER_CTRL_HI_b.WR_EN = FALSE;
|
||
|
// EFUSE->USER_CTRL_HI_b.WR_EN = TRUE;
|
||
|
//
|
||
|
// udelay(1000);
|
||
|
// while (EFUSE->USER_CTRL_HI_b.BUSY) ;
|
||
|
//
|
||
|
// if (EFUSE->USER_CTRL_HI_b.WR_CRC_ERR) {
|
||
|
// return FALSE;
|
||
|
// }
|
||
|
// return TRUE;
|
||
|
// }
|
||
|
|
||
|
BOOL EFUSE_Compare(EFUSE_AesKey* key) {
|
||
|
assert_param(key);
|
||
|
|
||
|
if (EFUSE->USER_CTRL_LOW_b.BUSY || EFUSE->USER_CTRL_HI_b.BUSY) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// compare low region
|
||
|
EFUSE->USER_DATA0_LOW = key->key0;
|
||
|
EFUSE->USER_DATA1_LOW = key->key1;
|
||
|
EFUSE->USER_DATA2_LOW = key->key2;
|
||
|
EFUSE->USER_DATA3_LOW = key->key3;
|
||
|
EFUSE->USER_CTRL_LOW_b.RD_EN = FALSE;
|
||
|
EFUSE->USER_CTRL_LOW_b.RD_EN = TRUE;
|
||
|
|
||
|
udelay(2);
|
||
|
while (EFUSE->USER_CTRL_LOW_b.BUSY) ;
|
||
|
|
||
|
if (EFUSE->USER_CTRL_LOW_b.COMPARE_FAIL) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// compare high region
|
||
|
EFUSE->USER_DATA0_HI = key->key4;
|
||
|
EFUSE->USER_DATA1_HI = key->key5;
|
||
|
EFUSE->USER_DATA2_HI = key->key6;
|
||
|
EFUSE->USER_DATA3_HI = key->key7;
|
||
|
EFUSE->USER_CTRL_HI_b.RD_EN = FALSE;
|
||
|
EFUSE->USER_CTRL_HI_b.RD_EN = TRUE;
|
||
|
|
||
|
udelay(2);
|
||
|
while (EFUSE->USER_CTRL_HI_b.BUSY) ;
|
||
|
|
||
|
if (EFUSE->USER_CTRL_HI_b.COMPARE_FAIL) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|