Skip to content

Commit 1d2fc3f

Browse files
committed
sdcardio: implement new library for SD card I/O
1 parent 56541cf commit 1d2fc3f

File tree

13 files changed

+784
-0
lines changed

13 files changed

+784
-0
lines changed

py/circuitpy_defns.mk

+5
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ endif
205205
ifeq ($(CIRCUITPY_SAMD),1)
206206
SRC_PATTERNS += samd/%
207207
endif
208+
ifeq ($(CIRCUITPY_SDCARDIO),1)
209+
SRC_PATTERNS += sdcardio/%
210+
endif
208211
ifeq ($(CIRCUITPY_STAGE),1)
209212
SRC_PATTERNS += _stage/%
210213
endif
@@ -362,6 +365,8 @@ SRC_SHARED_MODULE_ALL = \
362365
fontio/__init__.c \
363366
framebufferio/FramebufferDisplay.c \
364367
framebufferio/__init__.c \
368+
sdcardio/SDCard.c \
369+
sdcardio/__init__.c \
365370
gamepad/GamePad.c \
366371
gamepad/__init__.c \
367372
gamepadshift/GamePadShift.c \

py/circuitpy_mpconfig.h

+8
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,13 @@ extern const struct _mp_obj_module_t samd_module;
510510
#define SAMD_MODULE
511511
#endif
512512

513+
#if CIRCUITPY_SDCARDIO
514+
extern const struct _mp_obj_module_t sdcardio_module;
515+
#define SDCARDIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_sdcardio), (mp_obj_t)&sdcardio_module },
516+
#else
517+
#define SDCARDIO_MODULE
518+
#endif
519+
513520
#if CIRCUITPY_STAGE
514521
extern const struct _mp_obj_module_t stage_module;
515522
#define STAGE_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__stage), (mp_obj_t)&stage_module },
@@ -666,6 +673,7 @@ extern const struct _mp_obj_module_t ustack_module;
666673
ROTARYIO_MODULE \
667674
RTC_MODULE \
668675
SAMD_MODULE \
676+
SDCARDIO_MODULE \
669677
STAGE_MODULE \
670678
STORAGE_MODULE \
671679
STRUCT_MODULE \

py/circuitpy_mpconfig.mk

+3
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ CFLAGS += -DCIRCUITPY_RTC=$(CIRCUITPY_RTC)
157157
CIRCUITPY_SAMD ?= 0
158158
CFLAGS += -DCIRCUITPY_SAMD=$(CIRCUITPY_SAMD)
159159

160+
CIRCUITPY_SDCARDIO ?= $(CIRCUITPY_FULL_BUILD)
161+
CFLAGS += -DCIRCUITPY_SDCARDIO=$(CIRCUITPY_SDCARDIO)
162+
160163
# Currently always off.
161164
CIRCUITPY_STAGE ?= 0
162165
CFLAGS += -DCIRCUITPY_STAGE=$(CIRCUITPY_STAGE)

shared-bindings/busio/SPI.c

+8
Original file line numberDiff line numberDiff line change
@@ -410,3 +410,11 @@ const mp_obj_type_t busio_spi_type = {
410410
.make_new = busio_spi_make_new,
411411
.locals_dict = (mp_obj_dict_t*)&busio_spi_locals_dict,
412412
};
413+
414+
busio_spi_obj_t *validate_obj_is_spi_bus(mp_obj_t obj) {
415+
if (!MP_OBJ_IS_TYPE(obj, &busio_spi_type)) {
416+
mp_raise_TypeError_varg(translate("Expected a %q"), busio_spi_type.name);
417+
}
418+
return MP_OBJ_TO_PTR(obj);
419+
}
420+

shared-bindings/busio/SPI.h

+2
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,6 @@ uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t* self);
7070
// This is used by the supervisor to claim SPI devices indefinitely.
7171
extern void common_hal_busio_spi_never_reset(busio_spi_obj_t *self);
7272

73+
extern busio_spi_obj_t *validate_obj_is_spi_bus(mp_obj_t obj_in);
74+
7375
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_H

shared-bindings/sdcardio/SDCard.c

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "py/obj.h"
28+
#include "py/objproperty.h"
29+
#include "py/runtime.h"
30+
#include "py/objarray.h"
31+
32+
#include "shared-bindings/sdcardio/SDCard.h"
33+
#include "shared-module/sdcardio/SDCard.h"
34+
#include "common-hal/busio/SPI.h"
35+
#include "shared-bindings/busio/SPI.h"
36+
#include "shared-bindings/microcontroller/Pin.h"
37+
#include "supervisor/flash.h"
38+
39+
//| .. currentmodule:: sdcardio
40+
//|
41+
//| :class:`SDCard` -- SD Card Block Interface
42+
//| ===========================================
43+
//|
44+
45+
STATIC mp_obj_t sdcardio_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
46+
enum { ARG_spi, ARG_cs, ARG_baudrate, NUM_ARGS };
47+
static const mp_arg_t allowed_args[] = {
48+
{ MP_QSTR_spi, MP_ARG_REQUIRED | MP_ARG_OBJ },
49+
{ MP_QSTR_cs, MP_ARG_REQUIRED | MP_ARG_OBJ },
50+
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 1320000} },
51+
};
52+
MP_STATIC_ASSERT( MP_ARRAY_SIZE(allowed_args) == NUM_ARGS );
53+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
54+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
55+
56+
busio_spi_obj_t *spi = validate_obj_is_spi_bus(args[ARG_spi].u_obj);
57+
mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj);
58+
59+
sdcardio_sdcard_obj_t *self = m_new_obj(sdcardio_sdcard_obj_t);
60+
self->base.type = &sdcardio_SDCard_type;
61+
62+
common_hal_sdcardio_sdcard_construct(self, spi, cs, args[ARG_baudrate].u_int);
63+
64+
return self;
65+
}
66+
67+
68+
//| .. method:: count
69+
//|
70+
//| Returns the total number of sectors
71+
//|
72+
//| :return: The number of 512-byte blocks
73+
//| :rtpye: int
74+
//|
75+
mp_obj_t sdcardio_sdcard_count(mp_obj_t self_in) {
76+
sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t*)self_in;
77+
return mp_obj_new_int_from_ull(common_hal_sdcardio_sdcard_get_blockcount(self));
78+
}
79+
MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_count_obj, sdcardio_sdcard_count);
80+
81+
//| .. method:: deinit
82+
//|
83+
//| Disable permanently.
84+
//|
85+
//|
86+
mp_obj_t sdcardio_sdcard_deinit(mp_obj_t self_in) {
87+
sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t*)self_in;
88+
common_hal_sdcardio_sdcard_deinit(self);
89+
return mp_const_none;
90+
}
91+
MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_deinit_obj, sdcardio_sdcard_deinit);
92+
93+
94+
//| .. method:: readblocks
95+
//|
96+
//| Read one or more blocks from the card
97+
//|
98+
//| :param int start_block: The block to start reading from
99+
//| :param bytearray buf: The buffer to write into. Length must be multiple of 512.
100+
//|
101+
102+
mp_obj_t sdcardio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
103+
uint32_t start_block = mp_obj_get_int(start_block_in);
104+
mp_buffer_info_t bufinfo;
105+
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
106+
sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t*)self_in;
107+
int result = common_hal_sdcardio_sdcard_readblocks(self, start_block, &bufinfo);
108+
if (result < 0) {
109+
mp_raise_OSError(-result);
110+
}
111+
return mp_const_none;
112+
}
113+
114+
MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_readblocks_obj, sdcardio_sdcard_readblocks);
115+
116+
//| .. method:: writeblocks
117+
//|
118+
//| Write one or more blocks to the card
119+
//|
120+
//| :param int start_block: The block to start writing from
121+
//| :param bytearray buf: The buffer to read from. Length must be multiple of 512.
122+
//|
123+
124+
mp_obj_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) {
125+
uint32_t start_block = mp_obj_get_int(start_block_in);
126+
mp_buffer_info_t bufinfo;
127+
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
128+
sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t*)self_in;
129+
int result = common_hal_sdcardio_sdcard_writeblocks(self, start_block, &bufinfo);
130+
if (result < 0) {
131+
mp_raise_OSError(-result);
132+
}
133+
return mp_const_none;
134+
}
135+
MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_writeblocks_obj, sdcardio_sdcard_writeblocks);
136+
137+
STATIC const mp_rom_map_elem_t sdcardio_sdcard_locals_dict_table[] = {
138+
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&sdcardio_sdcard_count_obj) },
139+
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sdcardio_sdcard_deinit_obj) },
140+
{ MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&sdcardio_sdcard_readblocks_obj) },
141+
{ MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&sdcardio_sdcard_writeblocks_obj) },
142+
};
143+
STATIC MP_DEFINE_CONST_DICT(sdcardio_sdcard_locals_dict, sdcardio_sdcard_locals_dict_table);
144+
145+
const mp_obj_type_t sdcardio_SDCard_type = {
146+
{ &mp_type_type },
147+
.name = MP_QSTR_SDCard,
148+
.make_new = sdcardio_sdcard_make_new,
149+
.locals_dict = (mp_obj_dict_t*)&sdcardio_sdcard_locals_dict,
150+
};

shared-bindings/sdcardio/SDCard.h

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017, 2018 Scott Shawcroft for Adafruit Industries
7+
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in
17+
* all copies or substantial portions of the Software.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_SDCARDIO_SDCARD_H
29+
#define MICROPY_INCLUDED_SHARED_BINDINGS_SDCARDIO_SDCARD_H
30+
31+
extern const mp_obj_type_t sdcardio_SDCard_type;
32+
33+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO_FRAMEBUFFERDISPLAY_H

shared-bindings/sdcardio/__init__.c

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
28+
#include <stdint.h>
29+
30+
#include "py/obj.h"
31+
#include "py/runtime.h"
32+
33+
#include "shared-bindings/sdcardio/SDCard.h"
34+
35+
//| :mod:`sdcardio` --- Low-level routines for SD card I/O
36+
//| =====================================================================
37+
//|
38+
//| .. module:: sdcardio
39+
//| :synopsis: Low-level routines for SD card I/O
40+
//|
41+
//| .. toctree::
42+
//| :maxdepth: 3
43+
//|
44+
//| SDCard
45+
46+
STATIC const mp_rom_map_elem_t sdcardio_module_globals_table[] = {
47+
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sdcardio) },
48+
{ MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&sdcardio_SDCard_type) },
49+
};
50+
51+
STATIC MP_DEFINE_CONST_DICT(sdcardio_module_globals, sdcardio_module_globals_table);
52+
53+
const mp_obj_module_t sdcardio_module = {
54+
.base = { &mp_type_module },
55+
.globals = (mp_obj_dict_t*)&sdcardio_module_globals,
56+
};

shared-bindings/sdcardio/__init__.h

Whitespace-only changes.

0 commit comments

Comments
 (0)