freeRTOS + DMA (STM32).


I understand that the forum is not so specialized, but I will still ask my question here. Probably someone will tell you. There is a simple working program – freeRTOS + diode flashing (there is still a little crap, but not the point), the platform is STM32 (F217). I decided to try adding USART + DMA. Initialization takes place in the following order:

  1. порты GPIO (для диодов);
  2. контроллер NVIC (для лабуды =));

  3. DMA :

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    DMA_DeInit(DMA2_Stream7 );
    DMA_InitTypeDef DMA_InitStructure;
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;
    DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_BASE + offsetof(USART_TypeDef, DR);
    DMA_InitStructure.DMA_Memory0BaseAddr = (u32) buffer;
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_BufferSize = strlen(buffer);
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    //DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA2_Stream7, &DMA_InitStructure);`
  4. USART:

    USART_InitTypeDef USART_InitStructure;   //для инициализации USART
    //настроить выводы, к которым подключены RX и TX
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);   //тактирование GPIOA
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;          //линия RX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //вход, третье состояние
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);             //выполнить инициализацию
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;           //линия TX
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //макс частота сигнала
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;      //симетричный выход
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);             //выполнить инициализацию
    //настройка модуля USART
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No ;
    USART_InitStructure.USART_HardwareFlowControl =
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);
  5. DMA + USART:

    DMA_Cmd(DMA2_Stream7, ENABLE);

Actually, if you comment on the DMA initialization, the initial version of the program (flashing with a diode) works as it should. But if you uncomment – the LED stupidly lights up and that's it. Those. the task (but rather the sheduler) hangs.

What could be the reason?


It seems to me that you have not configured the pins correctly for yusart.
They must be configured as Alternative Functions.
Also, in this DMA_InitStructure.DMA_PeripheralBaseAddr you can simply put USART1->DR and that's it:

DMA_InitStructure.DMA_PeripheralBaseAddr = USART1->DR;

Please tell me if it worked …
Why aren't you using MXCube? Of course, the approach with HAL is a little different, but it works more stable than SPL …

Scroll to Top