AnsweredAssumed Answered

STM32F429 UART4/USART3 Continuous Receiving Problem

Question asked by kasapoglu.orkun on Apr 20, 2018
Latest reply on Apr 24, 2018 by kasapoglu.orkun

Hello. I'm using STM32F429II6 in our custom-board. Board is communicating with another system over UART/USART. Mechanism is simple; board sending request to the device and getting response. The response size is changing with request but all request's has constant size. I can transfer request and visualize it with a scope and again can see the response on the screen of the scope and RX (PC11) pin of the MCU. But in the MCU side it is just setting the RXNE flag for the first byte. After first read, flag is not set so the response reading function hanging on while loop of the RXNE flag check.

When I add a timeout it falls every time to timeout condition.

 

Device has 9600-8-E-1 serial specifications.

 

EDIT: There is an ORE error in the first reading. Then no more inputs.

 

Here is the code;

 

#define KSERIAL_BAUD                 9600
#define KSERIAL_DATA_LEN         USART_WordLength_9b
#define KSERIAL_STOP                 USART_StopBits_1
#define KSERIAL_PARITY               USART_Parity_Even
#define KSERIAL_MODE                 (USART_Mode_Tx | USART_Mode_Rx)
#define KSERIAL_FLOW_CTRL     USART_HardwareFlowControl_None

 

#if defined(__USE_USART3)
#define KSERIAL_COM              USART3

 

#define KSERIAL_COM_CLKEN()      RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE)
#define KSERIAL_COM_CLKDIS()     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, DISABLE)

 

#define KSERIAL_FORCE_RESET()    RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, ENABLE)
#define KSERIAL_RELEASE_RESET()  RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, DISABLE)

 

#define KSERIAL_COM_IRQn         USART3_IRQn
#else
#define KSERIAL_COM              UART4

 

#define KSERIAL_COM_CLKEN()      RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE)
#define KSERIAL_COM_CLKDIS()     RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, DISABLE)

 

#define KSERIAL_FORCE_RESET()    RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, ENABLE)
#define KSERIAL_RELEASE_RESET()  RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, DISABLE)

 

#define KSERIAL_COM_IRQn         UART4_IRQn
#endif

 

#define KSERIAL_PORT             GPIOC
#define KSERIAL_TX_PIN               GPIO_Pin_10
#if defined(__USE_USART3)
#define KSERIAL_TX_AF            GPIO_AF_USART3
#else
#define KSERIAL_TX_AF            GPIO_AF_UART4
#endif
#define KSERIAL_TX_PIN_SRC       GPIO_PinSource10

 

#define KSERIAL_RX_PIN               GPIO_Pin_11
#if defined(__USE_USART3)
#define KSERIAL_RX_AF            GPIO_AF_USART3
#else
#define KSERIAL_RX_AF            GPIO_AF_UART4
#endif
#define KSERIAL_RX_PIN_SRC       GPIO_PinSource11

 

#define KSERIAL_PORT_SRC         GPIO_PortSourceGPIOC
#define KSERIAL_PIN_SPEED        GPIO_Low_Speed
#define KSERIAL_PIN_PULL         GPIO_PuPd_UP
#define KSERIAL_PIN_MODE         GPIO_Mode_AF
#define KSERIAL_PIN_OUT_TYPE     GPIO_OType_PP

 

#define KSERIAL_PORT_CLKEN()     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE)

 

typedef enum
{
    KSERIAL_STATE_FAULT_RXCHECKSUM = -7,
    KSERIAL_STATE_FAULT_RXBUFFER = -6,
    KSERIAL_STATE_FAULT_TXBUFFER = -5,
    KSERIAL_STATE_FAULT_NULLPTR = -4,
    KSERIAL_STATE_FAULT_RXTIMEOUT = -3,
    KSERIAL_STATE_FAULT_TXTIMEOUT = -2,
    KSERIAL_STATE_FAULT_INITIALIZE = -1,
  KSERIAL_STATE_RESET = 0,
    KSERIAL_STATE_BUSY = 1,
    KSERIAL_STATE_READY = 2
}KS_StateTypeDef_t;

 

typedef struct
{
  uint8_t sync_data[3];
  uint8_t size;
  uint8_t cmd;
  uint8_t *dptr;
  uint8_t chcksm;
}KSerialData_t;

 

typedef struct
{
  USART_TypeDef *uHandle;

 

  KSerialData_t Rx;
  KSerialData_t Tx;
    
    KS_StateTypeDef_t m_state;
    
  uint8_t expected_rx_count;
}KSerial_Init_t;

 

static KSerial_Init_t KSerial;


int KSerialSendCMD(void);
int KSerialReadRESP(void);

 

void UART_MspInit(USART_TypeDef *huart)
{
  __IO GPIO_InitTypeDef gpio;
    
    if (huart == NULL)
        return;
    
    KSerial.uHandle = huart;
    
    /* Enable UART clock */
    KSERIAL_PORT_CLKEN();
    
    GPIO_PinAFConfig(KSERIAL_PORT, KSERIAL_RX_PIN_SRC, KSERIAL_RX_AF);
    GPIO_PinAFConfig(KSERIAL_PORT, KSERIAL_TX_PIN_SRC, KSERIAL_TX_AF);
    
    /* Configure USART3 Rx an Tx as alternate function */
    gpio.GPIO_Mode = KSERIAL_PIN_MODE;
    gpio.GPIO_OType = KSERIAL_PIN_OUT_TYPE;
    gpio.GPIO_PuPd = KSERIAL_PIN_PULL;
    gpio.GPIO_Speed = KSERIAL_PIN_SPEED;
    gpio.GPIO_Pin = KSERIAL_RX_PIN | KSERIAL_TX_PIN;
    
    GPIO_Init(KSERIAL_PORT, (GPIO_InitTypeDef *)&gpio);
}

 

