DTCM Memory Access Bus Errors During Stack Relocation

When attempting to relocate the stack from SRAM to DTCM (Data Tightly Coupled Memory) on an ARM Cortex-M7 microcontroller, such as the CYT4BFX, developers often encounter bus errors. These errors typically manifest as hard faults or access violations, preventing the system from functioning correctly. The root cause of these errors is often related to improper initialization or configuration of the DTCM memory region, which is a high-speed, low-latency memory block designed for critical data and stack operations.

The ARM Cortex-M7 architecture integrates DTCM and ITCM (Instruction Tightly Coupled Memory) to provide deterministic access times for time-sensitive operations. DTCM is particularly useful for stack and frequently accessed data, as it avoids contention with other bus masters accessing the main SRAM or external memory. However, DTCM is not enabled by default in many microcontroller implementations, and its configuration requires careful attention to the memory map, MPU (Memory Protection Unit) settings, and linker script adjustments.

The bus error during stack relocation to DTCM is a clear indication that the memory region is either not properly enabled or not correctly mapped in the memory space. This issue is compounded by the fact that the Cortex-M7’s memory system is highly configurable, with multiple memory regions, caches, and bus interfaces that must be coordinated to ensure correct operation.

DTCM Initialization and Memory Map Misconfiguration

The primary cause of bus errors when accessing DTCM is the lack of proper initialization in the startup code. On power-up or reset, the DTCM region is often disabled, and its base address and size must be explicitly configured. This configuration is typically done through the processor’s system control block (SCB) and memory protection unit (MPU). If the DTCM region is not enabled or is incorrectly mapped, any attempt to access it will result in a bus error.

Another common cause is the misalignment between the linker script and the actual memory map. The linker script must be updated to reflect the new memory regions, including DTCM, and the stack pointer must be explicitly set to point to the DTCM region. Failure to update the linker script or incorrectly specifying the stack pointer can lead to the stack being placed in an invalid or inaccessible memory region.

Additionally, the MPU settings must be configured to allow access to the DTCM region. The MPU is responsible for enforcing memory access permissions and attributes, and if the DTCM region is not properly configured in the MPU, access attempts will be blocked, resulting in a bus error. The MPU configuration must include the correct base address, size, and access permissions for the DTCM region.

Cache coherency issues can also contribute to bus errors when using DTCM. The Cortex-M7 features a data cache, and if the cache is not properly managed, it can lead to stale data or incorrect memory accesses. When using DTCM, it is essential to ensure that the cache is either disabled for the DTCM region or properly synchronized with the memory system.

Enabling DTCM and Optimizing Software for TCM Usage

To resolve the bus error and successfully relocate the stack to DTCM, the following steps must be taken:

1. Enable DTCM in the Startup Code:
The first step is to enable the DTCM region in the startup code. This involves setting the appropriate bits in the SCB to enable DTCM and configuring its base address and size. The exact registers and bit fields depend on the specific microcontroller implementation, but typically, this involves writing to the SCB->TCMCR (TCM Control Register) or a similar register. The base address and size of the DTCM region must be specified according to the microcontroller’s memory map.

2. Update the Linker Script:
The linker script must be updated to include the DTCM region and define the stack placement. This involves adding a new memory region for DTCM and specifying the stack pointer to point to the end of the DTCM region. For example, the linker script might include a section like this:

MEMORY
{
  DTCM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
  SRAM (rwx) : ORIGIN = 0x20010000, LENGTH = 256K
}
SECTIONS
{
  .stack (NOLOAD) :
  {
    . = ALIGN(8);
    _estack = .;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } > DTCM
}

This ensures that the stack is placed in the DTCM region and that the stack pointer is correctly initialized.

3. Configure the MPU:
The MPU must be configured to allow access to the DTCM region. This involves setting up an MPU region with the correct base address, size, and access permissions. The MPU region should be configured as normal memory with full access permissions (read-write-execute) for privileged and unprivileged modes. The MPU configuration can be done in the startup code or during runtime, depending on the application requirements.

4. Manage Cache Coherency:
If the data cache is enabled, it is essential to ensure that the DTCM region is either excluded from caching or properly synchronized. This can be done by configuring the cacheability attributes in the MPU or by using cache maintenance operations to invalidate or clean the cache as needed. For example, the following code snippet can be used to invalidate the data cache for the DTCM region:

SCB_InvalidateDCache_by_Addr((uint32_t*)DTCM_BASE, DTCM_SIZE);

5. Optimize Software for TCM Usage:
Once the DTCM is properly configured, the next step is to optimize the software to take advantage of the TCM regions. The stack is an ideal candidate for relocation to DTCM, as it benefits from the low-latency access and avoids contention with other memory accesses. Additionally, frequently accessed data structures, such as lookup tables, buffers, and critical variables, can be moved to DTCM to improve performance.

For ITCM, time-critical code sections, such as interrupt service routines (ISRs) and real-time tasks, can be placed in ITCM to ensure deterministic execution times. This involves modifying the linker script to place specific functions or sections in ITCM and ensuring that the code is compiled with the appropriate attributes. For example, the following code snippet can be used to place a function in ITCM:

__attribute__((section(".itcm"))) void critical_function(void) {
  // Time-critical code
}

6. Debugging and Validation:
After making the necessary changes, it is essential to validate the configuration and ensure that the system operates correctly. This involves checking the memory map, verifying the stack pointer initialization, and testing the system for any access violations or performance issues. Debugging tools, such as JTAG probes and memory inspection features, can be used to verify the DTCM configuration and monitor the system behavior.

By following these steps, developers can successfully relocate the stack to DTCM and optimize their software to take full advantage of the Cortex-M7’s TCM regions. This not only resolves the bus error issue but also improves the overall performance and determinism of the embedded system.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *