2023-02-10 02: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.
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.
2023-02-10 06:45 AM
Hello @DGast.1 ,
Please try to set : (with High priority)
and for PA5 :
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.
2023-02-10 08:24 AM
I tried and it didn't work.
2023-02-10 09: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:
nm nucleo-stm32h743zi2.elf | grep aligned_buff
08004130 r aligned_buff
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.
2023-02-10 09: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?
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.
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.
2023-02-19 01:53 PM
And this will solve your next problem...