Author Topic: [SOLVED] STM32F4 Hal: SPI problems: SPI sets itself to slave mode  (Read 25389 times)

0 Members and 1 Guest are viewing this topic.

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Dear all,

I do apologize for the mundane and boring question, but unfortunately I am learning all this by myself, so I need some very basic help.
I am using the Eclipse/GCC setup to develop a simple STM32F407 program to be able to communicate with the MPU9250.

So I though a logical first step would be to try and spit out some data out of the pins. Here is my code:

Code: [Select]
#include <stdio.h>
#include <stdlib.h>
#include "diag/Trace.h"
#include <stm32f4xx.h>
#include <stm32f4xx_hal.h>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wmissing-declarations"
#pragma GCC diagnostic ignored "-Wreturn-type"

int
main(int argc, char* argv[])
{

__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();


//PA4 NSS
//PA5 SCK
//PA6 MISO
//PA7 MOSI

GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|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);

GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

SPI_InitTypeDef SPI_InitStruct;
SPI_InitStruct.Mode = SPI_MODE_MASTER;
SPI_InitStruct.Direction = SPI_DIRECTION_2LINES;
SPI_InitStruct.DataSize = SPI_DATASIZE_8BIT;
SPI_InitStruct.CLKPolarity = SPI_POLARITY_HIGH;
SPI_InitStruct.CLKPhase = SPI_PHASE_2EDGE;
SPI_InitStruct.NSS = SPI_NSS_HARD_OUTPUT;
SPI_InitStruct.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
SPI_InitStruct.FirstBit = SPI_FIRSTBIT_MSB;
SPI_InitStruct.TIMode = SPI_TIMODE_DISABLE;
SPI_InitStruct.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
SPI_HandleTypeDef SPI_MPU;
SPI_MPU.Init = SPI_InitStruct;
SPI_MPU.Instance = SPI1;
HAL_SPI_Init(&SPI_MPU);

trace_printf("Spi on \n");
uint8_t t;
uint8_t r;

while(1){
t = 0x1A;
HAL_SPI_TransmitReceive(&SPI_MPU,&t,&r,1,1000);
t = 0x00;
HAL_SPI_TransmitReceive(&SPI_MPU,&t,&r,1,1000);
trace_printf("Sent: %#x Received: %#x \n",0x1A,r);

t = 0x1A | 0x80;
HAL_SPI_TransmitReceive(&SPI_MPU,&t,&r,1,1000);
t = 0xFF;
HAL_SPI_TransmitReceive(&SPI_MPU,&t,&r,1,1000);
trace_printf("Sent: %#x Received: %#x \n",0x1A | 0x80,r);

}
}

#pragma GCC diagnostic pop

My problem: When I probe the pins with my oscilloscope I get a square wave of around 12khz on the data lines and spiking on the clock, which seems to occur every transition of the data and every half period of the data.

And In all honesty I dont know where to start debugging. I feel like the GPIO pins are setup correctly because something is coming out, but i dont know why it is not the signal I am looking for.

On a different note, I am using semihosting on the stlink v2 and it is awfully slow (think a second per transmission slow). Am I doing something wrong? Is the stlink that slow? Is semihosting in general that slow? Any better options that are cheap? FTDI on a UART?

Thank you for all your considerations, and please do scream at me for any malpractices etc. This forum is my only way to interact about this kind of stuff so the more I learn the better :)
« Last Edit: December 03, 2016, 12:15:28 pm by BurnedResistor »
 

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems
« Reply #1 on: November 23, 2016, 08:40:05 pm »
Maybe do I need to poll something after the transmit method? I looked into the method and it seems like it already polls at the end

The Pictures: http://imgur.com/a/EE0gZ

