This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Working with interrupts on LPC2129

I'm just getting started with using the Keil uV3 compiler as well as the Phillips lpc2129. The application I am working on requires both UART0 & 1 as well as the I2C and I'm wondering if anyone has some <sample> code for enabling/using interrupts handy for this part that they might could pass along to help me get started.

Any links related to writing C code for the lpc2129 would also be appreciated.

regards & thanks
-mel

Parents
  • The forum complained about the text being too long so I had to split it....


    /******************************************************************************/

    /* This file is part of the uVision/ARM development tools */

    /* Copyright KEIL ELEKTRONIK GmbH 2002-2004 */

    /******************************************************************************/

    /* */

    /* SERIAL.C: Low Level Serial Routines */

    /* */

    /******************************************************************************/



    #include <LPC21xx.H> /* LPC21xx definitions */

    #include <stdio.h>

    #include "serial.h"

    #define CR 0x0D



    extern int sendchar (int ch); /* in serial.c */



    //

    // vars shared with the interrupt service routine

    //

    char tx0_buffer[1000];

    volatile char *tx0_tail = tx0_buffer,*tx0_head = tx0_buffer;

    volatile unsigned int tx0_count = 0;



    void uart0 (void) __attribute__ ((interrupt)); // Generate Interrupt





    void puthexw (int hex)

    {

    puthex((hex >>12) & 0xf);

    puthex((hex >>8) & 0xf);

    puthex((hex >>4) & 0xf);

    puthex(hex & 0xf);

    }

    void puthex (int hex)

    { /* Write Hex Digit to Serial Port */

    if (hex > 9) putchar('A' + (hex - 10));

    else putchar('0' + hex);

    }



    void putstr (char *p)

    { /* Write string */

    while (*p) {

    putchar (*p++);

    }

    }







    void init_serial(enum tBaudRate baud)

    { /* Initialize Serial Interface */

    PINSEL0 = 0x00000005; /* Enable RxD0 and TxD0 */

    U0LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */

    switch (baud)

    {

    case BR_1200:

    U0DLL = 0x0d;

    U0DLM = 0x03;

    break;

    case BR_2400:

    U0DLL = 0x86;

    U0DLM = 0x01;

    break;

    case BR_4800:

    U0DLL = 0xc3;

    U0DLM = 0x00;

    break;

    case BR_9600:

    U0DLL = 0x61;

    U0DLM = 0x00;

    break;

    case BR_19200:

    U0DLL = 0x30;

    U0DLM = 0x00;

    break;

    case BR_38400:

    U0DLL = 0x18;

    U0DLM = 0x00;

    break;

    }

    U0LCR = 0x03; /* DLAB = 0 */

    //U0IER = 0x02; /* enable tx interrupts */



    VICVectAddr1 = (unsigned long)uart0; // set interrupt vector in 1

    VICVectCntl1 = 0x20 | 6; // use it for uart0 Interrupt

    VICIntEnable |= 0x00000040; // Enable Uart0 Interrupt

    }



    /* implementation of putchar (also used by printf function to output data) */

    int sendchar (int ch) /* Write character to Serial Port */

    {

    char tmp;

    if (ch == '\n')

    {

    tmp = CR;

    add_char_to_tx_buff(&tmp,1);

    }

    tmp = (char)ch;

    add_char_to_tx_buff(&tmp,1);

    return ch;

    }

    int putchar (int ch) /* Write character to Serial Port */

    {

    char tmp;

    // if (ch == '\n') {

    // while (!(U0LSR & 0x20));

    // U0THR = CR; /* output CR */

    // }

    // while (!(U0LSR & 0x20));

    // return (U0THR = ch);

    if (ch == '\n')

    {

    tmp = CR;

    add_char_to_tx_buff(&tmp,1);

    }

    tmp = (char)ch;

    add_char_to_tx_buff(&tmp,1);

    return ch;

    }





    int getchar (void) { /* Read character from Serial Port */



    while (!(U0LSR & 0x01));



    return (U0RBR);

    }





    //

    // inserts chars into the tx circular buffer. enables tx ints if required

    // count has the number of chars to insert

    // returns 0 if not enough space in the buffer

    // returns 1 if successful

    //

    char add_char_to_tx_buff(char *ch,int count)

    {

    if((tx0_count + count) >= sizeof(tx0_buffer) )

    {

    return 0; // not enough space

    }

    VICIntEnClr = 0x00000040; // Disable Uart0 Interrupt



    if (tx0_head == tx0_tail) //if the buffer was empty

    {

    if (U0LSR & 0x20) //if the uart is EMPTY

    {

    U0IER = 0x02; // enable tx interrupts

    U0THR = *ch++; //send the first char out the UART

    count--;

    }

    }





    while (count!= 0)

    {

    *tx0_head++ = *ch++; //insert the char into the buffer

    if (tx0_head >= (tx0_buffer + sizeof(tx0_buffer)) )

    {

    tx0_head = tx0_buffer; //wrap index if req'd

    }

    tx0_count++;

    count--;

    }

    VICIntEnable = 0x00000040; // Enable Uart0 Interrupt

    return 1;

    }







    //

    // uart0 isr routine

    //

    void uart0(void)

    {

    if (U0LSR & 0x20)//if tx interrupt

    {

    if (tx0_head == tx0_tail) //buffer empty?

    {

    U0IER &= ~0x02; //disable the tx interrupt

    }

    else //we have something to send

    {

    tx0_count--;

    U0THR = *tx0_tail++;

    if (tx0_tail >= (tx0_buffer + sizeof(tx0_buffer)) )

    {

    tx0_tail = tx0_buffer; //wrap tail buffer

    }

    }

    }

    VICVectAddr = 0; // Acknowledge Interrupt

    }

    // end of file


