AnsweredAssumed Answered

STM32F4 Serial Interrupts Crash

Question asked by dpeterson3 on Apr 9, 2013
Latest reply on Apr 19, 2013 by dpeterson3
I've been trying to get interrupt driven serial working on the STM32F4 working for a few days with no luck.

If I try to enable the transmit interrupt, I get dumped off into a routine in the default startup code that's just an infinite loop with the comment "to preserve the system state for debugging."  A backtrace from GDB talks about the wwdg putting me there, but then reports the stack is corrupted and won't go back further. This happens sometimes when I call the NVIC init function and sometimes when I call the USART enable command, but it always happens.

If I don't enable the transmit interrupts, I will get past all the init stuff no problem and into the main loop. Last night, I finally got my logic level shifter working again to connect the board to my computer. I sent a command from GTKterm (I run linux) and instead of ending up in the interrupt routine like I expected, I was dumped off to the same place in the startup code with the same backtrace as before. I've checked everything I can think of to check, and I'm at a loss as to what's wrong.

[code]
/**********************************************************************
 * This file uses 2 of the usarts on the discovery board. The first
 *     talks to a computer. The second talks to the Wifly module.
 *
 * Author: Daniel Peterson (dpeterson309@yahoo.com)
 * History: 19 March 2013 - Code started
 *
**********************************************************************/
#include "../inc/stm32f4xx_conf.h"
#include "../inc/stm32f4xx_rcc.h"
#include "../inc/stm32f4xx_gpio.h"
#include "../inc/stm32f4xx_tim.h"
#include "../inc/stm32f4xx_usart.h"
#include "../inc/misc.h"

#define BLUE     GPIO_Pin_15
#define RED        GPIO_Pin_14
#define GREEN    GPIO_Pin_12
#define ORANGE    GPIO_Pin_13

//serial buffer variables
#define sBuffSize 128
//usart 3 first
uint16_t sBuff3[sBuffSize];
uint16_t bytesRecieved3;
uint16_t bytesRead3;
bool overflow3;

//usart 6
uint16_t sBuff6[sBuffSize];
uint16_t bytesRecieved6;
uint16_t bytesRead6;
bool overflow6;

/** setup the io ports */
void Init_IO(void)
{
        GPIO_InitTypeDef GPIOInit;
        //set up the pins with the LED's
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
        GPIOInit.GPIO_Pin = RED | GREEN | ORANGE | BLUE;
        GPIOInit.GPIO_Mode = GPIO_Mode_AF;
        GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
        GPIOInit.GPIO_OType = GPIO_OType_PP;
        GPIOInit.GPIO_PuPd = GPIO_PuPd_NOPULL;

        GPIO_Init(GPIOD, &GPIOInit);

        //connect the pins to the timer3 output compare registers
        GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);
        GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4);
        GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_TIM4);
        GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_TIM3);

        //setup the USART output pins
        //first one is USART 3, pins pc 10 and 11
        //second is USART 6, pins pc6 and pc7
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
        GPIOInit.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10 | GPIO_Pin_11;
        GPIOInit.GPIO_Mode = GPIO_Mode_AF;
        GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
        GPIOInit.GPIO_OType = GPIO_OType_PP;
        GPIOInit.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(GPIOC, &GPIOInit);

        GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);
        GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);
        GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
        GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
}

/** configure the serial ports */
void Init_USART(void)
{
    USART_InitTypeDef USARTInit;
    NVIC_InitTypeDef IntInit;

    USARTInit.USART_BaudRate=9600;
    USARTInit.USART_WordLength=USART_WordLength_8b;
    USARTInit.USART_StopBits=USART_StopBits_1;
    USARTInit.USART_Parity=USART_Parity_No;
    USARTInit.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
    USARTInit.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //enable TX and RX (TX=8H, RX=4H);
    USART_Init(USART3, &USARTInit);

    //enable the USART
    USART_Cmd(USART3, ENABLE);


    //setup and enable the serial interrupts
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
    //USART_ITConfig(USART3, USART_IT_TC, ENABLE);

    IntInit.NVIC_IRQChannel = USART3_IRQn;
    IntInit.NVIC_IRQChannelPreemptionPriority = 0;
    IntInit.NVIC_IRQChannelSubPriority = 0;
    IntInit.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&IntInit);


    //now the second USART
    USARTInit.USART_BaudRate=19200;
    USARTInit.USART_WordLength=USART_WordLength_8b;
    USARTInit.USART_StopBits=USART_StopBits_1;
    USARTInit.USART_Parity=USART_Parity_No;
    USARTInit.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
    USARTInit.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //enable TX and RX (TX=8H, RX=4H);
    USART_Init(USART6,&USARTInit);

    //enable the USART
    USART_Cmd(USART6, ENABLE);

    //setup and enable the serial interrupts
    USART_ITConfig(USART6, USART_IT_RXNE, ENABLE);
//    USART_ITConfig(USART6, USART_IT_TC, ENABLE);

    IntInit.NVIC_IRQChannel=USART6_IRQn;
    IntInit.NVIC_IRQChannelPreemptionPriority=0;
    IntInit.NVIC_IRQChannelSubPriority=0;
    IntInit.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&IntInit);
}

