HCS12 (MC9S12C32) WAI and Trigger C Occurred

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

HCS12 (MC9S12C32) WAI and Trigger C Occurred

4,985 Views
Deadstar
Contributor I
Hey there,

I am quite new to using the HCS12 and am having some problems. I am using the simple code below to try and create a simple output with a period of 64microS. I am doing it this way to expand on it later.

The problem I am having is that every so often periods are missed out, ie the output goes to 1 or 0 for say 10 cycles. I have no idea why it is doing this and it appears to be random. When I remove the WAI instruction it works perfectly and there are no missed periods. Does anyone know what is wrong?

Code:
MyCode:     SECTIONmain:Entry:                                    LDS #__SEG_END_SSTACK   ; Initialise Stack Pointer                                 BSET DDRT, #$01         ; Enable port T output            BSET TIOS, #%00000010   ; Set TIOS (Set TC1 to output compare)            BSET PTT, #$01          ; Set Port T to 1                        MOVB #$80, TSCR1        ; Timer enable                        LDD TCNT                ; Set TC1 to triger in 1ms             ADDD #256            STD TC1                        BSET TFLG1, #%00000010  ; Reset interrupt flag                        BSET TIE, #$02          ; Enable Interrupt for TC1                        CLI                        SPIN:       WAI                     ; Wait for interrupt then loop forever            BRA SPIN                        ISR_TC1:                                    LDAA PTT             EORA #$01                           STAA PTT                ; Set output to 1            LDD TC1                 ; Set TC1 to trigger in another 1ms            ADDD #256                          STD TC1                                       LDAA #$02               ; Reset the flag            STAA TFLG1                        RTI                                                                            

 I have used interrupts and timers before and they have worked OK. I am just not sure what the WAI is doing.

My second question is when a put a PLL code in here I get the error when I debug using P&E multilink "Trigger C Occured" when using the WAI statement. Why am I getting this error?

Thanks in advance,

Colin



Message Edited by Deadstar on 2008-02-13 06:20 PM
Labels (1)
0 Kudos
15 Replies

1,056 Views
Deadstar
Contributor I
My knowledge of the setup aint great so please bare with me.

Even if i just press the reset button on the board without using the debugger I get the same problem. Is that consistent with your theory?

Thanks

Colin
0 Kudos

1,056 Views
kef
Specialist I
Colin,
 
is /XIRQ pulled high? /XIRQ pin pulled low wakes the target even if X bit is set. Please check that it's not floating or pulled low by some external hardware.
 
WAI shouldn't interfere with BDM, unless you have CWAI or SYSWAI bits set. Please check CLKSEL register description. CWAI stops core clocks in wait mode and SYSWAI stops system (almost all) clocks. Of course BDM is not working in wait mode if any of these bits are set. I'm using CWAI in production firmware. It allows to keep all necessary peripherals clocked, but saves few mA's.
 
0 Kudos

1,056 Views
Steve
NXP Employee
NXP Employee
kef may have something. There may be other interrupts in the system.
If this is IRQ or XIRQ then they will have a higher priority than the timer interrupt. Now since you set the time for the next timer interrupt based on the "last" output compare value there is the possibility that you may not reach the ISR before the "next" time that you store. If this happens the OC will have a "next" value that is actually "in the past". The timer ISR will not occur before until the timer loops round again.
If this is the case the WAI is kind of a red-herring since it is simply adding a period where all interrupts are temporarily ignored which increases the possibility that a pending higher level interrupt can occur. Any other long instruction would have the same effect.
Check that your IRQ and XIRQ pins are pulled to VDD by a suitable resistor.
0 Kudos

1,056 Views
Deadstar
Contributor I
Hey there,

Thanks again guys for all the help.

I have checked the relevent IRQ and XIRQ pins and they are pulled to logic high.

I think I am gonig to abandon the quest for WAIT at this stage and move on. Thanks again, Ill probably come back to it later.

Another strange thing has developed though.

I am trying to use PORTA to create my output which involves using an interrupt to change it twice every 64uS.

My code is given below.

