SdFat: STM32L452 SPI2 port assignation not working
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 in here which is shown bellow.
Another thing is I went to find STM32Test.ino and it is mentioned that there is a V2 of the example but I can’t find it.
I wonder if I missed something.
/*
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
About this issue
- Original URL
- State: open
- Created 8 months ago
- Comments: 17 (10 by maintainers)
Yes the instance of the SPI class must be global or in memory that is not destroyed when it goes out of scope. SdFat only gets a pointer to the SPI instance.
When SPI_2 went out of scope it’s destructor was called and SdFat had a pointer to a section of recycled stack.
If the card is powered on and gets noise on clock with CS high, A card can go into SDIO mode. After that the only way to get it to SPI mode is power cycle.
The Arduino Due can even corrupt a card when you upload a program.