Skip navigation
Home > All Places > WICED Smart Bluetooth > WICED Smart Bluetooth Forums > Blog > 2014 > June > 22
RevisionChange DecriptionDate
1.0Initial06/22/14
1.1Added Aligned Memory Accesses10/28/14

Hello Community Members,

 

This BLOG should be used as a "guide" for examining the Memory Map configurations and Application Development.

 

This is a compilation of Memory Map questions and answers from several of our forum users and I thank you for your questions and answers.

 

The Memory Architecture consists of both RAM and ROM with external EEPROM in the BCM20732/36/37 devices.

The Memory Architecture of the BCM20732S/36S/37S consists of the RAM and ROM with Internal EEPROM.

 

ROM vs. RAM application assignment has caused some confusion in the past, so we eliminated this nomenclature in SDK 2.0.1.

 

The ROM contains:

 

  1. Embedded BLE stack
  2. L2CAP, GAP, GATT
  3. BT_SIG approved profiles such as proximity, heart rate monitor, thermometer, blood pressure monitor and time
  4. SMP
  5. HCI
  6. Drivers for I2C EEPROM, SPI EEPROM and SPI Serial flash

 

GATT:

 

  1. GATT database handles are 16 bit values from 0x00 to 0xFFFF
  2. This limits you to ~65K entries in the database
  3. With SDK 1.1.0, GATT characteristic length/max length is a 1 byte field
  4. SDK 2.0.1, it could optionally be a 2 byte field too
  5. The BT spec limits characteristics to a max of 512 bytes
  6. You will hit the available RAM limit long before your database gets anywhere close to this

 

ROM applications typically has some part of the application in the ROM and whatever user writes adds functionality to the ROM code

 

Application code is loaded in to NVRAM

RAM apps use LE Stack in the ROM

 

NVRAM:

 

Let's take an example from ws_upgrade.c in [uart|ota]_firmware_upgrade sample app from SDK 2.0.1

 

  1. When you read/write/delete NV items using bleprofile_*NVRAM, these operations are performed in the section marked VS1 in the picture above.
  2. The stack uses some of this for some internal book-keeping
  3. When you pair, all pairing information is stored in this area too
  4. So it is possible that you ran out of space when you attempted to store the 63 remaining bytes
  5. You can increase the the space allocated for VS1 by changing a couple of options in <SDK>/Platforms/BCM92073?TAG_Q32/2073?_EEPROM*.btp

 

Note: If you increase DLConfigVSLength, you may have to also increase ConfigDSLocation (which is the same as DS1 in the picture above) so that there is no overlap (the hex file conversion step when building will fail if it detects an overlap between the two regions).

 

 

Serial FLASH:

 

Serial Flash images are not compressed (because SF reads has only ~3% overhead and decompressing will make it slower).

 

BCM20736 will not access more than ~128kbytes from the base but the API uses 24 bit addresses (serial flashes use 24 bit addresses), so the entire SF should be accessible

 

The virtual addresses used by the FW API for EEPROM and SF is different

0xFF000000 for EEPROM and 0xF8000000 for Serial FLASH

 

These offsets should be used with bleappfwu_*().

 

PATCHES:

 

Patches take up 1900 bytes (today) assuming you only want the mandatory patches (no extra features that are being patched in).

So your application space gets ~28K (today)

 

MEMORY ARCHITECTURE BLOCK DIAGRAM:

 

Let's start with a Memory Map Diagram of the BCM20732:

 

 

The 30K is shared memory (between patches and the app) and the dynamically allocated buffers also take up some of this space.

 

 

The ‘total RAM footprint ‘ line at the end of the build is only the static portion of the app + patches (includes code + initialized and uninitialized data) in our flat memory model.

 

 

So you cannot take the app start address and add the app size and then subtract from 60K to get remaining size

 

The 4K CM3 Mapper is for the Cortex M3 Memory Map for Interrupts Stack, etc.

Note that our Stack (YELLOW) is 30K and is DATA ONLY.

 

The Patches Section (Features,Updates, etc) is combined with the User App but:

  1. The Patches_Init Code is overlayed and can be used by the App after the Patches are loaded
  2. The App_Init/BLE_SET_CONFIG is also overlayed by the Dynamic Allocation

 

 

 

 

 

 

Static variables that are NOT initialized end up in the data area:

 

  1. The ‘Data ONLY’ area in yellow is the data area allocated by the BLE stack that’s in the ROM
  2. So nothing new goes in here
  3. All application data (RW and ZI) and application code (Code + RO) goes into the same region in the RAM

 

 

SDK 2.0 Hello_Sensor Example App:

 

As an example, we take the Hello_Senor App and using the SDK Console Window, we see the Patches Start/End Addresses:

 

 

 

The Patches and Application Start Addresses are listed below:

 

 

 

 

As you can see, there is overlap between Patches and Beginning of Application

So after the Patches are finished loaded, a portion of the RAM is available for the Application

 

Here is what is happening:

 

  1. Patches start at where the ROM finished 0x00204568
  2. Patches end at 0x00204AFC, but the Application starts at 0x00204974 even before the Patches end
  3. So there is an overlap.
  4. Once the application ends at 0x00204C28, but dynamic allocation starts even before this.
  5. The reason is that in the order in which we boot, The Patches get copied in first and they will get initialized.
  6. Then the section of the code where there in Patch initialization, that will get reused and we will put the application on top of it and overlay the application.
  7. Once the Patch Init code is running, we can replace that section with the application code.
  8. We are re-using the RAM from the Boot Loader and Reusing the application initialization code also for dynamic allocation
  9. Once we have initialized, we don/t need that code anymore.
  10. The ROM boots and copies in ALL of the patches
  11. And then it will run the Patch Init Code and installs all of the MANDATORY patches
  12. Once that copy is done, you don’t need that Patch Init Code
  13. The ROM will copy the Application on top of it.
  14. Overwrite the Patch Init Code with Application Code
  15. Application Code will be 1.7K of code or less.
  16. The App calls the App Init Function and will say, available RAM is here
  17. Then the ROM starts Dynamic Allocation from here
  18. What goes in?
  19. Buffer,xx, Stack Buffer Tools, and Data
  20. Call Back Registrations
  21. Dump the Stack on the Peripheral UART and reset

 

Question – How much memory do you have?

  1. There is a function call CFG_MM_MemFreeBytes
  2. This is a pointer that keeps moving at every step
  3. When ROM finishes Initialization, available RAM is pointing to this
  4. When PATCHES finish Initialization, available RAM is pointing to this
  5. When the App finishes the Initialization, available RAM points to this area
  6. We can find how much we need by making 2 calls to RAM:
  7. By using init.c, we can take a snap shot of what this function returns and this will tell you where nm is at this point of time
  8. At the end of your Application Create Function, you take another snapshot of this guy and the difference between these 2 is your dynamic allocation

 

Notes:

The NVRAM has a lot of headers.

Serial FLASH is similar 0 – 4K

 

 

 

Questions:

 

Q: In the first diagram it suggests that the maximum size of an app should be 26K?

 

A: 26K is a good approximation because it really depends on what (HW/drivers/features) the app initializes and uses.  cfa_mm_MemFreeBytes() is the ultimate authority on the amount of RAM available

 

Q: Is there any way to estimate the amount needed for 'dynamic allocation' in that first diagram?

 

A: Not really, this is allocated for OS buffers, TX and RX buffers, stack buffer pools, thread stacks, callback registrations etc.

 

Q: If I end up with a total ram footprint of 26K , I am nervous that I might get overruns?

 

A: Yes

 

Q: What is the maximum stack size?

A: The app thread stack size is 1K (1024 bytes).

 

Q: What is the amount of space available for global and static variables?

A: The app code + globals (initialized and zero-initialized) all share the same space. So allocating more globals will reduce space for app code and vice-versa.

 

Q: Are there any built in functions of the stack that can be turned off to save space, for example if I disable the battery status profile does that cut down on the footprint?

A: No, here's why

Disabling battery monitor will not give you more space because its in the ROM.

 

 

 

This BLOG should get you going and I will be adding more later.

 

Additions:

The CPU core is an ARM Cortex M3 which supports unaligned accesses (so no exceptions will be thrown).

 

However, there is a performance penalty - the instruction will take multiple cycles to complete and the pipeline will stall (see ARM documentation). Load/Store multiple instructions do not support unaligned accesses.

 