Code: [Select]
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
{
#ifdef USE_SPI_CRC
  __IO uint16_t tmpreg = 0U;
#endif
  uint32_t tickstart = 0U;
  HAL_StatusTypeDef errorcode = HAL_OK;

  /* Check Direction parameter */
  assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));

  /* Process Locked */
  __HAL_LOCK(hspi);

  /* Init tickstart for timeout managment*/
  tickstart = HAL_GetTick();

  if(!((hspi->State == HAL_SPI_STATE_READY) || \
    ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->State == HAL_SPI_STATE_BUSY_RX))))
  {
    errorcode = HAL_BUSY;
    goto error;
  }

  if((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
  {
    errorcode = HAL_ERROR;
    goto error;
  }

  /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
  if(hspi->State == HAL_SPI_STATE_READY)
  {
    hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
  }

  /* Set the transaction information */
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  hspi->pRxBuffPtr  = (uint8_t *)pRxData;
  hspi->RxXferCount = Size;
  hspi->RxXferSize  = Size;
  hspi->pTxBuffPtr  = (uint8_t *)pTxData;
  hspi->TxXferCount = Size;
  hspi->TxXferSize  = Size;

  /*Init field not used in handle to zero */
  hspi->RxISR       = NULL;
  hspi->TxISR       = NULL;

#ifdef USE_SPI_CRC
  /* Reset CRC Calculation */
  if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
  {
    SPI_RESET_CRC(hspi);
  }
#endif

  /* Check if the SPI is already enabled */
  if((hspi->Instance->CR1 &SPI_CR1_SPE) != SPI_CR1_SPE)
  {
    /* Enable SPI peripheral */
    __HAL_SPI_ENABLE(hspi);
  }

  /* Transmit and Receive data in 16 Bit mode */
  if(hspi->Init.DataSize == SPI_DATASIZE_16BIT)
  {
    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
    {
      /* Check TXE flag */
      if((hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
      {
        hspi->Instance->DR = *((uint16_t *)pTxData);
        pTxData += sizeof(uint16_t);
        hspi->TxXferCount--;

#ifdef USE_SPI_CRC
        /* Enable CRC Transmission */
        if((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
        {
          SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
        }
#endif
      }

      /* Check RXNE flag */
      if((hspi->RxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)))
      {
        *((uint16_t *)pRxData) = hspi->Instance->DR;
        pRxData += sizeof(uint16_t);
        hspi->RxXferCount--;
      }
      if((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >=  Timeout))
      {
        errorcode = HAL_TIMEOUT;
        goto error;
      }
    }
  }
  /* Transmit and Receive data in 8 Bit mode */
  else
  {
    while((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
    {
      /* check TXE flag */
      if((hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
      {
        *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++);
        hspi->TxXferCount--;

#ifdef USE_SPI_CRC
        /* Enable CRC Transmission */
        if((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
        {
          SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
        }
#endif
      }

      /* Wait until RXNE flag is reset */
      if((hspi->RxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)))
      {
        (*(uint8_t *)pRxData++) = hspi->Instance->DR;
        hspi->RxXferCount--;
      }
      if((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >=  Timeout))
      {
        errorcode = HAL_TIMEOUT;
        goto error;
      }
    }
  }

#ifdef USE_SPI_CRC
  /* Read CRC from DR to close CRC calculation process */
  if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
  {
    /* Wait until TXE flag */
    if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
    {
      /* Error on the CRC reception */
      SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
      errorcode = HAL_TIMEOUT;
      goto error;
    }
    /* Read CRC */
    tmpreg = hspi->Instance->DR;
    /* To avoid GCC warning */
    UNUSED(tmpreg);
  }

  /* Check if CRC error occurred */
  if(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR))
  {
    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
    /* Clear CRC Flag */
    __HAL_SPI_CLEAR_CRCERRFLAG(hspi);

    errorcode = HAL_ERROR;
  }
#endif

  /* Check the end of the transaction */
  if(SPI_CheckFlag_BSY(hspi, Timeout, tickstart) != HAL_OK)
  {
    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
    errorcode = HAL_ERROR;
  }

error :
  hspi->State = HAL_SPI_STATE_READY;
  __HAL_UNLOCK(hspi);
  return errorcode;
}
 

Offline thm_w

  • Super Contributor
  • ***
  • Posts: 6337
  • Country: ca
  • Non-expert
Re: STM32F4 Hal: SPI problems
« Reply #2 on: November 24, 2016, 12:46:01 am »
Yes HAL function should be polling and wait for data, up until the timeout you've specified (1000).
Where is your clock setup and HAL init? To determine if you are using PLL, internal external clock, what frequency, etc. Use cubemx to generate the clock setup code. ex:
Code: [Select]
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

stlink is usually quite fast, but I haven't used semihosting. You can try switching to j-link if you've confirmed problem is stlink (can upgrade, check jtag speed, etc.)
I use breakpoint or live watch, but I think either method is good.
I don't know what the default clock speed of F407 would be, so maybe its really slow if it hasn't been setup.

You can also test if config is successful:
Code: [Select]
  if (HAL_SPI_Init(&SPI_MPU) != HAL_OK)
  {
    Error_Handler();
  }
« Last Edit: November 24, 2016, 12:50:22 am by thm_w »
Profile -> Modify profile -> Look and Layout ->  Don't show users' signatures
 
The following users thanked this post: BurnedResistor

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems
« Reply #3 on: November 24, 2016, 05:22:59 am »


Yes HAL function should be polling and wait for data, up until the timeout you've specified (1000).
Where is your clock setup and HAL init? To determine if you are using PLL, internal external clock, what frequency, etc. Use cubemx to generate the clock setup code. ex:
Code: [Select]
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

stlink is usually quite fast, but I haven't used semihosting. You can try switching to j-link if you've confirmed problem is stlink (can upgrade, check jtag speed, etc.)
I use breakpoint or live watch, but I think either method is good.
I don't know what the default clock speed of F407 would be, so maybe its really slow if it hasn't been setup.

You can also test if config is successful:
Code: [Select]
  if (HAL_SPI_Init(&SPI_MPU) != HAL_OK)
  {
    Error_Handler();
  }
I am using the setup code generate by the eclipse plugin that is made for the disco4 board I am using.

Here is the content of SystemClockConfig(void):

Code: [Select]

  // Enable Power Control clock
  __PWR_CLK_ENABLE();

  // The voltage scaling allows optimizing the power consumption when the
  // device is clocked below the maximum system frequency, to update the
  // voltage scaling value regarding system frequency refer to product
  // datasheet.
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

#warning "Please check if the SystemClock_Config() settings match your board!"
  // Comment out the warning after checking and updating.

  RCC_OscInitTypeDef RCC_OscInitStruct;

#if defined(HSE_VALUE) && (HSE_VALUE != 0)
  // Enable HSE Oscillator and activate PLL with HSE as source.
  // This is tuned for STM32F4-DISCOVERY; update it for your board.
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  // This assumes the HSE_VALUE is a multiple of 1 MHz. If this is not
  // your case, you have to recompute these PLL constants.
  RCC_OscInitStruct.PLL.PLLM = (HSE_VALUE/1000000u);

which is called here:

Code: [Select]
void
__initialize_hardware(void)
{
  // Initialise the HAL Library; it must be the first function
  // to be executed before the call of any HAL function.
  HAL_Init();

  // Enable HSE Oscillator and activate PLL with HSE as source
  SystemClock_Config();

  // Call the CSMSIS system clock routine to store the clock frequency
  // in the SystemCoreClock global RAM location.
  SystemCoreClockUpdate();
}

The outside crystal is 8mhz.

Could I probe the oscillator with an oscilloscope to confirm it is working, or would the extra capacitance from the tip screw it up? What kind of waveform would I excpect? I saw a very badly distorted sine/triangle wave at around 500Hz...


 

Offline stfsux

  • Contributor
  • Posts: 23
  • Country: 00
Re: STM32F4 Hal: SPI problems
« Reply #4 on: November 24, 2016, 01:18:07 pm »
Before checking the data line, check if clock line has the correct baudrate.
Check also your predefined macro (generally passed to the compiler command line (e.g. -D for gcc)).
There are a lot of #ifdef #ifndef in stmlib for your specific architecture.
 
The following users thanked this post: BurnedResistor

Offline thm_w

  • Super Contributor
  • ***
  • Posts: 6337
  • Country: ca
  • Non-expert
Re: STM32F4 Hal: SPI problems
« Reply #5 on: November 24, 2016, 07:36:18 pm »
Any reason the initialize call is not in main function listed above? Did you leave it out or does the compiler include it automatically.

You could probe the crystal or probe a buffered clock output:
Code: [Select]
  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1);Although I would try some other things first, and probe spi clock as stfsux noted.

SPI1 is on APB1 or 2 prescaler, although you have not set it the default should be 1x. You also have the SPI_BAUDRATEPRESCALER_x if it needs to be any slower.
« Last Edit: November 24, 2016, 07:38:23 pm by thm_w »
Profile -> Modify profile -> Look and Layout ->  Don't show users' signatures
 
The following users thanked this post: BurnedResistor

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems
« Reply #6 on: November 27, 2016, 02:26:18 pm »
Any reason the initialize call is not in main function listed above? Did you leave it out or does the compiler include it automatically.

You could probe the crystal or probe a buffered clock output:
Code: [Select]
  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1);Although I would try some other things first, and probe spi clock as stfsux noted.

SPI1 is on APB1 or 2 prescaler, although you have not set it the default should be 1x. You also have the SPI_BAUDRATEPRESCALER_x if it needs to be any slower.
Before checking the data line, check if clock line has the correct baudrate.
Check also your predefined macro (generally passed to the compiler command line (e.g. -D for gcc)).
There are a lot of #ifdef #ifndef in stmlib for your specific architecture.
Yes HAL function should be polling and wait for data, up until the timeout you've specified (1000).
Where is your clock setup and HAL init? To determine if you are using PLL, internal external clock, what frequency, etc. Use cubemx to generate the clock setup code. ex:
Code: [Select]
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

stlink is usually quite fast, but I haven't used semihosting. You can try switching to j-link if you've confirmed problem is stlink (can upgrade, check jtag speed, etc.)
I use breakpoint or live watch, but I think either method is good.
I don't know what the default clock speed of F407 would be, so maybe its really slow if it hasn't been setup.

You can also test if config is successful:
Code: [Select]
  if (HAL_SPI_Init(&SPI_MPU) != HAL_OK)
  {
    Error_Handler();
  }


Dear All,

taking the advice I received I decided my best next steps would be to create a project using CubeMX, import it into eclipse/arm add a while loop that constantly sensd a increasigng number and then check the SPU clock rate. However, after I did this, my project is refusing to boot. As soon as the debug persepcive opens I am stuck in the Hardwarefault Handler. The board is fine, I tested with previously know good projects/code.

My best guess is that the startup code from cubemx is bad, or I screwed up while importing it (more likely). Any ideas on how to debug the HardwareFault?

Any Idea on how I can best share the code/setup I have?
 

Offline Brutte

  • Frequent Contributor
  • **
  • Posts: 614
Re: STM32F4 Hal: SPI problems
« Reply #7 on: November 27, 2016, 03:05:12 pm »
Any ideas on how to debug the HardwareFault?
It is not HardwareFault but HardFault handler (just to help you google that).
 
The following users thanked this post: BurnedResistor

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems
« Reply #8 on: November 27, 2016, 04:18:55 pm »
Yup:) Thanks for helping me catch that typo :)
 

Offline tatus1969

  • Super Contributor
  • ***
  • Posts: 1273
  • Country: de
  • Resistance is futile - We Are The Watt.
    • keenlab
Re: STM32F4 Hal: SPI problems
« Reply #9 on: November 27, 2016, 05:32:46 pm »
have you compared your solution against the SPI demo project that normally comes with the ST HAL package?
We Are The Watt - Resistance Is Futile!
 
The following users thanked this post: BurnedResistor

Offline jmsigler

  • Regular Contributor
  • *
  • Posts: 57
  • Country: us
Re: STM32F4 Hal: SPI problems
« Reply #10 on: November 27, 2016, 06:52:07 pm »
I had the same problem when I was using plain gnrarmeclipse. I ended up switching to a method outlined in the book mastering stm32, which fixed my problem.
 
The following users thanked this post: BurnedResistor

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems
« Reply #11 on: November 27, 2016, 07:09:32 pm »
I had the same problem when I was using plain gnrarmeclipse. I ended up switching to a method outlined in the book mastering stm32, which fixed my problem.

Thats what I have been following :(

I decided to say screw it at switch to Atollic Free. short of printf it has everything I need and I am sick of dicking around with eclipse...

So I imported everything in atollic from cubeMX (which took all of 10 seconds I am in heaven)

But I am still not able to produce a clock from the SPI port...

However, a bit of progress: I managed to output the HSE to the clock out pin and I am getting 8mhz! Wohoo!

Is there any way of accesing the system or peripheral clock?  RCC_MCO1SOURCE_PLLCLK flag did nothing in Hal.. pint at gnd :(

Alright, here is my code:


the main function where the CLock, SPI and GPIO init functions are called, plus the infinte spi loop
Code: [Select]
/* 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_SPI1_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  uint8_t t = 0;
  uint8_t r = 0;
  while (1)
  {
  t++;
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
  HAL_SPI_TransmitReceive(&hspi1,&t,&r,1,3);
  }
  /* USER CODE END 3 */

}
[\code]

Here is the Clock intialization:
[code]
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Configure the main internal regulator output voltage
    */
  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 330;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  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_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }

  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_PLLCLK, RCC_MCODIV_1);

    /**Configure the Systick interrupt time
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
[\code]

GPIO and SPI init:

[code]

/* SPI1 init function */
static 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_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_HARD_INPUT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
  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();
  }

}

