Skip to content

Instantly share code, notes, and snippets.

@schollz
Last active July 21, 2023 02:06
Show Gist options
  • Save schollz/67445a165b324d354f432ebab3307a2d to your computer and use it in GitHub Desktop.
Save schollz/67445a165b324d354f432ebab3307a2d to your computer and use it in GitHub Desktop.
# Set minimum required version of CMake
cmake_minimum_required(VERSION 3.12)
# Include build functions from Pico SDK
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
# Set name of project (as PROJECT_NAME) and C/C++ standards
project(sd_fat_spi C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
# Creates a pico-sdk subdirectory in our project for the libraries
pico_sdk_init()
# Tell CMake where to find the executable source file
add_executable(${PROJECT_NAME}
main.c
hw_config.c
)
# Tell CMake where to find other source code
add_subdirectory(lib/no-OS-FatFS-SD-SPI-RPi-Pico/FatFs_SPI build)
# Create map/bin/hex/uf2 files
pico_add_extra_outputs(${PROJECT_NAME})
# Link to pico_stdlib (gpio, time, etc. functions)
target_link_libraries(${PROJECT_NAME}
pico_stdlib
FatFs_SPI
)
# Enable usb output, disable uart output
pico_enable_stdio_usb(${PROJECT_NAME} 1)
pico_enable_stdio_uart(${PROJECT_NAME} 0)
pico_add_extra_outputs(${PROJECT_NAME})
/* hw_config.c
Copyright 2021 Carl John Kugler III
Licensed under the Apache License, Version 2.0 (the License); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
*/
/*
This file should be tailored to match the hardware design.
There should be one element of the spi[] array for each hardware SPI used.
There should be one element of the sd_cards[] array for each SD card slot.
The name is should correspond to the FatFs "logical drive" identifier.
(See http://elm-chan.org/fsw/ff/doc/filename.html#vol)
The rest of the constants will depend on the type of
socket, which SPI it is driven by, and how it is wired.
*/
#include <string.h>
//
#include "my_debug.h"
//
#include "hw_config.h"
//
#include "ff.h" /* Obtains integer types */
//
#include "diskio.h" /* Declarations of disk functions */
/*
This example assumes the following hardware configuration:
| | SPI0 | GPIO | Pin | SPI | MicroSD | Description | | -----
| ---- | ----- | --- | -------- | --------- | ---------------------- | |
MISO | RX | 16 | 21 | DO | DO | Master In, Slave Out |
| MOSI | TX | 19 | 25 | DI | DI | Master Out, Slave In |
| SCK | SCK | 18 | 24 | SCLK | CLK | SPI clock | | CS0 |
CSn | 17 | 22 | SS or CS | CS | Slave (or Chip) Select | | DET
| | 22 | 29 | | CD | Card Detect | | GND
| | | 18,23 | | GND | Ground | | 3v3
| | | 36 | | 3v3 | 3.3 volt power |
*/
/*
This example assumes the following hardware configuration:
| | SPI0 | GPIO | Pin | SPI | MicroSD | Description | | -----
| ---- | ----- | --- | -------- | --------- | ---------------------- | |
MISO | RX | 12 | 21 | DO | DO | Master In, Slave Out |
| MOSI | TX | 15 | 25 | DI | DI | Master Out, Slave In |
| SCK | SCK | 14 | 24 | SCLK | CLK | SPI clock | | CS0 |
CSn | 13 | 22 | SS or CS | CS | Slave (or Chip) Select | | DET
| | 22 | 29 | | CD | Card Detect | | GND
| | | 18,23 | | GND | Ground | | 3v3
| | | 36 | | 3v3 | 3.3 volt power |
*/
// Hardware Configuration of SPI "objects"
// Note: multiple SD cards can be driven by one SPI if they use different slave
// selects.
static spi_t spis[] = { // One for each SPI.
{
.hw_inst = spi1, // SPI component
.miso_gpio = 12, // GPIO number (not Pico pin number)
.mosi_gpio = 15,
.sck_gpio = 14,
.baud_rate = 1000 * 1000
// .baud_rate = 12500 * 1000
// .baud_rate = 25 * 1000 * 1000 // Actual frequency: 20833333.
}};
// Hardware Configuration of the SD Card "objects"
static sd_card_t sd_cards[] = { // One for each SD card
{
.pcName = "0:", // Name used to mount device
.spi = &spis[0], // Pointer to the SPI driving this card
.ss_gpio = 13, // The SPI slave select GPIO for this SD card
.use_card_detect = false,
.card_detect_gpio = 10, // Card detect
.card_detected_true = 0 // What the GPIO read returns when a card is
// present.
}};
/* ********************************************************************** */
size_t sd_get_num() { return count_of(sd_cards); }
sd_card_t *sd_get_by_num(size_t num) {
if (num <= sd_get_num()) {
return &sd_cards[num];
} else {
return NULL;
}
}
size_t spi_get_num() { return count_of(spis); }
spi_t *spi_get_by_num(size_t num) {
if (num <= spi_get_num()) {
return &spis[num];
} else {
return NULL;
}
}
/* [] END OF FILE */
#include <stdio.h>
#include <time.h>
#include "ff.h"
#include "pico/stdlib.h"
#include "sd_card.h"
clock_t clock() { return (clock_t)time_us_64() / 10000; }
void doSomething(int seconds) { sleep_ms(seconds * 1000); }
int main() {
FRESULT fr;
FATFS fs;
FIL fil;
int ret;
char buf[100];
char filename[] = "hello.txt";
char buf2[100];
char filename2[] = "3.raw";
// Initialize chosen serial port
stdio_init_all();
// Wait for user to press 'enter' to continue
printf("\r\nSD card test. Press 'enter' to start.\r\n");
while (true) {
buf[0] = getchar();
if ((buf[0] == '\r') || (buf[0] == '\n')) {
break;
}
}
// Initialize SD card
if (!sd_init_driver()) {
printf("ERROR: Could not initialize SD card\r\n");
while (true)
;
}
// Mount drive
fr = f_mount(&fs, "0:", 1);
if (fr != FR_OK) {
printf("ERROR: Could not mount filesystem (%d)\r\n", fr);
while (true)
;
}
FILINFO fno;
f_stat(filename, &fno);
printf("%s: fsize: %d\n", filename, fno.fsize);
// Open file for writing ()
fr = f_open(&fil, filename, FA_WRITE | FA_CREATE_ALWAYS);
if (fr != FR_OK) {
printf("ERROR: Could not open file (%d)\r\n", fr);
while (true)
;
}
// Write something to file
ret = f_printf(&fil, "This is another test\r\n");
if (ret < 0) {
printf("ERROR: Could not write to file (%d)\r\n", ret);
f_close(&fil);
while (true)
;
}
ret = f_printf(&fil, "of writing to an SD card.\r\n");
if (ret < 0) {
printf("ERROR: Could not write to file (%d)\r\n", ret);
f_close(&fil);
while (true)
;
}
// Close file
fr = f_close(&fil);
if (fr != FR_OK) {
printf("ERROR: Could not close file (%d)\r\n", fr);
while (true)
;
}
// Open file for reading
fr = f_open(&fil, filename, FA_READ);
if (fr != FR_OK) {
printf("ERROR: Could not open file (%d)\r\n", fr);
while (true)
;
}
// Print every line in file over serial
printf("Reading from file '%s':\r\n", filename);
printf("---\r\n");
while (f_gets(buf, sizeof(buf), &fil)) {
printf(buf);
}
printf("\r\n---\r\n");
printf("\n\nReading from file '%s':\r\n", filename);
f_lseek(&fil, 3);
while (f_gets(buf, sizeof(buf), &fil)) {
printf(buf);
}
// Close file
fr = f_close(&fil);
if (fr != FR_OK) {
printf("ERROR: Could not close file (%d)\r\n", fr);
while (true)
;
}
// read 3.raw
f_stat(filename2, &fno);
printf("%s: fsize: %d\n", filename2, fno.fsize);
// Open file for reading
fr = f_open(&fil, filename2, FA_READ);
if (fr != FR_OK) {
printf("ERROR: Could not open file (%d)\r\n", fr);
while (true)
;
}
printf("\n\nReading from file '%s':\r\n", filename2);
int16_t count = 0;
while (f_gets(buf2, sizeof(buf2), &fil)) {
count += 32;
}
printf("read: %d bytes\n", count);
printf("\n\nReading 32 bytes from file '%s':\r\n", filename2);
count = 0;
f_lseek(&fil, 0);
while (f_gets(buf2, sizeof(buf2), &fil)) {
for (int8_t i = 0; i < sizeof(buf2); i++) {
printf("%x\n", buf2[i]);
count++;
if (count == 32) {
break;
}
}
if (count == 32) {
break;
}
}
// Close file
fr = f_close(&fil);
if (fr != FR_OK) {
printf("ERROR: Could not close file (%d)\r\n", fr);
while (true)
;
}
// // Unmount drive
// f_unmount("0:");
// Loop forever doing nothing
while (true) {
sleep_ms(1000);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment