I want to implement lwip server with stm32 - c

void Tcp_Task(void const * argument)
{
/* USER CODE BEGIN Tcp_Task */
struct netconn *conn, *newconn;
err_t err, accept_err;
struct netbuf *buf;
void *data;
u16_t len;
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_5, GPIO_PIN_SET);
LWIP_UNUSED_ARG(argument);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_5, GPIO_PIN_RESET);
conn = netconn_new(NETCONN_TCP);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_5, GPIO_PIN_SET);
if (conn!=NULL)
{
// netconn_bind(conn, NULL, port 번호)
err = netconn_bind(conn, NULL, 5001);
if (err == ERR_OK)
{
netconn_listen(conn);
while (1)
{
accept_err = netconn_accept(conn, &newconn);
if (accept_err == ERR_OK)
{
while (netconn_recv(newconn, &buf) == ERR_OK)
{
do
{
netbuf_data(buf, &data, &len);
memcpy(receivemsg, data, len);
// 메시지 송신
netconn_write(newconn, data, msg_len, NETCONN_COPY);
}
while (netbuf_next(buf) >= 0);
netbuf_delete(buf);
}
netconn_close(newconn);
netconn_delete(newconn);
}
osDelay(100);
}
}
else
{
netconn_delete(newconn);
}
}
/* Infinite loop */
for(;;)
{
osDelay(100);
}
/* USER CODE END Tcp_Task */
}
I want to use the above to implement lwip server with stm32, but if I debug the project, the server implementation works well, but it's not working because I just want to connect the power without removing the ST-Link wire and debugging it
If you see that the LED is blinking, the code seems to work normally, but strangely, it is not connected to the client
I think there's something about conn = netconn_new (NETCONN_TCP) or LWIP_UNUSED_ARG (argument), but if it's a problem here, shouldn't it not be debugged?
The test was well done by implementing the message response, but if it is not debugged, the client connection is not working
Isn't it usually debugged and if you get the desired result without any errors?
Please tell me the solution
Notes Blog :
https://blog.naver.com/eziya76/221867311729
Things set up in cubemx
lwip
freertos
eth
rcc

Related

Ethernet with STM32 and ENC28J60