Code:
; code sectionMyCode:     SECTIONmain:Entry:            LDS #__SEG_END_SSTACK   ; Initialise Stack Pointer                                    MOVB #$10, DDRB         ; Enable port A and B output            MOVB #$10, PORTB        ; Set Port B to 1 and A to 0            MOVB #$01, DDRA            MOVB #$00, PORTA                                    BSET TIOS, #%00000010   ; Set TIOS (Set TC1 to output compare)                        MOVB #$80, TSCR1        ; Timer enable                        LDD TCNT                ; Set TC1 to triger in 1ms             ADDD #512               ; Start first sync in 64microS            STD TC1                        BSET TFLG1, #%00000010  ; Reset interrupt flag                        BSET TIE, #$02          ; Enable Interrupt for TC1                        LDX #$0000              ; Set linenubmer to 240            STX LINENUMBER                        LDAA #$01               ; Set first sync to be            STAA SYNCON            LDAA #$00            STAA SYNCOFF                                    LDAA #$01               ; Start with horizontal sync            STAA DDRA            LDAA #$00            STAA PORTA                        CLI            ;************************ Loop Forever ************************            SPIN:       BCLR FLAG, 1            BRCLR FLAG, 1, *   ; Wait for interrupt                   ;********************* Output Video Data *********************            LDX LINENUMBER            CPX #2         ; If line number is <= 2       ;22                   BLE NOVIDEO     ; or >= 5 display no video    ;308            CPX #5            BGE NOVIDEO                                                               ; Else            LDAB #$1E       ; Wait for 375nSCOUNTER:    DBNE B, COUNTER            LDAA #$FF       ; Display logic 1 (white)            STAA PORTB            LDAB #$2C       ; Wait for 5.5uSCOUNTER2:   DBNE B, COUNTER2                        LDAA #$00       ; Display 0 again            STAA PORTBNOVIDEO:    BRA SPIN        ; Loop forever                        ;**************************************************************ISR_TC1:    ;                ;**************************************************************            LDD TC1         ; Set TC1 to trigger in another 64us            ADDD #512                          STD TC1                          MOVB SYNCON, PORTA  ; Start the sync pulse      ;4                         LDX LINENUMBER                                  ;1            INX             ; Increment line number         ;1            STX LINENUMBER                                  ;1            CPX #6          ; If the line number is 6       ;2    310            BNE DEC1                                        ;3/1            ;********** Create Vertical Sync Pulse ************************                                                              LDAA #$01                                       ;1            STAA SYNCON       ; Sync pulse will be short Hi ;1            LDAA #$00                                       ;1            STAA SYNCOFF                                    ;1            BRA ENDISR                                      ;3;**************************************************************            DEC1:       LDX LINENUMBER   ; If line number is 9 create   ;1            CPX #9         ; a horizontal sync              ;2   313            BNE ENDISR                                    ;3/1                       ;********** Create Horizontal Sync Pulse ***********************             HORSYNC:    LDAA #$00                                       ;1            STAA SYNCON       ; Sync pulse will be short Lo ;1            LDAA #$01                                       ;1            STAA SYNCOFF                                    ;1                        LDX #$0001        ; Set line number back to 0   ;1            STX LINENUMBER                                  ;1 ;**************************************************************           ENDISR:     NOP                                             ;1            NOP               ; Add waits to create sync    ;1            NOP               ; pulse of about 5 microS     ;1            NOP                                             ;1            NOP                                             ;1            NOP                                             ;1            NOP                                             ;1            MOVB SYNCOFF, PORTA ; End the sync pulse        ;4                        BSET FLAG, 1      ; Set the flag to keep main                              ; code in wait state.                                      LDAA #$02         ; Reset the TC7 flag            STAA TFLG1            RTI

 Now the strange thing that happens is that the output varies from -400mV to + 300mV rather than from 0V. Why does this negative appear and is there any way around it?

Thanks again in advance,

Colin