/** Configure pins as
        * Analog
        * Input
        * Output
        * EVENT_OUT
        * EXTI
     PA8   ------> RCC_MCO_1
*/
static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin : PA8 */
  GPIO_InitStruct.Pin = GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}
[\code]

And finally the spi hardware init called from the SPI_init hal function:
[code]
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(hspi->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();
 
    /**SPI1 GPIO Configuration   
    PA4     ------> SPI1_NSS
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_4|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);

  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }

}
[\code]

Making progress :)
 

Offline jmsigler

  • Regular Contributor
  • *
  • Posts: 57
  • Country: us
Re: STM32F4 Hal: SPI problems
« Reply #12 on: November 27, 2016, 07:51:27 pm »
You may have to add _HAL_SPI_ENABLE(&hspi) or something similar? I remember an enable function for spi, but I'm pretty sure that it would still work even if you didn't call this so maybe that isn't your problem.
 

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems
« Reply #13 on: November 27, 2016, 08:25:26 pm »
You may have to add _HAL_SPI_ENABLE(&hspi) or something similar? I remember an enable function for spi, but I'm pretty sure that it would still work even if you didn't call this so maybe that isn't your problem.

Hmm.... I just added but no cigar...

 

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems
« Reply #14 on: November 27, 2016, 08:31:27 pm »
Upon further inspection,  the Transmit function actually makes sure it is enabeled:
Code: [Select]

  if((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
  {
    /* Enable SPI peripheral */
    __HAL_SPI_ENABLE(hspi);
  }



