Cache coherence problem med STM Cortex M7 processor

Selvom jeg har arbejdet med embedded systemer i mange år, kan jeg stadig støde på ting jeg ikke har prøvet før. Et problem jeg ikke havde stødt på før er et problem, der hedder ”cache coherence”, og som jeg lige har brugt laaaang tid på.

Billedresultat for cortex m7

Problemet viste sig ved, at mit system pludselig begyndte at opføre sig meget underligt og ustabilt. Jeg fandt ret hurtigt ud af, at problemet forsvandt, når jeg reducerede FreeRtos’s heap størrelse, men det tog lang tid, at finde ud af hvorfor. Problemet var at noget af mit RAM forbrug blev flyttet fra TCM (Tightly-Coupled Memory) til SRAM når RAM forbruget oversteg 128K.

TCM er RAM som er non-cacheable (det vidste  jeg ikke), mens SRAM’en er cacheable. Når man så har 2 hardware komponenter, der begge skal accesse de samme adresser i hukommelsen. I mit tilfælde både CPU’en og DMA’en.

Der kan opstå det problem, at CPU’en skriver/læser from cachen, mens DMA’en læser fra SRAM’en før det cache’ede data bliver overført til SRAMen. Det vil sige, at nogle gange så virker DMA transferen, og nogle gange ikke. Det kan virkelig få et system til at opføre sig underligt.

Dette er åbenbart et kendt problem, der hedder ”Cache Coherence”. Jeg bruger en ST micro-controller, og ST har lavet en application note (AN-4839), hvor de skriver ”Always better to use non-cacheable regions for DMA buffers”, men hvordan gør man lige det ?.

 

Det kan gøre på følgende måde:

  1. I dit Linker scriptet reserver man et område til non-cacheable RAM (TCM). I mit tilfælde er de første 128K TCMRAM.
/* Specify the memory areas using single bank configuration*/

MEMORY

{

TCMRAM (xrw)     : ORIGIN = 0x20000000, LENGTH = 128K

RAM (xrw)        : ORIGIN = 0x20020000, LENGTH = 256K

Memory_B1(xrw)   : ORIGIN = 0x20060000, LENGTH = 0x80

Memory_B2(xrw)   : ORIGIN = 0x20060080, LENGTH = 0x80

Memory_B3(xrw)   : ORIGIN = 0x2007C000, LENGTH = 0x17d0

Memory_B4(xrw)   : ORIGIN = 0x2007D7D0, LENGTH = 0x17d0



STARTUP_VECTOR (rx)     : ORIGIN = 0x08000000, LENGTH = 1K

BOOTLOADER (rx)         : ORIGIN = 0x08000400, LENGTH = 63K

EMULATED_EEPROM (rx)    : ORIGIN = 0x08010000, LENGTH = 64K

ISR_VECTORS (rx)        : ORIGIN = 0x08020000, LENGTH = 1280

VERSION_AND_CHKSUM (rx) : ORIGIN = 0x08020500, LENGTH = 8

FW_DESCRIPTION (rx)     : ORIGIN = 0x08020508, LENGTH = 60

PRODUCTION_ID (rx)      : ORIGIN = 0x08020544, LENGTH = 188

BOOTLOADER_IMAGE (rx)   : ORIGIN = 0x08020600, LENGTH = 64K

FLASH (rx)              : ORIGIN = 0x08030600, LENGTH = 1899008

}

..

.DMASection     : { *(.DM_Buff_section) } >TCMRAM AT> FLASH

..

 

2. I din kode laver, du en global variable til,at indeholde alle de variable der skal være I TCM RAM

 

__attribute__ ((__section__(".DMASection"), used)) TCMRAM_s TCMRAM;

  1. Når du skal bruge TCMRAM et andet sted i kodeN, laver du en extern declartion to TCMRAM således
extern TCMRAM_s TCMRAM;



.

.

TCMRAM.cliUart.txBuffer[0]= cOutChar;

/Flemming Jahn

 

 

 

 

 

 

 

Leave a Reply

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