STM32 spi receive procedure without hal - stm32

Good afternoon,
I am a newbie in the programing of stm32. Just working on a project, where is a serious problem with timing. Trying to implement FOC on the PMSM motor where I need to do a calculation in 50us loop, which is fast to communicate with angle sensor via SPI and HAL. Let me explain the situation.
I tried to work with HAL, but as I read everywhere and explored by myself: if you need speed put it away. So my plan is to use CubeMX to configure all necessary registers and read data directly from the register DR. One small thing, that sensor communicates with a 16-bit frame.
Code that I produce:
__HAL_SPI_ENABLE(&hspi3);
HAL_GPIO_WritePin_Fast(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //switch off the pin
hspi3.Instance->DR = 0;
while ((hspi3.Instance->SR & SPI_FLAG_RXNE) == 0){} //Wait for Data Ready to Read
RxData = hspi3.Instance->DR; //Read Data Register Directly
HAL_GPIO_WritePin_Fast(GPIOD, GPIO_PIN_2, GPIO_PIN_SET); // switch on the pin
__HAL_SPI_DISABLE(&hspi3);
Configuration of spi periphery:
/**
* #brief SPI3 Initialization Function
* #param None
* #retval None
*/
static void MX_SPI3_Init(void)
{
/* USER CODE BEGIN SPI3_Init 0 */
/* USER CODE END SPI3_Init 0 */
/* USER CODE BEGIN SPI3_Init 1 */
/* USER CODE END SPI3_Init 1 */
/* SPI3 parameter configuration*/
hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_16BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 7;
hspi3.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi3.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI3_Init 2 */
/* USER CODE END SPI3_Init 2 */
}
In this state, it isn't working, has anyone idea how to solve this issue? Thank you

You have two mistakes:
First, you are reading the data register in the wait loop. You should have an empty loop that does nothing repeatedly until RXNE becomes 1, then read the data.
Second you don't do anything to trigger the clock. In master mode the clock starts when you write data for transmission. After driving the chip-select low, write something to DR:
HAL_GPIO_WritePin_Fast(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //switch off the pin
hspi3.Instance->DR = 0; // output something on MOSI while reading MISO
while ((hspi3.Instance->SR & SPI_FLAG_RXNE) == 0){} //Wait for Data Ready to Read
RxByte[0] = hspi3.Instance->DR; //Read Data Register Directly
HAL_GPIO_WritePin_Fast(GPIOD, GPIO_PIN_2, GPIO_PIN_SET); // switch on the pin

Related

Stm32f407 Uart Dma Multiple Array Tx

I tried to send Buffer from stm32f407 to terminal.Type is uint8_t and array is 15000. My code is works. but when i try to send 2 buffer like 5000 array, there is problem for second buffer. I use normal mode.What i should do to sending succesfully?
/* USART3 DMA Init */
/* USART3_TX Init */
hdma_usart3_tx.Instance = DMA1_Stream3;
hdma_usart3_tx.Init.Channel = DMA_CHANNEL_4;
hdma_usart3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart3_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart3_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart3_tx.Init.Mode = DMA_NORMAL;
hdma_usart3_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_usart3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart3_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(huart,hdmatx,hdma_usart3_tx);
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspInit 1 */
/* USER CODE END USART3_MspInit 1 */
void Send_Dataa(void)
{
HAL_UART_Transmit_DMA(wifi_uart, buf1, 5000);
HAL_UART_Transmit_DMA(wifi_uart, buf2, 5000);
}
If you check the return code from HAL_UART_Transmit_DMA(), you'll probably see it is returning HAL_BUSY. (Note you should always be checking the return codes from HAL functions.)
You'll need to wait until the first transmit is complete before starting the second transmit. You can use HAL_UART_GetState() to monitor the state of the UART.
The HAL does not chain together multiple DMA requests.

What could be the cause of a constant voltage offset on the STM32L041G6 adc

I have been testing the ADC on my STM32L0 with 12-bit resolution and for some reason, every measurement I take has a 0.048 V offset. I've tried a different supply voltage (from 1.8 V to 3.3 V), but the offset stays there.
This offset starts at the first count, when I apply 0 V to the ADC input and read 130 counts (with 1.8 V Vdda) it stays for the whole range.
My voltage source is very stable and I've verified my ADC input voltage and the STM32 supply voltage with 3 different accurate pieces of measuring equipment.
The voltage is applied to the circuit through a bnc connector connected to a signal generator, in my case I use the Dc output option with high impedance on a normal signal generator. As for the code, I used stm32cubemx to generate some of the code but I didn't use any calibration function, so unless it is enabled by default, I dont do any calibration. As for the adc pin, I just used cubemx to set-up IN0 as an adc input and didn't touch anything else. Then to read the adc, I used 2 hal function "HAL_ADC_START()" and "HAL_ADC_PollForConversion()". Then I send the result to be read by uart.
The board I'm using is a custom PCB, but I only placed the STM32 and some passive components to get it to function (coupling capacitors and reset pull-up).
I also tested multiple boards with different configurations and I always get this offset voltage. I outputed Vrefint and measured it, and I got 1.225 V (specified is 1.224 V) so the ADC reference seems fine too.
I was wondering if someone has a suggestion on the possible cause of this offset error? I've been looking for a solution but I'm having no luck so far, so I would really appreciate the input of more experienced developers.
Here is a simplified version of the code I use :
/* USER CODE BEGIN Header */
/**
******************************************************************************
* #file adc.c
* #brief This file provides code for the configuration
* of the ADC instances.
******************************************************************************
* #attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "adc.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
ADC_HandleTypeDef hadc;
/* ADC init function */
void MX_ADC_Init(void)
{
/* USER CODE BEGIN ADC_Init 0 */
/* USER CODE END ADC_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC_Init 1 */
/* USER CODE END ADC_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = ENABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC_Init 2 */
/* USER CODE END ADC_Init 2 */
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 */
/* USER CODE END ADC1_MspInit 0 */
/* ADC1 clock enable */
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**ADC GPIO Configuration
PA0-CK_IN ------> ADC_IN0
*/
GPIO_InitStruct.Pin = SENSOR_ANALOG_IN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(SENSOR_ANALOG_IN_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspDeInit 0 */
/* USER CODE END ADC1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ADC1_CLK_DISABLE();
/**ADC GPIO Configuration
PA0-CK_IN ------> ADC_IN0
*/
/* USER CODE BEGIN ADC1_MspDeInit 1 */
/* USER CODE END ADC1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
And here is the main file where I call the function to read the adc and send it to uart to be read :
#include "main.h"
#include "gpio.h"
#include "adc.h"
#include "usart.h"
#include <stdlib.h>
extern "C"
void execute(){
HAL_Delay(10);
HAL_ADC_Start(&hadc);
HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY);
const auto value = HAL_ADC_GetValue(&hadc);
char buffer [5];
itoa(value, buffer, 10);
HAL_UART_Transmit(&huart2, reinterpret_cast<uint8_t*>(buffer), 5, HAL_MAX_DELAY);
}
Here is the schematic, as I said, the test circuit only had the mcu and some passive components : https://im.ge/i/FbQPIp

STM32 SPI slave mode doesn't transmit properly

I am using an STM32G030C8T6 as an SPI (Slave device) which receives characters from a Raspberry pi (Master device), receiving works perfectly! no problems there, however when i try to send data from STM32 to Pi, it seems that the STM32 gets stuck for a while and Pi rx buffer is filled with only one bit in repeat e.g., if i send char buf[6] = {0,1,2,3,4,5}; Pi receives (111111) or (333333) depending on how many characters i am sending.
What do i actually want to do?
I want to transmit ADC data from STM32(slave mode) to Pi(master mode), so far it only receives one bit i repeat.
Can someone please help me achieve this?
Here's my SPI config:
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_SLAVE;
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.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
then the functions to read characters, send data and string
char SPI_read(void)
{
// SPI1->SR is the STATUS REGISTER on SPI1 Bus
// SPI1->DR is the DATA REGISTER on SPI1 Bus
char data;
while(!(SPI1->SR & SPI_SR_RXNE));
while(SPI1->SR & SPI_SR_BSY);
data = SPI1->DR;
printmsg("%c",data);
return data;
}
void spi_Send(char caracSend)
{
while(!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = caracSend;
}
void spi_send_string(char* stringSend)
{
int i=0;
unsigned int sizeChar = 0;
sizeChar = strlen(stringSend);
__NOP();
for(i=0;i<sizeChar;i++)
{
spi_Send(stringSend[i]);
}
}
Here's my function to receive data from Pi which i call in the main while loop.
void SPI_Receive_Commands(void)
{
while(HAL_GPIO_ReadPin(SPI_SS_GPIO_Port, SPI_SS_Pin) == GPIO_PIN_RESET);
{
HAL_SPI_Receive(&hspi1, (uint8_t *)spi_buf, 10, 100);
if(spi_buf[0] == 'v')
{
memset(spi_buf,'*',10);
printmsg("Character V received\r\n");
Battery_Voltage();
spi_send_string(batteryVoltage);
spi_Send('v');
printmsg("Sending battery voltage\r\n");
}
}
}
Thank you so much for helping me out in advance.
Initialisation. You need set the RX FIFO threshold to 1/4 as you read and write bytes. I do not know how to do it in HAL. Register level simply set FRXTH bit in the CR2 register
DR register has to be accessed in 8 bits operations.
You do not need to use BSY bit in polling mode unless you want to disable the SPI peripheral.
void spi_Send(char caracSend)
{
while(!(SPI1->SR & SPI_SR_TXE));
*(volatile uint8_t *)&SPI1->DR = caracSend;
}
void spi_send_string(char* str)
{
if(str) while(*str) spi_Send(*str++);
}
char SPI_read(void)
{
char data;
while(!(SPI1->SR & SPI_SR_RXNE));
data = *(volatile uint8_t *)&SPI1->DR;
return data;
}
Remember that raspberry pi HAS TO send dummy data to allow slave to send information. Slave does not generate the clock signal and clock has to be supplied by the Master

STM32F - SPI with DMA "ErrorCallback" and frames shifted

I am communicating 2 uC (an arduino display as MASTER and STM32F429 as slave).Its communication consists of 10 bytes in full duplex through SPI using DMA, every 150ms.
During some minutes the communication goes very good, both uC are sending their 10 bytes properly. During this time, I have noted that "HAL_SPI_ErrorCallback" function is called becasue I have added a counter within and it is increased little by little, but the comminication still goes well.
My first question is: Is it normal that sometimes ErrorCallback function is called randomly? due to noise or whatever the communication has an instantaneous error... I guess..
Here are a capture of the MISO signal in green, CLK in whie and CS in yellow
On the other hand, after a while (randomly 10 min, 1h ...) the communication is corrupted just in the MISO signal , the STM32 sends the 10 bytes frame but instead of sending Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7 Byte8 Byte9 Byte10, (LSB first)
it sends:
Byte10 Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7 Byte8 Byte9, IT IS MOVED TO RIGTH 1 byte!?!?
Attached you can see the capture "Working.jpg" with byte0 = 0x02 and the rest of the bytes = 0. In the other capture "NOT_working.jpg" is a capture with the problem. Both uC were working properly for a while and suddenly the STM32 uC started to send this frame all the time (the communication frame is byte = 0x02 and the rest of the bytes = 0 in order to see easily this error).
Working.jpg - which is MISO signal sending the frame properly
NOT_working.jpg - which is MISO signal sending the frame incorrectly
I have tried the communication in:
"Init.Mode = DMA_NORMAL" and "DMA_CIRCULAR", and both configuration have the same behaviour.
I have creaged the 2 variables in order to find out the problem:
DMA_counter_RX = __HAL_DMA_GET_COUNTER(&hdma_spi6_rx);
DMA_counter_TX = __HAL_DMA_GET_COUNTER(&hdma_spi6_tx);
And the the comunications goes well, DMA_counter_RX = 10 BUT DMA_counter_TX = 9. This values are normal. But as soon as the shift error occurs, both DMA counters are = 10.
Also this problem always happens in debug mode when I click on "suspend" (pause) and "resume"(play) as soon as I click on "resume" and the processor continues with the program, the MISO signal is shifted forever.
Additionally I am using TIM1, TIM5, TIM2, TIM3 and TIM4 for other things like PWM and interruptions but not related to SPI...
I have tried to solve this problem modifying all the NVIC priorities for all interruptions and so on but the problem get worst.
I am using System Workbench for STM32 latest version.
Any help is appreciate! Thanks in advance and best regards.
Alejandro
Sorry for long question... :(
Bellow you can see my configuration for SPI and DMA if it can help you:
void MX_DMA_Init(void)
{
__HAL_RCC_DMA2_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
}
void MX_SPI6_Init(void)
{
hspi6.Instance = SPI6;
hspi6.Init.Mode = SPI_MODE_SLAVE;
hspi6.Init.Direction = SPI_DIRECTION_2LINES;
hspi6.Init.DataSize = SPI_DATASIZE_8BIT;
hspi6.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi6.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi6.Init.NSS = SPI_NSS_HARD_INPUT;
hspi6.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi6.Init.TIMode = SPI_TIMODE_DISABLE;
hspi6.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi6.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi6) != HAL_OK)
{
Error_Handler();
}
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hspi->Instance==SPI6)
{
__HAL_RCC_SPI6_CLK_ENABLE();
/**SPI6 GPIO Configuration
PG8 ------> SPI6_NSS
PG12 ------> SPI6_MISO
PG13 ------> SPI6_SCK
PG14 ------> SPI6_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI6;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
hdma_spi6_rx.Instance = DMA2_Stream6;
hdma_spi6_rx.Init.Channel = DMA_CHANNEL_1;
hdma_spi6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi6_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi6_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi6_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi6_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi6_rx.Init.Mode = DMA_NORMAL;
hdma_spi6_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_spi6_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi6_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmarx,hdma_spi6_rx);
hdma_spi6_tx.Instance = DMA2_Stream5;
hdma_spi6_tx.Init.Channel = DMA_CHANNEL_1;
hdma_spi6_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi6_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi6_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi6_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi6_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi6_tx.Init.Mode = DMA_NORMAL;
hdma_spi6_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_spi6_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi6_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmatx,hdma_spi6_tx);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(SPI6_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(SPI6_IRQn);
}
}
During initialization code, I configure SPI6 and DMA as it is described before, just after that I enable communication using:
HAL_SPI_TransmitReceive_DMA(&hspi6, (uint8_t*)HMI_slave_TX_data, (uint8_t*)HMI_slave_RX_data, 10);
Also it were added the following 2 functions related to SPI communication:
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
if(hspi -> Instance == SPI6)
{
HAL_SPI_TransmitReceive_DMA(&hspi6, (uint8_t*)HMI_slave_TX_data, (uint8_t*)HMI_slave_RX_data, 10);
}
}
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
if(hspi -> Instance == SPI6)
{
HAL_SPI_TransmitReceive_DMA(&hspi6, (uint8_t*)HMI_slave_TX_data, (uint8_t*)HMI_slave_RX_data,10);
}
}
STM cube mx automatically created:
void DMA2_Stream5_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream5_IRQn 0 */
/* USER CODE END DMA2_Stream5_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_spi6_tx);
/* USER CODE BEGIN DMA2_Stream5_IRQn 1 */
/* USER CODE END DMA2_Stream5_IRQn 1 */
}
/**
* #brief This function handles DMA2 stream6 global interrupt.
*/
void DMA2_Stream6_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream6_IRQn 0 */
/* USER CODE END DMA2_Stream6_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_spi6_rx);
/* USER CODE BEGIN DMA2_Stream6_IRQn 1 */
/* USER CODE END DMA2_Stream6_IRQn 1 */
}
void SPI6_IRQHandler(void)
{
/* USER CODE BEGIN SPI6_IRQn 0 */
/* USER CODE END SPI6_IRQn 0 */
HAL_SPI_IRQHandler(&hspi6);
/* USER CODE BEGIN SPI6_IRQn 1 */
/* USER CODE END SPI6_IRQn 1 */
}
------------------------------EDITED----------------------------
I add 2 captures of the SPI register
SPI registers WORKING
SPI registers ERROR
I finally got the solution, I found what the problem was!
Usually, the CS signal goes from 1 to 0, then MISO and MOSI communicates, and once the communication finishes CS signal goes from 0 to 1, and the STM32F429 continues with the rest of the tasks...
This was happening every 150 ms, that's the period of thime both uC are communicating. But the STM32 uC has another tasks with more priority than SPI communication.
When one of this higher priority starts during SPI communication, and once this higher priority is done then the uC continues with the task was doing ( it was SPI), obviouslythis frame is lost and "HAL_SPI_ErrorCallback" is executed, and then SPI is restarted.If SPI is restarted when CS signal is 1, (spi idle), then there is no problem, SPI is restarted properly and the next frame will be received without problem. BUT if SPI is restarted when CS signal is 0 (STM32 SPI is selected and ready to communicate) then the STM32 is waiting to send and receive an amount of bytes but it will receives less, so an a mismatch of communication bytes is the key of the PROBLEM.
I have solved this issue just adding:
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
if(hspi -> Instance == SPI6)
{
while(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_8) != GPIO_PIN_SET) // CS signal
{
}
HAL_SPI_TransmitReceive_DMA(&hspi6, (uint8_t*)HMI_slave_TX_data, (uint8_t*)HMI_slave_RX_data,10);
}
}
I have to modify "WHILE" in order to not stop the processor , but it is the first approximation.
Now the communication is working all the time, but some times a frame is lost (and " HAL_SPI_ErrorCallback" is called) due to higher priority task. But it is normal, a CRC is implemented to note that.
Thanks for helping me and support the support.
I hope this helps to other people.
Best regards.
Alejandro.

