0
votes

Ok so I am trying to ditch energia texas instruments arduino style ide and I have used IAR for coding a Tiva C series development board where I was able to use pointers to memory locations to perform specific things like toggling led for example. I have had a hard time doing the same on a dev board running a MSP430FR5994 mcu, I know the memory address of the green led pin to be PORT 1 PIN 1 OR P1.1 on the board. I also have included the msp430.h header file for an api to the board from my ide. What I don't understand is why when in debug my code is changing the value of the correct registers to the correct numbers but it is not altering the board. I have also verified that it is connected to the board as it will not proceed to debug with it unplugged. My direct questions are this: 1 I should be able to alter memory locations with no headerfiles or any special api's as long as I know the specific addresses correct? 2 I did not see anything about clock gating in the data sheet and in debug I can see those registers changing values so is there something other than setting the pin direction and value that I need to do?( the default pin function is generic gpio I checked so I left that register alone. Any ideas or pointing out obvious errors in my approach would be very helpful thanks. In the code below I used the header file names as I could not get the direct pointers to work. Also I was confused by the data sheet as the base address for port 1 was written as 0200H which is 5 hex numbers when I was expecting 4 since the chip is 16bit system? I assumed with the offsets it meant 0x202H etc am I incorrect in this assumption? registers during debugging image

ti.com/lit/ds/symlink/msp430fr5994.pdf (datasheet port 1 mem locations page 130)

#include <msp430.h> 
/**
 * main.c
 */
int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    while(1){
    int i ;
    int j ;

    P1DIR = 2;
    //*((unsigned int *)0x204Hu) = 2;

    P1OUT = 2;
    //*((unsigned int *)0x202Hu)= 2;
    for( i = 0; i< 2 ; i++){}

    P1OUT = 0;
    //*((unsigned int *)0x202Hu)= 0;

    for (j = 0 ; j< 2; j++){}


    }

    return 0;
}
2
0200H is 16 bits 4 hex numbers. and yes in that context 0200H = 0x0200 = 0x200 = 0b0000001000000000 = 512old_timer
if you are trying to blink an led unless you have this on a scope you wont see it you need a longer delay and something that the optimizer if you turn on wont remove as dead code.old_timer
you are on the right track though. make the pin an output then in a loop do the on delay, off delay thingold_timer
'H' is not a hexadecimal value. It's datasheet shorthand for "hexadecimal". "0200h" means the same as "0x0200".kkrambo
Do you see the LED toggle if you single-step through the code with the debugger?kkrambo

2 Answers

0
votes

See section 12.3.1 of the MSP430FR59xx User's Guide.

After a BOR reset, all port pins are high-impedance with Schmitt triggers and their module functions disabled to prevent any cross currents. The application must initialize all port pins including unused ones (Section 12.3.2) as input high impedance, input with pulldown, input with pullup, output high, or output low according to the application needs by configuring PxDIR, PxREN, PxOUT, and PxIES accordingly. This initialization takes effect as soon as the LOCKLPM5 bit in the PM5CTL register (described in the PMM chapter) is cleared; until then, the I/Os remain in their high-impedance state with Schmitt trigger inputs disabled.

And here is the example blinky code provided in the MSP430FR599x Code Examples available to download from here.

#include <msp430.h>

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;               // Stop WDT

    // Configure GPIO
    P1OUT &= ~BIT0;                         // Clear P1.0 output latch for a defined power-on state
    P1DIR |= BIT0;                          // Set P1.0 to output direction

    PM5CTL0 &= ~LOCKLPM5;                   // Disable the GPIO power-on default high-impedance mode
                                            // to activate previously configured port settings

    while(1)
    {
        P1OUT ^= BIT0;                      // Toggle LED
        __delay_cycles(100000);
    }
}

You probably need to add that PM5CTL0 &= ~LOCKLPM5; line to your code.

And then single-step through your code in the debugger to observe the LED. Because if you let your code run at full speed the delay loops are way too short to observe the LED flash with your eye.

0
votes

This is derived from one of my examples; I don't have a card handy to test it on, but it should just work or be close.

startup.s

.word hang      /* 0xFFE0 */
.word hang      /* 0xFFE2 */
.word hang      /* 0xFFE4 */
.word hang      /* 0xFFE6 */
.word hang      /* 0xFFE8 */
.word hang      /* 0xFFEA */
.word hang      /* 0xFFEC */
.word hang      /* 0xFFEE */
.word hang      /* 0xFFF0 */
.word hang      /* 0xFFF2 */
.word hang      /* 0xFFF4 */
.word hang      /* 0xFFF6 */
.word hang      /* 0xFFF8 */
.word hang      /* 0xFFFA */
.word hang      /* 0xFFFC */
.word reset     /* 0xFFFE */

reset.s

.global reset
reset:

      mov #0x03FF,r1
      call #notmain
      jmp hang
    
    .global hang
    hang:
      jmp hang
    
    .globl dummy
    dummy:
        ret

so.c

void dummy ( unsigned short );

