Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic configuration #12

Merged
merged 10 commits into from
Sep 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion FatFs_SPI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ target_sources(FatFs_SPI INTERFACE
${CMAKE_CURRENT_LIST_DIR}/ff14a/source/ff.c
${CMAKE_CURRENT_LIST_DIR}/sd_driver/sd_spi.c
${CMAKE_CURRENT_LIST_DIR}/sd_driver/demo_logging.c
${CMAKE_CURRENT_LIST_DIR}/sd_driver/hw_config.c
# ${CMAKE_CURRENT_LIST_DIR}/sd_driver/hw_config.c
${CMAKE_CURRENT_LIST_DIR}/sd_driver/spi.c
${CMAKE_CURRENT_LIST_DIR}/sd_driver/sd_card.c
${CMAKE_CURRENT_LIST_DIR}/sd_driver/crc.c
Expand Down
6 changes: 1 addition & 5 deletions FatFs_SPI/ff14a/source/ffconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,7 @@
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/

#if defined N_SD_CARDS
# define FF_VOLUMES N_SD_CARDS
#else
# define FF_VOLUMES 1
#endif
# define FF_VOLUMES 2
/* Number of volumes (logical drives) to be used. (1-10) */


Expand Down
11 changes: 5 additions & 6 deletions FatFs_SPI/sd_driver/hw_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
extern "C" {
#endif

size_t const sd_get_num();
sd_card_t *const sd_get_by_num(size_t num);
sd_card_t *const sd_get_by_name(const char *const name);
size_t const spi_get_num();
spi_t *const spi_get_by_num(size_t num);
FATFS *const get_fs_by_name(const char *name);
size_t sd_get_num();
sd_card_t *sd_get_by_num(size_t num);

size_t spi_get_num();
spi_t *spi_get_by_num(size_t num);

#ifdef __cplusplus
}
Expand Down
6 changes: 3 additions & 3 deletions FatFs_SPI/sd_driver/sd_card.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ bool sd_card_detect(sd_card_t *pSD) {
// The socket is now empty
pSD->m_Status |= (STA_NODISK | STA_NOINIT);
pSD->card_type = SDCARD_NONE;
TRACE_PRINTF("No SD card detected!\n");
printf("No SD card detected!\n");
return false;
}
}
Expand Down Expand Up @@ -1122,8 +1122,8 @@ bool sd_init_driver() {
gpio_put(pSD->ss_gpio, 1); // In case set_dir does anything
}
for (size_t i = 0; i < spi_get_num(); ++i) {
spi_t *pSD = spi_get_by_num(i);
if (!my_spi_init(pSD)) return false;
spi_t *pSPI = spi_get_by_num(i);
if (!my_spi_init(pSPI)) return false;
}
return true;
}
Expand Down
10 changes: 7 additions & 3 deletions FatFs_SPI/sd_driver/sd_card.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
* ========================================
*/

// Note: The model used here is one FatFS per SD card.
// Multiple partitions on a card are not supported.

#ifndef _SD_CARD_H_
#define _SD_CARD_H_

