Constant UART ISRs

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

Constant UART ISRs

Jump to solution
2,041 Views
randylee
Contributor V

I'm attempting to being up a UART in MCUexpresso SDK 2.4 on an MK22FN part in interrupt mode (upper layers to deal with unexpected reception of packets from a peripheral).

This device (UART 0) is getting initialized as part of the regular BOARD_InitPeripherals() but I've turned off turning on the interrupts as I've got a bunch of setup to do prior to getting any ISRs. TX watermark is set to 0; RX watermark is set to 1 so as to get ISR for each char in and out.

As soon as I turn interrupts on (NVIC_SetPriority() followed by EnableIRQ()) for the UART I get a RX_TX (not error) ISR and it is constant.  Lines in and out look normal and idle.

Inside the ISR I grab the status with UART_GetStatusFlags() and it returns 0xC00000C00 which is pretty much what I'd expect given that there is nothing in the UART at that point far as I know (in or out).

The problem is that I return out of the ISR and get another one just as soon as I get out.  I can't figure out how to get the UART to stop giving me ISRs here.

I don't have problems on this part using KDS and PEX versions of this.  I've looked through that code and don't see anything I'm missing here far as I can figure. Adding the demo code from ...\driver_examples\uart\interruptuart_interrupt.c to this project, it acts the same way.

Any ideas?  I'm out of them myself...

Tags (2)
1 Solution
1,776 Views
randylee
Contributor V

Ah.  Looking in PEX code (yes, old code is better), I think I see what's going on.

In PEX the Interrupt is enabled when it goes into send block mode and then disabled in the ISR when it sees that we're at the end of a block (after calling the user done function).

If this code is correct, then this part is acting as it designed to do: It has an empty TX and it's going to keep telling that to you until such time as you tell it to shut up about it.

