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/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "SPIDevice.h"
|
|
|
|
#include "sdcard.h"
|
|
|
|
#include "hwdef/common/spi_hook.h"
|
2018-12-27 21:05:06 -04:00
|
|
|
#include <AP_BoardConfig/AP_BoardConfig.h>
|
2018-12-28 20:08:13 -04:00
|
|
|
#include "Semaphores.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
|
2018-12-27 21:05:06 -04:00
|
|
|
static bool sdcard_running;
|
2018-12-28 20:08:13 -04:00
|
|
|
static ChibiOS::Semaphore sem;
|
2018-04-28 21:09:09 -03:00
|
|
|
#endif
|
|
|
|
|
2018-12-27 21:05:06 -04:00
|
|
|
#if HAL_USE_SDC
|
|
|
|
static SDCConfig sdcconfig = {
|
|
|
|
NULL,
|
|
|
|
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
|
|
|
/*
|
2018-12-27 21:05:06 -04: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
|
|
|
*/
|
2018-12-27 21:05:06 -04:00
|
|
|
bool sdcard_init()
|
2018-05-26 05:59:41 -03:00
|
|
|
{
|
2018-04-28 21:09:09 -03:00
|
|
|
#ifdef USE_POSIX
|
2018-12-28 20:08:13 -04:00
|
|
|
sem.take(HAL_SEMAPHORE_BLOCK_FOREVER);
|
2018-12-28 19:50:17 -04:00
|
|
|
|
2018-12-27 21:05:06 -04:00
|
|
|
uint8_t sd_slowdown = AP_BoardConfig::get_sdcard_slowdown();
|
2018-04-28 21:09:09 -03:00
|
|
|
#if HAL_USE_SDC
|
2018-06-02 00:27:02 -03:00
|
|
|
|
2018-12-27 21:05:06 -04:00
|
|
|
if (SDCD1.bouncebuffer == nullptr) {
|
|
|
|
bouncebuffer_init(&SDCD1.bouncebuffer, 512);
|
|
|
|
}
|
2018-04-28 21:09:09 -03:00
|
|
|
|
2018-12-27 21:05:06 -04:00
|
|
|
if (sdcard_running) {
|
|
|
|
sdcard_stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t tries = 3;
|
|
|
|
for (uint8_t i=0; i<tries; i++) {
|
|
|
|
sdcconfig.slowdown = sd_slowdown;
|
|
|
|
sdcStart(&SDCD1, &sdcconfig);
|
|
|
|
if(sdcConnect(&SDCD1) == HAL_FAILED) {
|
|
|
|
sdcStop(&SDCD1);
|
|
|
|
continue;
|
|
|
|
}
|
2018-04-28 21:09:09 -03:00
|
|
|
if (f_mount(&SDC_FS, "/", 1) != FR_OK) {
|
|
|
|
sdcDisconnect(&SDCD1);
|
2018-12-27 21:05:06 -04:00
|
|
|
sdcStop(&SDCD1);
|
|
|
|
continue;
|
2018-04-28 21:09:09 -03:00
|
|
|
}
|
2018-12-27 21:05:06 -04:00
|
|
|
printf("Successfully mounted SDCard (slowdown=%u)\n", (unsigned)sd_slowdown);
|
|
|
|
|
|
|
|
// Create APM Directory if needed
|
2018-04-28 21:09:09 -03:00
|
|
|
mkdir("/APM", 0777);
|
2018-12-28 20:08:13 -04:00
|
|
|
mkdir("/APM/LOGS", 0777);
|
2018-12-27 21:05:06 -04:00
|
|
|
sdcard_running = true;
|
2018-12-28 20:08:13 -04:00
|
|
|
sem.give();
|
2018-12-27 21:05:06 -04:00
|
|
|
return true;
|
2018-04-28 21:09:09 -03:00
|
|
|
}
|
2018-05-26 05:59:41 -03:00
|
|
|
#elif HAL_USE_MMC_SPI
|
2018-12-27 21:05:06 -04:00
|
|
|
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");
|
2018-12-28 20:08:13 -04:00
|
|
|
sem.give();
|
2018-12-27 21:05:06 -04:00
|
|
|
return false;
|
2018-05-26 05:59:41 -03:00
|
|
|
}
|
2018-12-27 21:05:06 -04:00
|
|
|
device->set_slowdown(sd_slowdown);
|
2018-05-26 05:59:41 -03:00
|
|
|
|
2018-04-28 21:09:09 -03:00
|
|
|
mmcObjectInit(&MMCD1);
|
|
|
|
|
|
|
|
mmcconfig.spip =
|
|
|
|
static_cast<ChibiOS::SPIDevice*>(device.get())->get_driver();
|
|
|
|
mmcconfig.hscfg = &highspeed;
|
|
|
|
mmcconfig.lscfg = &lowspeed;
|
|
|
|
|
2018-12-27 21:05:06 -04:00
|
|
|
/*
|
|
|
|
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
|
|
|
|
2018-12-27 21:05:06 -04: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);
|
2018-12-27 21:05:06 -04:00
|
|
|
mmcStop(&MMCD1);
|
|
|
|
continue;
|
2018-04-28 21:09:09 -03:00
|
|
|
}
|
2018-12-27 21:05:06 -04:00
|
|
|
printf("Successfully mounted SDCard (slowdown=%u)\n", (unsigned)sd_slowdown);
|
|
|
|
|
|
|
|
// Create APM Directory if needed
|
2018-04-28 21:09:09 -03:00
|
|
|
mkdir("/APM", 0777);
|
2018-12-28 20:08:13 -04:00
|
|
|
mkdir("/APM/LOGS", 0777);
|
|
|
|
sem.give();
|
2018-12-27 21:05:06 -04:00
|
|
|
return true;
|
2018-04-28 21:09:09 -03:00
|
|
|
}
|
2018-12-27 21:05:06 -04:00
|
|
|
sdcard_running = false;
|
2018-04-28 21:09:09 -03:00
|
|
|
#endif
|
2018-12-28 20:08:13 -04:00
|
|
|
sem.give();
|
2018-04-28 21:09:09 -03:00
|
|
|
#endif
|
2018-12-27 21:05:06 -04:00
|
|
|
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)
|
|
|
|
{
|
2018-05-26 06:00:49 -03:00
|
|
|
#ifdef USE_POSIX
|
|
|
|
// unmount
|
|
|
|
f_mount(nullptr, "/", 1);
|
|
|
|
#endif
|
2018-12-27 21:05:06 -04:00
|
|
|
#if HAL_USE_SDC
|
|
|
|
if (sdcard_running) {
|
|
|
|
sdcDisconnect(&SDCD1);
|
|
|
|
sdcStop(&SDCD1);
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2018-12-28 19:50:17 -04:00
|
|
|
void sdcard_retry(void)
|
|
|
|
{
|
2018-12-30 18:36:09 -04:00
|
|
|
#ifdef USE_POSIX
|
2018-12-28 19:50:17 -04:00
|
|
|
if (!sdcard_running) {
|
|
|
|
sdcard_init();
|
|
|
|
}
|
2018-12-30 18:36:09 -04:00
|
|
|
#endif
|
2018-12-28 19:50:17 -04:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-05-26 05:59:41 -03:00
|
|
|
void spiSelectHook(SPIDriver *spip)
|
|
|
|
{
|
|
|
|
if (sdcard_running) {
|
|
|
|
device->get_semaphore()->take_blocking();
|
|
|
|
device->set_chip_select(true);
|
|
|
|
}
|
2018-04-28 21:09:09 -03:00
|
|
|
}
|
|
|
|
|
2018-05-26 05:59:41 -03:00
|
|
|
void spiUnselectHook(SPIDriver *spip)
|
|
|
|
{
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-05-26 05:59:41 -03:00
|
|
|
void spiSendHook(SPIDriver *spip, size_t n, const void *txbuf)
|
|
|
|
{
|
|
|
|
if (sdcard_running) {
|
|
|
|
device->transfer((const uint8_t *)txbuf, n, nullptr, 0);
|
|
|
|
}
|
2018-04-28 21:09:09 -03:00
|
|
|
}
|
|
|
|
|
2018-05-26 05:59:41 -03:00
|
|
|
void spiReceiveHook(SPIDriver *spip, size_t n, void *rxbuf)
|
|
|
|
{
|
|
|
|
if (sdcard_running) {
|
|
|
|
device->transfer(nullptr, 0, (uint8_t *)rxbuf, n);
|
|
|
|
}
|
2018-04-28 21:09:09 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|