I am working with STM32F103RB board and I want to simply echo everything I receive from my computer via serial port back to that port. I must do it using UART and DMA. I've set up DMA on USART2_RX with CubeMX in normal mode. My problem is that HAL_UART_RxCpltCallback
gets called only once. Interestingly I get the response on PC end but with additional 0xFC
byte. After that the controller stops reacting to new data sent through the serial port and won't do so until I unplug and plug controller back in with usb. Here is the code for call back and main function:
#define BUF_SIZE 16
uint8_t RX_BUF[BUF_SIZE] = {0};
uint8_t TX_BUF[BUF_SIZE] = {0};
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
HAL_UART_Receive_DMA(&huart2, RX_BUF, BUF_SIZE);
}
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_USART2_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_DMA(&huart2, RX_BUF, sizeof (RX_BUF));
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Edit: I am trying to do this on a Mac through USB-C dongle. Can this be the problem?
Calling complex functions in an ISR is a bad idea. Many of the HAL functions use the system tick to measure timeouts, and depending on your interrupt priorities, the tick may be blocked while your ISR runs.
It would be better to move any complex processing out of your ISR, into the main function. Just set a flag in the ISR to indicate when reception is complete. Something like:
static volatile bool uart_rx_done = false;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
uart_rx_done = true;
}
int main()
{
// Initialisation stuff
for (;;)
{
uart_rx_done = false;
HAL_UART_Receive_DMA(&huart2, RX_BUF, BUF_SIZE);
while (!uart_rx_done)
;
HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
}
}
First of all, check if you configured uart
and dma
interrupts correctly. in the stm21f1xx_it.c
file you should see these functions
void DMA1_Channel6_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel6_IRQn 0 */
/* USER CODE END DMA1_Channel6_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_usart2_rx);
/* USER CODE BEGIN DMA1_Channel6_IRQn 1 */
/* USER CODE END DMA1_Channel6_IRQn 1 */
}
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
and also a uart2
configuration in the MX_NVIC_Init()
function in your main.c
file.
But your main mistake is that you're not activating uart
receive interrupt at all. I suggest not using dma
for now, and try this to see if the uart
interrupt gets activated:
#define BUF_SIZE 16
bool uart_received = false;
uint8_t RX_BUF[BUF_SIZE] = {0};
uint8_t TX_BUF[BUF_SIZE] = {0};
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
uart_received = true;
HAL_UART_Receive_IT(&huart2, RX_BUF, BUF_SIZE);
}
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_USART2_UART_Init();
/* USER CODE BEGIN 2 */
//HAL_UART_Receive_DMA(&huart2, RX_BUF, sizeof (RX_BUF));
HAL_UART_Receive_IT(&huart2, RX_BUF, BUF_SIZE);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if (uart_received) {
HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
uart_received = false;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
If this works, then you can use HAL_UARTEx_ReceiveToIdle_DMA
for activating uart-dma
interrupt and HAL_UARTEx_RxEventCallback
for callback function (assuming the dam
interrupt is configured).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.