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.

Reading and Writing to FRAM2 on MSP430FR5994 + printf

Other Parts Discussed in Thread: MSP-EXP430FR5994, MSP430FR5994

(Original thread: )

Hi Katie,

This all appears to be great [the settings arrived at by you and Steven] and I think I will be taking advantage of this, but I do seem to have one additional problem.  I don't seem to be able to use printf("<string>") commands to send messages to the console.  Is this because we're using the large memory model now?  Would there be an easy fix for that?  

I'm using  Version: 6.1.3.00034 of Code Composer Studio.

The exact location the printf statement gets stuck at seems to be in a __TI_decompress_rle_core function within a file called "copy_decompress_rle.c"  The code I found there is copied below:

      /*---------------------------------------------------------------------*/
      /* MSP doesn't use memset for code size reasons and the memset won't   */
      /* work for the large code, small data model.                          */
      /*---------------------------------------------------------------------*/
      while(run_len--) WRITE8_ADV(outbuf, ch);

Thanks for any help you could render.

Regards,

- Tom

  • Hi Tom,

    I suspect that the watchdog timer (WDT) is timing out before you reach main due to a large number of initialized values perhaps. This would explain why you get trapped in the c init code that happens before main.  Please see this earlier post: . Basically, you just need to add this function to your project:

    int _system_pre_init(void)
    {
    
    WDTCTL = WDTPW + WDTHOLD;    /* disable watchdog timer  */
    return 1;
    
    }

    For using printf, there is some guidance here: http://processors.wiki.ti.com/index.php/Printf_support_for_MSP430_CCSTUDIO_compiler  and here http://processors.wiki.ti.com/index.php/Tips_for_using_printf

    However, we usually recommend against using printf if possible on MSP430 because it consumes so much system resources. Most people use other forms of debugging (toggling pins, sending data through simple UART routines, etc) instead.
    Regards,

    Katie

  • Hi Katie,

    Thanks for the response. I'm still trying to get the printf() statement working. The WTD might not be the issue, though.

    Here is some more information. I have a MSP-EXP430FR5994 LaunchPAD Development Kit. The silkscreen on the LaunchPad PCB itself indicates Rev 1.1. The actual part markings on the MSP430FR5994 chip itself span across 3 lines. The first line is: (TI-LOGO) 5CA8VTW G4 (with G4 underlined). The second line is: X430FR5994. The third line is REV A

    The version of CCS I'm using is 6.1.3.00034.

    The test program I'm running is quite simply a modified version of TI's demo "Blink The LED". The entire code may be found embedded below. The program will run and can be debugged so I'm sure it is reaching main(). FRAM2 writes and reads have been validated to work properly (i.e. I can pause the program after a read and validate that the arbitrary data sent to FRAM2 is read back correctly). The problem happens when the line for printf is uncommented. When trying to step over that command, the program will hang up at the __TI_decompress_rle_core function in the copy_decompress_rle.c file. I don't know what that means.

    A number of modifications were made to the project settings to access the FRAM2 memory per the suggestions I've found in the previous posts. These include setting the "data memory model" to large. Also changed were the settings for the MPU (as shown in the image below - which should match the settings found in previous posts). Unchanged were the library function assumptions for printf support (still set to minimal) and MSP430 Linker Basic Options of stack/heap size. I did try to increase those temporarily, but to no avail. The linker command file code was also modified per the suggestions found in the previous posts. Again, a code snippet for the relevant changes is embedded below.

    I'd really like to use the printf command because it is easy to use and I've used it before (prior to making changes to accommodate FRAM2 access). I want to continue using it to send debug messages [during the development phase of our project]to the console window within CCS over the USB interface from the Launchpad. I find this very helpful. The actual program I'm developing uses the RTC to sleep and wakes up with an Calendar Alarm Interrupt. Once awake, it samples a suite of sensors (e.g. accelerometer) and sleeps in-between samples [using a timer and associated interrupt] until a predetermined number of samples have been taken. Once all the data is "logged" (in FRAM2), it will be processed prior to resetting the RTC again. The messages help me know what the device is doing without pausing the program and losing correlation between the real time and the RTC (which is paused when the program is paused). That being said, I'm intrigued about your comment regarding "sending data through simple UART routines". If there is a way to not use printf to achieve the same result over the USB interface to the CCS console, I'd be interested to hear about it.

    Thanks so much,

    - Tom

    P.S. Internet reading makes me wonder if the console I/O Buffer memory definitions need to also be updated (.cio in the linker command file), but I don't know enough about that.  More reading makes me wonder about whether or not printf will even work at all in the large memory model (e.g. https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/37516).  Either way, I could really use some help because there are so many more details about using the MSP430 that I expected when I started this project (it's not as easy as I expected it to be).

    Anyway, here are the embedded details about the modified simple program that I'm testing for the FRAM access with printf.

    #include <msp430.h>
    #include <stdio.h>
    
    #pragma PERSISTENT(fram_data)
    unsigned short fram_data[0x02] = {0};
    unsigned short read_value;
    
    int main(void) {
        WDTCTL = WDTPW | WDTHOLD;               // Stop watchdog timer
        PM5CTL0 &= ~LOCKLPM5;                   // Disable the GPIO power-on default high-impedance mode
                                                // to activate previously configured port settings
        P1DIR |= 0x01;                          // Set P1.0 to output direction
    
        printf("Hello");
    
        for(;;) {
            volatile unsigned int i;            // volatile to prevent optimization
    
            __data20_write_short((unsigned long int)fram_data, 0xA4);
            read_value = __data20_read_short((unsigned long int)fram_data);
    
            P1OUT ^= 0x01;                      // Toggle P1.0 using exclusive-OR
    
            i = 10000;                          // SW Delay
            do i--;
            while(i != 0);
        }
    
        return 0;
    }

        GROUP(RW_IPE)
        {
    
            GROUP(READ_WRITE_MEMORY)
            {
    
                //.TI.persistent : {}              /* For #pragma persistent            */
                .cio           : {}              /* C I/O Buffer                      */
                .sysmem        : {}              /* Dynamic memory allocation area    */
            } PALIGN(0x0400), RUN_START(fram_rw_start)
    
            GROUP(IPENCAPSULATED_MEMORY)
            {
    
                .ipestruct     : {}              /* IPE Data structure             */
                .ipe           : {}              /* IPE                            */
                .ipe_const     : {}              /* IPE Protected constants        */
                .ipe:_isr      : {}              /* IPE ISRs                       */
            } PALIGN(0x0400), RUN_START(fram_ipe_start) RUN_END(fram_ipe_end) RUN_END(fram_rx_start)
    
        } > 0x4000
    
        .TI.persistent : {} >> FRAM2
    	.TI.noinit : {} >> FRAM2
    
        .cinit            : {}  > FRAM          /* Initialization tables             */
        .binit            : {}  > FRAM          /* Boot-time Initialization tables   */
        .pinit            : {}  > FRAM          /* C++ Constructor tables            */
        .init_array       : {}  > FRAM          /* C++ Constructor tables            */
        .mspabi.exidx     : {}  > FRAM          /* C++ Constructor tables            */
        .mspabi.extab     : {}  > FRAM          /* C++ Constructor tables            */
        .text:_isr        : {}  > FRAM          /* Code ISRs                         */
    
    #ifndef __LARGE_DATA_MODEL__
        .const            : {} > FRAM           /* Constant data                     */
    #else
        .const            : {} >> FRAM | FRAM2  /* Constant data                     */
    #endif
    
    #ifndef __LARGE_DATA_MODEL__
        .text             : {} > FRAM           /* Code                              */
    #else
        //.text             : {} >> FRAM2 | FRAM  /* Code                              */
        .text             : {} >> FRAM
    #endif

  • Hi Tom,

    I took a look into your issue - thanks for providing so much detail. I was able to reproduce the problem on my MSP-EXP430FR5994 Launchpad. The problem in this case is your linker file. Currently, it is placing .cio and .sysmem, used for the C I/O buffer and the heap, at the beginning of FRAM in the area labeled "READ_WRITE_MEMORY". However, this area isn't really read + write access because of the manual configuration in the MPU where you set FRAM2 as the only read + write area.

    We don't really want the heap and cio to be in the upper memory. So we have a couple of options:

    1. put .cio and .sysmem in RAM. This is easiest but it does use up some of your limited RAM.

    2. put .cio and .sysmem in a third section of FRAM that we also define as read + write access.

    For implementing option 1, you can simply comment out .cio and .sysmem from GROUP(READ_WRITE_MEMORY). Then right before you have your lines for .TI.persistent :{} >> FRAM2, you can add these lines:

    .cio           : {} > RAM             /* C I/O Buffer                      */
    .sysmem        : {} > RAM             /* Dynamic memory allocation area    */

    Then, you will also need to go to your Project > properties > Build > Advanced options > Language options, ande select level of printf support : full. Additionally, you will have to increase the heap size as described here:

    Finally, if you are trying to view the console output in CCS, make sure you have the console open, as well as you have to make sure the data will flush. I did this by adding \n to the end of your "Hello" message. You can also do this with a flush command (see the Flushing section here )

    As you can see, this is going to take up a lot of RAM (320 bytes for the heap) and it can also take up a lot of your stack. Additionally, this method is outputting back to the PC by actually using a breakpoint (invisibly to the user) so that the debugger can pull the data out. That means you could see performance impacts e.g. if you output waveforms on other pins, because it is actually halting the part for a moment to get this data out. This is why we typically recommend using something besides printf to get data out of the device. The MSP-EXP430FR5994 Launchpad includes a backchannel UART for this purpose - one of the UART modules on the device is connected through the emulation circuitry back to the USB and the PC. So you can send and receive data to a COM port on the PC using this UART module. If you check the MSP-EXP430FR5994 Launchpad user's guide www.ti.com/lit/pdf/slau678 section 2.2.4 Application (or Backchannel) UART, you can find more information about interfacing with this from the PC side. For your code, you need to write code for the eUSCI_A0 module to initialize and send )(and potentially receive) data via UART (typically we recommend using 9600 baud, none-parity). There are code examples for UART found here:

    Driverlib-style code:

    Register-level style code:

    Regards,

    Katie

**Attention** This is a public forum