void KSerialInit(KSerialData_t **pp_transmit, KSerialData_t **pp_receive)
{
    USART_InitTypeDef uart;
    NVIC_InitTypeDef nvic;
    
  if (KSerial.m_state == KSERIAL_STATE_RESET)
    {
        printf("KSerial state: RESET\n");
        /* Initialize the GPIO settings */
      UART_MspInit(KSERIAL_COM);
        
        /* Enable USART3 port clock */
      KSERIAL_COM_CLKEN();
        
        /* Configure the UART */
      uart.USART_BaudRate = KSERIAL_BAUD;
        uart.USART_WordLength = KSERIAL_DATA_LEN;
        uart.USART_StopBits = KSERIAL_STOP;
        uart.USART_Parity = KSERIAL_PARITY;
        uart.USART_Mode = KSERIAL_MODE;
        uart.USART_HardwareFlowControl = KSERIAL_FLOW_CTRL;
        
        USART_Init(KSerial.uHandle, &uart);
        
        nvic.NVIC_IRQChannel = KSERIAL_COM_IRQn;
        nvic.NVIC_IRQChannelCmd = ENABLE;
        nvic.NVIC_IRQChannelPreemptionPriority = 0x0;
        nvic.NVIC_IRQChannelSubPriority = 0x0;
        NVIC_Init(&nvic);

 

        USART_ITConfig(KSerial.uHandle, USART_IT_ERR, ENABLE);

 

        USART_ITConfig(KSerial.uHandle, USART_IT_ORE, ENABLE);
        USART_ITConfig(KSerial.uHandle, USART_IT_PE, ENABLE);
   
        USART_Cmd(KSerial.uHandle, ENABLE);
    }

 

  KSerial.expected_rx_count = 0;
    *pp_transmit = &KSerial.Tx;
    *pp_receive  = &KSerial.Rx;
    
    if (*pp_transmit != NULL && *pp_receive != NULL)
        KSerial.m_state = KSERIAL_STATE_READY;
    else
        KSerial.m_state = KSERIAL_STATE_FAULT_INITIALIZE;
}


uint8_t KSerialGetState(void)
{
    return KSerial.m_state;
}

 

uint8_t KSerial_ChecksumCalculator(KSerialData_t *sd)
{
  __IO uint8_t * __IO ptr = (uint8_t *)(sd->dptr);
    __IO uint16_t sum = sd->size + sd->cmd;
    __IO uint8_t csum = 0;
    __IO int n = sd->size - 2;
    
    for (; n > 0; n--)
    {
      sum += *(ptr++);
    }
    csum = ~((uint8_t)sum);
    
    return ++csum;
}


int KSerialSendCMD(void)
{
    __IO uint8_t * __IO txBuff = NULL;
    __IO uint8_t * __IO sdPtr = NULL;
  __IO int n;
    __IO int nn;
    
    KSerial.m_state = KSERIAL_STATE_BUSY;

 

    sdPtr = (uint8_t *)&KSerial.Tx;
    
    if (sdPtr == NULL)
    {
        KSerial.m_state = KSERIAL_STATE_FAULT_NULLPTR;
        return -1;
    }
    
    txBuff = (uint8_t *)malloc(KSerial.Tx.size + 4);
    
    if (txBuff == NULL)
    {
        KSerial.m_state = KSERIAL_STATE_FAULT_TXBUFFER;
        return -2;
    }
    
    /* Take the argument parameters to local data and transmit buffer */
    for (n = 0; n < 5; ++n)
        txBuff[n] = sdPtr[n];
    
    nn = n;
    
    for (n = 0; n < KSerial.Tx.size - 2; ++n)
      *(txBuff + nn + n) = *(KSerial.Tx.dptr + n);
    
    *(txBuff + nn + (n++)) = KSerial.Tx.chcksm;
    
    nn += n;
    n = nn;
    
    printf("Transmit data:\n");
    
    for (; nn > 0; --nn)
    {
        printf(" %2X,\t", *txBuff);
        if (nn == 1)
            printf("\n");
      USART_SendData(KSERIAL_COM, *(txBuff++));
        while (USART_GetFlagStatus(KSERIAL_COM, USART_FLAG_TXE) != SET);
//        USART_ClearFlag(KSERIAL_COM, USART_FLAG_TXE);
    }

//    ...

    return n;
}


int KSerialReadRESP(void)
{
  const int n = KSerial.expected_rx_count + 4;
    __IO uint8_t * __IO rxBuff = (__IO uint8_t *)malloc(sizeof(uint8_t) * n);
  __IO uint32_t timeout = 0;
    
    __IO uint8_t chcksm = 0;

 

    if (rxBuff == NULL)
    {
        KSerial.m_state = KSERIAL_STATE_FAULT_RXBUFFER;
        return -2;
    }
    
    for (KSerial.expected_rx_count = 0; KSerial.expected_rx_count < n; ++KSerial.expected_rx_count)
    {
        timeout = 0x100000;
      while (USART_GetFlagStatus(KSERIAL_COM, USART_FLAG_RXNE) != SET)
        {
//          if (timeout-- < 1)
//            {
//                KSerial.m_state = KSERIAL_STATE_FAULT_RXTIMEOUT;
//                return -4;
//            }
        }
        *(rxBuff++) = (uint8_t)USART_ReceiveData(KSERIAL_COM);
    }

//    ...

//    ...
    return n;
}

Outcomes