I also just debug-single stepped through the code, the spi config regs are definetly being written to. I have not checked them against my setup yet![/code]
 

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems
« Reply #15 on: November 27, 2016, 08:35:53 pm »
Also just checked that the Hal is not timing out.....
 

Offline thm_w

  • Super Contributor
  • ***
  • Posts: 6337
  • Country: ca
  • Non-expert
Re: STM32F4 Hal: SPI problems
« Reply #16 on: November 28, 2016, 10:43:12 pm »
Can you get the return value of the HAL function? Does it return an error, it should be timeout due to nothing received I would assume?

Quote
HAL_StatusTypeDef state;
state = HAL_SPI_TransmitReceive(&hspi1,&t,&r,1,3);

I'm using:
Quote
HAL_SPI_Transmit(tSPIx, &chByte, 1, 10);
But my code does not expect any reply. If you just want to blast data out, it might be worth trying.

Although it looks like what you have is OK. You could check the SPI regs if there is an enable clock or power on, etc.
Profile -> Modify profile -> Look and Layout ->  Don't show users' signatures
 
The following users thanked this post: BurnedResistor

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems
« Reply #17 on: November 30, 2016, 09:02:35 pm »
Can you get the return value of the HAL function? Does it return an error, it should be timeout due to nothing received I would assume?