Reply
  • The forum complained about the text being too long so I had to split it....


    /******************************************************************************/

    /* This file is part of the uVision/ARM development tools */

    /* Copyright KEIL ELEKTRONIK GmbH 2002-2004 */

    /******************************************************************************/

    /* */

    /* SERIAL.C: Low Level Serial Routines */

    /* */

    /******************************************************************************/



    #include <LPC21xx.H> /* LPC21xx definitions */

    #include <stdio.h>

    #include "serial.h"

    #define CR 0x0D



    extern int sendchar (int ch); /* in serial.c */



    //

    // vars shared with the interrupt service routine

    //

    char tx0_buffer[1000];

    volatile char *tx0_tail = tx0_buffer,*tx0_head = tx0_buffer;

    volatile unsigned int tx0_count = 0;



    void uart0 (void) __attribute__ ((interrupt)); // Generate Interrupt





    void puthexw (int hex)

    {

    puthex((hex >>12) & 0xf);

    puthex((hex >>8) & 0xf);

    puthex((hex >>4) & 0xf);

    puthex(hex & 0xf);

    }

    void puthex (int hex)

    { /* Write Hex Digit to Serial Port */

    if (hex > 9) putchar('A' + (hex - 10));

    else putchar('0' + hex);

    }



    void putstr (char *p)

    { /* Write string */

    while (*p) {

    putchar (*p++);

    }

    }







    void init_serial(enum tBaudRate baud)

    { /* Initialize Serial Interface */

    PINSEL0 = 0x00000005; /* Enable RxD0 and TxD0 */

    U0LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */

    switch (baud)

    {

    case BR_1200:

    U0DLL = 0x0d;

    U0DLM = 0x03;

    break;

    case BR_2400:

    U0DLL = 0x86;

    U0DLM = 0x01;

    break;

    case BR_4800:

    U0DLL = 0xc3;

    U0DLM = 0x00;

    break;

    case BR_9600:

    U0DLL = 0x61;

    U0DLM = 0x00;

    break;

    case BR_19200:

    U0DLL = 0x30;

    U0DLM = 0x00;

    break;

    case BR_38400:

    U0DLL = 0x18;

    U0DLM = 0x00;

    break;

    }

    U0LCR = 0x03; /* DLAB = 0 */

    //U0IER = 0x02; /* enable tx interrupts */



    VICVectAddr1 = (unsigned long)uart0; // set interrupt vector in 1

    VICVectCntl1 = 0x20 | 6; // use it for uart0 Interrupt

    VICIntEnable |= 0x00000040; // Enable Uart0 Interrupt

    }



    /* implementation of putchar (also used by printf function to output data) */

    int sendchar (int ch) /* Write character to Serial Port */

    {

    char tmp;

    if (ch == '\n')

    {

    tmp = CR;

    add_char_to_tx_buff(&tmp,1);

    }

    tmp = (char)ch;

    add_char_to_tx_buff(&tmp,1);

    return ch;

    }

    int putchar (int ch) /* Write character to Serial Port */

    {

    char tmp;

    // if (ch == '\n') {

    // while (!(U0LSR & 0x20));

    // U0THR = CR; /* output CR */

    // }

    // while (!(U0LSR & 0x20));

    // return (U0THR = ch);

    if (ch == '\n')

    {

    tmp = CR;

    add_char_to_tx_buff(&tmp,1);

    }

    tmp = (char)ch;

    add_char_to_tx_buff(&tmp,1);

    return ch;

    }





    int getchar (void) { /* Read character from Serial Port */



    while (!(U0LSR & 0x01));



    return (U0RBR);

    }





    //

    // inserts chars into the tx circular buffer. enables tx ints if required

    // count has the number of chars to insert

    // returns 0 if not enough space in the buffer

    // returns 1 if successful

    //

    char add_char_to_tx_buff(char *ch,int count)

    {

    if((tx0_count + count) >= sizeof(tx0_buffer) )

    {

    return 0; // not enough space

    }

    VICIntEnClr = 0x00000040; // Disable Uart0 Interrupt



    if (tx0_head == tx0_tail) //if the buffer was empty

    {

    if (U0LSR & 0x20) //if the uart is EMPTY

    {

    U0IER = 0x02; // enable tx interrupts

    U0THR = *ch++; //send the first char out the UART

    count--;

    }

    }





    while (count!= 0)

    {

    *tx0_head++ = *ch++; //insert the char into the buffer

    if (tx0_head >= (tx0_buffer + sizeof(tx0_buffer)) )

    {

    tx0_head = tx0_buffer; //wrap index if req'd

    }

    tx0_count++;

    count--;

    }

    VICIntEnable = 0x00000040; // Enable Uart0 Interrupt

    return 1;

    }







    //

    // uart0 isr routine

    //

    void uart0(void)

    {

    if (U0LSR & 0x20)//if tx interrupt

    {

    if (tx0_head == tx0_tail) //buffer empty?

    {

    U0IER &= ~0x02; //disable the tx interrupt

    }

    else //we have something to send

    {

    tx0_count--;

    U0THR = *tx0_tail++;

    if (tx0_tail >= (tx0_buffer + sizeof(tx0_buffer)) )

    {

    tx0_tail = tx0_buffer; //wrap tail buffer

    }

    }

    }

    VICVectAddr = 0; // Acknowledge Interrupt

    }

    // end of file


