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.

FRAM CTPL Library not operating properly after coming out of LPM3.5

I'm Using the FRAM Utility Library version 02.00.00.15.  I just got all the files to compile and all seems ok until I come out of LPM3.5.  I'm having problem getting my target to operate properly after coming out of LPM3.5, one of my peripheral devices, which was powered off is not communicating with the micro (FR5969) so I'm following the debugging advice in section 2.2.2 of the manual and defining CTPL_LPM_DEBUG in the Assembler Preprocessor window under IAR Embedded Workbench (IAR Assembler for MSP430 6.40.1 (6.40.1.950)).

The problem I ran into is errors in ctpl_low_level.s43.

Building configuration: target - Debug
Updating build tree...
ctpl_low_level.s43
Error[431]: Accessing SFR using incorrect size \fram_utils\ctpl_low_level.s43 127
Error[431]: Accessing SFR using incorrect size \fram_utils\ctpl_low_level.s43 127
Error[50]: Undefined symbol:'__STACK_END'      \fram_utils\ctpl_low_level.s43 127
Error[50]: Undefined symbol:'lpmDebug_return'  \fram_utils\ctpl_low_level.s43 127
Error[444]: PC offset must be even.            \fram_utils\ctpl_low_level.s43 127
Error[444]: PC offset must be even.            \fram_utils\ctpl_low_level.s43 127
Error while running Assembler
 
Total number of errors: 6
Total number of warnings: 0

Here's the MACRO code:

; Allow debugging in LPMx.5 by emulating wakeup
lpmDebug    MACRO
#if defined(CTPL_LPM_DEBUG)
        movx.a  #CTPL_RAM_START,R4                  ; fill dst
        movx.a  #(__STACK_END-CTPL_RAM_START),R5    ; fill length
        movx.a  #0xffff,R6                          ; fill value
        fillx   R4,R5,R6                            ; fill RAM contents with 0xffff
        LOCAL lpmDebug_top

So I defined __STACK_END as 2400h since CTPL_RAM_START was defined as 1c00h. This didn't fix the issue. The naming of __STACK_END is ???? Isn't the end of the stack the same place the RAM starts, since the stack starts at the top of RAM and works down?

I didn't see anyone else having this issue. Please help.

Thanks,

