Other Parts Discussed in Thread: MSP430FR5959
Tool/software: Code Composer Studio
I thought it would be nice if overwriting code would kick over the processor.. So I started looking at the MPU. There are various bits and pieces of information on how it's supposed to work. However I'm a bit confused just how automagically it works. It's implied that it should "just work" without doing anything as long as you have the "Enable MPU" ticked in the CCS general properties of the project. I'm not quite convinced however..
This is what the default linker file's MPU bits look like for MSP430FR5969:
#ifdef _MPU_ENABLE #define MPUPW (0xA500) /* MPU Access Password */ #define MPUENA (0x0001) /* MPU Enable */ #define MPULOCK (0x0002) /* MPU Lock */ #define MPUSEGIE (0x0010) /* MPU Enable NMI on Segment violation */ __mpu_enable = 1; // Segment definitions #ifdef _MPU_MANUAL // For custom sizes selected in the GUI mpu_segment_border1 = _MPU_SEGB1 >> 4; mpu_segment_border2 = _MPU_SEGB2 >> 4; mpu_sam_value = (_MPU_SAM0 << 12) | (_MPU_SAM3 << 8) | (_MPU_SAM2 << 4) | _MPU_SAM1; #else // Automated sizes generated by Linker #ifdef _IPE_ENABLE //if IPE is used in project too //seg1 = any read + write persistent variables //seg2 = ipe = read + write + execute access //seg3 = code, read + execute only mpu_segment_border1 = fram_ipe_start >> 4; mpu_segment_border2 = fram_rx_start >> 4; mpu_sam_value = 0x1573; // Info R, Seg3 RX, Seg2 RWX, Seg1 RW #else mpu_segment_border1 = fram_rx_start >> 4; mpu_segment_border2 = fram_rx_start >> 4; mpu_sam_value = 0x1513; // Info R, Seg3 RX, Seg2 R, Seg1 RW #endif #endif #ifdef _MPU_LOCK #ifdef _MPU_ENABLE_NMI mpu_ctl0_value = MPUPW | MPUENA | MPULOCK | MPUSEGIE; #else mpu_ctl0_value = MPUPW | MPUENA | MPULOCK; #endif #else #ifdef _MPU_ENABLE_NMI mpu_ctl0_value = MPUPW | MPUENA | MPUSEGIE; #else mpu_ctl0_value = MPUPW | MPUENA; #endif #endif #endif
To start with, from the linker file it appears that without defining _MPU_ENABLE_NMI somewhere, MPU essentially does nothing. Is there a GUI tickbox somewhere for that? It seems to me that there would be only one protected memory region called fram_rx_start. So actually splitting code between FRAM and FRAM2 is not working as intended? The default linker file splits code between FRAM2 and FRAM. "fram_rx_start" seems to be set automagically at the end of the IPENCAPSULATED_MEMORY. Since I don't have IPE active, would the fram_rx_start get assigned to e.g. beginning of FRAM2?
If the IDE is actually as clever as it implies, it seems that it would be enough to put _MPU_ENABLE_NMI to "Predefined Symbols" and add a line to NMI ISR as in the MPU driverlib example?
Alternatively I could go the whole hog and define my own memory regions in the linker file and so on. Which is actually what I did already before I started wondering just how is the MPU getting set up exactly.. Do the flags on MEMORY actually do anything? I modified the linker file to allocate 4+16kB for code/constants/ISR like so:
MEMORY { SFR : origin = 0x0000, length = 0x0010 PERIPHERALS_8BIT : origin = 0x0010, length = 0x00F0 PERIPHERALS_16BIT : origin = 0x0100, length = 0x0100 RAM : origin = 0x1C00, length = 0x0800 INFOA : origin = 0x1980, length = 0x0080 INFOB : origin = 0x1900, length = 0x0080 INFOC : origin = 0x1880, length = 0x0080 INFOD : origin = 0x1800, length = 0x0080 FRAM : origin = 0x4400, length = 0xAF80 FRAMRO (RXI) : origin = 0xF380, length = 0x0C00 FRAMRO2 (RXI) : origin = 0x10000,length = 0x4000
It would be again implied that setting (RXI) would keep that region "hands off" automagically, but.. On subject of flags, Initialize flag I'm not sure about. Intiialize when? After boot? During flashing when the #pragma PERSISTENT stuff gets initialized once?