I'm trying to run SPI Ethernet module ENC28J60 with STM32H7. I wrote some functions for ENC28J60 library. Now, I want to get ping from PC or Router, but I can not. If anyone can help me to run it, please answer this question.
After Ping, I want to access communication stm32 microcontrollers and ENC28J60. Unfortunately, I could not find suitable library and sample code.
Thanks,
Sajix
my .C file of ENC28J60:
#include "stm32_enc28j60.h"
extern SPI_HandleTypeDef hspi1;
static uint8_t Enc28_Bank;
uint8_t dataWatch8;
uint16_t dataWatch16;
//-> SPI Instruction Set
uint8_t ENC28_readOp(uint8_t oper, uint8_t addr){
uint8_t spiData[2];
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
spiData[0] = (oper| (addr & ADDR_MASK));
HAL_SPI_Transmit(&hspi1, spiData, 1, 100);
if(addr & 0x80)
{
HAL_SPI_Receive(&hspi1, &spiData[1], 1, 100);
}
HAL_SPI_Receive(&hspi1, &spiData[1], 1, 100);
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
return spiData[1];
}
void ENC28_writeOp(uint8_t oper, uint8_t addr, uint8_t data){
uint8_t spiData[2];
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
spiData[0] = (oper| (addr & ADDR_MASK));
spiData[1] = data;
HAL_SPI_Transmit(&hspi1, spiData, 2, 100);
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
}
//-> Select Bank
void ENC28_setBank(uint8_t addr)
{
if ((addr & BANK_MASK) != Enc28_Bank)
{
ENC28_writeOp(ENC28_BIT_FIELD_CLR, ECON1, ECON1_BSEL1|ECON1_BSEL0);
Enc28_Bank = addr & BANK_MASK;
ENC28_writeOp(ENC28_BIT_FIELD_SET, ECON1, Enc28_Bank>>5);
}
}
//-> Read & Write Control Registers
uint8_t ENC28_readReg8(uint8_t addr){
ENC28_setBank(addr);
return ENC28_readOp(ENC28_READ_CTRL_REG, addr);
}
void ENC28_writeReg8(uint8_t addr, uint8_t data){
ENC28_setBank(addr);
ENC28_writeOp(ENC28_WRITE_CTRL_REG, addr, data);
}
uint16_t ENC28_readReg16( uint8_t addr)
{
return ENC28_readReg8(addr) + (ENC28_readReg8(addr+1) << 8);
}
void ENC28_writeReg16(uint8_t addrL, uint16_t data)
{
ENC28_writeReg8(addrL, data);
ENC28_writeReg8(addrL+1, data >> 8);
}
//-> Read & Write Buf
void ENC28_readBuf(uint16_t len, uint8_t* data)
{
uint8_t spiData[2];
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
spiData[0] = ENC28_READ_BUF_MEM;
HAL_SPI_Transmit(&hspi1, spiData, 1, 100);
for(uint16_t x = 1; x < len; ++x){
HAL_SPI_Receive(&hspi1, &spiData[1], 1, 100);
};
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
}
void ENC28_writeBuf(uint16_t len, uint8_t* data)
{
uint8_t spiData[2];
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
spiData[0] = ENC28_WRITE_BUF_MEM;
HAL_SPI_Transmit(&hspi1, spiData, 1, 100);
HAL_SPI_Transmit(&hspi1, data, len, 100);
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
}
//-> Read & Write PHY Registers
uint16_t ENC28_readPhy(uint8_t addr)
{
ENC28_writeReg8(MIREGADR, addr); // Pass the PHY address to the MII
ENC28_writeReg8(MICMD, MICMD_MIIRD); // Enable Read bit
while (ENC28_readReg8(MISTAT) & MISTAT_BUSY); // Poll for end of reading
ENC28_writeReg8(MICMD, 0x00); // Disable MII Read
return ENC28_readReg8(MIRD) + (ENC28_readReg8(MIRD+1) << 8);
}
void ENC28_writePhy(uint8_t addr, uint16_t data)
{
ENC28_writeReg8(MIREGADR, addr);
ENC28_writeReg8(MIWR, data);
while (ENC28_readReg8(MISTAT) & MISTAT_BUSY);
}
//-> Initialization ENC28J60
void ENC28_Init(void)
{
//uint8_t spiData[2];
// (1): Disable the chip CS pin
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
HAL_Delay(1);
// (2): Perform soft reset to the ENC28J60 module
ENC28_writeOp(ENC28_SOFT_RESET, 0, ENC28_SOFT_RESET);
HAL_Delay(2);
// (3): Wait untill Clock is ready
while(!(ENC28_readOp(ENC28_READ_CTRL_REG, ESTAT) & ESTAT_CLKRDY));
// (4): Initialise RX and TX buffer size
ENC28_writeReg16(ERXST, RXSTART_INIT);
ENC28_writeReg16(ERXND, RXSTOP_INIT);
ENC28_writeReg16(ETXST, TXSTART_INIT);
ENC28_writeReg16(ETXND, TXSTOP_INIT);
ENC28_writeReg16(ERXRDPT, RXSTART_INIT);
ENC28_writeReg16(ERXWRPT, RXSTART_INIT);
// dataWatch16 = ENC28_readReg16(ERXND);
// (5): Reviece buffer filters
ENC28_writeReg8(ERXFCON, ERXFCON_UCEN|ERXFCON_ANDOR|ERXFCON_CRCEN);
// ENC28_writeReg8(ERXFCON, ERXFCON_UCEN|ERXFCON_PMEN|ERXFCON_CRCEN|ERXFCON_BCEN);
// dataWatch8 = ENC28_readReg8(ERXFCON);
// (6): MAC Control Register 1
ENC28_writeReg8(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS|MACON1_PASSALL);
// dataWatch8 = ENC28_readReg8(ERXFCON);
// (7): MAC Control Register 3
ENC28_writeOp(ENC28_BIT_FIELD_SET, MACON3,MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
// (8): NON/Back to back gap
ENC28_writeReg16(MAIPG, 0x0C12); // NonBackToBack gap
ENC28_writeReg8(MABBIPG, 0x12); // BackToBack gap
// (9): Set Maximum framelenght
ENC28_writeReg16(MAMXFL, MAX_FRAMELEN); // Set Maximum frame length (any packet bigger will be discarded)
// (10): Set the MAC address of the device
ENC28_writeReg8(MAADR1, MAC_1);
ENC28_writeReg8(MAADR2, MAC_2);
ENC28_writeReg8(MAADR3, MAC_3);
ENC28_writeReg8(MAADR4, MAC_4);
ENC28_writeReg8(MAADR5, MAC_5);
ENC28_writeReg8(MAADR6, MAC_6);
dataWatch8 = ENC28_readReg8(MAADR1);
dataWatch8 = ENC28_readReg8(MAADR2);
dataWatch8 = ENC28_readReg8(MAADR3);
dataWatch8 = ENC28_readReg8(MAADR4);
dataWatch8 = ENC28_readReg8(MAADR5);
dataWatch8 = ENC28_readReg8(MAADR6);
if(dataWatch8==MAC_6) HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
//**********Advanced Initialisations************//
// (1): Initialise PHY layer registers
ENC28_writePhy(PHLCON, PHLCON_LED);
ENC28_writePhy(PHCON2, PHCON2_HDLDIS);
// (2): Enable Rx interrupt line
ENC28_setBank(ECON1);
ENC28_writeOp(ENC28_BIT_FIELD_SET, ECON1, ECON1_RXEN);
// ENC28_writeOp(ENC28_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
// ENC28_writeOp(ENC28_BIT_FIELD_SET, EIR, EIR_PKTIF);
}
//-> Transmitting & Recieving Packets
void ENC28_packetSend(uint16_t len, uint8_t* dataBuf)
{
uint8_t retry = 0;
while(1)
{
ENC28_writeOp(ENC28_BIT_FIELD_SET, ECON1, ECON1_TXRST);
ENC28_writeOp(ENC28_BIT_FIELD_CLR, ECON1, ECON1_TXRST);
ENC28_writeOp(ENC28_BIT_FIELD_CLR, EIR, EIR_TXERIF|EIR_TXIF);
// prepare new transmission
if(retry == 0)
{
ENC28_writeReg16(EWRPT, TXSTART_INIT);
ENC28_writeReg16(ETXND, TXSTART_INIT+len);
ENC28_writeOp(ENC28_WRITE_BUF_MEM, 0, 0x00); //line 485 enc28j60.cpp
ENC28_writeBuf(len, dataBuf);
}
// initiate transmission
ENC28_writeOp(ENC28_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
uint16_t count = 0;
while ((ENC28_readReg8(EIR) & (EIR_TXIF | EIR_TXERIF)) == 0 && ++count < 1000U);
if (!(ENC28_readReg8(EIR) & EIR_TXERIF) && count < 1000U)
{
// no error; start new transmission
break;
}
// cancel previous transmission if stuck
ENC28_writeOp(ENC28_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
break;
}
}

UART ESP8266 and STM32

Hello Im trying to connect a ESP8266 to a STM32 via UART.
I want to use the STM32 to send AT commands to the ESP, so that the ESP can do HTTP GET requests.
The code down here works when I use my PC to send data via FTDI to the STM, then the interrupt is called everytime a byte is recieved.
But when i hook up the ESP8266 I don't get a response even thought im sending AT\r\n;
Also i just connected everything like so:
SMT32 Tx -- ESP Rx
ESP Tx -- FTDI Rx
And I sended the AT\r\n command from the SMT to the ESP and on my pc in putty I got the OK command back, so the ESP is responding. But the interrupt is not called.
#include "main.h"
#include "usb_device.h"
#include "usbd_cdc_if.h"
UART_HandleTypeDef huart1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
char Rx_Byte[1]; // Creating a single byte buffer
uint8_t Rx_Buffer[256]; // Full buffer
uint8_t Rx_Buffer_Index = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
HAL_UART_Receive_IT(&huart1, (uint8_t *)Rx_Byte, 1);
memcpy(Rx_Buffer + Rx_Buffer_Index, Rx_Byte, 1);
Rx_Buffer_Index++;
if (*Rx_Byte == '\r' || *Rx_Byte == '\n') {
// I could send data via putty and FTDI, and when enter was pressed it printed the data in the buffer back to you via uart
// HAL_UART_Transmit(&huart1, (uint8_t *) Rx_Buffer, Rx_Buffer_Index, 1000);
memset(Rx_Buffer, 0, sizeof(Rx_Buffer)); // Clear buffer
Rx_Buffer_Index = 0;
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USB_DEVICE_Init();
char echo_off[] = "ATE0\r\n";
char data[] = "AT\r\n";
HAL_Delay(1000);
HAL_UART_Transmit(&huart1, (uint8_t*)echo_off, sizeof(echo_off), 10);
while (1)
{
HAL_GPIO_TogglePin(GPIOA, LED_1_Pin);
HAL_UART_Transmit(&huart1, (uint8_t*)data, sizeof(data), 1000);
HAL_Delay(500);
}
}

Why stm32nucleo board uart can't receive message after almost three or four hundred times using HAL_UART_Receive_IT

I am developing uart communication on STMicroelectronics NUCLEO-G474RE Board(stm32G474RETX MCU, 64pins) using MDK-v5, but run into a perplexing problem these several days, make no progress on it and have to reach out to seek some help. If anyone could give me a right way to go, it would be appreciated greatly.
Code is not complicated, I use cubeMX to initialize the code base with usart2 configured, and use two threads based on cmsis v2 api for receiving occassinally and transmiting periodically(in 2 seconds).
The auto-generated usart2 init code
static void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_RTS;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
Interrupt call back code
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
printf("Interrupt error occured(0x%x)!!!\r\n", huart->ErrorCode);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)
{
UNUSED(huart);
if(huart == &huart2 || huart == &huart3){
uint8_t aEnterLine[] = "\r\n";
//HAL_UART_Transmit(huart, aEnterLine, sizeof(aEnterLine), 0xFFFF);
//HAL_UART_Transmit(huart, gRxBuffer, 11, 0xFFFF);
//HAL_UART_Transmit(huart, aEnterLine, sizeof(aEnterLine), 0xFFFF);
//printf("%s\r\n", gRxBuffer);
if(g_cmdExecuting == 0)
osEventFlagsSet(evt_id, 0x00000001U);
}else if(huart == &huart1){
}else{
}
HAL_UART_Receive_IT(huart, (unsigned char*)gRxBuffer, 11);
}
int8_t app_usart_transmit(uint8_t* buf, uint8_t len)
{
return 0;
}
int8_t app_usart_init(UART_HandleTypeDef* huart)
{
if(huart == NULL)
return -1;
if(huart == &huart2 || huart == &huart3){
uint8_t aTxStartMessage[] = "\r\n****UART-Hyperterminal commmunication based on IT****"
"\r\nEnter 10 characters using keyboard: \r\n";
HAL_UART_Transmit(huart, aTxStartMessage, sizeof(aTxStartMessage), 0xFFFF);
}
clear_rx_buffer();
HAL_UART_Receive_IT(huart, (uint8_t*)gRxBuffer, 11);
return 0;
}
rx & tx worker code
extern osMutexId_t myMutex01Handle;
extern osEventFlagsId_t evt_id;
extern osEventFlagsId_t evt_id1;
osTimerId_t timer_id;
static osThreadId gTask1Handle;
static const osThreadAttr_t gTask1Attrbutes = {
.name = "Task1",
.priority = (osPriority_t) osPriorityAboveNormal,
.stack_size = 512
};
static osThreadId gTask2Handle;
static const osThreadAttr_t gTask2Attrbutes = {
.name = "Task2",
.priority = (osPriority_t) osPriorityNormal,
.stack_size = 512
};
uint8_t g_cmdExecuting = 0;
uint8_t g_SemExec = 0;
uint32_t timer_cnt;
void update_stat_timer(void* argument)
{
timer_cnt++;
//osMutexAcquire(myMutex01Handle, osWaitForever);
printf("update_stat_timer executes %u times, ====++++====++++\r\n", timer_cnt);
//osMutexRelease(myMutex01Handle);
}
void update_stat_task_run(void* argument)
{
uint32_t count;
for(;;){
osDelay(2000);
count++;
osMutexAcquire(myMutex01Handle, osWaitForever);
printf("update_stat_task_run executes %d times, ====++++====++++\r\n", count);
osMutexRelease(myMutex01Handle);
}
}
void exec_cmd_task_run(void* argument)
{
uint32_t flags;
for(;;){
flags = osEventFlagsWait(evt_id, 0x00000001U, osFlagsWaitAny, osWaitForever);
g_cmdExecuting = 1;
osMutexAcquire(myMutex01Handle, osWaitForever);
osDelay(1000);
printf("exec_cmd_task Print\r\n");
osMutexRelease(myMutex01Handle);
g_cmdExecuting = 0;
}
}
int8_t app_task_init()
{
osStatus_t status;
gTask1Handle = osThreadNew(exec_cmd_task_run, NULL, &gTask1Attrbutes);
gTask2Handle = osThreadNew(update_stat_task_run, NULL, &gTask2Attrbutes);
//uint32_t exec = 1;
//timer_id = osTimerNew(update_stat_timer, osTimerPeriodic, &exec, NULL);
//if(status != osOK){
//;
//}
//osTimerStart(timer_id, 2000U);
return 0;
}
My Question:
It could receive and transmit msg at very begining, but after receiving three or four hundred times, it couldn't receive the msg anymore while the transmitting is ok, and I also use the timer api to replace the transmitting thread, the result is the same, it couldn't receive any msg after hundreds times.
the testing result pic
You can perform the HAL status and error checks using uint32_t HAL_UART_GetError(UART_HandleTypeDef * huart) and HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart) (http://www.disca.upv.es/aperles/arm_cortex_m3/llibre/st/STM32F439xx_User_Manual/group__uart__exported__functions__group4.html)
The source code for HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) and HAL_UART_RxCplt_Callback() is in https://github.com/ARMmbed/mbed-hal-st-stm32cubef4/blob/master/source/stm32f4xx_hal_uart.c
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
uint32_t tmp = 0;
tmp = huart->State;
if((tmp == HAL_UART_STATE_READY) || (tmp == HAL_UART_STATE_BUSY_TX))
{
if((pData == HAL_NULL ) || (Size == 0))
{
return HAL_ERROR;
}
/* Process Locked */
__HAL_LOCK(huart);
huart->pRxBuffPtr = pData;
huart->RxXferSize = Size;
huart->RxXferCount = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
/* Check if a transmit process is ongoing or not */
if(huart->State == HAL_UART_STATE_BUSY_TX)
{
huart->State = HAL_UART_STATE_BUSY_TX_RX;
}
else
{
huart->State = HAL_UART_STATE_BUSY_RX;
}
/* Enable the UART Parity Error Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_PE);
/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
__HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
/* Process Unlocked */
__HAL_UNLOCK(huart);
/* Enable the UART Data Register not empty Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
Note that the HAL mutually uses locking mechanisms (__HAL_LOCK, code line 107 in https://github.com/ARMmbed/mbed-os/blob/master/targets/TARGET_STM/TARGET_STM32L1/device/stm32l1xx_hal_def.h)
To get the UART status use i.e.
HAL_UART_StateTypeDef UARTStatus;
UARTStatus = HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
The definition of HAL_UART_StateTypeDef is
typedef enum
{
HAL_UART_STATE_RESET = 0x00, /*!< Peripheral is not yet Initialized */
HAL_UART_STATE_READY = 0x01, /*!< Peripheral Initialized and ready for use */
HAL_UART_STATE_BUSY = 0x02, /*!< an internal process is ongoing */
HAL_UART_STATE_BUSY_TX = 0x12, /*!< Data Transmission process is ongoing */
HAL_UART_STATE_BUSY_RX = 0x22, /*!< Data Reception process is ongoing */
HAL_UART_STATE_BUSY_TX_RX = 0x32, /*!< Data Transmission and Reception process is ongoing */
HAL_UART_STATE_TIMEOUT = 0x03, /*!< Timeout state */
HAL_UART_STATE_ERROR = 0x04 /*!< Error */
}HAL_UART_StateTypeDef;
(https://github.com/synthetos/Motate/blob/master/MotateProject/motate/cmsis/TARGET_STM/TARGET_DISCO_F407VG/stm32f4xx_hal_uart.h code line 97)
The definition of HAL_StatusTypeDef (general HAL status) is
typedef enum
{
HAL_OK = 0x00,
HAL_ERROR = 0x01,
HAL_BUSY = 0x02,
HAL_TIMEOUT = 0x03
} HAL_StatusTypeDef;
You can print the HAL status (i.e. with UART transmit or SWO ITM_SendChar((*ptr++));, see https://ralimtek.com/stm32_debugging/ )
The HAL has its own reference manual, the HAL status is described in the reference manual https://www.st.com/content/ccc/resource/technical/document/user_manual/2f/71/ba/b8/75/54/47/cf/DM00105879.pdf/files/DM00105879.pdf/jcr:content/translations/en.DM00105879.pdf on page 54 in chapter 2.9 HAL common resources.
Debugging techniques are described in https://www.st.com/content/ccc/resource/technical/document/application_note/group0/3d/a5/0e/30/76/51/45/58/DM00354244/files/DM00354244.pdf/jcr:content/translations/en.DM00354244.pdf, also for your programming adapter, that you can directly integrate in CubeMX (i use Atollic with integrated CubeMX because Atollic is based on Eclipse IDE and is almost identical to use)
Another debugging tutorial is https://ardupilot.org/dev/docs/debugging-with-gdb-on-stm32.html (if you are on linux).
This could also be a race condition either of the HAL or the OS. The problem that i have is that you do not post your full code, especially not concerning your OS and this is possibly critical here
So maybe first check the HAL status and then focus on the OS part (race conditions, buffer, stack or heap overflow, ... https://www.st.com/content/ccc/resource/technical/document/user_manual/2d/60/ff/15/8c/c9/43/77/DM00105262.pdf/files/DM00105262.pdf/jcr:content/translations/en.DM00105262.pdf)
Stack overflows are always critical on embedded systems so here is links https://barrgroup.com/embedded-systems/how-to/prevent-detect-stack-overflow , https://www.iar.com/support/resources/articles/detecting-and-avoiding-stack-overflow-in-embedded-systems/
Also see Uart dma receive interrupt stops receiving data after several minutes and UART receive interrupt stops triggering after several hours of successful receive
Many developers avoid using the HAL because it is a bit buggy and not very transparent, i personally would also not use it when i want full control over the system behavior

USART timeout interrupt for STM32F4 Discovery

My STM and Raspberry do successfully comunicate via USART. Rx and Tx word fine, until the Raspberry stops to send. Then the STM listens and listens for new chars. The code cycle is stuck until a char is received.
I want to implement a timeout interrupt.
This is what I found.
STM32H7 documentation (page 21)
Unfortunatelly it's for the wrong board. The receive timeout cannot be found in the reference manual for the STMF4. So I guess this functionality is not given for my board?
I am using Keil µVision V5.28.0.0 and standard peripherals.
Here is a code snippet
#include "main.h"
#include <stdio.h>
USART_InitTypeDef USART_InitStruct;
volatile uint32_t msTicks=0;
void USART_Initialise(void);
int USART_putchar(char ch);
void USART_puts(char str[]);
char USART_receive(void);
void Delay (int ms);
int main(void)
{
char buffer[20];
string test = "test";
USART_Initialise();
while (1)
{
char mode = USART_receive();
if (mode == '+')
{
sprintf(buffer, "%.2lf",test);
USART_puts(buffer);
}
Delay(300);
}//while
}//main
void USART_Initialise(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB1PeriphClockCmd (RCC_APB1Periph_USART3, ENABLE);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; //GPIO Pin 10 & 11
GPIO_Init(GPIOC, &GPIO_InitStruct);
USART_StructInit(&USART_InitStruct);
USART_InitStruct.USART_BaudRate=9600;
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;
USART_InitStruct.USART_Parity=USART_Parity_No;
USART_InitStruct.USART_StopBits=USART_StopBits_1;
USART_InitStruct.USART_WordLength=USART_WordLength_8b;
USART_Init(USART3, &USART_InitStruct);
USART_Cmd(USART3, ENABLE);
}
int USART_putchar(char ch)
{
USART_SendData(USART3, (uint8_t) ch);
while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{}
return ch;
}
void USART_puts(char str[])
{
while (*str != 0)
{
USART_putchar(*str);
str++;
}
}
char USART_receive(void)
{
while (USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == RESET){};
char rxd_receive = USART_ReceiveData(USART3);
return rxd_receive;
}
void SysTick_Handler(void) //für ISR kein Prototyp erforderlich
{
msTicks--;
}
void Delay (int ms)
{
msTicks = ms;
while (msTicks>0);
}
Change your receive function into:
int USART_receive(void)
{
if (USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == RESET)
{
return EOF;
}
return USART_ReceiveData(USART3);
}
Then you can decide what to do on receiving a character in the upper layer.
You might also put the timeout in the function. Then it will return EOF if the timeout happens. Since you say the UART does not include an own timeout functionality, you need to use one of the timers.

Why wouldn't my HAL_UART IT capture callback routine trigger?

I'm trying to establish communication between two STM32F103 MCU's via UART. I'm using STMCubeMX to build peripheral initalization. I've logicaly named the MCU's as MASTER and SLAVE. Slave UART is configured as Transmit only, while MASTER uart is recieve only. I'm using HAL drivers to program the MCU in AtollicTRUEstudio IDE. I want to send uint32_t value, buffer_USART1_rx is declared as volatile uint8_t buffer_USART1_rx[10]. Basicly SLAVE UART transmit is being triggered by Systick timer every 1 second, while MASTER UART is defined in IT mode, and soon as the interrupt happens it read the transmited value.
I connected the osciloscope probe to the PA10 RX pin of MASTER and i noticed the UART signal is fine and transmiting over the wires. But the value being transmitted is always 0 and breakpoint in HAL_UART_RxCpltCallback is never activated. Since the osciloscope signal is correct, i'm thinking it's a software issue.
Image of RX PA10 pin of MASTER stm32
This is from MASTER STM (code is located in main file)
UART initialization:
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
static void MX_NVIC_Init(void)
{
/* USART1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
__NOP();
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/*UART1 water level from SLAVE */
if(huart->Instance==USART1)
{
water_level=getUSART1();
/* Water level change triggers LCD refresh */
if(water_level_prev!=water_level)
{
lcd_screen_refresh=true;
}
water_level_prev=water_level;
}
else
{
__NOP();
}
/*UART2 target level from NANOPI */
if(huart->Instance==USART2)
{
target_level_pi=getUSART2();
/* Target level change triggers LCD refresh */
if(target_level_pi!=target_level_prev)
{
lcd_screen_refresh=true;
}
}
else
{
__NOP();
}
}
UART deserialize function:
uint32_t getUSART1()
{
uint32_t num=0;
num |= buffer_USART1_rx[0] << 24;
num |= buffer_USART1_rx[1] << 16;
num |= buffer_USART1_rx[2] << 8;
num |= buffer_USART1_rx[3];
return num;
}
In main file initialization of UART in IT mode:
/* Initialize TIM/UART interrupts */
HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_2);
HAL_UART_Receive_IT(&huart1, buffer_USART1_rx, 4);
SLAVE MCU configuration :
// This is in while loop
if(send_USART==true)
{
buffer[0] = test ;
buffer[1] = test >>8;
buffer[2] = test >> 16;
buffer[3] = test >> 24;
HAL_UART_Transmit(&huart1,buffer,4,2000);
}
else
{
__NOP();
}
// Callback
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
send_USART=false;
}
//Systick timer triggers UART transmit every 1 second
void HAL_SYSTICK_Callback()
{
sys_timer++;
if(sys_timer>=1000)
{
sys_timer=0;
send_USART=true;
}
else
{
__NOP();
}
}
//Global declaration of variables used
/* Timer variables */
uint8_t buffer[10];
volatile uint32_t sys_timer=0;
uint32_t test=10;
/* Boolean variables */
bool send_USART=false;
// UART initialization
/* USART1 init function */
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
static void MX_NVIC_Init(void)
{
/* USART1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
I expect the recieved value to be 10. (since i'm serializing "test" variable on SLAVE stm, and sending it on MASTER stm while deserializing it)
Nevermind, i've found the issue and what was causing it
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
if(huart1.RxState==HAL_UART_STATE_READY)
{
HAL_UART_Receive_IT(&huart1,buffer_USART1_rx,4);
uart1_received=4; //flag da je primljen podatak
__HAL_UART_FLUSH_DRREGISTER(&huart1);
__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE);
}
else
{
__NOP();
}
/* USER CODE END USART1_IRQn 1 */
}
The code for handling was above the HAL_UART_IRQHandler(&huart1); . That's why it only recieved data once. When I copied it below like on the code above, everything works fine.

Resources