I'm trying to receive UART interrupts - c

I want to receive UART interrupts, but shouldn't the basic structure of the interrupts be made like that?
Sometimes it doesn't work and sometimes it prints out printf ("test\r\n") but sometimes it doesn't print out the received data, but I don't know what the cause is Can you tell me the solution?
I tried to pull the HAL_UART_Receive_IT door out while, but it didn't work
I don't think it's a connection problem since I'm sending a message
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 */
/* USER CODE END USART1_IRQn 1 */
}
When I entered this code, there was an error
Error[Li006]: duplicate definitions for "USART1_IRQHandler";
The code below is the code that is currently experiencing a problem
uint8_t received_msg[10];
char check_msg[10];
//UART read
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
if(huart -> Instance == USART1){
printf("test\r\n");
HAL_UART_Receive_IT(&huart1, (uint8_t*)received_msg, sizeof(received_msg));
}
}
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
MX_TIM6_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim6);
calibrate(0.01, 4);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
rcvStat = HAL_UART_Receive_IT(&huart1, received_msg, sizeof(received_msg));
if(rcvStat != HAL_OK){
printf("error\r\n");
}
sprintf(check_msg, "%s", (char*)received_msg);
printf("%s\r\n", check_msg);
printf("%d, %d\r\n", timer, flag);
HAL_Delay(timer);
printf("---------------------\r\n");
memset(received_msg, 0, strlen(received_msg));
memset(check_msg, 0, strlen(check_msg));
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

Call the RX interrupt once before the while loop and then after you have recieved the data in the ISR. Remove it from the inside of the while.
It seems like in the update loop you are re-issuing the RX_IT call, you should call this once and wait for data to arrive (ISR fires) and then re-issue at that point inside of ISR. Otherwise with a message size greater than one byte, you could re-issue the IT function after it recieved a few bytes and miss some bytes since it requests 10 bytes before the interrupt fires after being issued once.
Your ISR should primarily only be there for moving the RX'd data from one spot, to another for processing.
Printf is a pig and will most likely cause you to miss messages coming in if they are coming in real-time and not a one-off message.
A suggestion, would be to implement some type of circular FIFO queue in the ISR which stuffs the data in a FIFO buffer and that FIFO is accessed in your control loop for parsing, or action. That way, you are reciving each symbol and quickly exiting the interrupt and all data should be there for processing. I have had great success with this method in the past.

Related

Enable the Ethernet in stm32F769I-Disco using c

The main aim is to get the IP address of the stm32 board using the ethernet port but I am not there yet. In code a temporary breakpoint occurred at HAL_Init();
I am having trouble in finding what's wrong with code also had difficulty in knowing the working of the api function in the code. Need help ,Thank you.
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"
#include "lwip.h"
#include "stdio.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>
#include "lwip/netif.h"
#include "netif/etharp.h"
#include "ethernetif.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;
osThreadId defaultTaskHandle;
struct netif gnetif;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
void StartDefaultTask(void const * argument);
//static void udp_client_connect(void);
static void MX_LWIP_Process(void);
extern struct netif gnetif;
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
//initialize the lwip stack
MX_LWIP_Init();
/* USER CODE BEGIN 2 */
// udp_client_connect();
/* USER CODE END 2 */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* definition and creation of defaultTask */
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* Start scheduler */
// osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
MX_LWIP_Process();
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
static void MX_LWIP_Process(void)
{
ethernetif_input(&gnetif);
ethernetif_set_link(&gnetif);
if (netif_is_link_up(&gnetif) && !netif_is_up(&gnetif))
{
netif_set_up(&gnetif);
dhcp_start(&gnetif);
}
}

Why does my UART Kernel Module not send the last 8 characters of my message?