Steve wrote:
kef may have something. There may be other interrupts in the system.
If this is IRQ or XIRQ then they will have a higher priority than the timer interrupt. Now since you set the time for the next timer interrupt based on the "last" output compare value there is the possibility that you may not reach the ISR before the "next" time that you store. If this happens the OC will have a "next" value that is actually "in the past". The timer ISR will not occur before until the timer loops round again.
If this is the case the WAI is kind of a red-herring since it is simply adding a period where all interrupts are temporarily ignored which increases the possibility that a pending higher level interrupt can occur. Any other long instruction would have the same effect.
Check that your IRQ and XIRQ pins are pulled to VDD by a suitable resistor.




0 Kudos

1,056 Views
MJW
NXP Employee
NXP Employee
Colin,

yes, if you see the same thing when pressing the reset button, that would fit my theory.

Another thing to keep in mind: kef mentioned SYSWAI and CWAI. Even if neither SYSWAI nor CWAI bits are set, BDM functions are still reduced to the hardware command set because BDM cannot cause a wake-up and firmware commands require the CPU to be active.

-MJW
0 Kudos

1,056 Views
JimDon
Senior Contributor III
First of all, do you mean you want a square wave with a 64us period? Or some kind of a pulse?
Please clarify. You probably need to set a low time as well.
I don't see you setting a mode in TCTL2 which means the timer is disconnect from the pin.
I'm guessing you want "Clear OCn output line to zero", which for channel 1 would be set bit 3 in  this register.
(see page 23 in the spec).


Why are you using the WAI instruction? Why not just loop. No doubt this causes a problem for the BDM, so why do it.
Most of the time "C" is used, so this instruction is rarely used. You can use it, but it may cause untested problems with the BDM.

As for your PLL code, please post it or we can not comment on it. Does it work without the WAI?
0 Kudos

1,056 Views
Deadstar
Contributor I
Thanks for the reply.

Why does the WAI statement mess things up? I would like to run some code after the ISR returns to the main code, hence why the WAI seemed so enticing. Is there another way?

Thanks again,

Colin
0 Kudos

1,056 Views
bigmac
Specialist III
Hello Colin,
 
The usual method for an ISR to control code execution within the main loop is to create a bit flag.  The ISR code would set the flag, and the flag status would be polled within the main loop to determine whether a section of code should be executed, or not.
 
Like JimD, I cannot visualize the circumstances where the use of WAI would be required.  To significantly reduce power consumption, use of one of the stop modes would give much lower power, but this does not seem to be your reason for using WAI.
 
It may have a very minor effect on the latency of the next interrupt, since there would be no need to complete the current instruction, before commencing the interrupt.  This would give a fixed number of cycles, rather than a slightly variable number, for the ISR code to commence execution.
 
But this does not provide an explanation of your observation.  Do you still observe the irregularity using JimD's modified ISR code?
 
Regards,
Mac
 


Message Edited by bigmac on 2008-02-14 02:13 PM
0 Kudos

1,056 Views
JimDon
Senior Contributor III
Well, I've been thru the spec, and I don't see any reason for this behavior.
Since the system clocks are supposed to still be running, the BDM module should work (though there could be a problem with the BDM it self) and the the timer should function as expected, as should the PLL.

I am not by my 12 board right now, but perhaps mac can try it. I  will try it later.

Nor do I see anything in the errata for this part.
Also, you code looks fine. In fact, it is very nicely done, and I don't see that you missed anything either.
Until we get to the bottom of this, you can use the code I illustrated to simulate the wait instruction.
BTW If you leave all the clocks running, WAI doesn't seem to reduce the power much, as the core is still all running.

Simluate WAI:

BCLR FLAG,1
BRCLR FLAG, 1, *


0 Kudos

1,056 Views
Deadstar
Contributor I
I have not been at my board since Jim's comment so I have not been able to try it so I will give it a bash today.

The reason I am looking to use the wait is I need to accurately go to the ISR every time it is called - i.e. I cannot afford a few extra cycles added in so I assumed the WAI would keep it constant every time. Would there be another way to do this without the WAI?

Thanks again for your help and Ill post again once I have tried Jim's suggestion.

Thanks again,

Colin


Message Edited by Deadstar on 2008-02-14 08:24 AM
0 Kudos

1,056 Views
MJW
NXP Employee
NXP Employee
Hello,

some things I want to add, about the WAI instruction:

