This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/CC2640R2F: External flash use

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(&timestamps, &timestamp, 4);

        }

        else

        {

            // Otherwise set latest end timestamp.

            memcpy(&timestamps[4], &timestamp, 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, &timestamp, 4);

        }

        else

        {

            // Otherwise set latest end timestamp.

            memcpy(&ittPrsAlarmTimeTrend[4], &timestamp, 4);

        }

        IttDeviceData_SetParameter(ITT_PRS_ALARM_TIME_TREND, TIMESTAMP_RANGE_LENGTH, ittPrsAlarmTimeTrend);

    }

#endif //!FEATURE_OAD

}

  • Hi Priya,

    Does this behavior occur with the BLE-Stack v2.2.1 project running on your custom board?

    What happens if you start with a project from the SimpleLink CC2640R2 SDK?
  • Rachel,

    The ble_sdk_2_02_01_18 project is more stable after the first hour of data logging.
    Standby approx. 50 uA.

    The simplelink_cc2640r2_sdk_1_35_00_33 shows a larger current overdraw after
    the first hour of data logging.

    Which project in SimpleLink CC2640R2 SDK uses the external flash?

    Thanks,
    Priya
  • Hi Priya,

    The Simple Peripheral OAD Off Chip project writes to external flash during the OAD process but you could test without going through an OAD by adding a call to ExtFlash_test to see if you see the same current jump.
  • Rachel,
    I imported a clean copy of simple_peripheral_cc2640r2lp_app_oad_offchip
    (and bim_oad_offchip_cc2640r2lp_app). I tailored it to the custom board pins.
    Clean copy current draw is fine, advertising interval was made 2 sec.

    I added the following lines pasted below. I can't get the debugger
    to halt here, no external flash chip select seen on the scope.
    Any idea why the periodic event/external flash access is not happening?

    Thanks,
    Priya


    static void SimpleBLEPeripheral_performPeriodicTask(void)
    {
    uint8_t datalog[1];
    datalog[0] = 0xb5;
    uint8_t addr = 176;
    if ( ExtFlash_open() ){
    ExtFlash_erase(addr, 4096);
    ExtFlash_write(addr, 4096, datalog);
    }

    #ifndef FEATURE_OAD_ONCHIP
    uint8_t valueToCopy;

    // Call to retrieve the value of the third characteristic in the profile
    if (SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &valueToCopy) == SUCCESS)
    {
    // Call to set that value of the fourth characteristic in the profile.
    // Note that if notifications of the fourth characteristic have been
    // enabled by a GATT client device, then a notification will be sent
    // every time this function is called.
    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
    &valueToCopy);
    }
    #endif //!FEATURE_OAD_ONCHIP
    }
  • I set up a clean copy of the simple_peripheral_cc2640r2lp_app on the custom board.
    I linked the ExtFlash.c and h files to the application. The board is showing a 1uA standby
    current draw. When I added ExtFlash_test(); to the SimpleBLEPeripheral_init function,
    the standby current draw is also 1 uA. So the external flash on the custom board is capable
    of powering down.


    Following an advertising event, I added these lines to the clean copy of
    simple_peripheral:

    if (pEvt->event_flag & SBP_ADV_CB_EVT)
    {

    uint8_t datalog[1];

    if ( ExtFlash_open() ){
    datalog[0] = 45;
    ExtFlash_erase(32, 4096);
    ExtFlash_write(32, 16, datalog);
    }

    ExtFlash_close();

    }

    I can see the external flash chip select active on the scope. However, the standby
    current draw is 10 uA. Is the external flash not powering down with these APIs?

    When the same lines of code were added to SimpleBLEPeripheral_performPeriodicTask(void),
    the external flash chip select never went active. A break point set inside this function never
    halted the debugger. Is there an explanation for this?

    Thanks,
    Priya