-Jim

  • Here's some more...

    The problem is in the coding of the macro of RTC_B... There's issues there.

    But looking at the code and linker file, I do not see where you save all 2048 bytes of RAM. Could you shed a light on this?
  • Hi Jim,

    I've looped in our software engineers about this issue. They will be responding shortly.

    Regards,

    James

    MSP Customer Applications
  • Hi Jim,

    I'm able to reproduce the same errors you're seeing in IAR. I need to get a better understanding of the issue and will continue to look into this next week. I'll be sure to keep you updated with any findings or fixes.

    Regards,

    Brent Peterson

  • Hi Jim,

    It looks like there were a few errors in translating the CTPL_LPM_DEBUG code from CCS assembly syntax to IAR. The attached "ctpl_low_level_macros.m43" should now be correct, I'm able to compile and run it on my system.  Can you please try to compile with the attached version and let me know if this fixes the issue on your end?

    Thank you,

    Brent Peterson

    ; Call statement for different code models
    callx   MACRO   src
    #if defined(__LARGE_CODE_MODEL__)
            calla   src
    #else
            call    src
    #endif
            ENDM
    
    ; Return statement for different code models
    retx    MACRO
    #if defined(__LARGE_CODE_MODEL__)
            reta
    #else
            ret
    #endif
            ENDM
    
    ; Define DMA if using DMA3
    #if defined(__MSP430_HAS_DMAX_3__)
    __MSP430_HAS_DMA__  EQU 1
    #endif
    
    ; Macro for performing copy with either CPU or DMA
    copyx    MACRO    src, dst, len
    #if defined(__MSP430_HAS_DMAX_3__)
            clr.b   &DMA0CTL_L      ; sw trigger, channel 0
            movx.a  src,&DMA0SA     ; set src address
            movx.a  dst,&DMA0DA     ; set dst address
            rra.w   len             ; divide length by 2
            mov.w   len, &DMA0SZ    ; set copy size
            mov.w   #DMASWDW+DMADT_1+DMASRCINCR_3+DMADSTINCR_3+DMAEN+DMAREQ,&DMA0CTL    ; trigger DMA copy
    #else
            LOCAL ctpl_copyLoop
    ctpl_copyLoop:
            movx.w  @src+, 0(dst)   ; copy stack word and increment src ptr
            addx.a  #2,dst          ; increment dst ptr
            subx.a  #2,len          ; decrement stack usage
            jnz     ctpl_copyLoop   ; loop if usage > 0
    #endif
            ENDM
    
    ; Macro for performing fill with either CPU or DMA
    fillx    MACRO    dst, len, val
    #if defined(__MSP430_HAS_DMA__)
            movx.w  val,0(dst)      ; fill first value
            clr.b   &DMA0CTL_L      ; sw trigger, channel 0
            movx.a  dst,&DMA0SA     ; set src address
            movx.a  dst,&DMA0DA     ; set dst address
            rra.w   len             ; divide length by 2
            mov.w   len, &DMA0SZ    ; set fill size
            mov.w   #DMASWDW+DMADT_1+DMASRCINCR_0+DMADSTINCR_3+DMAEN+DMAREQ,&DMA0CTL    ; trigger DMA fill
    #else
            LOCAL ctpl_fillLoop
    ctpl_fillLoop:
            movx.w  val,0(dst)      ; fill dst
            addx.a  #2,dst          ; increment dst ptr
            subx.a  #2,len          ; decrement stack usage
            jnz     ctpl_fillLoop   ; loop if usage > 0
    #endif
            ENDM
    
    ; Macro for configuring DCO for shutdown
    configureDcoShutdown    MACRO   div
    #if defined(__MSP430FR2XX_4XX_FAMILY__)
            bic.w   #SCG0,SR                            ; disable FLL
            mov.w   #DIVM__32+DIVS__1,&CSCTL3           ; Set maximum dividers
            mov.w   #DCORSEL_3,&CSCTL1                  ; Set DCO 8MHz
            clr.w   &CSCTL4                             ; Source MCLK and SMCLK from DCO
            mov.b   div,&CSCTL5_L                       ; Set timeout dividers
    #elif defined(__MSP430FR57XX_FAMILY__)
            mov.b   #CSKEY_H,&CSCTL0_H                  ; Unlock CS registers
            mov.w   #DIVM__32+DIVS__32,&CSCTL3          ; Set maximum dividers
            mov.w   #DCOFSEL_3,&CSCTL1                  ; Set DCO 8MHz
            mov.w   #SELM_3+SELS_3,&CSCTL2              ; Source MCLK and SMCLK from DCO
            mov.b   div,&CSCTL3_L                       ; Set timeout dividers
            clr.b   &CSCTL0_H                           ; Lock CS registers
    #elif defined(__MSP430FR5XX_6XX_FAMILY__)
            mov.b   #CSKEY_H,&CSCTL0_H                  ; Unlock CS registers
            mov.w   #DIVM__32+DIVS__32,&CSCTL3          ; Set maximum dividers
            mov.w   #DCOFSEL_6,&CSCTL1                  ; Set DCO 8MHz
            mov.w   #SELM_3+SELS_3,&CSCTL2              ; Source MCLK and SMCLK from DCO
            mov.b   div,&CSCTL3_L                       ; Set timeout dividers
            clr.b   &CSCTL0_H                           ; Lock CS registers
    #endif
                            ENDM
    
    ; Macro for configuring DCO for wakeup
    configureDcoWakeup  MACRO
    #if defined(__MSP430FR2XX_4XX_FAMILY__)
            bic.w   #SCG0,SR                            ; disable FLL
            mov.w   #DCORSEL_2,&CSCTL1                  ; set DCO to 4MHz (maximum boot freq)
    #elif defined(__MSP430FR57XX_FAMILY__)
            mov.b   #CSKEY_H,&CSCTL0_H                  ; unlock CS registers
            mov.w   #DIVM__2,&CSCTL3                    ; set DCO to 4MHz (maximum boot freq)
            clr.b   &CSCTL0_H                           ; lock CS registers
    #elif defined(__MSP430FR5XX_6XX_FAMILY__)
            mov.b   #CSKEY_H,&CSCTL0_H                  ; unlock CS registers
            mov.w   #DIVM__2,&CSCTL3                    ; set DCO to 4MHz (maximum boot freq)
            clr.b   &CSCTL0_H                           ; lock CS registers
    #endif
                        ENDM
    
    ; Macro for toggling the CTPL benchmark pin.
    benchmark   MACRO
    #if defined(CTPL_BENCHMARK)
            xor.b   #CTPL_BENCHMARK_PIN,&CTPL_BENCHMARK_OUT
    #endif
                ENDM
    
    ; Define RTCIFG if not defined (FR2XX and FR4XX)
    #if defined(__MSP430FR2XX_4XX_FAMILY__)
    #if !defined(RTCIFG)
    RTCIFG   EQU RTCIF
    #endif
    #endif
    
    ; Macro to check for GPIO interrupt event
    lpmDebug_port   MACRO   PXIE, PXIFG
            mov.w   &PXIE,R4                ; Get enabled interrupts
            and.w   &PXIFG,R4               ; Check set interrupt flags
            tst.w   R4                      ; Test if any interrupts were triggered
            jne     lpmDebug_return         ; Jump to return function
                    ENDM
    
    ; Macro to check for RTC interrupt event
    lpmDebug_rtc    MACRO
            mov.b   &RTCCTL,R4              ; Load RTC control register
            and.b   #(RTCIE+RTCIFG),R4      ; Mask bits
            cmp.b   #(RTCIE+RTCIFG),R4      ; Check RTC IE and IFG are both set
            jeq     lpmDebug_return         ; Jump to return function
                    ENDM
    
    ; Macro to check for RTC_B interrupt event
    lpmDebug_rtc_b  MACRO
            mov.b   &RTCCTL01_L,R4          ; Load RTC_B control 01 register
            rrum.w  #4,R4                   ; Shift right
            bit.b   R4,&RTCCTL01_L          ; Mask IFG bits
            jne     lpmDebug_return         ; Jump to return function
            mov.b   &RTCPS0CTL_L,R4         ; Load RTC_B prescale 0 register
            and.b   #(RT0PSIE+RT0PSIFG),R4  ; Mask bits
            cmp.b   #(RT0PSIE+RT0PSIFG),R4  ; Check RTC_B IE and IFG are both set
            jeq     lpmDebug_return         ; Jump to return function
            mov.b   &RTCPS1CTL_L,R4         ; Load RTC_B prescale 1 register
            and.b   #(RT1PSIE+RT1PSIFG),R4  ; Mask bits
            cmp.b   #(RT1PSIE+RT1PSIFG),R4  ; Check RTC_B IE and IFG are both set
            jeq     lpmDebug_return         ; Jump to return function
                    ENDM
    
    ; Macro to check for RTC_C interrupt event
    lpmDebug_rtc_c  MACRO
            mov.b   &RTCCTL0_L,R4           ; Load RTC_C control 0 register
            rrum.w  #4,R4                   ; Shift right
            bit.b   R4,&RTCCTL0_L           ; Mask IFG bits
            jne     lpmDebug_return         ; Jump to return function
            mov.b   &RTCPS0CTL_L,R4         ; Load RTC_C prescale 0 register
            and.b   #(RT0PSIE+RT0PSIFG),R4  ; Mask bits
            cmp.b   #(RT0PSIE+RT0PSIFG),R4  ; Check RTC_C IE and IFG are both set
            jeq     lpmDebug_return         ; Jump to return function
            mov.w   &RTCPS1CTL_L,R4         ; Load RTC_C prescale 1 register
            and.b   #(RT1PSIE+RT1PSIFG),R4  ; Mask bits
            cmp.b   #(RT1PSIE+RT1PSIFG),R4  ; Check RTC_C IE and IFG are both set
            jeq     lpmDebug_return         ; Jump to return function
                    ENDM
    
    ; Allow debugging in LPMx.5 by emulating wakeup
    lpmDebug    MACRO
    #if defined(CTPL_LPM_DEBUG)
            movx.a  #CTPL_RAM_START,R4                  ; fill dst
            movx.a  #(SFE(CSTACK)-CTPL_RAM_START),R5    ; fill length
            movx.a  #0xffff,R6                          ; fill value
            fillx   R4,R5,R6                            ; fill RAM contents with 0xffff
            LOCAL lpmDebug_top
            LOCAL lpmDebug_return
    lpmDebug_top:
    #if defined(PAIFG)
            lpmDebug_port   PAIE,PAIFG  ; Check PORTA IFG's
    #endif
    #if defined(PBIFG)
            lpmDebug_port   PBIE,PBIFG  ; Check PORTB IFG's
    #endif
    #if defined(PCIFG)
            lpmDebug_port   PCIE,PCIFG  ; Check PORTC IFG's
    #endif
    #if defined(PDIFG)
            lpmDebug_port   PDIE,PDIFG  ; Check PORTD IFG's
    #endif
    #if defined(PEIFG)
            lpmDebug_port   PEIE,PEIFG  ; Check PORTE IFG's
    #endif
    #if defined(PFIFG)
            lpmDebug_port   PFIE,PFIFG  ; Check PORTF IFG's
    #endif
    #if defined(__MSP430_HAS_RTC__)
            lpmDebug_rtc                ; Check RTC IFG's
    #endif
    #if defined(__MSP430_HAS_RTC_B__)
            lpmDebug_rtc_b              ; Check RTC_B IFG's
    #endif
    #if defined(__MSP430_HAS_RTC_C__)
            lpmDebug_rtc_c              ; Check RTC_C IFG's
    #endif
            jmp     lpmDebug_top        ; Jump to top
    lpmDebug_return:
            mov.b   #PMMPW_H,&PMMCTL0_H ; Unlock PMM registers
            mov.w   #PMMLPM5IFG,&PMMIFG ; Set LPMx.5 wakeup flag
            mov.b   #0,&PMMCTL0_H       ; Lock PMM registers
            mov.w   #0x0FFFE,R4     ; Reset vector
            mov.w   @R4,PC              ; Jump to reset vector
    #endif
                ENDM
    
    #if defined(__MSP430FR2XX_4XX_FAMILY__)
    
    ; Define FRWPPW if not defined (FR2XX and FR4XX)
    #if !defined(FRWPPW)
    FRWPPW  EQU 0
    #endif
    
    RSEG DATA16_P:DATA:SORT:NOROOT(1)
    ctpl_stateFRAM:
        DC16 0
    RSEG CODE:CODE
    
    ; Macro for unlocking FRAM.
    unlockFRAM  MACRO
            mov.w   &SYSCFG0,R15                        ; Save FRAM state
            and.w   #(BIT1+BIT0),R15                    ; Mask out other bits
            mov.w   #FRWPPW,&SYSCFG0                    ; Unlock FRAM
            mov.w   R15,&ctpl_stateFRAM                 ; Save state to FRAM
                ENDM
    
    ; Macro for restoring FRAM state.
    restoreFRAM MACRO
            mov.w   &ctpl_stateFRAM,R15                 ; Restore state fram FRAM
            bis.w   #FRWPPW,R15                         ; Set FRAM password bits
            mov.w   R15,&SYSCFG0                        ; Restore FRAM state
                ENDM
    
    #else
    ; Macro for unlocking FRAM.
    unlockFRAM  MACRO
                ENDM
    ; Macro for restoring FRAM state.
    restoreFRAM MACRO
                ENDM
    #endif
    

  • Okay...
    Awesome. Thanks. I'll try it and see...
    I've posted another issue with the FRAM Library regarding not implementing the AES save/restore functions. I'd love to see this added. It must of been an oversight. BTW, great job on the library. It works great so far. But please see my post regarding this issue since I added a couple other things.
    Thanks,
    -Jim

**Attention** This is a public forum