#define WDTCTL     (*((volatile unsigned short *)0x015C))

#define P1OUT (*((volatile unsigned short *)0x0202))
#define P1DIR (*((volatile unsigned short *)0x0204))

void notmain ( void )
{
    unsigned short ra;

    WDTCTL = 0x5A80;

    P1DIR|=0x02;

    while(1)
    {
        P1OUT |= 0x0002;
        for(ra=0;ra<10000;ra++) dummy(ra);
        P1OUT &= 0xFFFD;
        for(ra=0;ra<10000;ra++) dummy(ra);
    }
}

memmap

MEMORY
{
    rom : ORIGIN = 0xC000, LENGTH = 0xFFE0-0xC000
    ram : ORIGIN = 0x1C00, LENGTH = 0x2C00-0x1C00
    vect : ORIGIN = 0xFFE0, LENGTH = 0x20
}
SECTIONS
{
    VECTORS : { startup.o } > vect
    .text :  { *(.text*) } > rom
    .bss : { *(.bss*) } > ram
    .data : { *(.data*) } > ram
}

build

msp430-gcc -Wall -O2 -c so.c -o so.o
msp430-ld -T memmap reset.o so.o startup.o -o so.elf
msp430-objdump -D so.elf > so.list
msp430-objcopy -O ihex so.elf out.hex

examine output

so.elf:     file format elf32-msp430


Disassembly of section VECTORS:

0000ffe0 <VECTORS>:
    ffe0:   0a c0           bic r0, r10 
    ffe2:   0a c0           bic r0, r10 
    ffe4:   0a c0           bic r0, r10 
    ffe6:   0a c0           bic r0, r10 
    ffe8:   0a c0           bic r0, r10 
    ffea:   0a c0           bic r0, r10 
    ffec:   0a c0           bic r0, r10 
    ffee:   0a c0           bic r0, r10 
    fff0:   0a c0           bic r0, r10 
    fff2:   0a c0           bic r0, r10 
    fff4:   0a c0           bic r0, r10 
    fff6:   0a c0           bic r0, r10 
    fff8:   0a c0           bic r0, r10 
    fffa:   0a c0           bic r0, r10 
    fffc:   0a c0           bic r0, r10 
    fffe:   00 c0           bic r0, r0  

Disassembly of section .text:

0000c000 <reset>:
    c000:   31 40 ff 03     mov #1023,  r1  ;#0x03ff
    c004:   b0 12 0e c0     call    #0xc00e 
    c008:   00 3c           jmp $+2         ;abs 0xc00a

0000c00a <hang>:
    c00a:   ff 3f           jmp $+0         ;abs 0xc00a

0000c00c <dummy>:
    c00c:   30 41           ret         

0000c00e <notmain>:
    c00e:   0b 12           push    r11     
    c010:   b2 40 80 5a     mov #23168, &0x015c ;#0x5a80
    c014:   5c 01 
    c016:   a2 d3 04 02     bis #2, &0x0204 ;r3 As==10
    c01a:   a2 d3 02 02     bis #2, &0x0202 ;r3 As==10
    c01e:   0b 43           clr r11     
    c020:   0f 4b           mov r11,    r15 
    c022:   b0 12 0c c0     call    #0xc00c 
    c026:   1b 53           inc r11     
    c028:   3b 90 10 27     cmp #10000, r11 ;#0x2710
    c02c:   f9 23           jnz $-12        ;abs 0xc020
    c02e:   b2 f0 fd ff     and #-3,    &0x0202 ;#0xfffd
    c032:   02 02 
    c034:   0b 43           clr r11     
    c036:   0f 4b           mov r11,    r15 
    c038:   b0 12 0c c0     call    #0xc00c 
    c03c:   1b 53           inc r11     
    c03e:   3b 90 10 27     cmp #10000, r11 ;#0x2710
    c042:   f9 23           jnz $-12        ;abs 0xc036
    c044:   ea 3f           jmp $-42        ;abs 0xc01a

looks fine the vector table is there and points to the right place, etc.

10,000 might not be enough to see the led blink.

From the datasheet it appears that 0x202 is P1OUT and 0x204 is P1DIR

And you have to get it programmed into the board. I use mspdebug for the boards I have but that program may have stopped working on the eval boards from TI a while ago. And mspdebug supported the Intel hex format. So use objcopy for other formats.

If you were not wanting to use gnu tools then you still have to deal with the vector table and the bootstrap in front of the C code if you are trying to get away from someone's sandbox and do your own thing.

You are on the right path it may be as simple as your delay loops are way way too small and or getting optimized out since they are dead code as written.

If you rely on .bss or .data being initialized then you have more work to do in the linker script and bootstrap. I don't, so don't have that problem, actually wondering why .data was in this linker script...

I've matched addresses to the datasheet for your part, increasing the odds of success. If you use an external function and pass the loop variable to that function (the external can be C or asm, doesn't matter) then the optimizer won't remove it as dead code. That or add volatile on the loop variable and check the disassembly to see that it wasn't removed.