Quote
HAL_StatusTypeDef state;
state = HAL_SPI_TransmitReceive(&hspi1,&t,&r,1,3);

I'm using:
Quote
HAL_SPI_Transmit(tSPIx, &chByte, 1, 10);
But my code does not expect any reply. If you just want to blast data out, it might be worth trying.

Although it looks like what you have is OK. You could check the SPI regs if there is an enable clock or power on, etc.


Oh. It seems the hal is timing out! it returns HAL_TIMEOUT!
     Two possible options: The systick is not working causing it to timeout immediatly
                                     The spi is not setup correctly and does not return :/

« Last Edit: November 30, 2016, 09:05:57 pm by BurnedResistor »
 

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems
« Reply #18 on: November 30, 2016, 09:06:15 pm »
Just confirmed that it is not the systick....
 

Offline thm_w

  • Super Contributor
  • ***
  • Posts: 6337
  • Country: ca
  • Non-expert
Re: STM32F4 Hal: SPI problems
« Reply #19 on: November 30, 2016, 11:23:45 pm »
But do you have something connected that will return a response?
If not use the transmit only function. Or even use it for now for debugging.

The transmit should not return timeout unless something was really wrong.

Profile -> Modify profile -> Look and Layout ->  Don't show users' signatures
 
The following users thanked this post: BurnedResistor

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems
« Reply #20 on: December 01, 2016, 04:42:46 am »
But do you have something connected that will return a response?
If not use the transmit only function. Or even use it for now for debugging.

