HAL_UART_Transmit_IT: only a few bytes are sent - stm32

i've got a problem on my STM32F407 with FreeRTOS.
So Far most of the messages to a xbee module are sent. Only Sometimes (after 5 to 60 minutes) the TX process will be interrupted.
In the debug session i can see, that TXEIE ist not set anymore after the 2 bytes (of ~40). Also the TxXferCount of the UART_HandleTypeDef is 42 (TxXferSize: 44).
The flag TXE in SR-Register ist set but the TXEIE in CR1-Register not.
The ISR was active for 2 times to store them into data/shift registers. This i can see on logic analyzer.
But i can't figure out the source of the writing task/isr.
The Xbee module get messages and sends response messages.
Thanks for any Response!
The init:
GPIO_InitTypeDef GPIO_InitStruct;
__GPIOA_CLK_ENABLE();
__GPIOD_CLK_ENABLE();
__GPIOF_CLK_ENABLE();
/* RX-TX PIN */
GPIO_InitStruct.Pin = XBEE1_TX_PIN | XBEE1_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(XBEE1_TX_PORT, &GPIO_InitStruct);
/* Power*/
GPIO_InitStruct.Pin = XBEE1_PWR_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(XBEE1_PWR_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(XBEE1_PWR_PORT, XBEE1_PWR_PIN, GPIO_PIN_SET);
/* Reset PIN */
GPIO_InitStruct.Pin = XBEE1_RESET_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(XBEE1_RESET_PORT, &GPIO_InitStruct);
/* SLEEP_RQ PIN */
GPIO_InitStruct.Pin = XBEE1_SLEEP_RQ_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(XBEE1_SLEEP_RQ_PORT, &GPIO_InitStruct);
__USART2_CLK_ENABLE();
uart.Instance = USART2;
uart.Init.BaudRate = baud;
uart.Init.WordLength = UART_WORDLENGTH_8B;
uart.Init.StopBits = UART_STOPBITS_1;
uart.Init.Parity = UART_PARITY_NONE;
uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
uart.Init.Mode = UART_MODE_TX_RX;
if (HAL_UART_Init(&uart) != HAL_OK) {
Error_Handler(XBEE1_ERROR);
}
//clear pending IRQs
__HAL_UART_CLEAR_FLAG(&uart, UART_FLAG_RXNE);
__HAL_UART_CLEAR_FLAG(&uart, USART_FLAG_TC);
__HAL_UART_CLEAR_FLAG(&uart, USART_FLAG_ORE);
__HAL_UART_CLEAR_FLAG(&uart, USART_FLAG_PE);
__HAL_UART_CLEAR_FLAG(&uart, USART_FLAG_FE);
__HAL_UART_CLEAR_FLAG(&uart, USART_FLAG_NE);
__HAL_UART_CLEAR_FLAG(&uart, USART_FLAG_TXE);
/* NVIC */
HAL_NVIC_SetPriority(USART2_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
The Transmit
HAL_StatusTypeDef UART_Xbee1::send( uint8_t* pdata, size_t sz ) {
return HAL_UART_Transmit_IT(&uart, pdata, sz);
}
ISR
extern "C" void USART2_IRQHandler(void){
testpin1.on();
UART_HandleTypeDef* uart_c = &(Argos::xbee1->uart);
uint32_t tmp1 = 0;
uint32_t tmp2 = 0;
tmp1 = __HAL_UART_GET_FLAG(uart_c, UART_FLAG_RXNE);
tmp2 = __HAL_UART_GET_IT_SOURCE(uart_c, UART_IT_RXNE);
if((tmp1 != RESET) && (tmp2 != RESET)){
uint8_t in = (uint8_t)(uart_c->Instance->DR & (uint8_t)0x00FF);
*uart_c->pRxBuffPtr++ = in;
//overwrite expected bytes, when packet size is known
if(xbee1->inApiRecMode){
if( (uart_c->RxXferSize-uart_c->RxXferCount) == 1 ){
xbee1->apiSize = 0;
xbee1->apiSize = in << 8;
}else if( (uart_c->RxXferSize-uart_c->RxXferCount) == 2 ){
xbee1->apiSize |= in;
uart_c->RxXferCount = xbee1->apiSize + 2;
}
}
if( ((uart_c->RxXferCount)-1) == 0){
(uart_c->RxXferCount)--;
__HAL_UART_DISABLE_IT(uart_c, UART_IT_RXNE);
/* Check if a transmit process is ongoing or not */
if(uart_c->State == HAL_UART_STATE_BUSY_TX_RX){
uart_c->State = HAL_UART_STATE_BUSY_TX;
}else{
/* Disable the UART Parity Error Interrupt */
__HAL_UART_DISABLE_IT(uart_c, UART_IT_PE);
/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
__HAL_UART_DISABLE_IT(uart_c, UART_IT_ERR);
uart_c->State = HAL_UART_STATE_READY;
}
Message* msg = &(xbee1->msg_callBack);
msg->code = (uint8_t) XbeeContext::MessageType::RECEIVE_EVENT;
msg->value = 0;
xbee1->rcvCallback->sendMsg(msg);
}else if( (uart_c->RxXferCount) == 0){
Error_Handler(XBEE1_ERROR);
}else{
(uart_c->RxXferCount)--;
}
}else{
//other cases
HAL_UART_IRQHandler( uart_c );
}
testpin1.off();
}

where is this isr handler code comming from ?
it does not look any similar to what's in stm32f4 HAL 1.8 ?
if you use hal it should be better to just link your irq handler
to hal and define callback to managed error and completion.
HAL_UART_TxCpltCallback
HAL_UART_RxCpltCallback
HAL_UART_ErrorCallback

Related

STM32F4 HAL SPI_Receive dma just receive one time

I tried many methods and read reference, but i could not correctly read data from SPI_Receive_DMA mode.
In spi 1 , I want to continuously read Ad7606 data via spi in dma mode in one thread .
However, I always received same data in SPI1 dma mode . As if i didn't receive any new data. i know that if i just want to receive data in spi dma mode ,i have to also turn on TX and RX DMA channels.
i do not know which step i miss or wrong . Does anyone know how to solve this problem? Thanks for very much .
static void MX_SPI1_Init(void)
{
/* 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_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
/* DMA2_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
}
** Note
DMA2_Stream0 - > SPI1 Receive
DMA2_Stream3 - > SPI1 Transmit
DMA1_Stream4 - > SPI2 Transmit
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PB5 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* SPI1 DMA Init */
/* SPI1_RX Init */
hdma_spi1_rx.Instance = DMA2_Stream0;
hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3;
hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_rx.Init.Mode = DMA_NORMAL;
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx);
/* SPI1_TX Init */
hdma_spi1_tx.Instance = DMA2_Stream3;
hdma_spi1_tx.Init.Channel = DMA_CHANNEL_3;
hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_tx.Init.Mode = DMA_NORMAL;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx);
/* SPI1 interrupt Init */
HAL_NVIC_SetPriority(SPI1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_SPI1_Init();
MX_SPI2_Init();
MX_TIM7_Init();
MX_USART2_UART_Init();
uint8_t receive_buffer[256] ;
/* Init scheduler */
osKernelInitialize();
/*handle */
SendTaskHandle = osThreadNew(SendTaskFun, NULL, &SendTask_attributes);
ReceiveTaskHandle = osThreadNew(ReceiveTaskFun, NULL, &ReceiveTask_attributes);
osKernelStart();
while (1) {
}
}
void ReceiveTaskFun(void *argument)
{
for (;;) {
//-- SPI1 callback
HAL_SPI_RxCpltCallback(&hspi1);
HAL_GPIO_WritePin(GPIO_A, GPIO_PIN_7, 1); //-- cs=1 deactive
}
void DMA2_Stream0_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_spi1_rx);
}
void DMA2_Stream3_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_spi1_tx);
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
if (hspi->Instance == SPI1){
//-- Enable CS
HAL_GPIO_WritePin(GPIO_A, GPIO_PIN_7, 0); //-- cs=0 active low
//- - SPI2_DMA_receive
...... (Here is for receive data from AD7606 )
HAL_SPI_Receive_DMA(&hspi1, receive_buffer, 8);
}
}
Assuming all your functions are mapped correctly, current flow seems to be:
ReceiveTaskFun calls HAL_SPI_RxCpltCallback() which asserts your chip select, starts DMA transfer and returns
ReceiveTaskFun() deasserts your CS pin and goes into next loop.
HAL_SPI_RxCpltCallback() (called from ReceiveTaskFun) again asserts your CS pin and tries to set up DMA transfer and, most likely, fails. Check return value to see HAL_BUSY, because it hasn't finished transmitting
Meanwhile your DMA transfer might happen, might not (peripheral will be transmitting, whether your slave clocks out data or not), because you are toggling CS pin
When transfer of 8 bytes is done, HAL_SPI_RxCpltCallback() is called, which reasserts CS pin and starts DMA transfer. This might succeed, but since you are toggling CS pin all the time, all you get is garbage
Solution(s) could be:
Use delay in ReceiveTaskFun(). You know transmit + capture duration, use that as a basis
Use RTOS signalling from SPI interrupt - make your ReceiveTaskFun waits for signal from ISR callback and then set up new transfer.