Cannot mount SD using FatFS on STM32

I'm trying to write to a MicroSD-Card using STM32F405 chip.
The pins are connected correctly and each pin on the MicroSD-Card slot can be written to by using HAL_GPIO_WritePin. (Messured with ossciloscope) I'm using CubeMX to generate the init code for TrueStudio, so hopefully everything is ok there as well. But when I run the following code, f_mount returns FR_DISK_ERR. The MicroSD-Card can be written to and read from. If I use a different Device number, i.e. "1:", I get FR_INVALID_DRIVE
So my question is: what could cause FR_DISK_ERR except a faulty MicroSD-Card?
Here is my code so far:
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();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SDIO_SD_Init();
MX_FATFS_Init();
/* USER CODE BEGIN WHILE */
FATFS fileSystem;
FIL testFile;
uint8_t testBuffer[16] = "SD write success";
UINT testBytes;
FRESULT res;
while((res = f_mount(&fileSystem, SD_MOUNT_PATH, 1)) != FR_OK){
printf("%d", res); //used to debug res, only for TrueStudio Debugger
}
uint8_t path[13] = "testfile.txt";
path[12] = '\0';
res = f_open(&testFile, (char*)path, FA_WRITE | FA_CREATE_ALWAYS);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);
res = f_write(&testFile, testBuffer, 16, &testBytes);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
res = f_close(&testFile);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
}
in MX_FATFS_Init() FATFS_LinkDriver(&SD_Driver, SD_Path) is called and returns 0.
Without the SD_MOUNT_PATH macro, does the f_mount call look like this:
f_mount(&fileSystem, "0:", 1) ?'
Are you saying that f_open, f_write return FR_OK even if f_mount fails?!
FR_DISK_ERR usually means disk_read() or disk_write() failed. Try giving 100ms or 1 sec delay before using f_mount() and between between fatfs function calls.