This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SPI3 and SD Card

Hi Does anybody have a working example of an STM32F407VG reading and or writing an SD card using SPI3.

I have tried everything but always fails on mount with fsMediaError am at my wits end, i have even tried to follow example http://www.keil.com/appnotes/files/apnt_273.pdf and still not working.

  • GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI3);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI3);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI3);
    

    Pins for SPI3 are also for JTAG.

  • The OP isn't using the JTAG pins, got F1 board that does and you need to disable Full JTAG

    LED = PB1
    LED = PB2
    CS = PD3
    SCK = PC10
    MISO = PC11
    MOSI = PC12

    HSE = 25 MHZ
    SYSCLK = 150 MHZ

    SPI3 = APB1 = 37.5 MHZ?

    I don't know what board this is, and don't have resources to fool with. Would suggest dissecting clocks and peripheral register settings in viewer.

  • Probably a silly question but how do I do this?
    I was looking for the JTAG disable about 3 weeks ago. Could not find it in data sheet so assumed I was wrong.

  • On the F1, I used this to free SPI2 on PB13,14 and 15 while keeping SWD/SWV viable, not salient on F4

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
      /* JTAG-DP Disabled and SW-DP Enabled */
      GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
    

    On the F2/F4 GPIO_AF_SWJ and GPIO_AF_TRACE is zero, so should be able to mux off functionality

  • Thanks,
    looking at data sheet it says jtag is not for PC10,11,12 but pb3 and 4.
    Does jtag effect spi3 or the specific pins?

  • Ok, let's not get distracted by pins John selected. The PB3 pin is problematic, as are the pins I mentioned on the STM32F1.

    The pin muxing on the F2/F4 is far more flexible, the pins you mentioned should not conflict with JTAG.

  • That's what I was thinking, so I still am stuck on why I can't get the SD card to mount.

    Do we have any other ideas?

  • Ok, so if I understood correctly the same hardware configuration worked with another compiler, and using Keil and its libraries you don't see signals at the pins, and you don't have a working card. There's an interference that it works on a different SPI bus.

    I'm not yet convinced that the clocks, peripherals and pins are correctly configured, you've made declarative statements that they are correct, but you're also man-weeks into "not working". Beyond that you'd need to dig into the middleware code itself. I'm not looking to wade into this with my own resources, or build equivalent hardware, if you have code to present I'll look at that, guessing isn't my game.

  • Clock Config

    void SystemClock_Config(void)
    {
    
      RCC_OscInitTypeDef RCC_OscInitStruct;
      RCC_ClkInitTypeDef RCC_ClkInitStruct;
      RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
    
        /**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_HSE|RCC_OSCILLATORTYPE_LSE;
      RCC_OscInitStruct.HSEState = RCC_HSE_ON;
      RCC_OscInitStruct.LSEState = RCC_LSE_ON;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
      RCC_OscInitStruct.PLL.PLLM = 25;
      RCC_OscInitStruct.PLL.PLLN = 336;
      RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
      RCC_OscInitStruct.PLL.PLLQ = 7;
      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();
      }
    
      PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
      PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
      if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
      {
        Error_Handler();
      }
    
        /**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, 15, 15);
    }
    

  • SPI Config

    /* SPI3 init function */
    static void MX_SPI3_Init(void)
    {
    
      hspi3.Instance = SPI3;
      hspi3.Init.Mode = SPI_MODE_MASTER;
      hspi3.Init.Direction = SPI_DIRECTION_2LINES;
      hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
      hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
      hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
      hspi3.Init.NSS = SPI_NSS_SOFT;
      hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
      hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
      hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
      hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
      hspi3.Init.CRCPolynomial = 10;
      if (HAL_SPI_Init(&hspi3) != HAL_OK)
      {
        Error_Handler();
      }
      __SPI3_CLK_ENABLE();
    
    }
    
    

    GPIO Config

    static void MX_GPIO_Init(void)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct;
    
      /* GPIO Ports Clock Enable */
      __HAL_RCC_GPIOC_CLK_ENABLE();
      __HAL_RCC_GPIOH_CLK_ENABLE();
      __HAL_RCC_GPIOA_CLK_ENABLE();
      __HAL_RCC_GPIOB_CLK_ENABLE();
      __HAL_RCC_GPIOD_CLK_ENABLE();
    
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, GPIO_PIN_RESET);
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET);
    
      /*Configure GPIO pins : PB0 PB1 PB2 */
      GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
      /*Configure GPIO pin : PD3 */
      GPIO_InitStruct.Pin = GPIO_PIN_3;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
            GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;
            GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
            GPIO_InitStruct.Pull = GPIO_PULLUP;
            GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
            GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
      HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    }
    

  • Blink Thread - This Flashes every Second

    /* USER CODE BEGIN 4 */
    void Blink(void const *arg){
    
            while (1){
                    osDelay(1000);
                    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
                    WriteFile();
            }
    }
    

    It calls the writefile routine which should mount the card but fails.

    int32_t fs_mc_spi_control_ss (uint32_t drive_num, uint32_t ss){
            if (ss==0) {
                    HAL_GPIO_WritePin(GPIOD,GPIO_PIN_3,GPIO_PIN_SET);
                    return 1;
            }
              else {
                            HAL_GPIO_WritePin(GPIOD,GPIO_PIN_3,GPIO_PIN_RESET);
                return 0;
                    }
    }
    
    void WriteFile()
    {
            fsStatus st;
            if (finit("") == fsOK) {
            st=fmount("");
            if (st == fsOK) HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1); ;
            }
            FILE *f=fopen("try.txt","a");
                    if (f!=NULL) {
                            HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_2);
                            fprintf(f,"Test\n");
                            fclose(f);
                    }
    }
    
    

    The fs_mc_spi_control_ss function is setting the CS pin, I have tried reversing polarity.
    Also tried to lengthen the delay on the thread.

    Thanks so much for your time.

  • Enable the clock before you initialize the interface, the part is synchronous

    __SPI3_CLK_ENABLE(); // DO IT BEFORE

  • OK, I tried moving the __SPI3_CLK_ENABLE();
    Still no luck, could cry at this point :(