Other than saving the (varying) time to wait for an instruction boundary, WAI can have another positive effect on interrupt latency: it does pro-active interrupt stacking. There is no need to do this again, if an interrupt finally causes a wake-up - so this 5 cycles (at least) are saved on ISR entry.

Also, WAI shuts down the CPU. This does save some power, but (of course) not as much as the STOP modes would do.

-MJW

0 Kudos

1,056 Views
Deadstar
Contributor I
Thanks for your input MJW. So why does the WAI instruction cause the output to jump in what appears to be a random fasion?

Colin
0 Kudos

1,056 Views
MJW
NXP Employee
NXP Employee
Hello Colin,

the WAI instruction itself is probably not causing this problem.
But, as JimDon mentioned above, BDM cannot be used while the core is in wait mode.
So without knowing your exact setup, my guess would be that this is caused by the debugger connected to BDM (maybe it thinks it has lost sync with the MCU and tries to re-initialize/reset the target?).

-MJW
0 Kudos

1,056 Views
Deadstar
Contributor I
My basic goal is to run code every 64microS to change the output of portT. My code will grow alot more complicated than this but I am using this as a basis to start from. I am just curious as to why it doesnt work.

I did not set TCTL2 as I do not want to do anything with the pins. Should I just set it to $00?

This does produce a square wave with a period of 64microS but every so often the periods just dissapear then re-emrege. This happens whether I am running it through the debugger or just flash the code onto the device then reset it using the reset switch.

I am using a wait because in my future code I would like to run some code after the interrupt depending on other variables.

The PLL code is given below. When the WAI is not used and the PLL code is included everything works OK.

Code:
;**************************************************************;* Set PLL                                                    *;* PLLCLK = 2*OSCFREQ*(SNYR+1)/(REFDV+1)                      *;* BUSFREQ = PLLCLK/2                                         *;* SYNR = 2 & REFDV = 1 to give busfreq = 24MHz               *;**************************************************************               MOVB #$02, SYNR         ;Set values of registers        MOVB #$01, REFDV        MOVB #$00, CLKSEL        MOVB #$D1, PLLCTL         NOP                     ;Wait for clock to lock        NOP       PLLWAIT:        LDAA CRGFLG        BITA #$08               ;Check if clock has locked        BEQ PLLWAIT        LDAA CLKSEL             ;If clock has locked set PLL        ORAA #$E0        STAA CLKSEL;**************************************************************

 Sorry about my lack of knowledge, I am still learning! Thank you for helping, I appreciate it very much.

Colin

0 Kudos

1,056 Views
JimDon
Senior Contributor III
Try this it will generate the square wave and you don't need the the WAI instruction.


; variable/data section
MY_EXTENDED_RAM: SECTION

FLAG        ds.b 1



MyCode:     SECTION
main:
Entry:
          
            BSET DDRT, #$01         ; Enable port T output
            BSET TIOS, #%00000010   ; Set TIOS (Set TC1 to output compare)
            BSET PTT, #$01          ; Set Port T to 1

            BSET TCTL2,3             ; Set ch 1 to output toggle
            BCLR TCTL2,2
           ;
            MOVB #$90, TSCR1        ; Timer enable w /Fast clear.
            MOVB #0, FLAG
            LDD TCNT                ; Set TC1 to triger in 1ms
            ADDD #256
            STD TC1

            BSET TIE, #$02          ; Enable Interrupt for TC1

            LDS  #__SEG_END_SSTACK     ; initialize the stack pointer
            CLI                        ; enable interrupts
            BRCLR FLAG, 1, *         
           
EndlessLoop:
            BRA   EndlessLoop          ; restart.


            
ISR_TC1:         
                         
; Don't need to do this, as the output will toggle on it own.
;            LDAA PTT
;            EORA #$01              
;            STAA PTT                ; Set output to 1
            BSET FLAG,1
            LDD TC1                 ; Set TC1 to trigger in another 1ms
            ADDD #256             
            STD TC1   
; We set fast clear mode, so don't need this either.                      
;            LDAA #$02               ; Reset the flag
;            STAA TFLG1
           
            RTI
           









Message Edited by JimDon on 2008-02-13 05:28 PM
0 Kudos