Part Number: CC2640R2F
Other Parts Discussed in Thread: BLE-STACK
Tool/software: TI-RTOS
CC2640R2 custom 4x4 board, simplelink_cc2640r2_sdk_1_35_00_33, XDS200 debugger.
The project was successfully ported from ble_sdk_2_02_01_18 using the simple_peripheral project. To use the API’s to communicate with the external flash, ExtFlash.c and ExtFlash.h were linked to the application. FlashROM build configuration was used.
The ported project on the CC2640R2 custom board advertises, connects, and can communicate to an external processor through the UART, standby current draw unchanged after porting IF the external flash is not being used.
When the custom board is configured to use the external flash, the CC2640R2 does not enter standby after accessing the external flash. When the ble_sdk_2_02_01_18 project used the external flash, the standby current draw would be about 50uA indicating that the external flash may not have powered down as expected. The standby current draw was higher than ideal, but steady. With the CC2640R2 board, the system is totally upset after accessing the external flash. The meter indicates current overdraw a lot more often than the advertising interval.
Is there anything about the porting that can cause this current overload after external flash access?
1. Same middleware files are used before and after porting.
2. There is a notification that is sent out following read from the external flash. This calls the GATT_notification. Every hour, there is a write to the external flash. No notifications are sent during this time. But the first write (after one hour) is when the system stops entering standby.
I have attached code the app uses to select between two SPI slaves.
SPI slave 1 select
void ACAM_resume(void)
{
spi = SPI_open(CC2640R2_Custom_SPI0, &spiParams);
if (spi == NULL) {
System_printf("\nError opening SPI");
}
PIN_Id csnPin1 = PIN_ID(Board_ACSN);
SPI_control(spi, SPICC26XXDMA_SET_CSN_PIN, &csnPin1);
acamEnabled = 1;
}
SPI slave 2 select (external flash)
The middleware uses PIN APIs to select the external flash. To avoid the SPI_control API to interfere with this, the following two lines were added to ExtFlash.c:
static PIN_Id csnPin = PIN_ID( PIN_UNASSIGNED );
static bool Spi_open(uint32_t bitRate){
/* Disable the driver chip select function. This is handled by the
* extFlashSelect and extFlashDeselect methods */
SPI_control( spiHandle, SPICC26XXDMA_SET_CSN_PIN, &csnPin );
}
The write to the external flash happens every hour during the SBP periodic event. Here is that code:
static void SimpleBLEPeripheral_performPeriodicTask(void)
{
#ifndef FEATURE_OAD
timestamp++;
if (timestamp % 720 == 0) { // In 5 second intervals (720 = 1 hr)
ACAM_suspend();
// Write trend values.
if (ExtFlash_open() )
{
uint8_t datalog[DATA_LOG_LENGTH];
datalog[0] = (uint8_t) (timestamp & 0x000000ff);
datalog[1] = (uint8_t) ((timestamp & 0x0000ff00) >> 8);
datalog[2] = (uint8_t) ((timestamp & 0x00ff0000) >> 16);
datalog[3] = (uint8_t) ((timestamp & 0xff000000) >> 24);
datalog[4] = (uint8_t) (calc_prsAdvMode & 0x0000ff);
datalog[5] = (uint8_t) ((calc_prsAdvMode & 0x00ff00) >> 8);
datalog[6] = (uint8_t) ((calc_prsAdvMode & 0xff0000) >> 16);
datalog[7] = (uint8_t) (temperature & 0x00ff);
datalog[8] = (uint8_t) ((temperature & 0xff00) >> 8);
// Store standard trend value.
if (trends <= MAX_TRENDS)
{
uint8_t addr = DATA_LOG_LENGTH * trends;
if (addr % EXT_FLASH_PAGE_SIZE == 0) {
ExtFlash_erase(addr, EXT_FLASH_PAGE_SIZE);
}
if (ExtFlash_write(addr, DATA_LOG_LENGTH, datalog))
{
trends++;
}
else
{
failures++;
}
}
// Check if in alarm state and store trend value.
if (status != STATUS_OK && alarmTrends <= MAX_TRENDS)
{
uint8_t addr = (DATA_LOG_LENGTH * alarmTrends) + (MAX_TRENDS * DATA_LOG_LENGTH);
if (addr % EXT_FLASH_PAGE_SIZE == 0) {
ExtFlash_erase(addr, EXT_FLASH_PAGE_SIZE);
}
if (ExtFlash_write(addr, DATA_LOG_LENGTH, datalog))
{
alarmTrends++;
}
else {
failures++;
}
}
}
ExtFlash_close();
ACAM_resume();
uint8 timestamps[TIMESTAMP_RANGE_LENGTH];
IttDeviceData_GetParameter(ITT_PRS_TIMESTAMP_RCV, timestamps);
// Update start and end timestamp values.
// Check if start timestamp is set.
if (timestamps[0] == 0x00
&& timestamps[1] == 0x00
&& timestamps[2] == 0x00
&& timestamps[3] == 0x00)
{
memcpy(×tamps, ×tamp, 4);
}
else
{
// Otherwise set latest end timestamp.
memcpy(×tamps[4], ×tamp, 4);
}
IttDeviceData_SetParameter(ITT_PRS_TIMESTAMP_RCV, TIMESTAMP_RANGE_LENGTH, timestamps);
uint8 ittPrsAlarmTimeTrend[TIMESTAMP_RANGE_LENGTH];
IttDeviceData_GetParameter(ITT_PRS_ALARM_TIME_TREND, ittPrsAlarmTimeTrend);
// Check if start timestamp is set.
if (ittPrsAlarmTimeTrend[0] == 0x00
&& ittPrsAlarmTimeTrend[1] == 0x00
&& ittPrsAlarmTimeTrend[2] == 0x00
&& ittPrsAlarmTimeTrend[3] == 0x00)
{
memcpy(&ittPrsAlarmTimeTrend, ×tamp, 4);
}
else
{
// Otherwise set latest end timestamp.
memcpy(&ittPrsAlarmTimeTrend[4], ×tamp, 4);
}
IttDeviceData_SetParameter(ITT_PRS_ALARM_TIME_TREND, TIMESTAMP_RANGE_LENGTH, ittPrsAlarmTimeTrend);
}
#endif //!FEATURE_OAD
}