I am building a UART Kernel Module with the RTDM API. For the datasheet of this AUART, I worked with chapter 30 of the following link: Link of datasheet
The driver is very basic, it only has to send a buffer which is passed to it in user-space with write function. It works like this:
In open function, activate UART with UARTEN bit of UART Control Register
In write function, I activate the Transmitter with TXE bit of UART Control Register
Then, start sending characters with:
static void rt_mxs_auart_tx_chars(struct rt_mxs_auart_ctx *ctx)
{
int ch;
pr_info("Start transmitting\n");
while (ctx->out_npend > 0 &&
!(mxs_read(ctx->port, REG_STAT) & AUART_STAT_TXFF)) {
ch = ctx->out_buf[ctx->out_head++];
mxs_write(ch, ctx->port, REG_DATA);
ctx->out_head &= (OUT_BUFFER_SIZE - 1);
ctx->out_npend--;
}
if (mxs_read(ctx->port, REG_STAT) & AUART_STAT_TXFF){
pr_info("We've stopped transmitting because FIFO is full, remains: %d to be sent (bytes pending)\n", ctx->out_npend);
}
if(ctx->out_npend > 0 ) {
mxs_set(AUART_INTR_TXIEN, ctx->port, REG_INTR);
pr_info("%d bytes pending, setting AUART_INTR_TXIEN\n", ctx->out_npend);
}
else {
mxs_clr(AUART_INTR_TXIEN, ctx->port, REG_INTR);
pr_info("%d bytes pending, clearing AUART_INTR_TXIEN\n", ctx->out_npend);
}
}
TXIEN corresponds to Transmit Interrupt Enable, and AUART_STAT_TXFF means that the transmit FIFO is full. Here's the ctx structure:
struct rt_mxs_auart_ctx {
struct rtser_config config; /* current device configuration */
rtdm_irq_t irq_handle; /* device IRQ handle */
rtdm_lock_t lock; /* lock to protect context struct */
int in_head; /* RX ring buffer, head pointer */
int in_tail; /* RX ring buffer, tail pointer */
size_t in_npend; /* pending bytes in RX ring */
int in_nwait; /* bytes the user waits for */
rtdm_event_t in_event; /* raised to unblock reader */
char in_buf[IN_BUFFER_SIZE]; /* RX ring buffer */
volatile unsigned long in_lock; /* single-reader lock */
uint64_t *in_history; /* RX timestamp buffer */
int out_head; /* TX ring buffer, head pointer */
int out_tail; /* TX ring buffer, tail pointer */
size_t out_npend; /* pending bytes in TX ring */
rtdm_event_t out_event; /* raised to unblock writer */
char out_buf[OUT_BUFFER_SIZE]; /* TX ring buffer */
rtdm_mutex_t out_lock; /* single-writer mutex */
uint64_t last_timestamp; /* timestamp of last event */
int ioc_events; /* recorded events */
rtdm_event_t ioc_event; /* raised to unblock event waiter */
volatile unsigned long ioc_event_lock; /* single-waiter lock */
int ier_status; /* IER cache */
int mcr_status; /* MCR cache */
int status; /* cache for LSR + soft-states */
int saved_errors; /* error cache for RTIOC_GET_STATUS */
/*
* The port structure holds all the information about the UART
* port like base address, and so on.
*/
struct rt_mxs_auart_port *port;
};
In my interrupt handler, I do this:
if (istat & AUART_INTR_TXIS){
pr_info("Transmit Interrupt Status enabled\n");
rt_mxs_auart_tx_chars(ctx);
istat &= ~AUART_INTR_TXIS;
ret = RTDM_IRQ_HANDLED;
}
which means that if the interrupt status flag is active, we send data again with the same function rt_mxs_auart_tx_chars
My problem is that I do not seem to receive the end of my message. For example, if I try to send "This... is my second message" (29 char) I only get "This... is my sec" (17 char). The log is the following:
Calling open function
Calling write function
Enabling Transmitter
Start transmitting
We've stopped transmitting because FIFO is full, remains: 12 to be sent (bytes pending)
12 bytes pending, setting AUART_INTR_TXIEN
IRQ handler called
Transmit Interrupt Status enabled
Start transmitting
We've stopped transmitting because FIFO is full, remains: 4 to be sent (bytes pending)
4 bytes pending, setting AUART_INTR_TXIEN
Receive Interrupt Status or Receive Timeout Interrupt Status enabled
IRQ handler called
Transmit Interrupt Status enabled
Start transmitting
0 bytes pending, clearing AUART_INTR_TXIEN
Disabling Transmitter
How do you think can I correct this?

On-board LED, doesn't turn on/off

I just started working with STM32F407VGT Discovery kit and I for the start I wanted to turn on/off LED's on-board. I am using CubeMX to generate initialization code and SystemWorkBench Eclipse to compile and also ST-LINK STM32 for programming my board. In CubeMX I initialized PD12-PD15 ports as output. I used function HAL_GPIO_WritePin to set my LED's ON. After compilation and programming to device, nothing happens... Please give me some advice what I did wrong.
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Problem solved! It seems that ST-LINK is not uploading hex correctly, I used AC6 to upload and everythig seem to work fine

F_mount function is not working with STM32F401ReTx

I have written some simple code (with the help of STM32CubeMx) for STM32F407VGTx to create a file in SDcard. Although it works perfectly with 407, it is not working with STM32F401ReTx. To be clear, I have generated code with CubeMx specifically for 401(did not use the code for 407).
Even for 407, I am able to work with only Version 21 of CubeMx and firmware version 16. I have added the code below. Any ideas?
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_SDIO_SD_Init();
MX_FATFS_Init();
/* USER CODE BEGIN 2 */
if(f_mount(&myFatFS,SD_Path,1)==FR_OK)
{
HAL_Delay(1000);
f_open(&myFil,"new document.txt\0",FA_CREATE_ALWAYS | FA_WRITE);
f_close(&myFil);
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Problem is probably heap size f407 has more initial heap size than f401. Try to increase heap size in linker file.

fgets function doesn't work

When I write the following code. Putty prints the text but I can't type anything below ..
For example :
First he does a printf --> who are you ?
Then I do a fgets where I normally most type something , that doensn't work.
At last he does another printf where he say ; good to meet you ...
int main(void)
{
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
char name[10];
printf("Who are you? \n");
fgets(name,10,stdin);
printf("Good to meet you, %s.\n",name);
return(0);
}
can anyone help me ?
thanks !
You have overwritten the implemnetation of fputs in your source code. So your linker doesn't need to lookup the library implementation of that function. With your implementation of fputc you have connected the stdio-output-path to your UART transmitter.
You need to define the corresponding input-path. This could be done by implementing a fgetc function. In that can the library function fgets can call your function, polling the UART receiver.
The default implementation of stdio in embedded environment is highly vendor dependent. It can be connected to
the JTAG debugger
the microcontroller specific debug/console ports
nothing.
Therefore you are responsible to make the right implemantation of that connection. This can be more complecated than the fputc implementation because you have to check, if there is data received at the UART at the time of call.

Resources