Expand All @@ -28,11 +31,12 @@ extern "C" {
// "Class" representing SD Cards
typedef struct {
const char *pcName;
spi_t *const spi;
spi_t *spi;
// Slave select is here in sd_card_t because multiple SDs can share an SPI
uint ss_gpio; // Slave select for this SD card
const uint card_detect_gpio; // Card detect
const uint card_detected_true; // Varies with card socket
uint card_detect_gpio; // Card detect
uint card_detected_true; // Varies with card socket
// Following fields are used to keep track of the state of the card:
int m_Status; // Card status
uint64_t sectors; // Assigned dynamically
int card_type; // Assigned dynamically
Expand Down
24 changes: 14 additions & 10 deletions FatFs_SPI/sd_driver/sd_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,16 @@ void sd_spi_go_low_frequency(sd_card_t *this) {
}

// Would do nothing if this->ss_gpio were set to GPIO_FUNC_SPI.
void sd_spi_select(sd_card_t *this) {
uint8_t fill = SPI_FILL_CHAR;
spi_write_blocking(this->spi->hw_inst, &fill, 1);
// asm volatile("nop \n nop \n nop"); // FIXME
static void sd_spi_select(sd_card_t *this) {
gpio_put(this->ss_gpio, 0);
//asm volatile("nop \n nop \n nop"); // FIXME
// A fill byte seems to be necessary, sometimes:
uint8_t fill = SPI_FILL_CHAR;
spi_write_blocking(this->spi->hw_inst, &fill, 1);
LED_ON();
}

void sd_spi_deselect(sd_card_t *this) {
uint8_t fill = SPI_FILL_CHAR;
spi_write_blocking(this->spi->hw_inst, &fill, 1);
// asm volatile("nop \n nop \n nop"); // FIXME
static void sd_spi_deselect(sd_card_t *this) {
gpio_put(this->ss_gpio, 1);
//asm volatile("nop \n nop \n nop"); // FIXME
LED_OFF();
/*
MMC/SDC enables/disables the DO output in synchronising to the SCLK. This
Expand All @@ -56,6 +50,7 @@ void sd_spi_deselect(sd_card_t *this) {
line, the master device needs to send a byte after the CS signal is
deasserted.
*/
uint8_t fill = SPI_FILL_CHAR;
spi_write_blocking(this->spi->hw_inst, &fill, 1);
}

Expand All @@ -75,11 +70,20 @@ uint8_t sd_spi_write(sd_card_t *this, const uint8_t value) {
return received;
}

//uint8_t sd_spi_write(sd_card_t *this, const uint8_t value) {
// // TRACE_PRINTF("%s\n", __FUNCTION__);
// u_int8_t received = SPI_FILL_CHAR;
// bool success = spi_transfer(this->spi, &value, &received, 1);
// myASSERT(success);
// return received;
//}

bool sd_spi_transfer(sd_card_t *this, const uint8_t *tx, uint8_t *rx,
size_t length) {
return spi_transfer(this->spi, tx, rx, length);
}


void sd_spi_init_pl022(sd_card_t *this) {
// Let the PL022 SPI handle it.
// the CS line is brought high between each byte during transmission.
Expand Down
4 changes: 0 additions & 4 deletions FatFs_SPI/sd_driver/sd_spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@

bool sd_spi_transfer(sd_card_t *this, const uint8_t *tx, uint8_t *rx, size_t length);
uint8_t sd_spi_write(sd_card_t *this, const uint8_t value);
void sd_spi_select(sd_card_t *this);
void sd_spi_deselect(sd_card_t *this);
void sd_spi_acquire(sd_card_t *this);
void sd_spi_release(sd_card_t *this);
//void sd_spi_select(sd_card_t *this);
//void sd_spi_deselect(sd_card_t *this);
void sd_spi_go_low_frequency(sd_card_t *this);
void sd_spi_go_high_frequency(sd_card_t *this);
bool sd_spi_init(sd_card_t *this);
Expand Down
19 changes: 10 additions & 9 deletions FatFs_SPI/sd_driver/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ void spi_irq_handler(spi_t *pSPI) {
// If the data that will be transmitted is not important,
// pass NULL as tx and then the SPI_FILL_CHAR is sent out as each data
// element.

bool spi_transfer(spi_t *pSPI, const uint8_t *tx, uint8_t *rx, size_t length) {
myASSERT(512 == length);
myASSERT(512 == length || 1 == length);
myASSERT(tx || rx);
// myASSERT(!(tx && rx));

Expand All @@ -45,6 +44,7 @@ bool spi_transfer(spi_t *pSPI, const uint8_t *tx, uint8_t *rx, size_t length) {
tx = &dummy;
channel_config_set_read_increment(&pSPI->tx_dma_cfg, false);
}

// rx read increment is already false
if (rx) {
channel_config_set_write_increment(&pSPI->rx_dma_cfg, true);
Expand All @@ -59,15 +59,15 @@ bool spi_transfer(spi_t *pSPI, const uint8_t *tx, uint8_t *rx, size_t length) {
dma_channel_configure(pSPI->tx_dma, &pSPI->tx_dma_cfg,
&spi_get_hw(pSPI->hw_inst)->dr, // write address
tx, // read address
XFER_BLOCK_SIZE, // element count (each element is of
// size transfer_data_size)
false); // start
length, // element count (each element is of
// size transfer_data_size)
false); // start
dma_channel_configure(pSPI->rx_dma, &pSPI->rx_dma_cfg,
rx, // write address
&spi_get_hw(pSPI->hw_inst)->dr, // read address
XFER_BLOCK_SIZE, // element count (each element is of
// size transfer_data_size)
false); // start
length, // element count (each element is of
// size transfer_data_size)
false); // start

// start them exactly simultaneously to avoid races (in extreme cases
// the FIFO could overflow)
Expand All @@ -76,7 +76,8 @@ bool spi_transfer(spi_t *pSPI, const uint8_t *tx, uint8_t *rx, size_t length) {
/* Timeout 1 sec */
uint32_t timeOut = 1000;
/* Wait until master completes transfer or time out has occured. */
bool rc = sem_acquire_timeout_ms(&pSPI->sem, timeOut); // Wait for notification from ISR
bool rc = sem_acquire_timeout_ms(
&pSPI->sem, timeOut); // Wait for notification from ISR
if (!rc) {
// If the timeout is reached the function will return false
DBG_PRINTF("Notification wait timed out in %s\n", __FUNCTION__);
Expand Down
10 changes: 5 additions & 5 deletions FatFs_SPI/sd_driver/spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@
#include "pico/sem.h"

#define SPI_FILL_CHAR (0xFF)
#define XFER_BLOCK_SIZE 512 // Block size supported for SD card is 512 bytes
//#define XFER_BLOCK_SIZE 512 // Block size supported for SD card is 512 bytes

// "Class" representing SPIs
typedef struct {
// SPI HW
spi_inst_t *hw_inst;
const uint miso_gpio; // SPI MISO GPIO number (not pin number)
const uint mosi_gpio;
const uint sck_gpio;
const uint baud_rate;
uint miso_gpio; // SPI MISO GPIO number (not pin number)
uint mosi_gpio;
uint sck_gpio;
uint baud_rate;
// State variables:
uint tx_dma;
uint rx_dma;
Expand Down
31 changes: 16 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ On a SanDisk Class 4 16 GB card, I have been able to push the SPI baud rate as f

![image](https://github.com/carlk3/FreeRTOS-FAT-CLI-for-RPi-Pico/blob/master/images/IMG_1478.JPG "Prototype")

![image](https://www.raspberrypi.org/documentation/rp2040/getting-started/static/64b50c4316a7aefef66290dcdecda8be/Pico-R3-SDK11-Pinout.svg "Pinout")
![image](https://www.raspberrypi.org/documentation/microcontrollers/images/Pico-R3-SDK11-Pinout.svg "Pinout")

| | SPI0 | GPIO | Pin | SPI | MicroSD 0 | Description |
| ----- | ---- | ----- | --- | -------- | --------- | ---------------------- |
Expand All @@ -70,7 +70,7 @@ Even if it is provided by the hardware, you might not care about it if you inten

### Pull Up Resistors
* The SPI MISO (**DO** on SD card, **SPI**x **RX** on Pico) is open collector (or tristate). It should be pulled up. The Pico internal gpio_pull_up is weak: around 56uA or 60kΩ. It's best to add an external pull up resistor of around 5kΩ to 3.3v. You might get away without one if you only run one SD card and don't push the SPI baud rate too high.
* The SPI Slave Select (SS), or Chip Select (CS) line enables one SPI slave of possibly multiple slaves on the bus. This is what enables the tristate buffer for Data Out (DO), among other things. It's best to pull CS up so that it doesn't float before the Pico GPIO is initialized. It is imperative to pull it up for any devices on the bus that aren't initialized. For example, if you have two SD cards on one bus but the firmware is aware of only one card (see hw_config.c); you can't let the CS float on the unused one.
* The SPI Slave Select (SS), or Chip Select (CS) line enables one SPI slave of possibly multiple slaves on the bus. This is what enables the tristate buffer for Data Out (DO), among other things. It's best to pull CS up so that it doesn't float before the Pico GPIO is initialized. It is imperative to pull it up for any devices on the bus that aren't initialized. For example, if you have two SD cards on one bus but the firmware is aware of only one card (see hw_config); you can't let the CS float on the unused one.

## Notes about prewired boards with SD card sockets:
* I don't think the [Pimoroni Pico VGA Demo Base](https://shop.pimoroni.com/products/pimoroni-pico-vga-demo-base) can work with a built in RP2040 SPI controller. It looks like RP20040 SPI0 SCK needs to be on GPIO 2, 6, or 18 (pin 4, 9, or 24, respectively), but Pimoroni wired it to GPIO 5 (pin 7).
Expand All @@ -82,7 +82,8 @@ Even if it is provided by the hardware, you might not care about it if you inten
* Install source code:
`git clone --recurse-submodules git@github.com:carlk3/no-OS-FatFS-SD-SPI-RPi-Pico.git no-OS-FatFS`
* Customize:
* Tailor `sd_driver/hw_config.c` to match hardware
* Configure the code to match the hardware: You must provide a definition for the functions declared in `sd_driver/hw_config.h`.
See `simple_example.dir/hw_config.c`, `example/hw_config.c` or `dynamic_config_example/hw_config.cpp` for examples.
* Customize `ff14a/source/ffconf.h` as desired
* Customize `pico_enable_stdio_uart` and `pico_enable_stdio_usb` in CMakeLists.txt as you prefer.
(See *4.1. Serial input and output on Raspberry Pi Pico* in [Getting started with Raspberry Pi Pico](https://datasheets.raspberrypi.org/pico/getting-started-with-pico.pdf) and *2.7.1. Standard Input/Output (stdio) Support* in [Raspberry Pi Pico C/C++ SDK](https://datasheets.raspberrypi.org/pico/raspberry-pi-pico-c-sdk.pdf).)
Expand Down Expand Up @@ -229,18 +230,18 @@ When you're dealing with information storage, it's always nice to have redundanc

To add a second SD card on the same SPI, connect it in parallel, except that it will need a unique GPIO for the Card Select/Slave Select (CSn) and another for Card Detect (CD) (optional).

Name|SPI0|GPIO|Pin |SPI|MicroSD 0|MicroSD 1
----|----|----|----|---|---------|---------
CD1||14|19|||CD
CS1||15|20|SS or CS||CS
MISO|RX|16|21|DO|DO|DO
CS0||17|22|SS or CS|CS|CS
SCK|SCK|18|24|SCLK|SCK|SCK
MOSI|TX|19|25|DI|DI|DI
CD0||22|29||CD|
||||||
GND|||18, 23||GND|GND
3v3|||36||3v3|3v3
Name|SPI0|GPIO|Pin |SPI|SDIO|MicroSD 0|MicroSD 1
----|----|----|----|---|----|---------|---------
CD1||14|19||||CD
CS1||15|20|SS or CS|DAT3||CS
MISO|RX|16|21|DO|DAT0|DO|DO
CS0||17|22|SS or CS|DAT3|CS|
SCK|SCK|18|24|SCLK|CLK|SCK|SCK
MOSI|TX|19|25|DI|CMD|DI|DI
CD0||22|29|||CD|
|||||||
GND|||18, 23|||GND|GND
3v3|||36|||3v3|3v3

### Wiring:
As you can see from the table above, the only new signals are CD1 and CS1. Otherwise, the new card is wired in parallel with the first card.
Expand Down
44 changes: 44 additions & 0 deletions dynamic_config_example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Generated Cmake Pico project file

cmake_minimum_required(VERSION 3.13)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

# initalize pico_sdk from installed location
# (note this can come from environment, CMake cache etc)
#set(PICO_SDK_PATH "/home/carlk/pi/pico/pico-sdk")

# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)

project(dynamic_config_example C CXX ASM)

# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()

add_subdirectory(../FatFs_SPI build)

# Add executable. Default name is the project name, version 0.1
add_executable(dynamic_config_example
dynamic_config_example.cpp
hw_config.cpp
)

pico_set_program_name(dynamic_config_example "dynamic_config_example")
pico_set_program_version(dynamic_config_example "0.1")

# Choose source and destination for standard input and output:
# See 4.1. Serial input and output on Raspberry Pi Pico in Getting started with Raspberry Pi Pico (https://datasheets.raspberrypi.org/pico/getting-started-with-pico.pdf)
# and 2.7.1. Standard Input/Output (stdio) Support in Raspberry Pi Pico C/C++ SDK (https://datasheets.raspberrypi.org/pico/raspberry-pi-pico-c-sdk.pdf):
pico_enable_stdio_uart(dynamic_config_example 1)
pico_enable_stdio_usb(dynamic_config_example 1)

# Add the standard library and FatFS/SPI to the build
target_link_libraries(dynamic_config_example
pico_stdlib
FatFs_SPI
)

pico_add_extra_outputs(dynamic_config_example)

Loading