ardupilot/libraries/AP_HAL_ChibiOS/sdcard.cpp

270 lines
6.2 KiB
C++
Raw Normal View History

2018-04-28 21:09:09 -03:00
/*
* This file is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
2018-04-28 21:09:09 -03:00
*/
#include <hal.h>
2018-04-28 21:09:09 -03:00
#include "SPIDevice.h"
#include "sdcard.h"
#include "bouncebuffer.h"
2018-04-28 21:09:09 -03:00
#include "hwdef/common/spi_hook.h"
#include <AP_BoardConfig/AP_BoardConfig.h>
2019-08-01 02:07:48 -03:00
#include <AP_Filesystem/AP_Filesystem.h>
#include "bouncebuffer.h"
#include "stm32_util.h"
2018-04-28 21:09:09 -03:00
2018-05-26 05:59:41 -03:00
extern const AP_HAL::HAL& hal;
2018-04-28 21:09:09 -03:00
#ifdef USE_POSIX
static FATFS SDC_FS; // FATFS object
#ifndef HAL_BOOTLOADER_BUILD
static HAL_Semaphore sem;
2018-04-28 21:09:09 -03:00
#endif
static bool sdcard_running;
#endif
2018-04-28 21:09:09 -03:00
#if HAL_USE_SDC
static SDCConfig sdcconfig = {
SDC_MODE_4BIT,
0
};
#elif HAL_USE_MMC_SPI
2018-04-28 21:09:09 -03:00
MMCDriver MMCD1;
static AP_HAL::OwnPtr<AP_HAL::SPIDevice> device;
static MMCConfig mmcconfig;
static SPIConfig lowspeed;
static SPIConfig highspeed;
#endif
2018-05-26 05:59:41 -03:00
/*
initialise microSD card if avaialble. This is called during
AP_BoardConfig initialisation. The parameter BRD_SD_SLOWDOWN
controls a scaling factor on the microSD clock
2018-05-26 05:59:41 -03:00
*/
bool sdcard_init()
2018-05-26 05:59:41 -03:00
{
2018-04-28 21:09:09 -03:00
#ifdef USE_POSIX
#ifndef HAL_BOOTLOADER_BUILD
WITH_SEMAPHORE(sem);
uint8_t sd_slowdown = AP_BoardConfig::get_sdcard_slowdown();
#else
uint8_t sd_slowdown = 0; // maybe take from a define?
#endif
2018-04-28 21:09:09 -03:00
#if HAL_USE_SDC
2021-10-06 22:47:41 -03:00
#if STM32_SDC_USE_SDMMC2 == TRUE
auto &sdcd = SDCD2;
#else
auto &sdcd = SDCD1;
#endif
if (sdcd.bouncebuffer == nullptr) {
// allocate 4k bouncebuffer for microSD to match size in
// AP_Logger
2021-10-06 22:47:41 -03:00
bouncebuffer_init(&sdcd.bouncebuffer, 4096, true);
}
2018-04-28 21:09:09 -03:00
if (sdcard_running) {
sdcard_stop();
}
const uint8_t tries = 3;
for (uint8_t i=0; i<tries; i++) {
sdcconfig.slowdown = sd_slowdown;
2021-10-06 22:47:41 -03:00
sdcStart(&sdcd, &sdcconfig);
if(sdcConnect(&sdcd) == HAL_FAILED) {
sdcStop(&sdcd);
continue;
}
2018-04-28 21:09:09 -03:00
if (f_mount(&SDC_FS, "/", 1) != FR_OK) {
2021-10-06 22:47:41 -03:00
sdcDisconnect(&sdcd);
sdcStop(&sdcd);
continue;
2018-04-28 21:09:09 -03:00
}
printf("Successfully mounted SDCard (slowdown=%u)\n", (unsigned)sd_slowdown);
sdcard_running = true;
return true;
2018-04-28 21:09:09 -03:00
}
2018-05-26 05:59:41 -03:00
#elif HAL_USE_MMC_SPI
if (MMCD1.buffer == nullptr) {
// allocate 16 byte non-cacheable buffer for microSD
MMCD1.buffer = (uint8_t*)malloc_axi_sram(MMC_BUFFER_SIZE);
}
if (sdcard_running) {
sdcard_stop();
}
sdcard_running = true;
2018-04-28 21:09:09 -03:00
device = AP_HAL::get_HAL().spi->get_device("sdcard");
2018-05-26 05:59:41 -03:00
if (!device) {
printf("No sdcard SPI device found\n");
sdcard_running = false;
return false;
2018-05-26 05:59:41 -03:00
}
device->set_slowdown(sd_slowdown);
mmcObjectInit(&MMCD1, MMCD1.buffer);
2018-04-28 21:09:09 -03:00
mmcconfig.spip =
static_cast<ChibiOS::SPIDevice*>(device.get())->get_driver();
mmcconfig.hscfg = &highspeed;
mmcconfig.lscfg = &lowspeed;
/*
try up to 3 times to init microSD interface
*/
const uint8_t tries = 3;
for (uint8_t i=0; i<tries; i++) {
mmcStart(&MMCD1, &mmcconfig);
2018-04-28 21:09:09 -03:00
if (mmcConnect(&MMCD1) == HAL_FAILED) {
mmcStop(&MMCD1);
continue;
}
2018-04-28 21:09:09 -03:00
if (f_mount(&SDC_FS, "/", 1) != FR_OK) {
mmcDisconnect(&MMCD1);
mmcStop(&MMCD1);
continue;
2018-04-28 21:09:09 -03:00
}
printf("Successfully mounted SDCard (slowdown=%u)\n", (unsigned)sd_slowdown);
return true;
2018-04-28 21:09:09 -03:00
}
#endif
sdcard_running = false;
#endif // USE_POSIX
return false;
2018-04-28 21:09:09 -03:00
}
2018-05-26 05:59:41 -03:00
/*
stop sdcard interface (for reboot)
*/
void sdcard_stop(void)
{
#ifdef USE_POSIX
// unmount
f_mount(nullptr, "/", 1);
#endif
#if HAL_USE_SDC
2021-10-06 22:47:41 -03:00
#if STM32_SDC_USE_SDMMC2 == TRUE
auto &sdcd = SDCD2;
#else
auto &sdcd = SDCD1;
#endif
if (sdcard_running) {
2021-10-06 22:47:41 -03:00
sdcDisconnect(&sdcd);
sdcStop(&sdcd);
sdcard_running = false;
}
#elif HAL_USE_MMC_SPI
2018-05-26 05:59:41 -03:00
if (sdcard_running) {
mmcDisconnect(&MMCD1);
mmcStop(&MMCD1);
sdcard_running = false;
}
#endif
}
bool sdcard_retry(void)
{
#ifdef USE_POSIX
if (!sdcard_running) {
if (sdcard_init()) {
#if HAVE_FILESYSTEM_SUPPORT
// create APM directory
AP::FS().mkdir("/APM");
#endif
}
}
return sdcard_running;
#endif
return false;
}
2018-04-28 21:09:09 -03:00
#if HAL_USE_MMC_SPI
2018-05-26 05:59:41 -03:00
/*
hooks to allow hal_mmc_spi.c to work with HAL_ChibiOS SPI
layer. This provides bounce buffers for DMA, DMA channel sharing and
bus locking
*/
void spiStartHook(SPIDriver *spip, const SPIConfig *config)
{
device->set_speed(config == &lowspeed ?
AP_HAL::Device::SPEED_LOW : AP_HAL::Device::SPEED_HIGH);
2018-04-28 21:09:09 -03:00
}
2018-05-26 05:59:41 -03:00
void spiStopHook(SPIDriver *spip)
{
2018-04-28 21:09:09 -03:00
}
__RAMFUNC__ void spiAcquireBusHook(SPIDriver *spip)
{
if (sdcard_running) {
ChibiOS::SPIDevice *devptr = static_cast<ChibiOS::SPIDevice*>(device.get());
devptr->acquire_bus(true, true);
}
}
__RAMFUNC__ void spiReleaseBusHook(SPIDriver *spip)
{
if (sdcard_running) {
ChibiOS::SPIDevice *devptr = static_cast<ChibiOS::SPIDevice*>(device.get());
devptr->acquire_bus(false, true);
}
}
__RAMFUNC__ void spiSelectHook(SPIDriver *spip)
2018-05-26 05:59:41 -03:00
{
if (sdcard_running) {
device->get_semaphore()->take_blocking();
device->set_chip_select(true);
}
2018-04-28 21:09:09 -03:00
}
__RAMFUNC__ void spiUnselectHook(SPIDriver *spip)
2018-05-26 05:59:41 -03:00
{
if (sdcard_running) {
device->set_chip_select(false);
device->get_semaphore()->give();
}
2018-04-28 21:09:09 -03:00
}
2018-05-26 05:59:41 -03:00
void spiIgnoreHook(SPIDriver *spip, size_t n)
{
if (sdcard_running) {
device->clock_pulse(n);
}
2018-04-28 21:09:09 -03:00
}
__RAMFUNC__ void spiSendHook(SPIDriver *spip, size_t n, const void *txbuf)
2018-05-26 05:59:41 -03:00
{
if (sdcard_running) {
device->transfer((const uint8_t *)txbuf, n, nullptr, 0);
}
2018-04-28 21:09:09 -03:00
}
__RAMFUNC__ void spiReceiveHook(SPIDriver *spip, size_t n, void *rxbuf)
2018-05-26 05:59:41 -03:00
{
if (sdcard_running) {
device->transfer(nullptr, 0, (uint8_t *)rxbuf, n);
}
2018-04-28 21:09:09 -03:00
}
#endif