LPC2148 UART interrupt

0

I am using LPC2148 with SIM800L on UART1 using interrupt. When I use memset(buff, 0 , sizeof(buff)); in while(1) at first the program works fine but when while(1) loop runs again it prints error over and over but when I comment the memset(buff, 0, sizeof(buff)); it works fine.

So why it is not receiving the data on using memset function?

 #include <lpc214x.h>
 #include <stdio.h>
 #include <string.h>


 __irq void uart1_interrupt(void);

 void init_uart1(void);                     //////initialize uart1
 void uart1_write(char data);           //////send char on uart1
 void uart1_send_string(char *str);//////send string on uart1

 void Uart0_string(char *str);          //////send string on uart0
 void U0write(char data);                   //////send 
 char on uart0
 void init_uart0(void);                     //////initialize uart0

 void pll_init(void);
 void timer_init(void);
 void delay_ms(unsigned int ms);

 //void clear_data();                               /////clear buffer

 char buff[160];
 //char sms_receive[60];
 int i, a = 0;

 int main(void)
 {
    pll_init();
    timer_init();
    init_uart0();
    //init_uart1();


    VICVectAddr0 = (unsigned) uart1_interrupt;   /////attach interrupt routine
    VICVectCntl0 = (1<<5)|7;                                                                    ////enable uart irq slot for uart1
    VICIntEnable |= (1<<7); ////enable uart1 interrupt 
    VICIntSelect = 0x00000000;
    init_uart1();

    Uart0_string("gsm test\r\n");


    delay_ms(3000);

    while(1)
    {
        uart1_send_string("AT\r\n");
        delay_ms(400);
        if(strstr(buff,"OK"))
        {
            Uart0_string(buff);
        }

        else
        {
            Uart0_string("ERROR ");
        }

        delay_ms(3000);

        uart1_send_string("AT+CNMI=?\r\n");
        delay_ms(400);
        if(strstr(buff,"+CNMI"))
        {
            Uart0_string(buff);
        }

        else
        {
                Uart0_string("ERROR ");
        }

        delay_ms(3000);
        //clear_data();
        memset(buff, 0 , sizeof(buff)); 
    }
  }


 /*void clear_data()
 {
    for(i = 0; i<=sizeof(buff); i++)
    {
        buff[i] = 0;
    }
 }*/

 __irq void uart1_interrupt(void)
 {
    buff[a] = U1RBR;
    a++;
    VICVectAddr = 0x00;
 }

 void init_uart1(void)
 {
    PINSEL0 = PINSEL0 | 0x00050000;    ////UART1 pin selection

    U1LCR = 0x83;            ////8 bit, no parity, 1 stop bit, DLAB - 1
    U1DLL = 0x56;                ////86 in decimal
    U1DLM = 0x00;
    U1FDR = 0xF2;

    U1LCR &= 0x0f;          /////setting DLAB bit to 0

    U1IER = 0x01;               ////enable interrupt
 }

 void uart1_write(char data)
 {
    U1IER = 0x00;
    while(!(U1LSR &(1<<5)));        ////U1LSR contains THRE status bit, wait while THR is empty
    U1THR = data;
    U1IER = 0x01;
 }

 void uart1_send_string(char *str)
 {
    U1IER = 0x00;
    while(*str != '\0')
    {
        uart1_write(*str++);
    }
    U1IER = 0x01;
 }


 /*char uart1_receive()
 {
    while(!(U1LSR & (1<<0)));
    return U1RBR;
 }*/

 void init_uart0()
 {
    PINSEL0 = 0x00000005;   ////selects TxD P0.0 and RxD P0.1

    U0LCR = 0x83;           ////8 bit, no parity 1 stop bit, DLAB = 1
    U0DLL = 0x56;     //// 86 in decimal
    U0DLM = 0x00;
    U0FDR = 0xF2;           ////MULVAL and DIVADDVAL values

    U0LCR &= 0x0F;
 }

 void U0write(char data)
 {
    while(!(U0LSR & (1<<5)));  ///////wait till THR is not empty
    U0THR = data;                            /////// write data to Transmit in U0THR

 }

 void Uart0_string(char *str)
 {
    while(*str != '\0')
    {
        U0write(*str++);
    }
 }

 void pll_init(void)
 {
    PLL0CON = 0x01;        /////enable PLL////
    PLL0CFG = 0x24;              /////configure PLL/////
    PLL0FEED = 0xAA;             //////feed sequence/////
    PLL0FEED = 0x55;             //////feed sequence/////

    while(!(PLL0STAT & 0x00000400)); ///is locked////

    PLL0CON = 0x03;     ////connect PLL////
    PLL0FEED = 0xAA;
    PLL0FEED = 0x55;

    //VPBDIV = 0x01; /////// PCLK = CCLK = 60MHz
    VPBDIV = 0x00;   /////// PCLK = 60/4 = 15MHz
 }

 void timer_init(void)
 {
    //T0TCR = 0x00;
    T0CTCR = 0x0;       ////selection of timer mode with every rising pclk edge
    T0PR = 14999;           ////prescale register value will generate 1 ms at 60MHz
    T0TCR = 0x02;     ////reset the timer counter and prescale couter
 }

 void delay_ms(unsigned int ms)
 {
    //T0TC = 0x00000000;
    T0TCR = 0x02;     /////reset timer. Timer should be reset
    T0TCR = 0x01;     /////enable timer to generate delay
    T0MR0 = ms;
    while(T0TC < T0MR0); /////wait until Timer counter register reaches desired delay
    T0TCR = 0x00;     /////disable timer

 }

output when using memset(buff, 0, sizeof(buff))

gsm test
AT
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
ERROR ERROR ERROR ERROR

output when not using memset(buff, 0 , sizeof(buff)). I want to achive this output using memset(buff, 0 , sizeof(buff))

gsm test
AT
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
AT
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)

OK
AT
OK
c
interrupt
uart
asked on Stack Overflow Aug 8, 2019 by AuraGG • edited Aug 8, 2019 by Mike

2 Answers

0

a is reset only once at the start. The interrupt increments a on every character. When your main loop repeats, the ISR (interrupt service routine) will increment it further, finally overwriting the memory after buf.

That's why without memset() you get ever repeating the same result. The contents of buf is always checked from its beginning, but the received answers are stored one after the other.

Reset a on every entry in the loop, that should help.

However, writing (and/or reading) to the same variable from more than one thread is calling for disaster. Look for some lessons about multi-threaded programming. Yes, using interrupts is programming with multiple threads.

answered on Stack Overflow Aug 8, 2019 by the busybee
0

The while(1) loop in the main function does not make any input to char buff[160]. That is done only in the interrupt handler. So when you use memset to fill the buffer, it then begins with the string terminator character '\0' and the statements

if(strstr(buff,"OK"))

and

if(strstr(buff,"+CNMI"))

are false – NULL means no match was found – and so the error messages are output.

Note too that in the interrupt handler __irq void uart1_interrupt(void) you have

buff[a] = U1RBR; 
a++;

but nowhere is a limited or reset or wrapped to prevent buffer overrun. So there is a disaster waiting to happen.

answered on Stack Overflow Aug 8, 2019 by Weather Vane

User contributions licensed under CC BY-SA 3.0