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.
Dear All,
I have been checking each and every question related to this problem including the user's guide, but I haven't been able to write to and read from FRAM in MSP430FR5969. If useful, I am not using TI CCS or IAR but msp430gcc.
The (rather simple) code I am trying to run is as follows:
#define FRAM_START_ADDR 0xD000 #define FRAM_END_ADDR 0xE000 unsigned long *FRAM_write_ptr; unsigned long data; /*---------------------------------------------------------------------------*/ void fram_write(void) { data = 0x00000001; FRAM_write_ptr = (unsigned long *)FRAM_START_ADDR; PRINTF("Writing to 0x%" PRIXPTR "\n", (uintptr_t)FRAM_write_ptr); *FRAM_write_ptr = data; PRINTF("Data %lu VS FRAM_write_ptr %lX \n", data, FRAM_write_ptr); } /*---------------------------------------------------------------------------*/ void fram_read(void) { FRAM_write_ptr = (unsigned long *)FRAM_START_ADDR; PRINTF("Reading from 0x%" PRIXPTR "\n", (uintptr_t)FRAM_write_ptr); data = *FRAM_write_ptr; PRINTF("FRAM_write_ptr %lX\n", data); } /*---------------------------------------------------------------------------*/
And the output I get is:
Writing to 0xD000 Data 1 VS FRAM_write_ptr FFFFFFFF Reading from 0xD000 Data_write_ptr FFFFFFFF ...
Any help would be highly appreciated. Many thanks
Best wishes,
David
I suggest that you try your code again with the first two lines changed to:
#define FRAM_START_ADDR 0x1E00
#define FRAM_END_ADDR 0x1F00
Do not change anything else.
This chip has 2KB of SRAM from 0x1C00 to 0x23FF. I assume that your code does not need all of that.
In other words, I am asking "Can you read/write from/to SRAM?"
Hi @old_cow_yellow
Thanks for your reply. The code effectively works when using the memory space available for SRAM. However, that's SRAM allocated space, therefore volatile, and I already use most of it.
Since FRAM is a SRAM-like memory type, I expected to write to and read from FRAM as in a SRAM, and some people had mentioned this in other posts.
The FRAM address space where I am trying to write is supposed to be unrestricted, so it should be easy to use. But at this point I don't even know if I am actually writing.
Apart from the fact that I believe I am not accessing to FRAM correctly, I was wondering whether, for example, it is necessary to have the MCU completely on (no LPM) for any write/read operations. I have already tried this, but the result hasn't changed.
Any help would be highly appreciated.
Best wishes,
David
Hi All,
I've tried your suggestions. I had -Wall already in my CFLAGS but apparently there is no problem. I have also tried to configure the MPU as follows (I include more code now):
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <inttypes.h> #define DEBUG 1 #if DEBUG #include <stdio.h> #define PRINTF(...) printf(__VA_ARGS__) #define PRINTDEBUG(...) printf(__VA_ARGS__) #else #define PRINTF(...) #define PRINTDEBUG(...) #endif /*---------------------------------------------------------------------------*/ #ifdef FRAM_START_ADDR_CONF #define FRAM_START_ADDR FRAM_START_ADDR_CONF #else #define FRAM_START_ADDR 0xE000 #endif #ifdef FRAM_END_ADDR_CONF #define FRAM_END_ADDR FRAM_END_ADDR_CONF #else #define FRAM_END_ADDR 0xFFFF #endif /*---------------------------------------------------------------------------*/ unsigned long *FRAM_write_ptr; unsigned long data; /*---------------------------------------------------------------------------*/ static void fram_init(void) { /* * MPU segment boundaries: * Border 1 = 0x0E000 [MPUSEGB1 = 0x0E00] * Border 2 = 0x10000 [MPUSEGB2 = 0x1000] * Segment 1 = 0x0D000 - 0x0DFFF * Segment 2 = 0x0E000 - 0x0FFFF * Segment 3 = 0x10000 - 0x13EFF * * Segment 2 is write unprotected. */ MPUCTL0_H = MPUPW_H; MPUSEGB1 = 0x0E00; MPUSEGB2 = 0x1000; MPUSAM = MPUSEG2WE | MPUSEG2RE; MPUCTL0_L &= ~(MPULOCK | MPUENA); MPUCTL0_H = 0; } /*---------------------------------------------------------------------------*/ static uint8_t fram_write(uint32_t *writeAddress, const void *writeData) { data = 0x00000001; FRAM_write_ptr = (unsigned long *)FRAM_START_ADDR; PRINTF("Writing to 0x%" PRIXPTR "\n", (uintptr_t)FRAM_write_ptr); *FRAM_write_ptr = data; PRINTF("Data %lu VS FRAM_write_ptr %lX \n", data, *FRAM_write_ptr); return FRAM_SUCCESS; } /*---------------------------------------------------------------------------*/ static uint8_t fram_read(uint32_t *readAddress, uint32_t *readData, uint16_t len) { FRAM_write_ptr = (unsigned long *)FRAM_START_ADDR; PRINTF("Reading from 0x%" PRIXPTR "\n", (uintptr_t)FRAM_write_ptr); data = *FRAM_write_ptr; PRINTF("FRAM_write_ptr %lX\n", data); return FRAM_SUCCESS; } /*---------------------------------------------------------------------------*/ int main(int argc, char **argv) { msp430_init(); /* Initialize all msp430 pins (PxDIR = 0, PxOUT = 0, * PxSELx =0, PxREN = 0xFF) – each peripheral will * configure the necessary pins as required. * Configure clock: ACLK = LFX, SMCLK = MCLK = DCO = 8MHz. * Also, if SYSRSTIV == SYSRSTIV_LPM5WU, then PM5CTL0 &= ~LOCKLPM5 */ uart1_init(115200); /* Configure UCA1 to use serial communication*/ fram_init(); while(1){ /* Set timer to 1 second, after which we perform a FRAM write and a read operation */ set_timer(1 second); // Here, mem_offset and write_buf are useless considering what I do in fram_write if(fram_write(&mem_offset, &write_buf) == FRAM_ERROR) { PRINTF("Fail: Write to FRAM failed\n"); exit(1); } // Here, mem_offset and read_buf are useless considering what I do in fram_write if(fram_read(&mem_offset, &read_buf, sizeof(read_buf)) == FRAM_ERROR) { PRINTF("Fail: Read from FRAM failed\n"); exit(1); } } } /*---------------------------------------------------------------------------*/
And the output is:
... Writing to 0xE000 Data 1 VS FRAM_write_ptr FFFFFFFF Reading from 0xE000 FRAM_write_ptr FFFFFFFF ...
Any ideas? Thanks in advance.
Best wishes,
David
Thank you for the prompt reply.
I am not sure if you did try the modified code and is explaining that result. Or you are explaining the inevitable result and thus did not try the modified code. Could you confirm?
Now, let us look at it at a different angle. One of the source code line is:
FRAM_write_ptr = (unsigned long *)FRAM_START_ADDR;
Is this line compiled into something like this?
mov.w #0xD000,&FRAM_write_ptr
Another source code line:
*FRAM_write_ptr = data;
Is this line compiled into something like these?
mov.w &FRAM_write_ptr,R15
mov.w &data,0(R15)
mov.w &data+2,2(R15)
Hi All,
Thanks for your help and sorry for the trouble :$
Yeah, the code I included before is just to explain more or less what I intended to do. What I was trying to do however is, from what I understood from the user's guide, to allocate a specific address range (through memory segmentation) and enable write/read access. From Clemens's answer I doubt now that I was actually doing it right!
Anyhow, in reply to old_cow_yellow, for example the function fram_write:
uint8_t fram_write(uint32_t *writeAddress, const void *writeData) { data = 0x00000001; FRAM_write_ptr = (unsigned long *)FRAM_START_ADDR; PRINTF("Writing to 0x%" PRIXPTR "\n", (uintptr_t)FRAM_write_ptr); *FRAM_write_ptr = data; PRINTF("Data %lu VS FRAM_write_ptr %lX \n", data, *FRAM_write_ptr); return FRAM_SUCCESS; }
is compiled as:
uint8_t fram_write(uint32_t *writeAddress, const void *writeData) { data = 0x00000001; 10598: 40 18 92 43 movx #1, &0x020ae;r3 As==01 1059c: ae 20 1059e: 40 18 82 43 clrx &0x020b0 105a2: b0 20 FRAM_write_ptr = (unsigned long *)FRAM_START_ADDR; 105a4: 8f 00 00 e0 mova #0x0e000,r15 105a8: 60 0f aa 20 mova r15, &0x020aa PRINTF("Writing to 0x%" PRIXPTR "\n", (uintptr_t)FRAM_write_ptr); 105ac: 00 18 70 12 pushx.a #57344 ;#0x0e000 105b0: 00 e0 105b2: 01 18 70 12 pushx.a #79644 ;#0x1371c 105b6: 1c 37 105b8: b0 13 0e 4b calla #0x04b0e 105bc: a1 00 08 00 adda #0x00008,r1 *FRAM_write_ptr = data; 105c0: 2f 00 aa 20 mova &0x020aa,r15 105c4: 40 18 9f 42 movx &0x020ae,0(r15) ;0x00000(r15) 105c8: ae 20 00 00 105cc: 40 18 9f 42 movx &0x020b0,2(r15) ;0x00002(r15) 105d0: b0 20 02 00 PRINTF("Data %lu VS FRAM_write_ptr %lX \n", data, *FRAM_write_ptr); 105d4: 2f 00 aa 20 mova &0x020aa,r15 105d8: 1f 12 02 00 push 2(r15) ;0x0002(r15) 105dc: 2f 12 push @r15 105de: 40 18 12 12 pushx &0x020b0 105e2: b0 20 105e4: 40 18 12 12 pushx &0x020ae 105e8: ae 20 105ea: 01 18 70 12 pushx.a #79662 ;#0x1372e 105ee: 2e 37 105f0: b0 13 0e 4b calla #0x04b0e 105f4: a1 00 0c 00 adda #0x0000c,r1 return FRAM_SUCCESS; }
I am starting to believe that it may be a problem of printf. Though I don't understand then when I tried with SRAM address space it worked! Also, shall I modify the MPU registers at all? What I was trying to do before does actually make any sense?
Thanks,
David
I try to avoid using printf. But that does not mean I have any mistrust of it.
Could you try to print out the contents of all MPU registers? (In 4 Hex digits.) They are all 16-bit registers. Their symbolic names are as follows.
MPUCTL0, MPUCTL1, MPUSEGB2, MPUSEGB1, MPUSAM, MPUIPC0, MPUIPSEGB2, and MPUIPSEGB1.
(If your header file does not have these symbolic names, their addresses are 0x05A0, 0x05A2, …, and 0x05AE respectively.)
You enabled read and write access to segment 2 but disabled all access to the other 2 segments so it is a good thing that you never enabled the MPU. At reset, the default values are to allow all access to every segment. To write protect a segment you need to clear the appropriate bit. This is how I protected my code and the vectors in assembly:
mov r9,&MPUSEGB1 ; B1 = CTOP bic #MPUSEG1WE,&MPUSAM ; write protect segment 1 mov #0xfc0,&MPUSEGB2 ; B2 = 0xfc00 (segment 3 is upper mem) bic #MPUSEG3WE,&MPUSAM ; write protect segment 3 mov #MPUPW+MPUENA+MPUSEGIE,&MPUCTL0 ; Enable MPU mov.b #0,&MPUCTL0_H ; disable MPU access
Hi,
That's actually what I did first, and the result was 0x0000 for every register. Then I started looking at google to see whether there was a special way to read from registers, and I got immerse in assembly code ad various options to end up doing nothing in the end as the result didn't change.
I will install CCS on Monday and will play with it. Thanks All for you kind help. I will update with more news.
David
Hi,
I am indeed using a simulator, but I was trying to make this work testing the real hardware.
I made the code work in CCS after fixing a few issues. The code is very very simple. If useful for anyone:
#define MMIO32(x) (*(volatile unsigned long *)(x)) /*---------------------------------------------------------------------------*/ uint8_t fram_write(uint32_t writeAddress, const void *writeData) { if( (writeAddress < FRAM_START_ADDR) || (writeAddress > FRAM_END_ADDR) ) { PRINTF("%s:: not valid address\n", __FUNCTION__); return FRAM_ERROR; } MMIO32(writeAddress) = *(uint32_t*)writeData; return FRAM_SUCCESS; } /*---------------------------------------------------------------------------*/ uint8_t fram_read(uint32_t readAddress, uint32_t *readData) { if( (readAddress < FRAM_START_ADDR) || (readAddress > FRAM_END_ADDR) ) { PRINTF("%s:: not valid address\n", __FUNCTION__); return FRAM_ERROR; } *readData = MMIO32(readAddress); return FRAM_SUCCESS; } /*---------------------------------------------------------------------------*/
I started digging a bit more in the OS environment I am using to program the msp430. I found a problem that I don't know exactly how it is related: the CFLAGS/LDFLAGS I was using to enable 20-bit support. I made a port to work with this msp430 in such OS environment, and it seems I had the CFLAGS/LDFLAGS messed up. Now it works, finally.
I am really grateful for your help, but also very sorry for bothering you so much with all of this.
David
**Attention** This is a public forum