Thanks

 

JT

RevisionChange DecriptionDate
1.0Initial06/22/14

Hello Community Members,

 

This BLOG should be used as a "guide" for examining Sleep and Deep_Sleep techniques.

This is a compilation of Sleep and Deep Sleep questions and answers from several of our forum users and I thank you for your questions and answers.

 

Let's start out with a explanation of how to place the BCM2073x in Sleep and Deep_Sleep modes and then move to sample Q/A regarding a few use cases.

 

Sleep Deep_Sleep Modes:

 

Here's a list of the Sleep/Deep Sleep modes:

 

  • Pause
    • The processor is idle if sleep is not allowed or there is not enough time to sleep due to processor or BLE Radio Activity
    • All state information is maintained
    • Near 0 cycle latency to wake up
  • Sleep
    • When lower power consumption is required
    • All state information is maintained
    • Can be woken up by timer or GPIO/ Keyscan /Quadrature sensors
    • About 2 mS latency to wake up
  • Deep Sleep
    • No state information is maintained
    • Can be woken up by GPIO/ Keyscan /Quadrature sensors
    • Includes ability to wake after configured time
      • With internal clock, can wake anywhere from 64mS to ~36 Hrs.
      • With external 32 KHz xtal, 128mS to ~144 Hrs

 

Deep_Sleep: Known on the BCM2073x devices as HIDOFF (Taken from the Human Interface Device OFF mode from Classic Bluetooth.

 

 

Waking the Device:

 

  1. Wake by GPIO:
  2. Note that there are 14 GPIOs on the module and most can drive/sink up to 2mA and are capable of waking device from sleep or deep sleep.
  3. All GPIO interrupts are serialized to the application thread.
  4. If the device is sleeping, the latency to get to the application thread context interrupt handler will generally be under 3mS.
  5. If not sleeping and not connected, then this will be of the order of a few tens of uS.
  6. In addition, there are multiple low power modes, and in many cases the firmware automatically handles low power states (as mentioned previously).
  7. The application may choose to participate in sleep and deep sleep decisions.

 

Permanently Disable Sleep

 

  1. To permanently disable sleep, register a callback using devlpm_registerForLowPowerQueries() and then in the callback, always return 0.
  2. For an example, see ws_upgrade_uart.c in uart_firmware_upgrade sample application.
  3. Note that this will drain more power than when sleep is enabled.

 

 

Notes regarding HidOff:

 

Deep_Sleep (HIDOFF) is not supported while the connection is up.

 

However, a connection can be kept when sleep is enabled (but not when deep sleep engages).

 

When the device is connected/scanning/advertising, it will always sleep between RF activity if the application allows it and there is sufficient time before the next scheduled activity.

 

Deep_Sleep (HIDOFF) does not retain state, so the chip cannot enter deep sleep when connected.

 

The most important point in determining Sleep and Deep Sleep modes is when to do it:

 

In many of our SDK 2.0 examples, power is automatically managed by the firmware based on input device activity.

As a power-saving task, the firmware controls the disabling of the on-chip regulator when in deep sleep mode - More on this later.

 

This BITES everyone - Be careful:

 

The BCM20732A0.cgs file has a Low Power Configuration section:

 

By default:
"Sleep enable" = 1

Change to 0 to disable the sleep function.


################################################################################
#  Low power configuration
###############################################################################
ENTRY "Sleep Mode Configuration"
{
    "Sleep mode" = "HIDD"
    "Sleep enable" = 1 ; Change to 0
}
##############################################################################

 

Sleep Current Consumption is roughly 24uA using the internal power management of the BCM20732.

 

In 1.5uA deep sleep, the xtal, IR and PWM blocks will be turned off.

 

The PWM does not operate in sleep or in deep sleep, and the PWM block is not capable of interrupting or waking up the processor.

 

GPIOs, peripheral uart, IR transmit, Keyscan and quadrature inputs can interrupt/wake the processor.

 

GPIOs that are output enabled will remain so and drive as configured in sleep/deep sleep.

 

Sleep operation in BLE Packet Transmissions:

 

Q: When sending packets periodically for BLE (e.g. 25 ms to 4 seconds), does the BLE stack put the 20732 in 1.5 uA deep sleep mode between the transmissions or is just the sleep mode (20+ uA)?

 

A: No, when advertising or in connection, the device will not go into deep sleep. However, it will go into other low power modes like sleep and pause based on the connection/ADV interval and other activities. If you want to ADV every few minutes, it is possible to ADV for some seconds, then configure timed wake from deep sleep and then enter deep sleep. After the configured time, the device will be woken up and then the application will be initialized.

 

Q: In deep sleep mode, the data sheet says core and base are turned off. Does that mean it loses the RAM contents? If so, where does application software store state information when it goes into deep sleep? The EE or an offboard chip?

 

A: Yes, in deep sleep the chip will lose its RAM contents. When woken up, the application will be loaded to RAM from the NV storage and re-initialized. This is very similar to a power-on-reset except that in the case of a wake from deep sleep, some HW state information is retained so that the application can find out what caused the wake.

 

Sleep Times:

 

Our BCM2073x device includes the ability to wake after configured time.

 

With the internal clock, this value is anywhere from 64mS to ~36 Hrs.

With an external 32 KHz xtal, 128mS - ~144 Hrs is possible.

 

PREVENTING THE DEVICE FROM GOING TO SLEEP WHEN USING THE P_UART:

 

If you are working with the PUART and in particular trying to Rx data with the PUART you will need to ensure that the following functions shown below are added into your PUART_Init() function.

 

You will also see these functions in the 'uart_firmware_upgrade' example.

 

The reason these are needed is otherwise the Device will put the PUART to sleep.

 

These functions disable the device from putting the PUART to sleep:

 

Put these inside of your PUART_Init() function devlpm_init();

 

// Since we are not using any flow control, disable sleep when download starts.

// If HW flow control is configured or app uses its own flow control mechanism,

// this is not required.

devlpm_registerForLowPowerQueries(Puart_device_lpm_queriable, 0);

//Callback function that is registered from function shown above:

devlpm_register...()

// Callback called by the FW when ready to sleep/deep-sleep. Disable both by returning 0

// when there is an active download ongoing.

UINT32 Puart_device_lpm_queriable(LowPowerModePollType type, UINT32 context)

{

// Disable sleep.

return 0;

}

 

 

Wake time from deep sleep:

 

Determination of Wake time from deep sleep is a combination of many factors:


Since this involves a full boot, it depends on whether you are using the BCM20732S/36S modules or BCM2073x SOC design, EEPROM or Serial flash (application + patch size), speed of NV access.

 

20732S modules:

 

The 20732S contains an EEPROM internally:

Boot Time: boot time* ~= 50ms + ~45mS/KByte of application + patch code (whats printed at the end of a build) assuming default I2C speed (400 KHz).

 

The 20732 chip-on-board design:

 

EEPROM Case:

You can increase the read speeds to 1MHz instead of the default 400 KHz.
But the boot time will not reduce by 2.5 times because there is a lot of processing involved during this process.
So this will be 50mS + ~30mS/KByte of app + patch code.

 

Serial FLASH Case:
When NV storage is serial FLASH, boot time ~= 50mS + 4mS/KByte of code.

 

BCM20736/7 modules:

 

EEPROM Case:

boot time ~= 20mS + ~35mS/KByte of app + patch code @ 400 KHz.
If I2C speed is increased to 1 MHz, this should be ~ 20mS + 23mS/KByte.

 

Serial FLASH Case:

boot time ~= 20mS + 900uS/KByte when SPI speed is 12 MHz.


Note: *boot time here is the time from wake interrupt to application create call.

 

 

Advertising and Sleep Modes:

 

When advertising (ADV) or in connection, the device will not go into deep sleep.

 

However, it will go into other low power modes like sleep and pause based on the connection/ADV interval and other activities.

 

If you want to ADV every few minutes, it is possible to ADV for some seconds, then configure timed wake from deep sleep and then enter deep sleep.

 

After the configured time, the device will be woken up and then the application will be initialized.

 

Crystal and Sleep:

 

The external 32KHz oscillator is optional with respect to timed wake from deep sleep.

 

The internal 128KHz LPO is used for sleep and timed wake from deep sleep

 

More later..

 

Please provide comments/questions

 

Thanks

 

JT

Filter Blog

By date:
By tag: