STM32L452 SPI2 port assignation not working

Home Forums STM32 STM32L452 SPI2 port assignation not working

Viewing 5 reply threads
  • Author
    Posts
    • #27967
      Nezha
      Participant

        Hello,

        I’m trying to connect my STM32L452 chip to an SD Card for logging purpose but it doesn’t seem to work using port assignation delivered by STM32duino.
        I tried using STM32Cube libraries and it’s working, so the problem is not on my PCB but really the SdFat and/or STM32duino and the way I’m initializing things.

        I tried to use the code example you provided in here which is shown bellow with the only modification being the SPI port values. I wonder if only STM32F1 and F4 are supported and is there a way to make it work for L4 boards.

        /*
          SD card test for stm32 and SdFat library
         
          This example shows how use the utility libraries
         
            SD card attached to the secondary SPI as follows:
                SS    = PB2;
                MOSI  = PC3;
                MISO  = PC2;
                SCK   = PB10;
         
           by Mischianti Renzo <https://mischianti.org>
          
           https://www.mischianti.org
        */
        #include <SPI.h>
        #include "SdFat.h"
         
        SdFat SD;
        
        // Define your pin configuration for SPI2
        const int spi2ClockPin = PB10;    // SCK (Serial Clock)
        const int spi2MisoPin = PC2;     // MISO (Master In Slave Out)
        const int spi2MosiPin = PC3;     // MOSI (Master Out Slave In)
        const int spi2chipSelectPin = PB2;  // CS (Chip Select)
         
        #define SD2_CONFIG SdSpiConfig(spi2chipSelectPin, USER_SPI_BEGIN,SD_SCK_MHZ (10))
        
        void printDirectory(File dir, int numTabs);
         
        void setup() {
          // Open serial communications and wait for port to open:
          Serial.begin(9600);
          while (!Serial) {
            ; // wait for serial port to connect. Needed for native USB port only
          }
        
          SPIClass SPI_2(spi2MosiPin, spi2MisoPin, spi2ClockPin);
          SPI_2.begin(spi2chipSelectPin);
        
         // SPI_2.setFrequency(1000000);
          Serial.print("\nInitializing SD card...");
         
          // we'll use the initialization code from the utility libraries
          // since we're just testing if the card is working!
          if (!SD.begin(SD2_CONFIG)) {
          // if (!SD.begin(SD_CS_PIN)) {
            Serial.println("initialization failed. Things to check:");
            Serial.println("* is a card inserted?");
            Serial.println("* is your wiring correct?");
            Serial.println("* did you change the chipSelect pin to match your shield or module?");
            while (1);
          } else {
            Serial.println("Wiring is correct and a card is present.");
          }
         
          uint32_t cardSize = SD.card()->sectorCount();
         
          // print the type of card
          Serial.println();
          Serial.print("Card type:         ");
          switch (SD.card()->type()) {
          case SD_CARD_TYPE_SD1:
            Serial.println(F("SD1"));
            break;
          case SD_CARD_TYPE_SD2:
            Serial.println(F("SD2"));
            break;
         
          case SD_CARD_TYPE_SDHC:
            if (cardSize < 70000000) {
              Serial.println(F("SDHC"));
            } else {
              Serial.println(F("SDXC"));
            }
            break;
         
          default:
            Serial.println(F("Unknown"));
          }
         
         
        //  print the type and size of the first FAT-type volume
          uint32_t volumesize;
          Serial.print("Volume type is:    FAT");
          Serial.println(int(SD.vol()->fatType()), DEC);
         
          Serial.print("Card size:  ");
          Serial.println((float) 0.000512*cardSize);
         
          Serial.print("Total bytes: ");
          Serial.println(0.000512*SD.vol()->clusterCount()*SD.sectorsPerCluster());
         
          Serial.print("Free bytes: ");
          Serial.println(0.000512*SD.vol()->freeClusterCount()*SD.sectorsPerCluster());
         
          File dir =  SD.open("/");
          printDirectory(dir, 0);
         
        }
         
        void loop(void) {
        }
         
        void printDirectory(File dir, int numTabs) {
          while (true) {
         
            File entry =  dir.openNextFile();
            if (! entry) {
              // no more files
              break;
            }
            for (uint8_t i = 0; i < numTabs; i++) {
              Serial.print('\t');
            }
            entry.printName(&Serial);
         
            if (entry.isDirectory()) {
              Serial.println("/");
              printDirectory(entry, numTabs + 1);
            } else {
              // files have sizes, directories do not
              Serial.print("\t\t");
              Serial.print(entry.size(), DEC);
              uint16_t pdate;
              uint16_t ptime;
              entry.getModifyDateTime(&pdate, &ptime);
         
              Serial.printf("\tLAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", FS_YEAR(pdate), FS_MONTH(pdate), FS_DAY(pdate), FS_HOUR(ptime), FS_MINUTE(ptime), FS_SECOND(ptime));
            }
            entry.close();
          }
        }
        
        #ifdef __cplusplus
        extern "C" {
        #endif
          /**
          * @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
          */
            if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) {
              Error_Handler();
            }
        
            /** Initializes the RCC Oscillators according to the specified parameters
          * in the RCC_OscInitTypeDef structure.
          */
            RCC_OscInitStruct.OscillatorType      = RCC_OSCILLATORTYPE_HSI;
            RCC_OscInitStruct.HSIState            = RCC_HSI_ON;
            RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
            RCC_OscInitStruct.PLL.PLLState        = RCC_PLL_NONE;
            if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
              Error_Handler();
            }
        
            /** Initializes the CPU, AHB and APB buses clocks
          */
            RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                          | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
            RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_HSI;
            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_0) != HAL_OK) {
              Error_Handler();
            }
          }
        
        #ifdef __cplusplus
        }
        #endif
      • #27975
        Renzo Mischianti
        Keymaster

          Hi Nezha,
          I write a little article about that and when I do the test, I follow the pinout I retrieve from the STMicroelectronic core code.

          I check your pin selection, and it seems to be ok.

          
          #ifdef HAL_SPI_MODULE_ENABLED
          WEAK const PinMap PinMap_SPI_MOSI[] = {
            {PA_7,      SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
            {PA_12,     SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
            {PB_5,      SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
            {PB_5_ALT1, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
            {PB_15,     SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
            {PC_3,      SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
            {PC_12,     SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
            {NC,        NP,   0}
          };
          #endif
          
          #ifdef HAL_SPI_MODULE_ENABLED
          WEAK const PinMap PinMap_SPI_MISO[] = {
            {PA_6,      SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
            {PA_11,     SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
            {PB_4,      SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
            {PB_4_ALT1, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
            {PB_14,     SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
            {PC_2,      SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
            {PC_11,     SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
            {NC,        NP,   0}
          };
          #endif
          
          #ifdef HAL_SPI_MODULE_ENABLED
          WEAK const PinMap PinMap_SPI_SCLK[] = {
            {PA_1,      SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
            {PA_5,      SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
            {PB_3,      SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
            {PB_3_ALT1, SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
            {PB_10,     SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
            {PB_13,     SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)},
            {PC_10,     SPI3, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_SPI3)},
            {NC,        NP,   0}
          };
          #endif
          

          The SS isn’t so important but if you can try the default also

          
          // SPI definitions
          #ifndef PIN_SPI_SS
            #define PIN_SPI_SS            PA4
          #endif
          #ifndef PIN_SPI_SS1
            #define PIN_SPI_SS1           PA15
          #endif
          #ifndef PIN_SPI_SS2
            #define PIN_SPI_SS2           PB0
          #endif
          #ifndef PIN_SPI_SS3
            #define PIN_SPI_SS3           PNUM_NOT_DEFINED
          #endif
          #ifndef PIN_SPI_MOSI
            #define PIN_SPI_MOSI          PA7
          #endif
          #ifndef PIN_SPI_MISO
            #define PIN_SPI_MISO          PA6
          #endif
          #ifndef PIN_SPI_SCK
            #define PIN_SPI_SCK           PA1
          #endif
          

          In the code, you begin two times the spi interface, and I think It can generate some problems.
          Try to use a configuration declaration like this

          
          //    SD card attached to the secondary SPI as follows:
          //        SS    = PB2;
          //        MOSI  = PC3;
          //        MISO  = PB15;
          //        SCK   = PB10;
          
          #define SD_CS_PIN PB12
          static SPIClass mySPI2(PC2, PC3, PB10, SD_CS_PIN);
          #define SD2_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(18), &mySPI2)
          

          then only one begin.

          
            // we'll use the initialization code from the utility libraries
            // since we're just testing if the card is working!
            if (!SD.begin(SD2_CONFIG)) {
            // if (!SD.begin(SD_CS_PIN)) {
              Serial.println("initialization failed. Things to check:");
              Serial.println("* is a card inserted?");
              Serial.println("* is your wiring correct?");
              Serial.println("* did you change the chipSelect pin to match your shield or module?");
              while (1);
            } else {
              Serial.println("Wiring is correct and a card is present.");
            }
          
          

          But check the STM32duino core can change the pin.

          Try to use also the example I wrote and tested for the Arduino environment.

          How to use SD card with stm32 and SdFat library

          Bye Renzo

        • #27976
          Nezha
          Participant

            Hello Renzo,

            Thank you for your response! I actually tried your example but it did not work that’s why I posted in the forum. I don’t think I tried to start it twice. Here’s a code that I did for SPI1 port of my PCB and it works well.

            void setup() {
              Serial.begin(9600);
            
              ///////////////////////////////////////////////
              //        RADIO SETUP
              ///////////////////////////////////////////////
            
              SPIClass SPI_1(SPI1_MOSI, SPI1_MISO, SPI1_SCK);
              SPI_1.begin(SPI1_CS);
              // initialize SX1262 with default settings
            
              Serial.print(F("[SX1262] Initializing ... "));

            I also tried the QuickStart example and it worked by hardcoding the default SPI values.

            I did also change

            #define SPI_DRIVER_SELECT 1
            #define USE_SPI_ARRAY_TRANSFER 4

            And then -see attachment- I kind of also forced the default SPI pins to be SPI2 ports: (CS = PB2, MOSI = PC3, MISO = PC2, SCK = PB10)
            Where in the code could I hard code the pins it’s taking without compromising SPI1 port? Because I cannot just do it this way since I’m also using SPI1 for other purposes.

            For references you can see the second attachment that shows the output of the quickstart test which shows that the lib was able to connect with the SD CARD on SPI2.

            I wonder why would it work when I hardcode the SPI values, but not when I assign custom ones..

            I tried what you suggested and also this way to no luck:

            #define SD_CS_PIN PB2
              static SPIClass mySPI2(PC3, PC2, PB10);
              mySPI2.begin(SD_CS_PIN);
              #define SD2_CONFIG SdSpiConfig(SD_CS_PIN, USER_SPI_BEGIN, SD_SCK_MHZ(100), &mySPI2)
            
              if (!sd.begin(SD2_CONFIG)) {

            I wonder if the bug is on sd.begin() side.

            • This reply was modified 1 year, 11 months ago by Nezha.
          • #28008
            Renzo Mischianti
            Keymaster

              Hi Nezha,
              your problem. It’s very strange.
              I think you can try to use a “first choice” SPI2 and “second choice” in coherence, like so:

              PB15
              PB14
              PB10

              and

              PC3
              PC2
              PB13

              After that test, you can try the official STMicroelectronics core to check if STM32duino.

              Bye Renzo

            • #28045
              Nezha
              Participant

                Hello Renzo,

                Thank you for your time. So I finally made it work. For some reason, it takes different tries to make the initialization happen.
                If I power cycle, I need to reset the board and unmount/remount the card so the initialization would work.

                All this to say this is working on a STM32L4 !

                You can check the issue I posted on SdFat github repo.
                https://github.com/greiman/SdFat/issues/447

              • #28048
                Renzo Mischianti
                Keymaster

                  Hi Nezha,
                  thanks for your feedback, not all makers work with STM32, if you’d like to share your projects we are happy to publish Them.
                  Bye Renzo

              Viewing 5 reply threads
              • You must be logged in to reply to this topic.
              Exit mobile version