DMA in EVE board 3

I am trying to do DMA in eve3-43inch LCD TFT ( matrix orbital), TFT screen working without DMA but as soon I add DMA settings DMA does not respond ing. What might be the reason? I using EVE81.h library. These codes I have added to make SPI initialization with DMA.
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PB5 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* SPI1 DMA Init */
/* SPI1_RX Init */
hdma_spi1_rx.Instance = DMA2_Stream0;
hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3;
hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_rx.Init.Mode = DMA_NORMAL;
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx);
/* SPI1_TX Init */
hdma_spi1_tx.Instance = DMA2_Stream3;
hdma_spi1_tx.Init.Channel = DMA_CHANNEL_3;
hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_tx.Init.Mode = DMA_CIRCULAR; //DMA_NORMAL;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;//DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx);
/* SPI1 interrupt Init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
Here I am transmitting as DMA or normal way. These codes working without DMA. After making it to transmit or receive through DMA LCD not responding.
void HAL_SPI_WriteBuffer(uint8_t *Buffer, uint32_t Length)
{
HAL_SPI_Enable();
volatile int result = HAL_SPI_Transmit(&hspi1, Buffer, Length, 1000);
//volatile int result = HAL_SPI_Transmit_DMA(&hspi1, Buffer, Length);
HAL_SPI_Disable();
}
void HAL_SPI_ReadBuffer(uint8_t *Buffer, uint32_t Length)
{
//EVE requires one dummy read/write before actual data can be read
Buffer[0] = 0;
volatile int result = HAL_SPI_Transmit(&hspi1, Buffer, 1, 1000);
HAL_SPI_Receive(&hspi1, Buffer, Length,1000);
//volatile int result = HAL_SPI_Transmit_DMA(&hspi1, Buffer, 1);
//HAL_SPI_Receive_DMA(&hspi1, Buffer, Length);
}
uint8_t HAL_SPI_Write(uint8_t data)
{
//volatile int result = HAL_SPI_Transmit(&hspi1, &data, 1, 1000);
volatile int result = HAL_SPI_Transmit_DMA(&hspi1, &data, 1);
return 0;
}

spi master fires uncontrollable dma tc interrupts without receiving nothing

I've already asked this question on the mbed forum, but I did not received an answer.
Introduction
I have two Nucleo L432kc board, I want to make them communicate with the SPI protocol using DMA.
In the following scheme you can see the actual hardware setup:
What works
If I send data from the master to the slave I receive them correctly and when the master is not transmitting the slave does not receive anything.
Master's code
#include <mbed.h>
uint8_t dma_buffer_tx[4];
uint8_t dma_buffer_rx[4];
uint8_t buff[4];
uint32_t receive_buff_length = 4;
unsigned int c = 0;
Serial pc(USBTX,USBRX,921600);
DigitalOut led(LED3);
SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi1_tx;
void Error_Handler(){
led.write(1);
while(1){}
}
static void HAL_GPIO_Init(void){
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi1.Instance==SPI1)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA1 ------> SPI1_SCK
PA11 ------> SPI1_MISO
PA12 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
else
Error_Handler();
}
static void SPI1_Init(void)
{
__HAL_RCC_SPI1_CLK_ENABLE();
/* 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.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
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();
}
/* SPI1 interrupt Init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
}
static void DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* SPI1 DMA Init */
/* SPI1_RX Init */
hdma_spi1_rx.Instance = DMA1_Channel2;
hdma_spi1_rx.Init.Request = DMA_REQUEST_1;
hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_rx.Init.Mode = DMA_NORMAL;
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&hspi1,hdmarx,hdma_spi1_rx);
/* DMA interrupt init */
/* DMA1_Channel2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
/* SPI1 DMA Init */
/* SPI1_TX Init */
hdma_spi1_tx.Instance = DMA1_Channel3;
hdma_spi1_tx.Init.Request = DMA_REQUEST_1;
hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_tx.Init.Mode = DMA_NORMAL;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&hspi1,hdmatx,hdma_spi1_tx);
/* DMA interrupt init */
/* DMA1_Channel3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
}
extern "C"{
void DMA1_Channel3_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(DMA1_Channel3_IRQn);
HAL_DMA_IRQHandler(&hdma_spi1_tx);
}
void DMA1_Channel2_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(DMA1_Channel2_IRQn);
HAL_DMA_IRQHandler(&hdma_spi1_rx);
}
void SPI1_IRQHandler(void)
{
HAL_SPI_IRQHandler(&hspi1);
}
}
void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi1){
for(int i = 0; i < receive_buff_length/2; i++){
buff[i] = dma_buffer_rx[i];
}
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi1){
for(int i = receive_buff_length/2; i < receive_buff_length; i++){
buff[i] = dma_buffer_rx[i];
}
printf("%u\n",*(unsigned int *)buff); // to understan when I am actually receiving data
memset(dma_buffer_rx,0,sizeof(dma_buffer_rx));
}
void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi1){
c += 5;
dma_buffer_tx[0] = c & 0xFF;
dma_buffer_tx[1] = (c >> 8) & 0xFF;
}
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi1){
dma_buffer_tx[2] = (c >> 16) & 0xFF;
dma_buffer_tx[3] = (c >> 24) & 0xFF;
}
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* SPI INIT */
SPI1_Init();
/* GPIO USART2 INIT */
HAL_GPIO_Init();
/* DMA INIT */
DMA_Init();
c = 1000;
dma_buffer_rx[0] = c & 0xFF;
dma_buffer_rx[1] = (c >> 8) & 0xFF;
dma_buffer_rx[2] = (c >> 16) & 0xFF;
dma_buffer_rx[3] = (c >> 24) & 0xFF;
while(true){
HAL_SPI_Transmit_DMA(&hspi1,dma_buffer_rx,receive_buff_length);
wait(0.001);
}
}
Slave's code
#include <mbed.h>
uint8_t dma_buffer_tx[4];
uint8_t dma_buffer_rx[4];
uint8_t buff[4];
uint32_t receive_buff_length = 4;
unsigned int c = 0;
Serial pc(USBTX,USBRX,921600);
DigitalOut led(LED3);
SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi1_tx;
void Error_Handler(){
led.write(1);
while(1){}
}
static void HAL_GPIO_Init(void){
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi1.Instance==SPI1)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA1 ------> SPI1_SCK
PA11 ------> SPI1_MISO
PA12 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
else
Error_Handler();
}
static void SPI1_Init(void)
{
__HAL_RCC_SPI1_CLK_ENABLE();
/* 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.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
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();
}
/* SPI1 interrupt Init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
}
static void DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* SPI1 DMA Init */
/* SPI1_RX Init */
hdma_spi1_rx.Instance = DMA1_Channel2;
hdma_spi1_rx.Init.Request = DMA_REQUEST_1;
hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_rx.Init.Mode = DMA_NORMAL;
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&hspi1,hdmarx,hdma_spi1_rx);
/* DMA interrupt init */
/* DMA1_Channel2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
/* SPI1 DMA Init */
/* SPI1_TX Init */
hdma_spi1_tx.Instance = DMA1_Channel3;
hdma_spi1_tx.Init.Request = DMA_REQUEST_1;
hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_tx.Init.Mode = DMA_NORMAL;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&hspi1,hdmatx,hdma_spi1_tx);
/* DMA interrupt init */
/* DMA1_Channel3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
}
extern "C"{
void DMA1_Channel3_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(DMA1_Channel3_IRQn);
HAL_DMA_IRQHandler(&hdma_spi1_tx);
}
void DMA1_Channel2_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(DMA1_Channel2_IRQn);
HAL_DMA_IRQHandler(&hdma_spi1_rx);
}
void SPI1_IRQHandler(void)
{
HAL_SPI_IRQHandler(&hspi1);
}
}
void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi1){
for(int i = 0; i < receive_buff_length/2; i++){
buff[i] = dma_buffer_rx[i];
}
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi1){
for(int i = receive_buff_length/2; i < receive_buff_length; i++){
buff[i] = dma_buffer_rx[i];
}
printf("%u\n",*(unsigned int *)buff); // to understan when I am actually receiving data
memset(dma_buffer_rx,0,sizeof(dma_buffer_rx));
}
void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi1){
c += 5;
dma_buffer_tx[0] = c & 0xFF;
dma_buffer_tx[1] = (c >> 8) & 0xFF;
}
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi1){
dma_buffer_tx[2] = (c >> 16) & 0xFF;
dma_buffer_tx[3] = (c >> 24) & 0xFF;
}
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* SPI INIT */
SPI1_Init();
/* GPIO USART2 INIT */
HAL_GPIO_Init();
/* DMA INIT */
DMA_Init();
c = 1000;
dma_buffer_rx[0] = c & 0xFF;
dma_buffer_rx[1] = (c >> 8) & 0xFF;
dma_buffer_rx[2] = (c >> 16) & 0xFF;
dma_buffer_rx[3] = (c >> 24) & 0xFF;
while(true){
HAL_SPI_Receive_DMA(&hspi1,dma_buffer_rx,receive_buff_length);
}
}
What does not work
If I change the role in the communication, so I send the data from the salve to the master swapping the following lines
[...]
HAL_SPI_Transmit_DMA(&hspi1,dma_buffer_rx,receive_buff_length);
wait(0.001);
[...]
with:
[...]
HAL_SPI_Receive_DMA(&hspi1,dma_buffer_rx,receive_buff_length);
[...]
Even if the slave is not powered up the master continusly receives interrupts and invokes the HAL_SPI_RxCpltCallback. If we power up the slave the master prints random numbers.
What I have already tried without success
I've tested the master code on a Nucleo F446 board.
I've set pull-down and pull-up resistors on the MISO pin.
I've tried different cable for the hw connection.
I've tried to directly use the HAL_SPI_TransmitReceive_DMA function, but the behaviour is the same.
Considerations
Walking throught the HAL_SPI_Receive_DMA source I've noticed that in the SPI_MODE_MASTER the HAL_SPI_TransmitReceive_DMA fuction is actually called.
I think that the same buffer is used for transmission and reception, but I don't know how to prove that.
I've also printed the hdma_spi1_rx.Instance->CNDTR and I've noticed that the value increments to 4 whitch is actually the number of bytes that we are going to receive.
SPI master always receives data when it is transmitting. This is how the SPI works. Even if the SPI is not transmitting, the master reads the data all the time.

