2021-01-09 08:50 AM
Dear all,
I have a SPI Master, that sends out a "hello word" message working.
The signals are correct and my scope can decode them.
However, I can't, for the love of god get a slave working. Not DMA, not IT and not even
blocking mode.
Here is my code for init.
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_HARD_INPUT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_LSB;
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();
}
then calling the receive method again and again,
but no matter when I break with the debugger, I always see 0s :
while (1)
{
uint8_t res = HAL_SPI_Receive(&hspi1, buffer, 5, HAL_MAX_DELAY);
// breaking here with debugger and looking into buffer - always 5 first bytes are zero
}
What I really want is a DMA transfer (so, a callback when a message is complete), but I have given up on that thanks to the absolutely incomprehensible STs documentation for that so far. Just trying to receive any data in any way for now.
Any hints?
Thank you and best regards
Stefan
2021-01-09 09:07 AM
What chip?
Is res == HAL_OK?
Are your pins initialized?
Breaking inside an infinite loop with only 1 statement might not return when you think it would.
2021-01-09 09:26 AM
I am using the nucleo board with the L4011K4 chip.
Pins are all set to alternate function; I do not explicitly initialize them (dont see any init in generated GPIO init).
Yes, res == HAL_OK.
Maybe this gives a hint:
I changed to and break at HAL_DELAY
if(HAL_SPI_Receive(&hspi1, buffer, 5, HAL_MAX_DELAY) != HAL_OK){
Error_Handler();
}
HAL_Delay(10);
Result is still 00000s
HAL_SPI_Receive takes about a second to come back (and sender sends a packet every 100ms)
More hints:
When enabling interrupt and DMA, the HAL_Delay never comes back. Maybe we leave that as a next step,
but maybe this info gives some clue.
Still, any help appreciated.
2021-01-09 09:35 AM
Your initialization is missing the BaudRatePrescaler field.
Pin initialization would be in stm32xxxx_hal_msp.c. Ensure the pins you're looking at are the ones connected.
Include all relevant code. I don't think snippets are helping anyone here.
If HAL_Delay isn't working, clearly something else is wrong. Probably not the source of this issue.
2021-01-09 11:54 AM
OK, tried that. CubeMX does not give me the options field for clock scaler on a SPI client (which makes sense, I guess).
However, tried to set it manually by chaning generated code, but no success. Yes, PINs are correct (at least if the
A4 print on the board means PA4 and so on).
I deleted to hole project and restarted. Nothing. As per request (and by the way, thank you a lot for helping me here!!!)
the complete code of my main.c is here:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi1;
/* USER CODE BEGIN PV */
char buffer [11];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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_SPI1_Init();
/* USER CODE BEGIN 2 */
HAL_Delay(100);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(HAL_SPI_Receive(&hspi1, buffer, sizeof(buffer), HAL_MAX_DELAY) != HAL_OK){
Error_Handler();
}
HAL_Delay(10);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_4;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief SPI1 Initialization Function
* @param None
* @retval None
*/
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_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_HARD_INPUT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_LSB;
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();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : VCP_TX_Pin VCP_RX_Pin */
GPIO_InitStruct.Pin = VCP_TX_Pin|VCP_RX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : LD3_Pin */
GPIO_InitStruct.Pin = LD3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LD3_GPIO_Port, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
2021-01-09 12:36 PM
> I am using the nucleo board with the L4011K4 chip.
Do you mean NUCLEO-L011K4?
https://www.st.com/en/evaluation-tools/nucleo-l011k4.html
If something is failing, you would never know because Error_Handler just silently returns. Put an infinite loop in there so you can at least catch errors.
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
while (1);
/* USER CODE END Error_Handler_Debug */
}
Still missing a BaudRatePrescaler in your initialization, although if it default to 0, it's probably fine.
You're not doing anything useful with buffer, so maybe it's optimizing it out? But maybe not.
Try to use HAL_SPI_TransmitReceive instead. If that doesn't work, and you've double checked the pins, and done the stuff above, I'm out of ideas.
2021-01-09 01:37 PM
Also be aware of SB16/SB18 which, by default are on and connects PA6 to PB6 and PA5 to PB7.
2021-01-10 04:23 AM
@TDK , thank you very much - I see how hard you try. But I am giving up on that chip and HAL.
The Scope can easily decode the signal, but no matter what I try (and I quadruple-checked all pins and signals)
i get no response from the receive or transmitreceive function.
receive_DMA ends up hanging completely (systick not updated any more, HAL_delay not returning and checking in debugger
shows that the RXcplt handler also stuck in timeout check).
If @STM32 MCUs you can and want to try, contact me for really anyhting (I can send you test-code, can even send the nuclo-kit flashed)
, I can reconsider using that chip and HAL in production. So far, I need to help my client and time is running out.
2021-01-10 06:25 AM
> But I am giving up on that chip and HAL.
Hard to help when I'm still missing a lot of info. I'm still guessing on what board you're using. "L4011K4" is not a chip. You still haven't said what pins you're using, apart from PA4. Last time you were using blocking functions, now it looks like you're trying DMA. Good luck.