So basically I'm not using this SDK like it's intended to be used (it's assuming you're using all the normal directions into it with all kinds of TransferStart things and whatnot and creating handles and yada, yada, yada.  Come into this SDK from the side and you're in real trouble.

Short answer: Problem solved: cockpit error abetted by lack of documentation.

View solution in original post

0 Kudos
14 Replies
1,776 Views
scottm
Senior Contributor II

I'm not using the SDK so I'm not sure how you're expected to do it there, but it sounds like the RDRF flag isn't getting cleared.  That's assuming it's a receive data interrupt you're getting.  To clear it, you need to read S1 while it's set, and then read D.

This, incidentally, is the main reason I'm not using the SDK.  The documentation is next to worthless and you still need to read the reference manual to figure out how to use the hardware properly - and then you've got to try to piece together how to make the SDK do what you want.  I can't even tell what your status flags mean from the SDK docs - it doesn't establish a relationship between the hardware registers and the results of UART_GetStatusFlags().

I would set a breakpoint in your ISR, and watch the UART registers as you step through.  RDRF should be clear before the ISR exits.  If it is and you're still going right back to the ISR, check the other flags and see if you have some other interrupt source.  Watch the registers directly, not just what the SDK API gives you.

I'm going to rant a bit here in case anyone from NXP is listening.  I've got the SDK API reference manual in front of me, and the first thing I notice is that there's no version number given - it just says Rev 0.  I skip to the UART section and there's an overview (33.1) that just lists four modules, with not a word of description for any of them.

Reading down a bit, I see "Transactional receive APIs support the ring buffer".  What ring buffer?  The definite article 'the' suggests a specific ring buffer that should be known to the reader.  Does it support a ring buffer?  Or is the ring buffer something they forgot to explain?

All of the use cases refer to SDK locations and provide no additional explanation.  I will say that this is marginally an improvement over the last version, where non-functional and syntactically invalid example code was given here.  But why are we reading the manual at all and not just looking at the source, in that case?

 

Now we get more automatically-generated clutter.  There is very little of substance for several pages, and section 33.2.3.3.0.78 takes up most of a page while providing zero useful information.

UART_Init()'s description has a little bit of useful text, but notice that it just says srcClock_Hz is "UART clock source frequency in HZ".  No hint as to how that's determined - you have to go back to the reference manual.  But the UART section doesn't say what the clock source is.  So you flip back to the chip configuration section and check the UART configuration - but the block diagram is useless and doesn't show any clocks.  In the text you eventually find that UARTs 0 and 1 use the core clock and the others use the bus clock.

Now, since NXP made you generate an SDK specifically for this part - you can't even download SDK documentation without generating an SDK for a specific part - you might think that they'd have captured this in the SDK, but no - it doesn't integrate with the clocks tool or anything else, and you have to know the specifics of the UART configuration for your part.

Ok, rant over.

Scott

1,776 Views
randylee
Contributor V

OK, the UART_GetStatusFlags() is returnig 0xC00000C0.  This is a 32 bit value of 4 different registers according to the code.(SFIFO, ED, S2 and S1) so this is telling me:

SFIFO == 0xc0 is TXEMP, RXEMPT which I expect since I haven't written anything and there isn't anything incoming at all

ED == 0x00 meaning that there aren't any noise and no parity error (which is good considering this is 115200, 8,N,1

S2 == 0x00 meaning that it is seeing no activity and basically everything is normal

S1 == 0xC0 is telling me that TDRE and TC meaning that xmit is done and complete (I haven't sent anything out so yes, I'd expect that.

If I read from D at this point, it gives me another ISR claiming RX underrun which is pretty much what I'd expect.

so this ISR status isn't telling me anything that is out of normal or anything that should be generating an ISR at this point....

Hmmmm...

0 Kudos
1,776 Views
scottm
Senior Contributor II

Hmm.  Nothing jumps out at me, but I'd try alternately disabling RX and TX in the config and see if either one of those (or both) causes the interrupts to go away.  Also, watch the registers directly and don't trust the SDK's UART_GetStatusFlags().  I'm not saying it's wrong, I'm just saying check the registers yourself just to be sure.

0 Kudos
1,777 Views
randylee
Contributor V

Ah.  Looking in PEX code (yes, old code is better), I think I see what's going on.

In PEX the Interrupt is enabled when it goes into send block mode and then disabled in the ISR when it sees that we're at the end of a block (after calling the user done function).

If this code is correct, then this part is acting as it designed to do: It has an empty TX and it's going to keep telling that to you until such time as you tell it to shut up about it.

So basically I'm not using this SDK like it's intended to be used (it's assuming you're using all the normal directions into it with all kinds of TransferStart things and whatnot and creating handles and yada, yada, yada.  Come into this SDK from the side and you're in real trouble.

Short answer: Problem solved: cockpit error abetted by lack of documentation.

0 Kudos
1,776 Views
randylee
Contributor V

turning off RX I get the same thing.  That's really strange.

If I turn off the rx interrupts using UART_DisableInterrupts(kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable) I still get ISRs as soon as I do EnableIRQ()

If I turn off ALL interrupts using UART_DisableInterrupts(kUART_AllInterruptsEnable) I still get ISRs as soon as I do EnableIRQ()

Oh this is peculiar.

0 Kudos
1,776 Views
randylee
Contributor V

update: Retesting is showing that this disable interrupts is actually disabling the interrupts.  I get none with that turned off.  I'll do some more AB testing to see what else I've screwed up in characterization.

0 Kudos
1,776 Views
randylee
Contributor V

after more testing I'm finding that it has something to do with transmit IRQs

If I do things in this order:

    UART_DisableInterrupts(DEMO_UART, kUART_AllInterruptsEnable);
    UART_EnableInterrupts(DEMO_UART, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable);

I get well behaved RX ISRs.  If I add:

    UART_EnableInterrupts(DEMO_UART, kUART_TransmissionCompleteInterruptEnable);

This thing is continuous ISR (about 3 uS out of the ISR it reasserts)

so the status registers are saying that, in fact, the TX is empty.  Yup.

0 Kudos
1,776 Views
scottm
Senior Contributor II

Can you check your vector table and make sure no other IRQs are pointing at that ISR?  You should also be able to check the NVIC and see what the current vector number is, IIRC.

0 Kudos
1,776 Views
randylee
Contributor V

only entry is vector table:     UART0_RX_TX_IRQHandler,     // 47: UART0 Receive/Transmit interrupt

if I used NVIC_GetActive(UART0_RX_TX_IRQn) I get a 1 indicating that this ISR is active.

0 Kudos
1,776 Views
converse
Senior Contributor V

Could there be a h/w issue? Is it your board a a purchased board?

0 Kudos
1,776 Views
randylee
Contributor V

there is always that possibility as this is not a purchased board. The trouble is this is a UART. Those are pretty immutable s hardware goes.....

0 Kudos
1,776 Views
converse
Senior Contributor V

Did you clear the interrupt in the NVIC?

0 Kudos
1,776 Views
randylee
Contributor V

No.  That's a good guess.  When I do it (NVIC_ClearPendingIRQ()) it doesn't stop the bahviour.  Still getting hammered.  Whatever this is, is solid on.  Right after clearing it I can do NVIC_GetActive() and it returns 1.  NVIC_GetPendingIRQ() is showing 0 meaning that nothing at the end of the ISR is showing that this is pending.  But I get another ISR immediately.

0 Kudos
1,776 Views
randylee
Contributor V

I agree with every word of this.  Doxygen documentation sucks.  You have to read the code anyway to figure out what the things are doing really (at that level of documentation) so you might as well just read the comments in the code.... which means that the code should be better commented as well.

at this point, I'm giving NXP the benefit of the doubt with the understanding that they are waaaaaaaay behind in the tools and environment and haven't gotten to real documentation yet.

Still it makes it hard to do dev work on stuff.

I'll check the read D here.  Since it wasn't telling me there was anything there to read, I didn't.  I'll do that and dump it.

0 Kudos