Children
  • Thanks for the code, for the most part what I came up with was (about) the same. I am not using printf and therefor have not added syscalls.c to my project. Also adding that file will require some work on my part as I have three different put/get-char calls (et al. putchar_uart0, putchar_uart1, putchar_i2c) but no get/put char as required in syscalls.c.

    My code is not performing correctly regarding the interrupts for uart1. I'll post the code here and also in a new thread for possible extra help.

    First of all, here is the main loop...

    	while(1)  {
    
    		cTemp = getchar_uart1();
    		if( cTemp )
    			putchar_uart1( cTemp );
    		cTemp = 0;
    
    	}
    
    

    As you can see it is simply echoing any Rx'd bytes back out uart1. This works fine when I have the uart1 interrupts disabled. However, when I enable nothing happens that I can see, both by monitoring the output and using the uV3 debugger. I suspect that something is amiss in my interrupt code so I'll post that and maybe you can spot what I'm doing wrong...

    void u1_interrupt (void) __attribute__ ((interrupt));   /* generate interrupt */
    
    /*************************************************************************/
    /**************************  interrupt for uart1  ************************/
    void u1_interrupt (void)  {
    	char intrpt;
    	intrpt = U1IIR;   /* reset U1IIR register */
    // for now just trying to echo the Rx'd byte back out uart1...
    	intrpt = U1RBR;	// clear Rx buffer, and reset interrupt
    	putchar_uart1( intrpt );
    
    	VICVectAddr = 0;   /* acknowledge interrupt */
    }/*end u1_interrupt() */
    
    
    
    void init_uart1( void )  {
    	PINSEL0 |= 0x00550000;   /* set P0.8, P0.9, P0.10 and P0.11 as TxD1, RxD1, RTS1, CTS1 */
    	U1LCR = 0x83;   /* set DLAB and word size (8bits), defaults for others yield */
    						 /* no parity, one stop bit, and no break */
    	U1DLL = 0x61;   /* yields 9600 Baud */
    	U1DLM = 0x00;   /* explicit initialization - is also the default */
    	U1LCR &= 0x7f;   /* clear DLAB */
    
    /* set up the interrupts */
    	U1IER = 0x05;   /* enable RBR and RLS interrupts */
    	VICVectAddr1 = (unsigned long) u1_interrupt;   /* set interrupt vector */
    	VICVectCntl1 = 0x20 | 7;   /* use VICVectAddr1 for UART1 interrupts */
    	VICIntEnable = 0x00000080;   /* enable uart1 interrupts */
    
    }/* end init_uart1()
    

    any suggestions?

  • I thought it worth mentioning that I can see the Rx Data Ready interrupt triggering when I am single stepping in the debug mode but flow does NOT jump it my ISR.

    also FYI: with regards to posting code... use the

    </per> tags to retain formatting
    

  • "</per> tags to retain formatting"

    That should be < pre > (to start) and < /pre > (to end) - but without the extra spaces.

    It's clearly shown at the top of the form when you make a post!

  • excuse my typos... I got the first one correct which was why it wasn't displayed which is also why you put the spaces between the brackets (I hadn't thought of that either)