The transmit should not return timeout unless something was really wrong.



Code: [Select]

  uint8_t t = 0;

  hspi1.Instance->CR1 |=  SPI_CR1_SPE;
  volatile HAL_StatusTypeDef state;
  while (1)
  {
  t++;
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
  state = HAL_SPI_Transmit(&hspi1, &t, 1, 100);
  asm volatile("mov r0, r0");
  asm volatile("mov r0, r0");
  asm volatile("mov r0, r0");
  asm volatile("mov r0, r0");
  asm volatile("mov r0, r0");

  }

I am break pointing on the last NOP because I wanted to make sure the debug was not interfering with the systick timer on which the timeout is based!

Still returning HAL_TIMEOUT!

I am at a loss. I hope I will have time to sit my ass down, and compare the values in the SPI regs against the datasheet! Any other ideas about what could be wrong?

Out of curiosity, would a spi transmit receive call without anything attached work but read 0 in return as there is no acknowledge built into the protocol?
« Last Edit: December 01, 2016, 04:48:41 am by BurnedResistor »
 

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems
« Reply #21 on: December 01, 2016, 06:06:08 am »
Just checked, on the disco 4 board I am using the spi bus is connected to a MEMS device. However that should not cause it to timeout?

I dont need any of the other devices on the board, so I might just cut the traces for good measure. Sadly no jumpers to do so:(

...
WTF?

For some reason the SPI periph's Master/Slave bit is set to master after the init, but cleared during the Transmit call?
...

Further narrowed it down. Appearantly enabeling the SPI peripheral:


Code: [Select]
hspi1.Instance->CR1 |=  SPI_CR1_SPE;

Does not enable it, but disables master mode! I did check the SPI_CR1_SPE is the correct bitmask!

Nothing on the ST errate for the chip...

« Last Edit: December 01, 2016, 06:10:11 am by BurnedResistor »
 

Offline tatus1969

  • Super Contributor
  • ***
  • Posts: 1273
  • Country: de
  • Resistance is futile - We Are The Watt.
    • keenlab
Re: STM32F4 Hal: SPI problems: SPI sets itself to slave mode (does not enable?)
« Reply #22 on: December 01, 2016, 07:13:50 am »
does your code contaion concurrent access, like main+interrupt, or multithreading?
We Are The Watt - Resistance Is Futile!
 

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems: SPI sets itself to slave mode (does not enable?)
« Reply #23 on: December 01, 2016, 07:47:26 am »
does your code contaion concurrent access, like main+interrupt, or multithreading?

nope.

It only contains the spi handler
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4078
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: STM32F4 Hal: SPI problems: SPI sets itself to slave mode (does not enable?)
« Reply #24 on: December 01, 2016, 09:05:55 am »
I noticed you had to set the SSM bit for MSTR and SPE to stay engaged. Makes sense if you think about it.
Code: [Select]
  __HAL_RCC_SPI2_FORCE_RESET();
  __NOP();
  __HAL_RCC_SPI2_RELEASE_RESET();
  SPI2->CR1 |= (4<<SPI_CR1_BR_Pos);
  SPI2->CR1 |= SPI_CR1_SSM;           // Software chip select
  SPI2->CR1 |= SPI_CR1_SSI;
  SPI2->CR1 |= SPI_CR1_MSTR | SPI_CR1_SPE;
Btw: this is all init required for master mode.
 
The following users thanked this post: BurnedResistor

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems: SPI sets itself to slave mode (does not enable?)
« Reply #25 on: December 01, 2016, 11:00:19 am »
I noticed you had to set the SSM bit for MSTR and SPE to stay engaged. Makes sense if you think about it.
Code: [Select]
  __HAL_RCC_SPI2_FORCE_RESET();
  __NOP();
  __HAL_RCC_SPI2_RELEASE_RESET();
  SPI2->CR1 |= (4<<SPI_CR1_BR_Pos);
  SPI2->CR1 |= SPI_CR1_SSM;           // Software chip select
  SPI2->CR1 |= SPI_CR1_SSI;
  SPI2->CR1 |= SPI_CR1_MSTR | SPI_CR1_SPE;
Btw: this is all init required for master mode.


Oh wow! That did it :)

