new: sdcard agnostic middleware layer + audio read benchmark

This commit is contained in:
Anthony Rabine 2023-07-24 15:55:03 +02:00
parent 89fa2f9466
commit 51b202abfb
15 changed files with 366 additions and 356 deletions

View file

@ -34,6 +34,8 @@
"config.h": "c",
"rp2040.h": "c",
"numbers": "c",
"systick.h": "c"
"systick.h": "c",
"critical_section.h": "c",
"serializers.h": "c"
}
}

View file

@ -35,6 +35,7 @@ set(OST_SRCS
system/debug.c
system/picture.c
system/filesystem.c
system/sdcard.c
system/qor.c
system/qor_armv6m.s
system/audio_player.c

View file

@ -17,7 +17,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(PICO_SRCS
${CMAKE_CURRENT_LIST_DIR}/pico_hal_wrapper.c
${CMAKE_CURRENT_LIST_DIR}/pico_lcd_spi.c
${CMAKE_CURRENT_LIST_DIR}/pico_sdcard_spi.c
${CMAKE_CURRENT_LIST_DIR}/pico_i2s.c
)

View file

@ -19,7 +19,6 @@
// Local
#include "pico_lcd_spi.h"
#include "pico_sdcard_spi.h"
#include "audio_player.h"
#include "pico_i2s.h"
@ -61,8 +60,10 @@ const uint8_t ROTARY_A = 6;
const uint8_t ROTARY_B = 7;
const uint8_t ROTARY_BUTTON = 3;
#define SDCARD_SCK 18
#define SDCARD_MOSI 19
#define SDCARD_MISO 16
const uint8_t SD_CARD_CS = 17;
const uint8_t SD_CARD_PRESENCE = 24;
static bool sys_timer_callback(struct repeating_timer *t)
@ -144,14 +145,20 @@ void ost_system_initialize()
gpio_set_irq_enabled_with_callback(ROTARY_BUTTON, GPIO_IRQ_EDGE_FALL, true, &gpio_callback);
//------------------- Init SDCARD
// gpio_init(SD_CARD_CS);
// gpio_put(SD_CARD_CS, 1);
// gpio_set_dir(SD_CARD_CS, GPIO_OUT);
gpio_init(SD_CARD_CS);
gpio_put(SD_CARD_CS, 1);
gpio_set_dir(SD_CARD_CS, GPIO_OUT);
// gpio_init(SD_CARD_PRESENCE);
// gpio_set_dir(SD_CARD_PRESENCE, GPIO_IN);
gpio_init(SD_CARD_PRESENCE);
gpio_set_dir(SD_CARD_PRESENCE, GPIO_IN);
// pico_sdcard_spi_init(1000000);
spi_init(spi0, 1000 * 1000); // slow clock
spi_set_format(spi0, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
gpio_set_function(SDCARD_SCK, GPIO_FUNC_SPI);
gpio_set_function(SDCARD_MOSI, GPIO_FUNC_SPI);
gpio_set_function(SDCARD_MISO, GPIO_FUNC_SPI);
//------------------- Init Sound
static const audio_i2s_config_t config = {
@ -164,8 +171,6 @@ void ost_system_initialize()
// pico_i2s_setup(&config);
init_spi();
audio_init(&audio_ctx);
//------------------- System timer (1ms)
@ -217,15 +222,14 @@ void ost_hal_gpio_set(ost_hal_gpio_t gpio, int value)
// ----------------------------------------------------------------------------
// SDCARD HAL
// ----------------------------------------------------------------------------
void sdcard_set_slow_clock()
void ost_hal_sdcard_set_slow_clock()
{
// spi_init(100000, 0);
spi_set_baudrate(spi0, 10000);
}
void sdcard_set_fast_clock()
void ost_hal_sdcard_set_fast_clock()
{
spi_set_baudrate(spi0, 1000 * 1000);
spi_set_baudrate(spi0, 40000000UL);
}
void ost_hal_sdcard_cs_high()
@ -238,12 +242,19 @@ void ost_hal_sdcard_cs_low()
gpio_put(SD_CARD_CS, 0);
}
uint8_t ost_hal_sdcard_spi_transfer(uint8_t dat)
void ost_hal_sdcard_spi_exchange(const uint8_t *buffer, uint8_t *out, uint32_t size)
{
uint8_t out;
pico_ost_hal_sdcard_spi_transfer(&dat, &out, 1);
spi_write_read_blocking(spi0, buffer, out, size);
}
return out;
void ost_hal_sdcard_spi_write(const uint8_t *buffer, uint32_t size)
{
spi_write_blocking(spi0, buffer, size);
}
void ost_hal_sdcard_spi_read(uint8_t *out, uint32_t size)
{
spi_read_blocking(spi0, 0xFF, out, size);
}
uint8_t ost_hal_sdcard_get_presence()
@ -295,38 +306,33 @@ void ost_display_transfer_multi(uint8_t *buff, uint32_t btr)
// extern shared_state_t shared_state;
void hal_audio_test();
// #include "pico/critical_section.h"
#include "pico/critical_section.h"
critical_section_t acrit;
// critical_section_t acrit;
void ost_audio_play(const char *filename)
{
#ifndef OST_AUDIO_TEST
audio_play(&audio_ctx, filename);
critical_section_init(&acrit);
// audio_i2s_set_enabled(true);
audio_process(&audio_ctx);
#else
hal_audio_test();
#endif
// audio_process(&audio_ctx);
// audio_step = 1;
}
#ifndef OST_AUDIO_TEST
int ost_audio_process()
{
return audio_process(&audio_ctx);
}
void ost_audio_register_callback(ost_audio_callback_t cb)
{
}
void ost_hal_audio_frame_end()
{
critical_section_enter_blocking(&acrit);
critical_section_exit(&acrit);
// uint dma_channel = shared_state.dma_channel;
// if (dma_irqn_get_channel_status(PICO_AUDIO_I2S_DMA_IRQ, dma_channel))
// {
@ -355,11 +361,7 @@ void __isr __time_critical_func(audio_i2s_dma_irq_handler)()
*/
}
void ost_hal_audio_loop()
{
}
#else
#if 0 // legacy audio test
#define SAMPLE_RATE (44100)
#define DMA_BUF_LEN (32)

View file

@ -1,63 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "hardware/spi.h"
#include "hardware/dma.h"
#define SDCARD_SCK 18
#define SDCARD_MOSI 19
#define SDCARD_MISO 16
static uint dma_tx;
void pico_sdcard_spi_init(int clock)
{
spi_init(spi0, clock);
spi_set_format(spi0, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
gpio_set_function(SDCARD_SCK, GPIO_FUNC_SPI);
gpio_set_function(SDCARD_MOSI, GPIO_FUNC_SPI);
gpio_set_function(SDCARD_MISO, GPIO_FUNC_SPI);
// Grab some unused dma channels
// dma_tx = dma_claim_unused_channel(true);
// uint dma_rx = dma_claim_unused_channel(true);
// Force loopback for testing (I don't have an SPI device handy)
// hw_set_bits(&spi_get_hw(spi_default)->cr1, SPI_SSPCR1_LBM_BITS);
/*
static uint8_t txbuf[TEST_SIZE];
static uint8_t rxbuf[TEST_SIZE];
for (uint i = 0; i < TEST_SIZE; ++i)
{
txbuf[i] = rand();
}
*/
}
void pico_ost_hal_sdcard_spi_transfer(const uint8_t *buffer, uint8_t *out, uint32_t size)
{
spi_write_read_blocking(spi0, buffer, out, size);
/* ------- DMA
// We set the outbound DMA to transfer from a memory buffer to the SPI transmit FIFO paced by the SPI TX FIFO DREQ
// The default is for the read address to increment every element (in this case 1 byte = DMA_SIZE_8)
// and for the write address to remain unchanged.
printf("Configure TX DMA\n");
dma_channel_config c = dma_channel_get_default_config(dma_tx);
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
channel_config_set_dreq(&c, spi_get_dreq(spi_default, true));
dma_channel_configure(dma_tx, &c,
&spi_get_hw(spi_default)->dr, // write address
buffer, // read address
size, // element count (each element is of size transfer_data_size)
false); // don't start yet
dma_start_channel_mask((1u << dma_tx));
dma_channel_wait_for_finish_blocking(dma_tx);
*/
}

View file

@ -1,6 +0,0 @@
#pragma once
#include <stdint.h>
void pico_sdcard_spi_init(int clock);
void pico_ost_hal_sdcard_spi_transfer(const uint8_t *buffer, uint8_t *out, uint32_t size);

View file

@ -8,17 +8,16 @@
#include <string.h>
#include "ost_hal.h"
#include "libutil.h"
#include "serializers.h"
// 1 sample = one 16-bit data for left, one 16-bit data for right (stereo example)
#define SIZE_OF_SAMPLES (1024)
#define SIZE_OF_SAMPLES (128) // in bytes
// Audio Double Buffer for DMA transfer
int32_t audio_buf[2][SIZE_OF_SAMPLES];
// int16_t audio_buf16[2][SIZE_OF_SAMPLES];
// Audio Buffer for File Read
uint8_t raw_buf[SIZE_OF_SAMPLES * 2 * 2]; // x2 for 16-bit, L+R
uint8_t raw_buf[SIZE_OF_SAMPLES * 2 * 2]; // x2 for 16-bit, and x2 for L+R
int32_t DAC_ZERO_VALUE = 1; //
@ -237,14 +236,14 @@ static int get_audio_buf(audio_ctx_t *ctx, int32_t *buf_32b)
return _next_is_end;
}
void audio_process(audio_ctx_t *ctx)
int audio_process(audio_ctx_t *ctx)
{
int nxt1 = (ctx->count & 0x1) ^ 0x1;
int nxt2 = 1 - nxt1;
// dma_flag_clear(DMA1, DMA_CH1, DMA_FLAG_FTF);
// dma_channel_disable(DMA1, DMA_CH1);
ost_hal_audio_frame_end();
ost_hal_audio_frame_end();
if (ctx->next_is_end)
{
@ -269,7 +268,8 @@ void audio_process(audio_ctx_t *ctx)
ctx->dma_trans_number = SIZE_OF_SAMPLES / 4;
}
ctx->count++;
// dma_interrupt_flag_clear(DMA1, DMA_CH1, DMA_INT_FLAG_G); /* not needed */
return ctx->playing;
}
int audio_play(audio_ctx_t *ctx, const char *fname_ptr)

View file

@ -44,7 +44,7 @@ typedef struct
} audio_ctx_t;
void audio_init(audio_ctx_t *ctx);
void audio_process(audio_ctx_t *ctx);
int audio_process(audio_ctx_t *ctx);
int audio_play(audio_ctx_t *ctx, const char *fname_ptr);
void audio_pause(audio_ctx_t *ctx);
void audio_stop(audio_ctx_t *ctx);

View file

@ -1,3 +1,158 @@
#if 1
/*------------------------------------------------------------------------*/
/* STM32F100: MMCv3/SDv1/SDv2 (SPI mode) control module */
/*------------------------------------------------------------------------*/
/*
/ Copyright (C) 2018, ChaN, all right reserved.
/
/ * This software is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/-------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------
Module Private Functions
---------------------------------------------------------------------------*/
#include "ost_hal.h"
#include "debug.h"
#include "ff.h"
#include "diskio.h"
#include "sdcard.h"
#include "ffconf.h"
/*-----------------------------------------------------------------------*/
/* Initialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize(
BYTE drv /* Physical drive number (0..) */
)
{
if (drv)
return STA_NOINIT;
ost_hal_sdcard_set_slow_clock(); // detect using a slow SPI clock for more robustness
if (sdcard_init() != SD_RESPONSE_NO_ERROR)
return STA_NOINIT;
ost_hal_sdcard_set_fast_clock(); // Then switch to fast clock!
return 0;
}
/*-----------------------------------------------------------------------*/
/* Return Drive Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status(
BYTE drv /* Physical drive number (0..) */
)
{
if (drv)
return STA_NOINIT;
return 0;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read(
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res;
if (pdrv || !count)
return RES_PARERR;
if (count == 1)
res = (DRESULT)sdcard_sector_read(sector, buff);
else
res = (DRESULT)sdcard_sectors_read(sector, buff, count);
if (res == 0x00)
return RES_OK;
return RES_ERROR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if _READONLY == 0
DRESULT disk_write(
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
if (pdrv || !count)
return RES_PARERR;
if (count == 1)
res = (DRESULT)sdcard_sector_write(sector, buff);
else
res = (DRESULT)sdcard_sectors_write(sector, buff, count);
if (res == 0)
return RES_OK;
return RES_ERROR;
}
#endif /* _READONLY */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl(
BYTE drv, /* Physical drive number (0..) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
SD_CardInfo cardinfo;
DRESULT res;
if (drv)
return RES_PARERR;
switch (ctrl)
{
case CTRL_SYNC:
// res = ( SD_WaitReady() == SD_RESPONSE_NO_ERROR ) ? RES_OK : RES_ERROR
res = RES_OK;
break;
case GET_BLOCK_SIZE:
*(WORD *)buff = FF_MAX_SS;
res = RES_OK;
break;
case GET_SECTOR_COUNT:
if (sdcard_get_card_info(&cardinfo) != SD_RESPONSE_NO_ERROR)
res = RES_ERROR;
else
{
*(DWORD *)buff = cardinfo.CardCapacity;
res = (*(DWORD *)buff > 0) ? RES_OK : RES_PARERR;
}
break;
case CTRL_TRIM:
res = (sdcard_sectors_erase(((DWORD *)buff)[0], ((DWORD *)buff)[1]) == SD_RESPONSE_NO_ERROR)
? RES_OK
: RES_PARERR;
break;
default:
res = RES_PARERR;
break;
}
return res;
}
#endif
#if 0
#define PIN_SPI0_CS 17
#define PIN_SPI0_SCK 18
#define PIN_SPI0_MOSI 19
@ -24,26 +179,26 @@
---------------------------------------------------------------------------*/
/* MMC/SD command */
#define CMD0 (0) /* GO_IDLE_STATE */
#define CMD1 (1) /* SEND_OP_COND (MMC) */
#define ACMD41 (0x80 + 41) /* SEND_OP_COND (SDC) */
#define CMD8 (8) /* SEND_IF_COND */
#define CMD9 (9) /* SEND_CSD */
#define CMD10 (10) /* SEND_CID */
#define CMD12 (12) /* STOP_TRANSMISSION */
#define ACMD13 (0x80 + 13) /* SD_STATUS (SDC) */
#define CMD16 (16) /* SET_BLOCKLEN */
#define CMD17 (17) /* READ_SINGLE_BLOCK */
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */
#define ACMD23 (0x80 + 23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24 (24) /* WRITE_BLOCK */
#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
#define CMD32 (32) /* ERASE_ER_BLK_START */
#define CMD33 (33) /* ERASE_ER_BLK_END */
#define CMD38 (38) /* ERASE */
#define CMD55 (55) /* APP_CMD */
#define CMD58 (58) /* READ_OCR */
#define CMD0 (0) /* GO_IDLE_STATE */
#define CMD1 (1) /* SEND_OP_COND (MMC) */
#define ACMD41 (0x80 + 41) /* SEND_OP_COND (SDC) */
#define CMD8 (8) /* SEND_IF_COND */
#define CMD9 (9) /* SEND_CSD */
#define CMD10 (10) /* SEND_CID */
#define CMD12 (12) /* STOP_TRANSMISSION */
#define ACMD13 (0x80 + 13) /* SD_STATUS (SDC) */
#define CMD16 (16) /* SET_BLOCKLEN */
#define CMD17 (17) /* READ_SINGLE_BLOCK */
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */
#define ACMD23 (0x80 + 23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24 (24) /* WRITE_BLOCK */
#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
#define CMD32 (32) /* ERASE_ER_BLK_START */
#define CMD33 (33) /* ERASE_ER_BLK_END */
#define CMD38 (38) /* ERASE */
#define CMD55 (55) /* APP_CMD */
#define CMD58 (58) /* READ_OCR */
/* MMC card type flags (MMC_GET_TYPE) */
#define CT_MMC 0x01 /* MMC ver 3 */
@ -642,3 +797,5 @@ DRESULT disk_ioctl(
return res;
}
#endif

View file

@ -1,147 +0,0 @@
/*
* File: libutil.h
* Author: anthony
*
* Created on 18 septembre 2019, 17:19
*/
#ifndef LIBUTIL_H
#define LIBUTIL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#ifndef BIT
#define BIT(x) (1UL << (x))
#endif
// -----------------------------------------------------------------------------
// 8-bit data
// -----------------------------------------------------------------------------
static inline bool u8_is_bit_set(uint8_t value, uint8_t bit)
{
return ((value & BIT(bit)) == 0U) ? false : true;
}
static inline uint8_t u8_clr_bit(uint8_t value, uint8_t bit)
{
return value &= ~BIT(bit);
}
static inline uint8_t u8_set_bit(uint8_t value, uint8_t bit)
{
return value |= BIT(bit);
}
static inline uint8_t u8_toggle_bit(uint8_t value, uint8_t bit)
{
return value ^= BIT(bit);
}
// -----------------------------------------------------------------------------
// 16-bit data
// -----------------------------------------------------------------------------
static inline uint16_t beu16_get(const uint8_t *buff)
{
uint16_t val = ((uint16_t)buff[0]) << 8U;
val += buff[1] & 0xFFU;
return val;
}
static inline void beu16_put(uint8_t *buff, uint16_t data)
{
buff[0] = (data >> 8U) & 0xFFU;
buff[1] = data & 0xFFU;
}
static inline void leu16_put(uint8_t *buff, uint16_t data)
{
buff[0] = data & 0xFFU;
buff[1] = (data >> 8U) & 0xFFU;
}
static inline uint16_t leu16_get(const uint8_t *buff)
{
uint16_t val = ((uint16_t)buff[1]) << 8U;
val += buff[0] & 0xFFU;
return val;
}
static inline uint16_t u16_clr_bit(uint16_t value, uint8_t bit)
{
return value &= ~BIT(bit);
}
static inline uint16_t u16_set_bit(uint16_t value, uint8_t bit)
{
return value |= BIT(bit);
}
static inline bool u16_is_bit_set(uint16_t value, uint8_t bit)
{
return ((value & BIT(bit)) == 0U) ? false : true;
}
// -----------------------------------------------------------------------------
// 32-bit data
// -----------------------------------------------------------------------------
static inline uint32_t beu32_get(const uint8_t *a)
{
uint32_t val = 0;
val |= (((uint32_t) a[0]) << 24);
val |= (((uint32_t) a[1]) << 16);
val |= (((uint32_t) a[2]) << 8);
val |= ((uint32_t) a[3]);
return val;
}
static inline void beu32_put(uint8_t *buff, uint32_t data)
{
buff[0] = (data >> 24U) & 0xFFU;
buff[1] = (data >> 16U) & 0xFFU;
buff[2] = (data >> 8U) & 0xFFU;
buff[3] = data & 0xFFU;
}
static inline uint32_t leu32_get(const uint8_t *a)
{
uint32_t val = 0;
val |= (((uint32_t) a[3]) << 24);
val |= (((uint32_t) a[2]) << 16);
val |= (((uint32_t) a[1]) << 8);
val |= ((uint32_t) a[0]);
return val;
}
static inline void leu32_put(uint8_t *buff, uint32_t data)
{
buff[3] = (data >> 24U) & 0xFFU;
buff[2] = (data >> 16U) & 0xFFU;
buff[1] = (data >> 8U) & 0xFFU;
buff[0] = data & 0xFFU;
}
static inline uint32_t u32_set_bit(uint32_t value, uint8_t bit)
{
return value |= BIT(bit);
}
static inline bool u32_is_bit_set(uint32_t value, uint8_t bit)
{
return ((value & BIT(bit)) == 0U) ? false : true;
}
#ifdef __cplusplus
}
#endif
#endif /* LIBUTIL_H */

View file

@ -148,14 +148,67 @@ void UserTask_2(void *args)
// SD CARD TASK
// ===========================================================================================================
static qor_tcb_t AudioTcb;
static uint32_t AudioStack[1024];
static uint32_t AudioStack[4096];
static qor_mbox_t AudioMailBox;
typedef struct
{
uint8_t ev;
} ost_audio_event_t;
ost_audio_event_t audio_queue[10];
// End of DMA transfer callback
static void audio_callback(void)
{
}
void AudioTask(void *args)
{
picture_show("example.bmp");
// ost_audio_play("out2.wav");
qor_mbox_init(&AudioMailBox, (void **)&audio_queue, 10);
ost_audio_register_callback(audio_callback);
gpio_init(1);
gpio_set_dir(1, GPIO_OUT);
static bool onetime = true;
gpio_put(1, 0);
while (1)
{
if (onetime)
{
onetime = false;
gpio_put(1, 1);
ost_audio_play("out2.wav");
gpio_put(1, 0);
int isPlaying = 0;
int count = 0;
do
{
isPlaying = ost_audio_process();
count++;
} while (isPlaying);
debug_printf("Packets: %d\r\n", count);
}
// ost_event_t *e = NULL;
// uint32_t res = qor_mbox_wait(&b, (void **)&e, 30);
// if (res == QOR_MBOX_OK)
// {
// }
ost_hal_gpio_set(OST_GPIO_DEBUG_LED, 0);
qor_sleep(500);
ost_hal_gpio_set(OST_GPIO_DEBUG_LED, 1);
@ -196,7 +249,7 @@ int main()
// qor_create_thread(&tcb1, UserTask_1, 2, "UserTask_1");
// qor_create_thread(&tcb2, UserTask_2, 1, "UserTask_2");
qor_create_thread(&AudioTcb, AudioTask, AudioStack, 1024, 3, "AudioTask"); ///< High priority for audio
qor_create_thread(&AudioTcb, AudioTask, AudioStack, sizeof(AudioStack) / sizeof(AudioStack[0]), 3, "AudioTask"); ///< High priority for audio
qor_start(&IdleTcb, IdleTask, IdleStack, 1024);
return 0;

View file

@ -48,6 +48,9 @@ extern "C"
void ost_system_delay_ms(uint32_t delay);
void ost_audio_play(const char *filename);
int ost_audio_process();
typedef void (*ost_audio_callback_t)(void);
void ost_audio_register_callback(ost_audio_callback_t cb);
// ----------------------------------------------------------------------------
// GPIO HAL
@ -59,6 +62,9 @@ extern "C"
// SDCARD HAL
// ----------------------------------------------------------------------------
void ost_hal_sdcard_set_slow_clock(void);
void ost_hal_sdcard_set_fast_clock(void);
/**
* @brief Deselect the SD-Card by driving the Chip Select to high level (eg: 3.3V)
*
@ -71,13 +77,13 @@ extern "C"
*/
void ost_hal_sdcard_cs_low();
/**
* @brief
*
* @param dat Data to send
* @return uint8_t
*/
uint8_t ost_hal_sdcard_spi_transfer(uint8_t dat);
// We have a separated API here to allow specific optimizations such as the use of DMA
void ost_hal_sdcard_spi_exchange(const uint8_t *buffer, uint8_t *out, uint32_t size);
void ost_hal_sdcard_spi_write(const uint8_t *buffer, uint32_t size);
void ost_hal_sdcard_spi_read(uint8_t *out, uint32_t size);
/**
* @brief Return 1 if the SD card is physically inserted, otherwise 0
@ -103,7 +109,6 @@ extern "C"
// ----------------------------------------------------------------------------
void ost_hal_audio_frame_end();
void ost_hal_audio_frame_start(const volatile void *, int dma_trans_number);
void ost_hal_audio_loop();
#ifdef __cplusplus
}

View file

@ -3,7 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libutil.h"
#include "serializers.h"
#include "ost_hal.h"
#include "debug.h"

View file

@ -125,6 +125,12 @@ static void SD_Bus_Hold(void)
ost_hal_sdcard_cs_low();
}
static uint8_t SD_SpiWriteByte(uint8_t byte)
{
ost_hal_sdcard_spi_exchange(&byte, &byte, 1);
return byte;
}
/**
* @brief Release SPI bus used by SD card
* @param None
@ -133,7 +139,7 @@ static void SD_Bus_Hold(void)
static void SD_Bus_Release(void)
{ /* Deselect SD Card: set SD chip select pin high */
ost_hal_sdcard_cs_high();
ost_hal_sdcard_spi_transfer(0xFF); /* send dummy byte: 8 Clock pulses of delay */
SD_SpiWriteByte(0xFF); /* send dummy byte: 8 Clock pulses of delay */
}
/**
@ -148,20 +154,20 @@ static SD_Error SD_SendCmd(uint8_t cmd, uint32_t arg, uint8_t crc)
uint8_t res;
uint16_t i = SD_NUM_TRIES;
/* send a command */
ost_hal_sdcard_spi_transfer((cmd & 0x3F) | 0x40); /*!< byte 1 */
ost_hal_sdcard_spi_transfer((uint8_t)(arg >> 24)); /*!< byte 2 */
ost_hal_sdcard_spi_transfer((uint8_t)(arg >> 16)); /*!< byte 3 */
ost_hal_sdcard_spi_transfer((uint8_t)(arg >> 8)); /*!< byte 4 */
ost_hal_sdcard_spi_transfer((uint8_t)arg); /*!< byte 5 */
ost_hal_sdcard_spi_transfer(crc | 0x01); /*!< byte 6: CRC */
SD_SpiWriteByte((cmd & 0x3F) | 0x40); /*!< byte 1 */
SD_SpiWriteByte((uint8_t)(arg >> 24)); /*!< byte 2 */
SD_SpiWriteByte((uint8_t)(arg >> 16)); /*!< byte 3 */
SD_SpiWriteByte((uint8_t)(arg >> 8)); /*!< byte 4 */
SD_SpiWriteByte((uint8_t)arg); /*!< byte 5 */
SD_SpiWriteByte(crc | 0x01); /*!< byte 6: CRC */
/* a byte received immediately after CMD12 should be discarded... */
if (cmd == SD_CMD_STOP_TRANSMISSION)
ost_hal_sdcard_spi_transfer(0xFF);
SD_SpiWriteByte(0xFF);
/* SD Card responds within Ncr (response time),
which is 0-8 bytes for SDSC cards, 1-8 bytes for MMC cards */
do
{
res = ost_hal_sdcard_spi_transfer(0xFF);
res = SD_SpiWriteByte(0xFF);
/* R1 response always starts with 7th bit set to 0 */
} while ((res & SD_CHECK_BIT) != 0x00 && i-- > 0);
return (SD_Error)res;
@ -177,7 +183,7 @@ static SD_Error SD_WaitReady(void)
uint16_t i = SD_NUM_TRIES;
while (i-- > 0)
{
if (ost_hal_sdcard_spi_transfer(0xFF) == 0xFF)
if (SD_SpiWriteByte(0xFF) == 0xFF)
{
// debug_printf( " [[ WAIT delay %d ]] ", SD_NUM_TRIES - i );
return SD_RESPONSE_NO_ERROR;
@ -194,10 +200,10 @@ static SD_Error SD_WaitReady(void)
*/
static void SD_GetResponse4b(uint8_t *pres)
{
pres[3] = ost_hal_sdcard_spi_transfer(0xFF);
pres[2] = ost_hal_sdcard_spi_transfer(0xFF);
pres[1] = ost_hal_sdcard_spi_transfer(0xFF);
pres[0] = ost_hal_sdcard_spi_transfer(0xFF);
pres[3] = SD_SpiWriteByte(0xFF);
pres[2] = SD_SpiWriteByte(0xFF);
pres[1] = SD_SpiWriteByte(0xFF);
pres[0] = SD_SpiWriteByte(0xFF);
}
/**
@ -222,7 +228,7 @@ static uint8_t SD_WaitBytesRead(void)
uint8_t b;
do
{
b = ost_hal_sdcard_spi_transfer(0xFF);
b = SD_SpiWriteByte(0xFF);
} while (b == 0xFF && i-- > 0);
// if (b != 0xFF)
@ -243,7 +249,7 @@ static SD_Error SD_WaitBytesWritten(void)
uint32_t i = SD_NUM_TRIES_WRITE;
while (i-- > 0)
{
if (ost_hal_sdcard_spi_transfer(0xFF) == 0xFF)
if (SD_SpiWriteByte(0xFF) == 0xFF)
{
// debug_printf(" [[ WRITE delay %lu ]] ", SD_NUM_TRIES_WRITE - i);
return SD_RESPONSE_NO_ERROR;
@ -263,7 +269,7 @@ static SD_Error SD_WaitBytesErased(void)
uint32_t i = SD_NUM_TRIES_ERASE;
while (i-- > 0)
{
if (ost_hal_sdcard_spi_transfer(0xFF) == 0xFF)
if (SD_SpiWriteByte(0xFF) == 0xFF)
{
// debug_printf(" [[ ERASE delay %lu ]] ", SD_NUM_TRIES_ERASE - i);
return SD_RESPONSE_NO_ERROR;
@ -292,16 +298,17 @@ static SD_Error SD_ReceiveData(uint8_t *data, uint16_t len)
if (b != 0xFF)
{ /* most cards send transmission start token, don't fail if it's not the case... */
data[i] = b;
if (data[i] == SD_DATA_BLOCK_READ_START) /* 0xFE */
data[i] = ost_hal_sdcard_spi_transfer(0xFF); /* just get the next byte... */
if (data[i] == SD_DATA_BLOCK_READ_START) /* 0xFE */
data[i] = SD_SpiWriteByte(0xFF); /* just get the next byte... */
/* receive the rest of data... */
for (i = 1; i < len; ++i)
data[i] = ost_hal_sdcard_spi_transfer(0xFF);
// for (i = 1; i < len; ++i)
// data[i] = SD_SpiWriteByte(0xFF);
ost_hal_sdcard_spi_read(&data[1], len);
/* get CRC bytes (not really needed by us, but required by SD) */
ost_hal_sdcard_spi_transfer(0xFF);
ost_hal_sdcard_spi_transfer(0xFF);
SD_SpiWriteByte(0xFF);
SD_SpiWriteByte(0xFF);
return SD_RESPONSE_NO_ERROR;
}
@ -434,7 +441,7 @@ static SD_Error SD_GoIdleState(void)
break;
}
debug_printf(" card initialized successfully\n");
debug_printf(" card initialized successfully\r\n");
return SD_RESPONSE_NO_ERROR;
}
@ -466,7 +473,7 @@ SD_Error sdcard_init()
/* send dummy byte 0xFF (rise MOSI high for 2500*8 SPI bus clock cycles) */
while (i++ < SD_NUM_TRIES_RUMPUP)
{
ost_hal_sdcard_spi_transfer(SD_DUMMY_BYTE);
SD_SpiWriteByte(SD_DUMMY_BYTE);
}
/* step 3:
@ -517,10 +524,10 @@ SD_Error sdcard_sector_read(uint32_t readAddr, uint8_t *pBuffer)
SD_Bus_Release(); /* release SPI bus... */
if (state == SD_RESPONSE_NO_ERROR)
debug_printf("OK\n");
else
debug_printf("KO(%d)\n", state);
// if (state == SD_RESPONSE_NO_ERROR)
// debug_printf("OK\r\n");
// else
// debug_printf("KO(%d)\r\n", state);
return state;
}
@ -566,10 +573,10 @@ SD_Error sdcard_sectors_read(uint32_t readAddr, uint8_t *pBuffer, uint32_t nbSec
SD_Bus_Release(); /* release SPI bus... */
if (state == SD_RESPONSE_NO_ERROR)
debug_printf("OK\n");
else
debug_printf("KO(%d)\n", state);
// if (state == SD_RESPONSE_NO_ERROR)
// debug_printf("OK\r\n");
// else
// debug_printf("KO(%d)\r\n", state);
return state;
}
@ -602,19 +609,19 @@ SD_Error sdcard_sector_write(uint32_t writeAddr, const uint8_t *pBuffer)
state = SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK, writeAddr, 0xFF);
if (state == SD_RESPONSE_NO_ERROR)
{ /* wait at least 8 clock cycles (send >=1 0xFF bytes) before transmission starts */
ost_hal_sdcard_spi_transfer(SD_DUMMY_BYTE);
ost_hal_sdcard_spi_transfer(SD_DUMMY_BYTE);
ost_hal_sdcard_spi_transfer(SD_DUMMY_BYTE);
SD_SpiWriteByte(SD_DUMMY_BYTE);
SD_SpiWriteByte(SD_DUMMY_BYTE);
SD_SpiWriteByte(SD_DUMMY_BYTE);
/* send data token to signify the start of data transmission... */
ost_hal_sdcard_spi_transfer(SD_DATA_SINGLE_BLOCK_WRITE_START); /* 0xFE */
SD_SpiWriteByte(SD_DATA_SINGLE_BLOCK_WRITE_START); /* 0xFE */
/* send data... */
while (BlockSize-- > 0)
ost_hal_sdcard_spi_transfer(*pBuffer++);
SD_SpiWriteByte(*pBuffer++);
/* put 2 CRC bytes (not really needed by us, but required by SD) */
ost_hal_sdcard_spi_transfer(SD_DUMMY_BYTE);
ost_hal_sdcard_spi_transfer(SD_DUMMY_BYTE);
SD_SpiWriteByte(SD_DUMMY_BYTE);
SD_SpiWriteByte(SD_DUMMY_BYTE);
/* check data response... */
res = (SD_DataResponse)(ost_hal_sdcard_spi_transfer(0xFF) & SD_RESPONSE_MASK); /* mask unused bits */
res = (SD_DataResponse)(SD_SpiWriteByte(0xFF) & SD_RESPONSE_MASK); /* mask unused bits */
if ((res & SD_RESPONSE_ACCEPTED) != 0)
{ /* card is now processing data and goes to BUSY mode, wait until it finishes... */
state = SD_WaitBytesWritten(); /* make sure card is ready before we go further... */
@ -625,10 +632,10 @@ SD_Error sdcard_sector_write(uint32_t writeAddr, const uint8_t *pBuffer)
SD_Bus_Release(); /* release SPI bus... */
if (state == SD_RESPONSE_NO_ERROR)
debug_printf("OK\n");
else
debug_printf("KO(%d)\n", state);
// if (state == SD_RESPONSE_NO_ERROR)
// debug_printf("OK\r\n");
// else
// debug_printf("KO(%d)\r\n", state);
return state;
}
@ -675,22 +682,22 @@ SD_Error sdcard_sectors_write(uint32_t writeAddr, const uint8_t *pBuffer, uint32
if (state == SD_RESPONSE_NO_ERROR)
{
/* send some dummy bytes before transmission starts... */
ost_hal_sdcard_spi_transfer(0xFF);
ost_hal_sdcard_spi_transfer(0xFF);
ost_hal_sdcard_spi_transfer(0xFF);
SD_SpiWriteByte(0xFF);
SD_SpiWriteByte(0xFF);
SD_SpiWriteByte(0xFF);
/* transfer data... */
while (nbSectors-- > 0 && state != SD_RESPONSE_FAILURE)
{ /* --- {{ send data packet */
ost_hal_sdcard_spi_transfer(SD_DATA_MULTIPLE_BLOCK_WRITE_START); /* 0xFC */
{ /* --- {{ send data packet */
SD_SpiWriteByte(SD_DATA_MULTIPLE_BLOCK_WRITE_START); /* 0xFC */
/* send data... */
while (BlockSize-- > 0)
ost_hal_sdcard_spi_transfer(*pBuffer++);
SD_SpiWriteByte(*pBuffer++);
/* put CRC bytes (not really needed by us, but required by SD) */
ost_hal_sdcard_spi_transfer(0xFF);
ost_hal_sdcard_spi_transfer(0xFF);
SD_SpiWriteByte(0xFF);
SD_SpiWriteByte(0xFF);
/* --- }} */
/* check data response... */
res = (SD_DataResponse)(ost_hal_sdcard_spi_transfer(0xFF) & SD_RESPONSE_MASK); /* mask unused bits */
res = (SD_DataResponse)(SD_SpiWriteByte(0xFF) & SD_RESPONSE_MASK); /* mask unused bits */
if ((res & SD_RESPONSE_ACCEPTED) != 0)
{ /* card is now processing data and goes to BUSY mode, wait until it finishes... */
state = SD_WaitBytesWritten(); /* make sure card is ready before we go further... */
@ -699,8 +706,8 @@ SD_Error sdcard_sectors_write(uint32_t writeAddr, const uint8_t *pBuffer, uint32
state = SD_RESPONSE_FAILURE;
}
/* notify SD card that we finished sending data to write on it */
ost_hal_sdcard_spi_transfer(SD_DATA_MULTIPLE_BLOCK_WRITE_STOP); /* 0xFD */
ost_hal_sdcard_spi_transfer(0xFF); /* read and discard 1 byte from card */
SD_SpiWriteByte(SD_DATA_MULTIPLE_BLOCK_WRITE_STOP); /* 0xFD */
SD_SpiWriteByte(0xFF); /* read and discard 1 byte from card */
/* card is now processing data and goes to BUSY mode, wait until it finishes... */
state = SD_WaitReady(); /* make sure card is ready before we go further... */
}
@ -763,10 +770,10 @@ SD_Error sdcard_sectors_erase(uint32_t eraseAddrFrom, uint32_t eraseAddrTo)
SD_Bus_Release(); /* release SPI bus... */
if (state == SD_RESPONSE_NO_ERROR)
debug_printf("OK\n");
else
debug_printf("KO(%d)\n", state);
// if (state == SD_RESPONSE_NO_ERROR)
// debug_printf("OK\r\n");
// else
// debug_printf("KO(%d)\r\n", state);
return state;
}