19fd7a3551
OR-ing an offset to a base address instead of adding it is dangerous because it can only work if the base address is aligned enough for the offset. Moreover, if the base address or the offset has a value unknown at compile time, then the assembly instructions dedicated to 'base + offset' addressing on most CPUs can't be emitted by the compiler because this would require the alignment of the base address against the offset to be known in order to optimize 'base | offset' into 'base + offset'. In that case, the compiler has to emit more instructions in order to compute 'base | offset' on most CPUs, e.g. on ARM, which means larger binary size and slower execution. Hence, replace all occurrences of 'base | offset' with 'base + offset'. This must become a coding rule. Here are the results for the cc2538-demo example: - Compilation of uart_init(): * before: REG(regs->base | UART_CC) = 0; 200b78: f446 637c orr.w r3, r6, #4032 ; 0xfc0 200b7c: f043 0308 orr.w r3, r3, #8 200b80: 2200 movs r2, #0 200b82: 601a str r2, [r3, #0] * now: REG(regs->base + UART_CC) = 0; 200b7a: 2300 movs r3, #0 200b7c: f8c4 3fc8 str.w r3, [r4, #4040] ; 0xfc8 - Size of the .text section: * before: 0x4c7c * now: 0x4c28 * saved: 84 bytes Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
105 lines
3.0 KiB
C
105 lines
3.0 KiB
C
/** @file hal/micro/cortexm3/mfg-token.c
|
|
* @brief Cortex-M3 Manufacturing-Token system
|
|
*
|
|
* <!--(C) COPYRIGHT 2010 STMicroelectronics. All rights reserved. -->
|
|
*/
|
|
#include PLATFORM_HEADER
|
|
#include "error.h"
|
|
#include "hal/micro/cortexm3/flash.h"
|
|
#include "mfg-token.h"
|
|
|
|
|
|
|
|
|
|
#define DEFINETOKENS
|
|
#define TOKEN_MFG(name,creator,iscnt,isidx,type,arraysize,...) \
|
|
const uint16_t TOKEN_##name = TOKEN_##name##_ADDRESS;
|
|
#include "hal/micro/cortexm3/token-manufacturing.h"
|
|
#undef TOKEN_DEF
|
|
#undef TOKEN_MFG
|
|
#undef DEFINETOKENS
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const uint8_t nullEui[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF };
|
|
|
|
|
|
void halInternalGetMfgTokenData(void *data, uint16_t ID, uint8_t index, uint8_t len)
|
|
{
|
|
uint8_t *ram = (uint8_t*)data;
|
|
|
|
//0x7F is a non-indexed token. Remap to 0 for the address calculation
|
|
index = (index==0x7F) ? 0 : index;
|
|
|
|
if(ID == MFG_EUI_64_LOCATION) {
|
|
//There are two EUI64's stored in the Info Blocks, St and Custom.
|
|
//0x0A00 is the address used by the generic EUI64 token, and it is
|
|
//token.c's responbility to pick the returned EUI64 from either St
|
|
//or Custom. Return the Custom EUI64 if it is not all FF's, otherwise
|
|
//return the St EUI64.
|
|
tokTypeMfgEui64 eui64;
|
|
halCommonGetMfgToken(&eui64, TOKEN_MFG_CUSTOM_EUI_64);
|
|
if(MEMCOMPARE(eui64,nullEui, 8 /*EUI64_SIZE*/) == 0) {
|
|
halCommonGetMfgToken(&eui64, TOKEN_MFG_ST_EUI_64);
|
|
}
|
|
MEMCOPY(ram, eui64, 8 /*EUI64_SIZE*/);
|
|
} else {
|
|
//read from the Information Blocks. The token ID is only the
|
|
//DATA_BIG_INFO_BASE-relative 16-bit offset of the token. Since the
|
|
//info blocks exist in the range DATA_BIG_INFO_BASE-DATA_BIG_INFO_END,
|
|
//we need to add the ID to DATA_BIG_INFO_BASE to get the real address.
|
|
uint32_t realAddress = (DATA_BIG_INFO_BASE+ID) + (len*index);
|
|
uint8_t *flash = (uint8_t *)realAddress;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MEMCOPY(ram, flash, len);
|
|
}
|
|
}
|
|
|
|
|
|
void halInternalSetMfgTokenData(uint16_t token, void *data, uint8_t len)
|
|
{
|
|
StStatus flashStatus;
|
|
uint32_t realAddress = (DATA_BIG_INFO_BASE+token);
|
|
uint8_t * flash = (uint8_t *)realAddress;
|
|
uint32_t i;
|
|
|
|
//The flash library (and hardware) requires the address and length to both
|
|
//be multiples of 16bits. Since this API is only valid for writing to
|
|
//the CIB, verify that the token+len falls within the CIB.
|
|
assert((token&1) != 1);
|
|
assert((len&1) != 1);
|
|
assert((realAddress>=CIB_BOTTOM) && ((realAddress+len-1)<=CIB_TOP));
|
|
|
|
//CIB manufacturing tokens can only be written by on-chip code if the token
|
|
//is currently unprogrammed. Verify the entire token is unwritten. The
|
|
//flash library performs a similar check, but verifying here ensures that
|
|
//the entire token is unprogrammed and will prevent partial writes.
|
|
for(i=0;i<len;i++) {
|
|
assert(flash[i] == 0xFF);
|
|
}
|
|
|
|
//Remember, the flash library operates in 16bit quantities, but the
|
|
//token system operates in 8bit quantities. Hence the divide by 2.
|
|
flashStatus = halInternalFlashWrite(realAddress, data, (len/2));
|
|
assert(flashStatus == ST_SUCCESS);
|
|
}
|
|
|