2023-06-25 1:49 PM - edited 2023-06-25 1:53 PM
I've been writing apps using the STM HAL drivers for a while. I'd like to move to the low level drivers in order to have a better understanding of what's happening in my app. Comms over a UART with DMA is a critical part of most of my apps so I'm starting with that in a simple loop back configuration (TX connected to RX). It seems like using CubeMX to generate the startup code is a good place to start. And I add the code required to do what I need. I've been able to get the TX part of simple UART app working. I've got a logic analyzer hooked up to TX and I see the message I'm sending show up when I expect it. In addition if I put breakpoints in the TX callbacks, I can see the program get to the callbacks. Unfortunately, nothing seems to be happening on the RX side. The app doesn't get to the breakpoints in the RX callbacks and the rxBuffer doesn't get any data. I'd appreciate any suggestions about what I'm doing wrong. The main.c file is attached and here's the relevant code:
ALIGN_32BYTES(const uint8_t txBuffer[]) = "$PUBX,00*33\r\n";
uint8_t txBufferSize = sizeof(txBuffer);
ALIGN_32BYTES(const uint8_t rxBuffer[32]) = { 0 };
uint8_t rxBufferSize = 8;
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_SDMMC1_SD_Init();
MX_USART1_UART_Init();
//MX_BDMA2_Init();
//MX_LPUART1_UART_Init();
//MX_FATFS_Init();
//MX_LPTIM1_Init();
//MX_TIM1_Init();
//MX_IWDG1_Init();
//MX_USART2_UART_Init();
//MX_RTC_Init();
//MX_WWDG1_Init();
//MX_UART4_Init();
//MX_I2C1_Init();
/* USER CODE BEGIN 2 */
//Blink LED just to make sure basics are working
for (int i = 0; i < 10; i++)
{
LL_GPIO_SetOutputPin(LEDGreen_GPIO_Port, LEDGreen_Pin);
LL_mDelay(100);
LL_GPIO_ResetOutputPin(LEDGreen_GPIO_Port, LEDGreen_Pin);
LL_mDelay(100);
}
/* USER CODE END 2 */
//Stream 0 = RX
LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_0);
LL_DMA_EnableIT_TE(DMA1, LL_DMA_STREAM_0);
LL_DMA_ConfigAddresses(DMA1,
LL_DMA_STREAM_0,
(uint32_t)rxBuffer,
LL_USART_DMA_GetRegAddr(USART1, LL_USART_DMA_REG_DATA_RECEIVE),
LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_STREAM_0));
LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_0, rxBufferSize);
//Stream 1 = TX
LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_1);
LL_DMA_EnableIT_TE(DMA1, LL_DMA_STREAM_1);
LL_DMA_ConfigAddresses(DMA1,
LL_DMA_STREAM_1,
(uint32_t)txBuffer,
LL_USART_DMA_GetRegAddr(USART1, LL_USART_DMA_REG_DATA_TRANSMIT),
LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_STREAM_1));
LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_1, txBufferSize);
LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_0);
LL_USART_EnableDMAReq_RX(USART1);
LL_USART_EnableDirectionRx(USART1);
LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_1);
LL_USART_EnableDMAReq_TX(USART1);
LL_USART_EnableDirectionTx(USART1);
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
LL_mDelay(1000);
LL_mDelay(10);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
LL_USART_InitTypeDef USART_InitStruct = { 0 };
LL_GPIO_InitTypeDef GPIO_InitStruct = { 0 };
LL_RCC_SetUSARTClockSource(LL_RCC_USART16_CLKSOURCE_PCLK2);
/* Peripheral clock enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOB);
/**USART1 GPIO Configuration
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_6 | LL_GPIO_PIN_7;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USART1 DMA Init */
/* USART1_RX Init */
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_STREAM_0, LL_DMAMUX1_REQ_USART1_RX);
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_STREAM_0, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_0, LL_DMA_PRIORITY_LOW);
LL_DMA_SetMode(DMA1, LL_DMA_STREAM_0, LL_DMA_MODE_NORMAL);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_0, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_0, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_0, LL_DMA_PDATAALIGN_BYTE);
LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_0, LL_DMA_MDATAALIGN_BYTE);
LL_DMA_DisableFifoMode(DMA1, LL_DMA_STREAM_0);
/* USART1_TX Init */
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_STREAM_1, LL_DMAMUX1_REQ_USART1_TX);
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_STREAM_1, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_1, LL_DMA_PRIORITY_LOW);
LL_DMA_SetMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MODE_NORMAL);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_1, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_1, LL_DMA_PDATAALIGN_BYTE);
LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_1, LL_DMA_MDATAALIGN_BYTE);
LL_DMA_DisableFifoMode(DMA1, LL_DMA_STREAM_1);
/* USART1 interrupt Init */
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;
USART_InitStruct.BaudRate = 9600;
USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
USART_InitStruct.Parity = LL_USART_PARITY_NONE;
USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
LL_USART_Init(USART1, &USART_InitStruct);
LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_8);
LL_USART_SetRXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_8);
LL_USART_DisableFIFO(USART1);
LL_USART_ConfigAsyncMode(USART1);
/* USER CODE BEGIN WKUPType USART1 */
/* USER CODE END WKUPType USART1 */
LL_USART_Enable(USART1);
/* Polling USART1 initialisation */
while ((!(LL_USART_IsActiveFlag_TEACK(USART1))) || (!(LL_USART_IsActiveFlag_REACK(USART1))))
{
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
static void MX_DMA_Init(void)
{
/* Init with LL driver */
/* DMA controller clock enable */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
/* DMA interrupt init */
/* DMA1_Stream0_IRQn interrupt configuration */
NVIC_SetPriority(DMA1_Stream0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
NVIC_EnableIRQ(DMA1_Stream0_IRQn);
/* DMA1_Stream1_IRQn interrupt configuration */
NVIC_SetPriority(DMA1_Stream1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
NVIC_EnableIRQ(DMA1_Stream1_IRQn);
/* DMA1_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);
/* DMA1_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
/* DMA1_Stream4_IRQn interrupt configuration */
NVIC_SetPriority(DMA1_Stream4_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
NVIC_EnableIRQ(DMA1_Stream4_IRQn);
/* DMA1_Stream5_IRQn interrupt configuration */
NVIC_SetPriority(DMA1_Stream5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
NVIC_EnableIRQ(DMA1_Stream5_IRQn);
/* DMA1_Stream6_IRQn interrupt configuration */
NVIC_SetPriority(DMA1_Stream6_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
NVIC_EnableIRQ(DMA1_Stream6_IRQn);
/* DMA1_Stream7_IRQn interrupt configuration */
NVIC_SetPriority(DMA1_Stream7_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
NVIC_EnableIRQ(DMA1_Stream7_IRQn);
}
void dma1TXDoneCallback(void)
{
uint8_t tx_cmplt = 1;
}
void dma1RXDoneCallback(void)
{
uint8_t rx_cmplt = 1;
}
void uart1DMAErrorCallback(void)
{
LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_0);
LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_1);
//led_blink(LED_BLINK_RATE_ERROR);
}
void DMA1_Stream0_IRQHandler(void)
{
if (LL_DMA_IsActiveFlag_TC0(DMA1))
{
LL_DMA_ClearFlag_TC0(DMA1);
dma1RXDoneCallback();
}
else if (LL_DMA_IsActiveFlag_TE0(DMA1))
{
LL_DMA_ClearFlag_TE0(DMA1);
uart1DMAErrorCallback();
}
else
{
//Do something
}
}
void DMA1_Stream1_IRQHandler(void)
{
if (LL_DMA_IsActiveFlag_TC1(DMA1))
{
LL_DMA_ClearFlag_TC1(DMA1);
dma1TXDoneCallback();
}
else if (LL_DMA_IsActiveFlag_TE1(DMA1))
{
LL_DMA_ClearFlag_TE1(DMA1);
uart1DMAErrorCallback();
}
else
{
//Do something...
}
}
Solved! Go to Solution.
2023-07-04 7:42 AM - edited 2023-07-04 7:44 AM
I was able to get this working with all your help. The problems were all dumb mistakes on my part that your suggestions helped me find. Thanks a tonne.