SPI MISO value 255

i am trying to move my program to hal and my SPI is receiving only 255. What did i forget to set?
Function for reading:
uint8_t addressMsb[1] = { READ_ADDRESS | RTD_MSB_ADDRESS };
uint8_t addressLsb[1] = { READ_ADDRESS | RTD_LSB_ADDRESS };
uint8_t Temp_Msb[1];
uint8_t Temp_Lsb[1];
...
PT_CS1_LOW;
HAL_SPI_Transmit(&hspi1, (uint8_t*) addressMsb, 1, 10);
HAL_SPI_Receive(&hspi1, (uint8_t*) Temp_Msb, 1, 10);
PT_CS1_HIGH;
for(int i = 0; i<10;i++);
PT_CS1_LOW;
HAL_SPI_Transmit(&hspi1, (uint8_t*) addressLsb, 1, 10);
HAL_SPI_Receive(&hspi1, (uint8_t*) Temp_Lsb, 1, 10);
PT_CS1_HIGH;
...
Settings:
void MX_SPI1_Init(void)
{
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_HIGH;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
...
__HAL_RCC_SPI1_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
I know that it isnt a HW fail because a selfmade function on this board works. (frequency and settings are the same)
the old function:
if (!((SPI1)->CR1 & SPI_CR1_SPE)){
while(((SPI1)->SR & (SPI_SR_TXE | SPI_SR_RXNE)) == 0 || (SPI1)->SR & SPI_SR_BSY))SPI_WAIT(SPIx);
SPI1->DR = data;
while(((SPI1)->SR & (SPI_SR_TXE | SPI_SR_RXNE)) == 0 || ((SPI1)->SR & SPI_SR_BSY))SPI_WAIT(SPIx);
return SPI1->DR;
}
Sry guys my mistake,
if someone needs a working example for MAX31865 you can take the code up there... I powered down my computer and my HW for 5 minutes and now is everthink working even with HAL. It is suspicious that it did work with the old program and with HAL dont and after restart are both working... but now i know the HAL code is from principle is not wrong.
READ_ADDRESS = 0x00
RTD_MSB_ADDRESS = 0x01
RTD_LSB_ADDRESS = 0x02