Thank you so much!

Not noted in the cube mx anywhere, what a great piece of software :(


Thank you all for your help!

For future reference, I will attach the final working code :)


« Last Edit: December 01, 2016, 11:23:08 am by BurnedResistor »
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4078
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: STM32F4 Hal: SPI problems: SPI sets itself to slave mode (does not enable?)
« Reply #26 on: December 02, 2016, 01:40:52 pm »
I try to avoid hal and cube as much as possible. It is included when starting, but converted to save ROM and complexity.
Only the headers stay inluded for the definitions, and the rcc. Since that is usually working fine, and significantly complicated.
 

Offline BurnedResistorTopic starter

  • Regular Contributor
  • *
  • Posts: 192
  • Country: at
Re: STM32F4 Hal: SPI problems: SPI sets itself to slave mode (does not enable?)
« Reply #27 on: December 03, 2016, 12:12:38 pm »
I try to avoid hal and cube as much as possible. It is included when starting, but converted to save ROM and complexity.
Only the headers stay inluded for the definitions, and the rcc. Since that is usually working fine, and significantly complicated.

I am planning on implementing the project with the cube hal, to gain an understanding of what the exact requirements for me are, and then write my own HAL which perfecty meets those requirements. I tried going straight to that, but this is my first time developing such a big project and on this platform so I did not get far!

Interestingly I did not see the whole SSM bit business anywhere in the datasheet nor reference manual!
 Fun times....

Thank you everybody for helping!
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4078
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: STM32F4 Hal: SPI problems: SPI sets itself to slave mode (does not enable?)
« Reply #28 on: December 03, 2016, 01:08:30 pm »
I am planning on implementing the project with the cube hal, to gain an understanding of what the exact requirements for me are, and then write my own HAL which perfecty meets those requirements. I tried going straight to that, but this is my first time developing such a big project and on this platform so I did not get far!

Not quite true.
Quote
Configuring the SPI in master mode
In the master configuration, the serial clock is generated on the SCK pin.
Procedure
1. Select the BR[2:0] bits to define the serial clock baud rate (see SPI_CR1 register).
2. Select the CPOL and CPHA bits to define one of the four relationships between the
data transfer and the serial clock (see Figure 239).
3. Set the DFF bit to define 8- or 16-bit data frame format
4. Configure the LSBFIRST bit in the SPI_CR1 register to define the frame format.
5. If the NSS pin is required in input mode, in hardware mode, connect the NSS pin to a high-level signal during the complete byte transmit sequence. In NSS software mode, set the SSM and SSI bits in the SPI_CR1 register. If the NSS pin is required in output mode, the SSOE bit only should be set.
6. The MSTR and SPE bits must be set (they remain set only if the NSS pin is connected to a high-level signal).

These things make mcu development hell sometimes. There is this peripheral that only works if you set some bit in specific way, described only at one place in the middle of the text. Which you didn't read since you skipped to the registers immediately.  :(

Goodluck!
 

Offline Geryboy666

  • Newbie
  • Posts: 1
  • Country: de
Re: [SOLVED] STM32F4 Hal: SPI problems: SPI sets itself to slave mode
« Reply #29 on: March 14, 2017, 12:30:39 pm »
I had the same problem, STM32F411RE, Gnu Arm Eclipse HAL Lib 1.4.xx

However the problem wasn't enabling any Bits in the Control Registers...

1st I got a Timeout Error because my Baudratescaler was to small, I used 2 and got Timeouts, then I used 64 which was fine.

In the inital post his MISO PIN was declared Input, however all 3 PINS, MISO, MOSI, SCK need to be AF_PP in MODE, and AF5_SPIx in Alternate.

then use NSS as Software, and declare another random GPIO PIN as NSS and select the Slave via your own Code.


Code: [Select]
//GLOBAL VAR
SPI_HandleTypeDef SPI_Handle; // global fuer ISR
int
main(int argc, char* argv[])
{
// CLKs Enable
__HAL_RCC_SPI1_CLK_ENABLE(); // MUSS an sein, ist richtig
__HAL_RCC_GPIOA_CLK_ENABLE();
// SPI Config start
SPI_Handle.Instance = SPI1; // D13 bis D11
SPI_Handle.Init.Mode = SPI_MODE_MASTER;
SPI_Handle.Init.Direction = SPI_DIRECTION_2LINES; // transmit and receive
SPI_Handle.Init.DataSize = SPI_DATASIZE_8BIT; // 8 bit Packete
SPI_Handle.Init.CLKPolarity = SPI_POLARITY_LOW; // idle @ low state
SPI_Handle.Init.CLKPhase =SPI_PHASE_1EDGE; // Phase = 0, rising edge = sample
SPI_Handle.Init.NSS = SPI_NSS_SOFT;
SPI_Handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
SPI_Handle.Init.FirstBit = SPI_FIRSTBIT_MSB;
SPI_Handle.Init.TIMode = SPI_TIMODE_DISABLE; // Motorola standard verwenden
SPI_Handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
SPI_Handle.Init.CRCPolynomial =0;
// SPI Config end
// SPI Init
if (HAL_SPI_Init(&SPI_Handle)!= HAL_OK)
{
printf("Fehler bei SPI Init\n");
}
// Interrupt enable
HAL_NVIC_SetPriority(SPI1_IRQn, 2,1);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
// GPIO Config start
// CLK,MISO,MOSI

GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_9; // D8
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin =  GPIO_PIN_5| GPIO_PIN_6 |GPIO_PIN_7; // D13 = CLK, A2 = NSS , D11 = MOSI, D12 = MISO
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // Push Pull
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
//GPIO Init
HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);

//var

const uint32_t timeout = 100;
const uint16_t SIZE = 3; // Puffergroeße = 1 Byte
double temp;
HAL_StatusTypeDef HAL_Status; // 0 = ok, 1 = Error, 2 = Busy, 3 = timeout
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET); // Slave sleep

  while (1)
    {

  uint8_t transmit[3] = {0b00000110, 0b00000000, 0b00000000};
  uint8_t receive [3] = {0,0,0};
  HAL_Delay(2000);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET); // Slave wake up

if( (HAL_Status = HAL_SPI_TransmitReceive(&SPI_Handle,&transmit,&receive,SIZE,timeout)) != HAL_OK)
{
printf("1st TransmitReceive Error: %d\n", HAL_Status);
}

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET); // Slave sleep
  //temp = (receive2 <<8) | receive3; // 12 BIT ADC Wert zusammenfuegen
  printf("Receive: %d\t%d\n", receive[1],  receive[2] ); // debug
  printf("Transmit: %d\t%d\t %d\n", transmit[1],transmit[2],transmit[0] ); // debug
  printf("Temp = %f\n", temp); // debug
  printf("SIZE = %d\n", SIZE);
  //temp = (temp *500.0)/4096; // 5 V Ref, 1°C pro 10mV => 500/2^12
  //printf("Temp = %f\n", temp);
    }
}

this codes makes the nucleo master, and uses the MCP3208 as Slave, which reads out a Temp sensor on Channel 0. The 1st Transfer Byte is the setup, the 2nd is the channel select, the 3rd is 0 to give the IC enough clocks. The 2nd and 3rd Receive Bytes are the result.
« Last Edit: March 14, 2017, 12:34:45 pm by Geryboy666 »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf