stm: Add sdioio support for feather_stm32f405_express
Currently, only the bus specs of the stm32f405xx have been coded. Other stm-family chips need (at a minimum) the specs added in their periph.[ch] files.
This commit is contained in:
parent
d30f11163c
commit
4adbd23b75
@ -1,5 +1,17 @@
|
|||||||
|
#include "py/objtuple.h"
|
||||||
#include "shared-bindings/board/__init__.h"
|
#include "shared-bindings/board/__init__.h"
|
||||||
|
|
||||||
|
const mp_rom_obj_tuple_t sdio_data_tuple = {
|
||||||
|
{&mp_type_tuple},
|
||||||
|
4,
|
||||||
|
{
|
||||||
|
MP_ROM_PTR(&pin_PC08),
|
||||||
|
MP_ROM_PTR(&pin_PC09),
|
||||||
|
MP_ROM_PTR(&pin_PC10),
|
||||||
|
MP_ROM_PTR(&pin_PC11),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
|
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA04) },
|
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA04) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) },
|
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA05) },
|
||||||
@ -31,5 +43,9 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
|
|||||||
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_SDIO_CLOCK), MP_ROM_PTR(&pin_PC12) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_PD02) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_SDIO_DATA), MP_ROM_PTR(&sdio_data_tuple) },
|
||||||
};
|
};
|
||||||
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
|
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
|
||||||
|
@ -169,7 +169,7 @@ STATIC int check_pins(busio_spi_obj_t *self,
|
|||||||
if (spi_taken) {
|
if (spi_taken) {
|
||||||
mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
|
mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
|
||||||
} else {
|
} else {
|
||||||
mp_raise_ValueError(translate("Invalid SPI pin selection"));
|
mp_raise_ValueError_varg(translate("Invalid %q pin selection"), MP_QSTR_SPI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
356
ports/stm/common-hal/sdioio/SDCard.c
Normal file
356
ports/stm/common-hal/sdioio/SDCard.c
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "shared-bindings/sdioio/SDCard.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/microcontroller/__init__.h"
|
||||||
|
#include "shared-bindings/util.h"
|
||||||
|
#include "boards/board.h"
|
||||||
|
#include "supervisor/shared/translate.h"
|
||||||
|
#include "common-hal/microcontroller/Pin.h"
|
||||||
|
|
||||||
|
#ifndef DEBUG_SDIO
|
||||||
|
#define DEBUG_SDIO (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DEBUG_SDIO
|
||||||
|
#define DEBUG_PRINT(...) ((void)mp_printf(&mp_plat_print, __VA_ARGS__))
|
||||||
|
#else
|
||||||
|
#define DEBUG_PRINT(...) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STATIC bool reserved_sdio[MP_ARRAY_SIZE(mcu_sdio_banks)];
|
||||||
|
STATIC bool never_reset_sdio[MP_ARRAY_SIZE(mcu_sdio_banks)];
|
||||||
|
|
||||||
|
STATIC const mcu_periph_obj_t *find_pin_function(const mcu_periph_obj_t *table, size_t sz, const mcu_pin_obj_t *pin, int periph_index) {
|
||||||
|
for(size_t i = 0; i<sz; i++, table++) {
|
||||||
|
if(periph_index == table->periph_index && pin == table->pin ) {
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//match pins to SDIO objects
|
||||||
|
STATIC int check_pins(sdioio_sdcard_obj_t *self,
|
||||||
|
const mcu_pin_obj_t * clock, const mcu_pin_obj_t * command,
|
||||||
|
uint8_t num_data, mcu_pin_obj_t ** data) {
|
||||||
|
bool sdio_taken = false;
|
||||||
|
|
||||||
|
const uint8_t sdio_clock_len = MP_ARRAY_SIZE(mcu_sdio_clock_list);
|
||||||
|
const uint8_t sdio_command_len = MP_ARRAY_SIZE(mcu_sdio_command_list);
|
||||||
|
const uint8_t sdio_data0_len = MP_ARRAY_SIZE(mcu_sdio_data0_list);
|
||||||
|
const uint8_t sdio_data1_len = MP_ARRAY_SIZE(mcu_sdio_data1_list);
|
||||||
|
const uint8_t sdio_data2_len = MP_ARRAY_SIZE(mcu_sdio_data2_list);
|
||||||
|
const uint8_t sdio_data3_len = MP_ARRAY_SIZE(mcu_sdio_data3_list);
|
||||||
|
|
||||||
|
|
||||||
|
// Loop over each possibility for clock. Check whether all other pins can
|
||||||
|
// be used on the same peripheral
|
||||||
|
for (uint i = 0; i < sdio_clock_len; i++) {
|
||||||
|
const mcu_periph_obj_t *mcu_sdio_clock = &mcu_sdio_clock_list[i];
|
||||||
|
if (mcu_sdio_clock->pin != clock) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int periph_index = mcu_sdio_clock->periph_index;
|
||||||
|
|
||||||
|
const mcu_periph_obj_t *mcu_sdio_command = NULL;
|
||||||
|
if (!(mcu_sdio_command = find_pin_function(mcu_sdio_command_list, sdio_command_len, command, periph_index))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mcu_periph_obj_t *mcu_sdio_data0 = NULL;
|
||||||
|
if(!(mcu_sdio_data0 = find_pin_function(mcu_sdio_data0_list, sdio_data0_len, data[0], periph_index))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mcu_periph_obj_t *mcu_sdio_data1 = NULL;
|
||||||
|
if(num_data > 1 && !(mcu_sdio_data1 = find_pin_function(mcu_sdio_data1_list, sdio_data1_len, data[1], periph_index))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mcu_periph_obj_t *mcu_sdio_data2 = NULL;
|
||||||
|
if(num_data > 2 && !(mcu_sdio_data2 = find_pin_function(mcu_sdio_data2_list, sdio_data2_len, data[2], periph_index))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mcu_periph_obj_t *mcu_sdio_data3 = NULL;
|
||||||
|
if(num_data > 3 && !(mcu_sdio_data3 = find_pin_function(mcu_sdio_data3_list, sdio_data3_len, data[3], periph_index))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reserved_sdio[periph_index-1]) {
|
||||||
|
sdio_taken = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->clock = mcu_sdio_clock;
|
||||||
|
self->command = mcu_sdio_command;
|
||||||
|
self->data[0] = mcu_sdio_data0;
|
||||||
|
self->data[1] = mcu_sdio_data1;
|
||||||
|
self->data[2] = mcu_sdio_data2;
|
||||||
|
self->data[3] = mcu_sdio_data3;
|
||||||
|
|
||||||
|
return periph_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sdio_taken) {
|
||||||
|
mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
|
||||||
|
} else {
|
||||||
|
mp_raise_ValueError_varg(translate("Invalid %q pin selection"), MP_QSTR_SDIO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self,
|
||||||
|
const mcu_pin_obj_t * clock, const mcu_pin_obj_t * command,
|
||||||
|
uint8_t num_data, mcu_pin_obj_t ** data, uint32_t frequency) {
|
||||||
|
|
||||||
|
int periph_index = check_pins(self, clock, command, num_data, data);
|
||||||
|
SDIO_TypeDef * SDIOx = mcu_sdio_banks[periph_index - 1];
|
||||||
|
|
||||||
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||||
|
|
||||||
|
// /* GPIOC and GPIOD Periph clock enable */
|
||||||
|
// RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | SD_DETECT_GPIO_CLK, ENABLE);
|
||||||
|
|
||||||
|
/* Configure data PC.08, PC.09, PC.10, PC.11 pins: D0, D1, D2, D3 pins */
|
||||||
|
for (int i=0; i<num_data; i++) {
|
||||||
|
GPIO_InitStruct.Pin = pin_mask(data[i]->number);
|
||||||
|
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||||
|
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||||
|
GPIO_InitStruct.Alternate = self->data[i]->altfn_index;
|
||||||
|
HAL_GPIO_Init(pin_port(data[i]->port), &GPIO_InitStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure PD.02 CMD line */
|
||||||
|
GPIO_InitStruct.Alternate = self->command->altfn_index;
|
||||||
|
GPIO_InitStruct.Pin = pin_mask(command->number);
|
||||||
|
HAL_GPIO_Init(pin_port(command->port), &GPIO_InitStruct);
|
||||||
|
|
||||||
|
/* Configure PC.12 pin: CLK pin */
|
||||||
|
GPIO_InitStruct.Alternate = self->clock->altfn_index;
|
||||||
|
GPIO_InitStruct.Pin = pin_mask(clock->number);
|
||||||
|
HAL_GPIO_Init(pin_port(clock->port), &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// XXX hard coded pin
|
||||||
|
#define SD_DETECT_PIN GPIO_PIN_12
|
||||||
|
#define SD_DETECT_GPIO_PORT GPIOB
|
||||||
|
|
||||||
|
/*!< Configure SD_SPI_DETECT_PIN pin: SD Card detect pin */
|
||||||
|
GPIO_InitStruct.Pin = SD_DETECT_PIN;
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||||
|
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||||
|
HAL_GPIO_Init(SD_DETECT_GPIO_PORT, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
__HAL_RCC_SDIO_CLK_ENABLE();
|
||||||
|
|
||||||
|
self->handle.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV;
|
||||||
|
self->handle.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
|
||||||
|
self->handle.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
|
||||||
|
self->handle.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
|
||||||
|
self->handle.Init.BusWide = SDIO_BUS_WIDE_1B;
|
||||||
|
self->handle.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
|
||||||
|
self->handle.Instance = SDIOx;
|
||||||
|
|
||||||
|
HAL_StatusTypeDef r = HAL_SD_Init(&self->handle);
|
||||||
|
if (r != HAL_OK) {
|
||||||
|
mp_raise_ValueError_varg(translate("SDIO Init Error %d"), (int)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
HAL_SD_CardInfoTypeDef info;
|
||||||
|
r = HAL_SD_GetCardInfo(&self->handle, &info);
|
||||||
|
if (r != HAL_OK) {
|
||||||
|
mp_raise_ValueError_varg(translate("SDIO GetCardInfo Error %d"), (int)r);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->num_data = 1;
|
||||||
|
if (num_data == 4) {
|
||||||
|
if ((r = HAL_SD_ConfigWideBusOperation(&self->handle, SDIO_BUS_WIDE_4B)) == HAL_SD_ERROR_NONE) {
|
||||||
|
DEBUG_PRINT("Switched bus to 4B mode\n");
|
||||||
|
self->handle.Init.BusWide = SDIO_BUS_WIDE_4B;
|
||||||
|
self->num_data = 4;
|
||||||
|
} else {
|
||||||
|
DEBUG_PRINT("WideBus_Enable returned %r, leaving at 1B mode\n", (int)r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self->capacity = info.BlockNbr * (info.BlockSize / 512);
|
||||||
|
self->frequency = 25000000;
|
||||||
|
|
||||||
|
reserved_sdio[periph_index - 1] = true;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t common_hal_sdioio_sdcard_get_count(sdioio_sdcard_obj_t *self) {
|
||||||
|
return self->capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t common_hal_sdioio_sdcard_get_frequency(sdioio_sdcard_obj_t *self) {
|
||||||
|
return self->frequency; // self->frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t common_hal_sdioio_sdcard_get_width(sdioio_sdcard_obj_t *self) {
|
||||||
|
return self->num_data; // self->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void check_whole_block(mp_buffer_info_t *bufinfo) {
|
||||||
|
if (bufinfo->len % 512) {
|
||||||
|
mp_raise_ValueError(translate("Buffer must be a multiple of 512 bytes"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void wait_write_complete(sdioio_sdcard_obj_t *self) {
|
||||||
|
if (self->state_programming) {
|
||||||
|
HAL_SD_CardStateTypedef st = HAL_SD_CARD_PROGRAMMING;
|
||||||
|
// This waits up to 60s for programming to complete. This seems like
|
||||||
|
// an extremely long time, but this is the timeout that micropython's
|
||||||
|
// implementation uses
|
||||||
|
for (int i=0; i < 60000 && st == HAL_SD_CARD_PROGRAMMING; i++) {
|
||||||
|
st = HAL_SD_GetCardState(&self->handle);
|
||||||
|
HAL_Delay(1);
|
||||||
|
};
|
||||||
|
self->state_programming = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void debug_print_state(sdioio_sdcard_obj_t *self, const char *what) {
|
||||||
|
#if DEBUG_SDIO
|
||||||
|
HAL_SD_CardStateTypedef st = HAL_SD_GetCardState(&self->handle);
|
||||||
|
DEBUG_PRINT("%s, st=0x%x State=0x%x ErrorCode=0x%x\n", what, (int)st, self->handle.State, self->handle.ErrorCode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void check_for_deinit(sdioio_sdcard_obj_t *self) {
|
||||||
|
if (common_hal_sdioio_sdcard_deinited(self)) {
|
||||||
|
raise_deinited_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) {
|
||||||
|
check_for_deinit(self);
|
||||||
|
check_whole_block(bufinfo);
|
||||||
|
wait_write_complete(self);
|
||||||
|
self->state_programming = true;
|
||||||
|
common_hal_mcu_disable_interrupts();
|
||||||
|
HAL_StatusTypeDef r = HAL_SD_WriteBlocks(&self->handle, bufinfo->buf, start_block, bufinfo->len / 512, 1000);
|
||||||
|
common_hal_mcu_enable_interrupts();
|
||||||
|
if (r != HAL_OK) {
|
||||||
|
debug_print_state(self, "after writeblocks error");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
// debug_print_state(self, "after writeblocks OK");
|
||||||
|
// debug_print_state(self, "after writeblocks complete");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) {
|
||||||
|
check_for_deinit(self);
|
||||||
|
check_whole_block(bufinfo);
|
||||||
|
wait_write_complete(self);
|
||||||
|
common_hal_mcu_disable_interrupts();
|
||||||
|
HAL_StatusTypeDef r = HAL_SD_ReadBlocks(&self->handle, bufinfo->buf, start_block, bufinfo->len / 512, 1000);
|
||||||
|
common_hal_mcu_enable_interrupts();
|
||||||
|
if (r != HAL_OK) {
|
||||||
|
debug_print_state(self, "after readblocks error");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_sdioio_sdcard_configure(sdioio_sdcard_obj_t *self, uint32_t frequency, uint8_t bits) {
|
||||||
|
check_for_deinit(self);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_sdioio_sdcard_deinited(sdioio_sdcard_obj_t *self) {
|
||||||
|
return self->command == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void never_reset_mcu_periph(const mcu_periph_obj_t *periph) {
|
||||||
|
if (periph) {
|
||||||
|
never_reset_pin_number(periph->pin->port,periph->pin->number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void reset_mcu_periph(const mcu_periph_obj_t *periph) {
|
||||||
|
if (periph) {
|
||||||
|
reset_pin_number(periph->pin->port,periph->pin->number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_sdioio_sdcard_deinit(sdioio_sdcard_obj_t *self) {
|
||||||
|
if (common_hal_sdioio_sdcard_deinited(self)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reserved_sdio[self->command->periph_index - 1] = false;
|
||||||
|
never_reset_sdio[self->command->periph_index - 1] = false;
|
||||||
|
|
||||||
|
reset_mcu_periph(self->command);
|
||||||
|
self->command = NULL;
|
||||||
|
|
||||||
|
reset_mcu_periph(self->clock);
|
||||||
|
self->command = NULL;
|
||||||
|
|
||||||
|
for (size_t i=0; i<MP_ARRAY_SIZE(self->data); i++) {
|
||||||
|
reset_mcu_periph(self->data[i]);
|
||||||
|
self->data[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self) {
|
||||||
|
if (common_hal_sdioio_sdcard_deinited(self)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (never_reset_sdio[self->command->periph_index] - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
never_reset_sdio[self->command->periph_index - 1] = true;
|
||||||
|
|
||||||
|
never_reset_mcu_periph(self->command);
|
||||||
|
never_reset_mcu_periph(self->clock);
|
||||||
|
|
||||||
|
for (size_t i=0; i<MP_ARRAY_SIZE(self->data); i++) {
|
||||||
|
never_reset_mcu_periph(self->data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdioio_reset() {
|
||||||
|
for (size_t i=0; i<MP_ARRAY_SIZE(reserved_sdio); i++) {
|
||||||
|
if (!never_reset_sdio[i]) {
|
||||||
|
reserved_sdio[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
ports/stm/common-hal/sdioio/SDCard.h
Normal file
50
ports/stm/common-hal/sdioio/SDCard.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_BUSIO_SDIO_H
|
||||||
|
#define MICROPY_INCLUDED_STM32_COMMON_HAL_BUSIO_SDIO_H
|
||||||
|
|
||||||
|
#include "common-hal/microcontroller/Pin.h"
|
||||||
|
|
||||||
|
#include "peripherals/periph.h"
|
||||||
|
|
||||||
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mp_obj_base_t base;
|
||||||
|
SD_HandleTypeDef handle;
|
||||||
|
uint8_t num_data:3, state_programming:1;
|
||||||
|
bool has_lock;
|
||||||
|
const mcu_periph_obj_t *command;
|
||||||
|
const mcu_periph_obj_t *clock;
|
||||||
|
const mcu_periph_obj_t *data[4];
|
||||||
|
uint32_t frequency;
|
||||||
|
uint32_t capacity;
|
||||||
|
} sdioio_sdcard_obj_t;
|
||||||
|
|
||||||
|
void sdioio_reset(void);
|
||||||
|
|
||||||
|
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_BUSIO_SDIO_H
|
0
ports/stm/common-hal/sdioio/__init__.c
Normal file
0
ports/stm/common-hal/sdioio/__init__.c
Normal file
0
ports/stm/common-hal/sdioio/__init__.h
Normal file
0
ports/stm/common-hal/sdioio/__init__.h
Normal file
@ -6,6 +6,7 @@ USB_SERIAL_NUMBER_LENGTH ?= 24
|
|||||||
ifeq ($(MCU_VARIANT),STM32F405xx)
|
ifeq ($(MCU_VARIANT),STM32F405xx)
|
||||||
CIRCUITPY_FRAMEBUFFERIO ?= 1
|
CIRCUITPY_FRAMEBUFFERIO ?= 1
|
||||||
CIRCUITPY_RGBMATRIX ?= 1
|
CIRCUITPY_RGBMATRIX ?= 1
|
||||||
|
CIRCUITPY_SDIOIO ?= 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(MCU_SERIES),F4)
|
ifeq ($(MCU_SERIES),F4)
|
||||||
|
@ -194,3 +194,25 @@ const mcu_tim_pin_obj_t mcu_tim_pin_list[TIM_PIN_ARRAY_LEN] = {
|
|||||||
TIM(8, 3, 2, &pin_PI06),
|
TIM(8, 3, 2, &pin_PI06),
|
||||||
TIM(8, 3, 3, &pin_PI07),
|
TIM(8, 3, 3, &pin_PI07),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//SDIO
|
||||||
|
SDIO_TypeDef * mcu_sdio_banks[1] = {SDIO};
|
||||||
|
|
||||||
|
const mcu_periph_obj_t mcu_sdio_clock_list[1] = {
|
||||||
|
PERIPH(1, 12, &pin_PC12),
|
||||||
|
};
|
||||||
|
const mcu_periph_obj_t mcu_sdio_command_list[1] = {
|
||||||
|
PERIPH(1, 12, &pin_PD02),
|
||||||
|
};
|
||||||
|
const mcu_periph_obj_t mcu_sdio_data0_list[1] = {
|
||||||
|
PERIPH(1, 12, &pin_PC08),
|
||||||
|
};
|
||||||
|
const mcu_periph_obj_t mcu_sdio_data1_list[1] = {
|
||||||
|
PERIPH(1, 12, &pin_PC09),
|
||||||
|
};
|
||||||
|
const mcu_periph_obj_t mcu_sdio_data2_list[1] = {
|
||||||
|
PERIPH(1, 12, &pin_PC10),
|
||||||
|
};
|
||||||
|
const mcu_periph_obj_t mcu_sdio_data3_list[1] = {
|
||||||
|
PERIPH(1, 12, &pin_PC11),
|
||||||
|
};
|
||||||
|
@ -61,4 +61,15 @@ extern const mcu_periph_obj_t mcu_uart_rx_list[UART_RX_ARRAY_LEN];
|
|||||||
TIM_TypeDef * mcu_tim_banks[TIM_BANK_ARRAY_LEN];
|
TIM_TypeDef * mcu_tim_banks[TIM_BANK_ARRAY_LEN];
|
||||||
const mcu_tim_pin_obj_t mcu_tim_pin_list[TIM_PIN_ARRAY_LEN];
|
const mcu_tim_pin_obj_t mcu_tim_pin_list[TIM_PIN_ARRAY_LEN];
|
||||||
|
|
||||||
|
//SDIO
|
||||||
|
extern SDIO_TypeDef * mcu_sdio_banks[1];
|
||||||
|
|
||||||
|
extern const mcu_periph_obj_t mcu_sdio_clock_list[1];
|
||||||
|
extern const mcu_periph_obj_t mcu_sdio_command_list[1];
|
||||||
|
extern const mcu_periph_obj_t mcu_sdio_data0_list[1];
|
||||||
|
extern const mcu_periph_obj_t mcu_sdio_data1_list[1];
|
||||||
|
extern const mcu_periph_obj_t mcu_sdio_data2_list[1];
|
||||||
|
extern const mcu_periph_obj_t mcu_sdio_data3_list[1];
|
||||||
|
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_STM32_PERIPHERALS_STM32F405XX_PERIPH_H
|
#endif // MICROPY_INCLUDED_STM32_PERIPHERALS_STM32F405XX_PERIPH_H
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
#include "common-hal/pulseio/PulseIn.h"
|
#include "common-hal/pulseio/PulseIn.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if CIRCUITPY_SDIOIO
|
||||||
|
#include "common-hal/sdioio/SDCard.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "clocks.h"
|
#include "clocks.h"
|
||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
@ -224,6 +227,9 @@ void reset_port(void) {
|
|||||||
spi_reset();
|
spi_reset();
|
||||||
uart_reset();
|
uart_reset();
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CIRCUITPY_SDIOIO
|
||||||
|
sdioio_reset();
|
||||||
|
#endif
|
||||||
#if CIRCUITPY_PULSEIO
|
#if CIRCUITPY_PULSEIO
|
||||||
timers_reset();
|
timers_reset();
|
||||||
pwmout_reset();
|
pwmout_reset();
|
||||||
|
Loading…
Reference in New Issue
Block a user