stm32 pulse count up mode with reset, why not reset? (two signal reset count and steps)

I make this easy example, with count pulse input TI1 and reset pulse input TI2
when enable reset trigger counter give random numbers!
stm32 driver https://github.com/mbedmicro/mbed/blob/9b7d23d47153c298a6d24de9a415202705889d11/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32L4/stm32l4xx_hal_tim.h
function is like this:
/* Select the TIM_SMCR_TS_1 signal as Input trigger for the TIM */
htim->Instance->SMCR &= ~TIM_SMCR_TS;
htim->Instance->SMCR |= TIM_SMCR_TS_1;
Use the TIM_SMCR_TS_1 to reset the TIM counter each edge detection */
htim->Instance->SMCR &= ~TIM_SMCR_SMS;
htim->Instance->SMCR |= TIM_SLAVEMODE_RESET;
code:
#include "mbed.h"
#include "stm32f4xx.h"
#include "stm32f4xx_hal_tim_ex.h"
//direction to PA_9 -- step pulse to PA_8
uint16_t count1;
void pulsecount(void)
{
TIM_HandleTypeDef timer;
TIM_IC_InitTypeDef ICconfiginit;
TIM_ClockConfigTypeDef counter;
TIM_SlaveConfigTypeDef SlaveModeselect;
GPIO_InitTypeDef GPIO_InitStruct;
__TIM1_CLK_ENABLE();
__GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
timer.Instance = TIM1;
timer.Init.Period = 0xffff;
timer.Init.Prescaler = 0;
timer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
timer.Init.CounterMode = TIM_COUNTERMODE_UP;
ICconfiginit.ICFilter = 0x0f;
ICconfiginit.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
ICconfiginit.ICPrescaler = TIM_ICPSC_DIV1;
ICconfiginit.ICSelection = TIM_ICSELECTION_DIRECTTI;
counter.ClockSource = TIM_CLOCKSOURCE_TI1;
counter.ClockFilter = 0x0f;
SlaveModeselect.SlaveMode = TIM_SLAVEMODE_RESET;
SlaveModeselect.InputTrigger = TIM_TS_TI2FP2;
HAL_TIM_IC_Init(&timer);
HAL_TIM_IC_ConfigChannel(&timer, &ICconfiginit, TIM_CHANNEL_1);
HAL_TIM_ConfigClockSource(&timer, &counter);
HAL_TIM_SlaveConfigSynchronization(&timer, &SlaveModeselect); ///<<< not reset
HAL_TIM_IC_Start(&timer, TIM_CHANNEL_1);
TIM1->EGR = 1; // Generate an update event
TIM1->CR1 = 1; // Enable the counter
}
int main()
{
pulsecount();
while (1) {
count1=TIM1->CNT;
printf("%d\r\n", count1);
wait(1.0);
};
}