SPI DMA configuration generated by STM32CubeMX does not work
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-02-10 2:55 AM
I have used STM32CubeMX to generate the configuration required to use SPI1 with DMA for a nucleo H743ZI2 board:
Then, I generate the code as a Makefile project and modify the main function to have:
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_USB_OTG_FS_PCD_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
uint8_t buff[8] = {0};
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_StatusTypeDef rc = HAL_SPI_Transmit_DMA(&hspi1, (uint8_t*)buff, 8);
HAL_Delay (1000); /* Insert delay 100 ms */
}
/* USER CODE END 3 */
}
I inspect pin PA5 (as STM32CubeMX indicates is the SPI1 SCK) with my oscilloscope and I see nothing. What is it failing?
Here are the initialization functions:
static void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 0x0;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi1.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi1.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
/* DMA1_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}
Solved! Go to Solution.
- Labels:
-
DMA
-
SPI
-
STM32CubeMX
-
STM32H7 Series
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-02-10 10:39 AM
I have tried to do this quick hack:
static uint32_t* aligned_buff = (uint32_t*)0x24000000;
[...]
uint8_t* buff = (uint8_t*)aligned_buff;
[...]
HAL_StatusTypeDef rc = HAL_SPI_Transmit_DMA(&hspi1, buff, 8);
And it works.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-02-10 6:45 AM
Hello @DGast.1​ ,
Please try to set : (with High priority)
- SPI1_TX_DMA_STREAM DMA2_Stream3
- SPI1_RX_DMA_STREAM DMA2_Stream2
and for PA5 :
- GPIO Mode as GPIO_MODE_AF_PP;
- GPIO as PULLDOWN
- Speed ad HIGH
Hope I helped you!
Foued
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-02-10 8:24 AM
I tried and it didn't work.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-02-10 9:28 AM
I have found the problem.
At first, I was declaring my transmit buffer in the stack (as explained above):
uint8_t buff[8] = {0};
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_StatusTypeDef rc = HAL_SPI_Transmit_DMA(&hspi1, (uint8_t*)buff, 8);
HAL_Delay (1000); /* Insert delay 100 ms */
}
That doesn't work. However, if I do this:
static const uint32_t aligned_buff[2] = {0};
static const uint8_t* buff = (uint8_t*)aligned_buff;
[...]
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_StatusTypeDef rc = HAL_SPI_Transmit_DMA(&hspi1, buff, 8);
HAL_Delay (1000); /* Insert delay 100 ms */
}
[...]
Then, it works. However, if I remove the `const` from the transmit buffers, it stops working:
static uint32_t aligned_buff[2] = {0};
static uint8_t* buff = (uint8_t*)aligned_buff;
[...]
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_StatusTypeDef rc = HAL_SPI_Transmit_DMA(&hspi1, buff, 8);
HAL_Delay (1000); /* Insert delay 100 ms */
}
[...]
The above doesn't work. How is this poissible?
I have verified the difference between declaring `const` and not doing so, with regards to memory allocation. My `elf` file headers are like:
```
arm-none-eabi-objdump -h nucleo-stm32h743zi2.elf
nucleo-stm32h743zi2.elf: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .isr_vector 00000298 08000000 08000000 00010000 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 00003e98 08000298 08000298 00010298 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .rodata 00000020 08004130 08004130 00014130 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .init_array 00000004 08004150 08004150 00014150 2**2
CONTENTS, ALLOC, LOAD, DATA
4 .fini_array 00000004 08004154 08004154 00014154 2**2
CONTENTS, ALLOC, LOAD, DATA
5 .data 00000010 20000000 08004158 00020000 2**2
CONTENTS, ALLOC, LOAD, DATA
6 .bss 00000198 20000010 08004168 00020010 2**2
ALLOC
7 ._user_heap_stack 00000600 200001a8 08004168 000201a8 2**0
ALLOC
8 .ARM.attributes 0000002e 00000000 00000000 00020010 2**0
CONTENTS, READONLY
9 .debug_info 0000fdbb 00000000 00000000 0002003e 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
10 .debug_abbrev 00001d32 00000000 00000000 0002fdf9 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
11 .debug_loc 00007576 00000000 00000000 00031b2b 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
12 .debug_aranges 00000900 00000000 00000000 000390a8 2**3
CONTENTS, READONLY, DEBUGGING, OCTETS
13 .debug_ranges 00000980 00000000 00000000 000399a8 2**3
CONTENTS, READONLY, DEBUGGING, OCTETS
14 .debug_line 0000aa0f 00000000 00000000 0003a328 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
15 .debug_str 00003f0f 00000000 00000000 00044d37 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
16 .comment 0000004d 00000000 00000000 00048c46 2**0
CONTENTS, READONLY
17 .debug_frame 000015c8 00000000 00000000 00048c94 2**2
CONTENTS, READONLY, DEBUGGING, OCTETS
```
Then, using `nm`, I get this results:
- When using `const`:
nm nucleo-stm32h743zi2.elf | grep aligned_buff
08004130 r aligned_buff
- When not using `const`:
nm nucleo-stm32h743zi2.elf | grep buff
2000002c b aligned_buff
As you can see, in case of being const, it goes to `.rodata`, otherwise it goes to `.data`. One is in flash, the other is in RAM, and one is 64 bit aligned and the other isn't.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-02-10 9:32 AM
I have tried doing
__attribute__((__aligned__(8))) static uint32_t aligned_buff[2] = {0};
__attribute__((__aligned__(8))) static uint8_t* buff = (uint8_t*)aligned_buff;
so both variables are 64 bits aligned, but still doesn't work.
How is this possible? Does this mean that the buffer used to trigger DMA operations must be in flash? Why?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-02-10 10:27 AM
I have read this in the datasheet
So it seems DMA buffers can only be located at specific regions.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-02-10 10:39 AM
I have tried to do this quick hack:
static uint32_t* aligned_buff = (uint32_t*)0x24000000;
[...]
uint8_t* buff = (uint8_t*)aligned_buff;
[...]
HAL_StatusTypeDef rc = HAL_SPI_Transmit_DMA(&hspi1, buff, 8);
And it works.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-02-19 1:53 PM
And this will solve your next problem...
