1
\$\begingroup\$

I used uart receive using polling method. But same I want to use in ISR. How can I write a ISR function. For example if I am using CC2541. In the manual I have seen that Vector Table for Port 1(where UART is connected) is P1INT_VECTOR. But I don't know how to write a function. After some search I found many people used a function like below.

#pragma vector = P1INT_VECTOR
__interrupt void p0_ISR(void)
{
    /*Some statement*/
}

But I don't know what is p0_ISR. I didn't see this in the manual or datasheet. This interrupt function has any prototype?. Can some one help me to understand this. So that I can implement to every microcontroller not only CC2541

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Interrupts do not take arguments or return values. Basically, it's just a bare subroutine that gets 'called' by the hardware. An interrupt signal into the core generates the equivalent of a 'call' instruction wherever the processor happens to be executing code, storing the current address and then jumping directly into the ISR.

Generally a UART interrupt will grab a byte out of the UART receive register and then store it in a global receive buffer. You'll need to be careful with how you access the global receive buffer outside of the ISR as it is possible for the ISR to be called WHILE you are updating receive buffer metadata (pointers, counters, etc). You need to write code that can deal with this properly, either by carefully making sure the ISR cannot trample over the read routine or by disabling interrupts briefly to prevent the ISR from running at critical moments. There are standard concurrent programming techniques that can be used here.

There are a couple of (somewhat complex) interrupt-driven UART drivers for both transmit and receive in this repository: https://github.com/alexforencich/templates

\$\endgroup\$
2
  • \$\begingroup\$ Still i didn't get it. How can i bring that interrupt to my higher layer. Can you some example with any vector table and how to use with #pragma. It will be useful to me. \$\endgroup\$ Commented Dec 23, 2014 at 5:49
  • \$\begingroup\$ Take a look at github.com/alexforencich/templates/blob/master/at91.c/usart.c . The chip this is targeted for uses a register for the ISR address instead of a vector table (see line 113) and leverages the DMA engine. \$\endgroup\$ Commented Dec 23, 2014 at 6:32
0
\$\begingroup\$

P0_ISR() is the name of the function that's being defined. Its code goes where /* Some statement */ is. The #pragma sets up that function to be called by the P1INT interrupt.

Interrupts are not part of the C standard, so they are inherently hardware- and compiler-specific. Usually there will be a keyword or a pragma or both to indicate that the function is an interrupt. This usually just strips out some of the normal context save and reload, since the CPU will handle that when it returns from the interrupt.

To set up the hardware for an interrupt, you need to enable the interrupt in the peripheral, enable (unmask) the interrupt in the CPU, and write the ISR address (or a branch instruction) to the vector table. Again, this is hardware-specific. In your code, it looks like there might be some built-in initialization routine that works with the #pragma to fill the vector table.

\$\endgroup\$
2
  • \$\begingroup\$ Still i didn't get it. How can i bring that interrupt to my higher layer \$\endgroup\$ Commented Dec 23, 2014 at 5:39
  • 1
    \$\begingroup\$ What higher layer? You have a C function. What more do you want to do? \$\endgroup\$
    – Adam Haun
    Commented Dec 23, 2014 at 6:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.