MCF52233 - External INT vs. DMA INT

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

MCF52233 - External INT vs. DMA INT

3,639 Views
Kremer
Contributor I
 Hi all
 
 I´m having a problem regarding interrupts on MCF52233. I´m using code warrior 6.3 and i have an external INT (IRQ4 from EPORT) starting a data aquisition process on my application. It triggers about 240 times per second and after filling a buffer it starts a DMA transfer to my digital filter. When the DMA completes, it´s isr starts a digital filter calculations. All the scheme is working fine, except while the filter routine (in the DMA0 isr) is performing calculations the mcu doesn´t recognize the external IRQ4. Right after the filter finishes, the IRQ4 start flowing again and this cycle goes on.
 I want to detect IRQ4 while the filter is running, eg, while the DMA0 isr is calculating the filter, the IRQ4 can be detected and it´s isr can continue to fill the buffer.
 I think it´s an interrupt priority and level issue.
 I know that IRQ4 is a fixed priority IRQ (midpoint priority) but even when i set the DMA0 interrupt level to 1 and interrupt priority to 1, the IRQ4 detection still can´t take the cpu while the DMA0 isr is still running.
The following line was supposed to set level and priority fro DMA0 to 1 (lowest priority).
 
 MCF_INTC0_ICR9 = (MCF_INTC_ICR_IL(1) | MCF_INTC_ICR_IP(1)); // DMA interrupt level and priority 1
 What i´m forgetting to do? Any hints are welcome.
 
 Thank you
 
 
Alban Edit: mention part number in subject line

Message Edited by Alban on 2007-03-14 06:29 PM

Labels (1)
0 Kudos
6 Replies

448 Views
Arev
Contributor III
Hello,

If you are using C for ISR routine, have a look to the "ISR priority problem on MCF5213 (C.W. 6.3)" Message in the "CodeWarrior Dev Tools" Forum.

I Hope this helps..

Bye 
 
0 Kudos

448 Views
Kremer
Contributor I
 Hi Arev
 
 Thank you for your help.
 Actually, that thread is very interesting, but i was already using __declspec(interrupt) on my code.
 To give it a shot, i tried to do what the release notes tell about with no results. In my opinion this SR write should never be required. Anyway, this compiler has problems with interrupt leveling and priorities and i simply couldn´t keep detecting the IRQ4 when the DMA0 isr is still running, but i´m sure the event that should trigger the IRQ4 is happening.
 For now, i had to create a separate task for filtering calculations and on the DMA0 isr i just enable a flag that let´s this task perform calculations. So DMA0 isr is as short as it could be and doesn´t block the IRQ4 isr anymore. But the problem is still there. Any hints about this leveling and priority is helpful.
 
 Thank you
0 Kudos

448 Views
SimonMarsden_de
Contributor II
Hi

I think the suggestion of using __declspec is a good one. I discovered recently that the default behaviour of the CodeWarrior compiler (for processors which support STRLDSR) is to start the interrupt service routine with the following ColdFire instruction:

    STRLDSR  #0x2700


This will raise the interrupt fence to level 7, thereby blocking any lower priority interrupts. The effect would be that you IRQ4 interrupt is blocked when the DMA ISR is executing - not what you want !

To check if this is the case, try disassembling the start of the DMA ISR, and look for the STRLDSR instruction.

Fortunately, you can change this behaviour. You'll probably find that you have the following declaration in your header files somewhere (e.g. mwerks.h):

    #define __interrupt__ __declspec(interrupt)


To prevent the STRLDSR instruction from being generated at all, change this to read:

    #define __interrupt__ __declspec(interrupt:0)





In fact you can also change the value used as the argument to STRLDSR by specifying e.g:

    #define __interrupt__ __declspec(interrupt:0x2400)



This would cause all interrupt service routines to start with:

    STRLDSR #0x2400


...which is dangerous but occasionally useful if you actually want to drop the interrupt fence from within a high priority ISR to re-enable lower priority interrupts.



Hope this helps


Simon
0 Kudos

448 Views
Kremer
Contributor I
 Hi Simon
 
 Actually i´m using this __declspec "feature" to avoid the SR write but with no results. Check de disassembled code for the ISR routine os DMA0: (first instructions is writing level 7 on the SR).
 
Code:
0000C0A8: 40E746FC2700    strldsr  #0x27000000C0AE: 4FEFFFEC        lea      -20(a7),a70000C0B2: 48D74303        movem.l  d0-d1/a0-a1/a6,(a7)0000C0B6: 43F940000000    lea      0x40000000 (0x40000000),a10000C0BC: 2C49            movea.l  a1,a60000C0BE: 4DEE0C0C        lea      3084(a6),a60000C0C2: 223C00000200    move.l   #512,d10000C0C8: 2016            move.l   (a6),d00000C0CA: 8280            or.l     d0,d10000C0CC: 2C81            move.l   d1,(a6)0000C0CE: 7001            moveq    #1,d00000C0D0: 13400108        move.b   d0,264(a1)0000C0D4: 42B92000069A    clr.l    0x2000069A (0x2000069a)0000C0DA: 203C00000100    move.l   #256,d00000C0E0: 41F920000AD8    lea      0x20000AD8 (0x20000ad8),a00000C0E6: 23880800        move.l   a0,(a1,d0.l)0000C0EA: 41F920000ED8    lea      0x20000ED8 (0x20000ed8),a00000C0F0: 23480104        move.l   a0,260(a1)0000C0F4: 203920000696    move.l   0x20000696 (0x20000696),d00000C0FA: E588            lsl.l    #2,d00000C0FC: 23400108        move.l   d0,264(a1)0000C100: 203C805A0000    move.l   #-2141585408,d00000C106: 2340010C        move.l   d0,268(a1)0000C10A: 223CFFFFFDFF    move.l   #-513,d10000C110: 2016            move.l   (a6),d00000C112: C280            and.l    d0,d10000C114: 2C81            move.l   d1,(a6)0000C116: 7001            moveq    #1,d00000C118: 13C02000192C    move.b   d0,0x2000192C (0x2000192c)0000C11E: 4CD74303        movem.l  (a7),d0-d1/a0-a1/a60000C122: 4FEF0018        lea      24(a7),a70000C126: 4E73            rte

 
 
 Here it is how i declare the ISR:
 
Code:
__declspec(interrupt:0) void dma0_isr(void){  MCF_INTC0_IMRL |= MCF_INTC_IMRL_MASK9;  /* Limpa Interrupção de DMA0 */ MCF_DMA_DSR0 = MCF_DMA_DSR_DONE; /* desabilita transmissão do buffer para cálculo */ en_tx=0;  /* Reconfigura DMA0 */ MCF_DMA_SAR0 = (volatile unsigned long)ad_rd; MCF_DMA_DAR0 = (volatile unsigned long)fir_in32; MCF_DMA_BCR0 = fir_limit*4; MCF_DMA_DCR0 = 0 | MCF_DMA_DCR_INT                  | MCF_DMA_DCR_SINC                  | MCF_DMA_DCR_DINC                  | MCF_DMA_DCR_SSIZE(MCF_DMA_DCR_SSIZE_BYTE)                  | MCF_DMA_DCR_DSIZE(MCF_DMA_DCR_DSIZE_BYTE);  MCF_INTC0_IMRL &= ~MCF_INTC_IMRL_MASK9; /* Habilita Task FIR a calcular */ fir_set=1;}

 
 That´s for the case i don´t do any calculations on DMA isr, only setup a new DMA transfer.
 Seems like __declspec isn´t working. Any hints are welcome.
 
 Thank you all
 
0 Kudos

448 Views
Kremer
Contributor I
Alright, sorry, __declspec wasn´t working on that routine because i was declaring a function prototype wich hadn´t the (interrupt:0) on it, just (interrupt), so that´s why the compiler was generating the SR push and write instruction, even when the isr declaration had the interrupt:0 on it...
0 Kudos

448 Views
SimonMarsden_de
Contributor II
Strange - it works for me.

I tried your actual example code, pasted into a new MCF52223 project created from CodeWarrior stationery...

With your example exactly as it is, I do not get a STRLDSR instruction.

If I change it to:
    _declspec(interrupt) void dma0_isr(void)


...then I get a STRLDSR #0x2700.

If I change it to:

    _declspec(interrupt:0xABCD) void dma0_isr(void)



...then I get a STRLDSR #0xABCD.

I can only guess that we have different versions of the CodeWarrior 6.3 compiler. You could try getting the latest updates from Freescale's web site. If you crack this, I'd be interested to hear the cause.


Cheers


Simon
0 Kudos