/** serial access routines */
//usart3 first
/** read a single value from the buffer */
uint16_t readSerial3(void)
{
    uint16_t value;
    if ((bytesRead3 < bytesRecieved3) && !overflow3)
    {
        value = sBuff3[bytesRead3]; //start reading at bytesRead (it stores where it stopped reading, so it should be  behind the bytesRecieved counter
        if (bytesRead3++ > sBuffSize) bytesRead3 = 0; //go back to the beginning if we have reached the end
    }
    else if((bytesRead3 > bytesRecieved3) && overflow3)
    {
        value = sBuff3[bytesRead3]; //start reading at bytesRead (it stores where it stopped reading, so it should be  behind the bytesRecieved counter
        if (bytesRead3++ > sBuffSize)
        {
            bytesRead3 = 0; //go back to the beginning if we have reached the end
            overflow3 = 0; //reset the overflow flag because the counter overflowed as well
        }
    }
    else value = 0; //if reader has caught up to the buffer, just return 0;
    return value;
}
/** get how much data is buffered. That way we're not reading an empty buffer */
uint16_t getBytesAvaiable3(void)
{
    //make sure to return the correct value if the buffer has started over
    if (bytesRead3 <= bytesRecieved3) return (bytesRecieved3 - bytesRead3);
    else return ((sBuffSize - bytesRead3) + bytesRecieved3);
}
void sendString3(const char *data)
{
    while (*data)
    {
        //wait for the previous byte to be transmitted (basically block until I get a buffer implemented)
        while (!(USART3->SR & 0x00000040))
        USART_SendData(USART3, *data);
        data++;
    }
}


//now for USART6
uint16_t readSerial6(void)
{
    uint16_t value;
    if ((bytesRead6 < bytesRecieved6) && !overflow6)
    {
        value = sBuff6[bytesRead6]; //start reading at bytesRead (it stores where it stopped reading, so it should be  behind the bytesRecieved counter
        if (bytesRead6++ > sBuffSize) bytesRead6 = 0; //go back to the beginning if we have reached the end
    }
    else if((bytesRead6 > bytesRecieved6) && overflow6)
    {
        value = sBuff6[bytesRead6]; //start reading at bytesRead (it stores where it stopped reading, so it should be  behind the bytesRecieved counter
        if (bytesRead6++ > sBuffSize)
        {
            bytesRead6 = 0; //go back to the beginning if we have reached the end
            overflow6 = 0; //reset the overflow flag because the counter overflowed as well
        }
    }
    else value = 0; //if reader has caught up to the buffer, just return 0;
    return value;
}
/** get how much data is buffered. That way we're not reading an empty buffer */
uint16_t getBytesAvaiable6(void)
{
    //make sure to return the correct value if the buffer has started over
    if (bytesRead6 <= bytesRecieved6) return (bytesRecieved6 - bytesRead6);
    else return ((sBuffSize - bytesRead6) + bytesRecieved6);
}
void sendString6(const char *data)
{
    while (*data)
    {
        //wait for the previous byte to be transmitted (basically block until I get a buffer implemented)
        while (!(USART6->SR & 0x00000040))
        USART_SendData(USART6, *data);
        data++;
    }
}
/** routine to configure the wifi module to get on the home network */
void config_wifi(void)
{
    //first put it in command mode
    sendString3("$$$");
    //now set the passphrase
    sendString3("set wlan phrase MayTheForceBeWithYou");
    //now send the network ID
    sendString3("set wlan ssid ITS_A_TRAP");
    //get DHCP from the network
    sendString3("set ip dhcp 1");
    //now join
    sendString3("join ITS_A_TRAP");
    return;
}

/** now the main function of the program */
int main (void)
{
    Init_IO();
    Init_USART();
    sendString6("Initialization Complete");
    config_wifi();
    sendString6("Wifi Supposedly Configured");
    while (1)
    {
        //just toggle LEDs on and off
        if (getBytesAvaiable6() > 0)
        {
            if (readSerial6() == '1') GPIO_SetBits(GPIOD, BLUE | GREEN);
            if (readSerial6() == '2') GPIO_SetBits(GPIOD, ORANGE | RED);
            if (readSerial6() == '3') GPIO_ResetBits(GPIOD, BLUE | GREEN);
            if (readSerial6() == '4') GPIO_ResetBits(GPIOD, ORANGE | RED);
            sendString6("got it\n");
        }
    }
    return 0;
}


/** interrupt routines */
void USART3_IRQHandler(void)
{
    if (USART_GetITStatus(USART3,USART_IT_RXNE))
    {
        sBuff3[bytesRecieved3] = USART3->DR; //grab the latest packet
            if (bytesRecieved3++ > sBuffSize)
            {
                bytesRecieved3 = 0; //return the counter to 0 if the buffer overflows; an error will occur when checking packets, signaling an overflow
                overflow3 = 1; //set the buffer overflow flag
            }
    }
}
/** usart 6 interrupt handler */
void USART6_IRQHandler(void)
{
    if (USART_GetITStatus(USART6, USART_IT_RXNE))
    {
        sBuff6[bytesRecieved6] = USART6->DR; //grab the latest packet
            if (bytesRecieved6++ > sBuffSize)
            {
                bytesRecieved6 = 0; //return the counter to 0 if the buffer overflows; an error will occur when checking packets, signaling an overflow
                overflow6 = 1; //set the buffer overflow flag
            }
    }
}

[/code]

Outcomes