Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
M
micropython
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
card10
micropython
Commits
6edffd0d
Commit
6edffd0d
authored
Nov 16, 2015
by
Dave Hylands
Committed by
Damien George
Nov 24, 2015
Browse files
Options
Downloads
Patches
Plain Diff
stmhal: Add dma support for sdcard.
This started out using IgorLektorovEpam work in PR #1389 and reworked it.
parent
b677f034
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
stmhal/sdcard.c
+76
-69
76 additions, 69 deletions
stmhal/sdcard.c
with
76 additions
and
69 deletions
stmhal/sdcard.c
+
76
−
69
View file @
6edffd0d
...
@@ -24,8 +24,6 @@
...
@@ -24,8 +24,6 @@
* THE SOFTWARE.
* THE SOFTWARE.
*/
*/
// TODO make it work with DMA
#include STM32_HAL_H
#include STM32_HAL_H
#include
"py/nlr.h"
#include
"py/nlr.h"
...
@@ -34,6 +32,8 @@
...
@@ -34,6 +32,8 @@
#include
"pin.h"
#include
"pin.h"
#include
"genhdr/pins.h"
#include
"genhdr/pins.h"
#include
"bufhelper.h"
#include
"bufhelper.h"
#include
"dma.h"
#include
"irq.h"
#if MICROPY_HW_HAS_SDCARD
#if MICROPY_HW_HAS_SDCARD
...
@@ -64,8 +64,12 @@
...
@@ -64,8 +64,12 @@
#endif
#endif
// TODO: I think that as an optimization, we can allocate these dynamically
// if an sd card is detected. This will save approx 260 bytes of RAM
// when no sdcard was being used.
static
SD_HandleTypeDef
sd_handle
;
static
SD_HandleTypeDef
sd_handle
;
static
DMA_HandleTypeDef
sd_rx_dma
,
sd_tx_dma
;
static
DMA_InitTypeDef
sd_rx_dma_init
,
sd_tx_dma_init
;
void
sdcard_init
(
void
)
{
void
sdcard_init
(
void
)
{
GPIO_InitTypeDef
GPIO_Init_Structure
;
GPIO_InitTypeDef
GPIO_Init_Structure
;
...
@@ -98,13 +102,45 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
...
@@ -98,13 +102,45 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
// enable SDIO clock
// enable SDIO clock
__SDIO_CLK_ENABLE
();
__SDIO_CLK_ENABLE
();
// GPIO have already been initialised by sdcard_init
// NVIC configuration for SDIO interrupts
HAL_NVIC_SetPriority
(
SDIO_IRQn
,
IRQ_PRI_SDIO
,
IRQ_SUBPRI_SDIO
);
HAL_NVIC_EnableIRQ
(
SDIO_IRQn
);
// TODO: Since SDIO is fundamentally half-duplex, we really only need to
// tie up one DMA channel. However, the HAL DMA API doesn't
// seem to provide a convenient way to change the direction. I believe that
// its as simple as changing the CR register and the Init.Direction field
// and make DMA_SetConfig public.
// Configure DMA Rx parameters
sd_rx_dma_init
.
PeriphInc
=
DMA_PINC_DISABLE
;
sd_rx_dma_init
.
MemInc
=
DMA_MINC_ENABLE
;
sd_rx_dma_init
.
PeriphDataAlignment
=
DMA_PDATAALIGN_WORD
;
sd_rx_dma_init
.
MemDataAlignment
=
DMA_MDATAALIGN_WORD
;
sd_rx_dma_init
.
Mode
=
DMA_PFCTRL
;
sd_rx_dma_init
.
Priority
=
DMA_PRIORITY_VERY_HIGH
;
sd_rx_dma_init
.
FIFOMode
=
DMA_FIFOMODE_ENABLE
;
sd_rx_dma_init
.
FIFOThreshold
=
DMA_FIFO_THRESHOLD_FULL
;
sd_rx_dma_init
.
MemBurst
=
DMA_MBURST_INC4
;
sd_rx_dma_init
.
PeriphBurst
=
DMA_PBURST_INC4
;
// Configure DMA Tx parameters
sd_tx_dma_init
.
PeriphInc
=
DMA_PINC_DISABLE
;
sd_tx_dma_init
.
MemInc
=
DMA_MINC_ENABLE
;
sd_tx_dma_init
.
PeriphDataAlignment
=
DMA_PDATAALIGN_WORD
;
sd_tx_dma_init
.
MemDataAlignment
=
DMA_MDATAALIGN_WORD
;
sd_tx_dma_init
.
Mode
=
DMA_PFCTRL
;
sd_tx_dma_init
.
Priority
=
DMA_PRIORITY_VERY_HIGH
;
sd_tx_dma_init
.
FIFOMode
=
DMA_FIFOMODE_ENABLE
;
sd_tx_dma_init
.
FIFOThreshold
=
DMA_FIFO_THRESHOLD_FULL
;
sd_tx_dma_init
.
MemBurst
=
DMA_MBURST_INC4
;
sd_tx_dma_init
.
PeriphBurst
=
DMA_PBURST_INC4
;
// interrupts are not used at the moment
// GPIO have already been initialised by sdcard_init
// they are needed only for DMA transfer (I think...)
}
}
void
HAL_SD_MspDeInit
(
SD_HandleTypeDef
*
hsd
)
{
void
HAL_SD_MspDeInit
(
SD_HandleTypeDef
*
hsd
)
{
HAL_NVIC_DisableIRQ
(
SDIO_IRQn
);
__SDIO_CLK_DISABLE
();
__SDIO_CLK_DISABLE
();
}
}
...
@@ -168,6 +204,10 @@ uint64_t sdcard_get_capacity_in_bytes(void) {
...
@@ -168,6 +204,10 @@ uint64_t sdcard_get_capacity_in_bytes(void) {
return
cardinfo
.
CardCapacity
;
return
cardinfo
.
CardCapacity
;
}
}
void
SDIO_IRQHandler
(
void
)
{
HAL_SD_IRQHandler
(
&
sd_handle
);
}
mp_uint_t
sdcard_read_blocks
(
uint8_t
*
dest
,
uint32_t
block_num
,
uint32_t
num_blocks
)
{
mp_uint_t
sdcard_read_blocks
(
uint8_t
*
dest
,
uint32_t
block_num
,
uint32_t
num_blocks
)
{
// check that dest pointer is aligned on a 4-byte boundary
// check that dest pointer is aligned on a 4-byte boundary
if
(((
uint32_t
)
dest
&
3
)
!=
0
)
{
if
(((
uint32_t
)
dest
&
3
)
!=
0
)
{
...
@@ -179,90 +219,57 @@ mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo
...
@@ -179,90 +219,57 @@ mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo
return
SD_ERROR
;
return
SD_ERROR
;
}
}
// We must disable IRQs because the SDIO peripheral has a small FIFO
HAL_SD_ErrorTypedef
err
=
SD_OK
;
// buffer and we can't let it fill up in the middle of a read.
// This will not be needed when SD uses DMA for transfer.
mp_uint_t
atomic_state
=
MICROPY_BEGIN_ATOMIC_SECTION
();
HAL_SD_ErrorTypedef
err
=
HAL_SD_ReadBlocks_BlockNumber
(
&
sd_handle
,
(
uint32_t
*
)
dest
,
block_num
,
SDCARD_BLOCK_SIZE
,
num_blocks
);
MICROPY_END_ATOMIC_SECTION
(
atomic_state
);
return
err
;
if
(
query_irq
()
==
IRQ_STATE_ENABLED
)
{
}
dma_init
(
&
sd_rx_dma
,
DMA_STREAM_SDIO_RX
,
&
sd_rx_dma_init
,
DMA_CHANNEL_SDIO_RX
,
DMA_PERIPH_TO_MEMORY
,
&
sd_handle
);
sd_handle
.
hdmarx
=
&
sd_rx_dma
;
mp_uint_t
sdcard_write_blocks
(
const
uint8_t
*
src
,
uint32_t
block_num
,
uint32_t
num_blocks
)
{
err
=
HAL_SD_ReadBlocks_BlockNumber_DMA
(
&
sd_handle
,
(
uint32_t
*
)
dest
,
block_num
,
SDCARD_BLOCK_SIZE
,
num_blocks
)
;
// check that src pointer is aligned on a 4-byte boundary
if
(
err
==
SD_OK
)
{
if
(((
uint32_t
)
src
&
3
)
!=
0
)
{
// wait for DMA transfer to finish, with a large timeout
return
SD_ERROR
;
err
=
HAL_SD_CheckReadOperation
(
&
sd_handle
,
100000000
)
;
}
}
// check that SD card is initialised
dma_deinit
(
sd_handle
.
hdmarx
);
if
(
sd_handle
.
Instance
==
NULL
)
{
sd_handle
.
hdmarx
=
NULL
;
return
SD_ERROR
;
}
else
{
err
=
HAL_SD_ReadBlocks_BlockNumber
(
&
sd_handle
,
(
uint32_t
*
)
dest
,
block_num
,
SDCARD_BLOCK_SIZE
,
num_blocks
);
}
}
// We must disable IRQs because the SDIO peripheral has a small FIFO
// buffer and we can't let it drain to empty in the middle of a write.
// This will not be needed when SD uses DMA for transfer.
mp_uint_t
atomic_state
=
MICROPY_BEGIN_ATOMIC_SECTION
();
HAL_SD_ErrorTypedef
err
=
HAL_SD_WriteBlocks_BlockNumber
(
&
sd_handle
,
(
uint32_t
*
)
src
,
block_num
,
SDCARD_BLOCK_SIZE
,
num_blocks
);
MICROPY_END_ATOMIC_SECTION
(
atomic_state
);
return
err
;
return
err
;
}
}
#if 0
mp_uint_t
sdcard_write_blocks
(
const
uint8_t
*
src
,
uint32_t
block_num
,
uint32_t
num_blocks
)
{
DMA not implemented
bool sdcard_read_blocks_dma(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
// check that dest pointer is aligned on a 4-byte boundary
if (((uint32_t)dest & 3) != 0) {
return false;
}
// check that SD card is initialised
if (sd_handle.Instance == NULL) {
return false;
}
// do the read
if (HAL_SD_ReadBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE) != SD_OK) {
return false;
}
// wait for DMA transfer to finish, with a large timeout
if (HAL_SD_CheckReadOperation(&sd_handle, 100000000) != SD_OK) {
return false;
}
return true;
}
bool sdcard_write_blocks_dma(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
// check that src pointer is aligned on a 4-byte boundary
// check that src pointer is aligned on a 4-byte boundary
if
(((
uint32_t
)
src
&
3
)
!=
0
)
{
if
(((
uint32_t
)
src
&
3
)
!=
0
)
{
return
false
;
return
SD_ERROR
;
}
}
// check that SD card is initialised
// check that SD card is initialised
if
(
sd_handle
.
Instance
==
NULL
)
{
if
(
sd_handle
.
Instance
==
NULL
)
{
return
false
;
return
SD_ERROR
;
}
}
SD_Error
status
;
HAL_
SD_Error
Typedef
err
=
SD_OK
;
status = HAL_SD_WriteBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)src, block_num, SDCARD_BLOCK_SIZE, num_blocks);
if
(
query_irq
()
==
IRQ_STATE_ENABLED
)
{
if (status != SD_OK) {
dma_init
(
&
sd_tx_dma
,
DMA_STREAM_SDIO_TX
,
&
sd_tx_dma_init
,
DMA_CHANNEL_SDIO_TX
,
DMA_MEMORY_TO_PERIPH
,
&
sd_handle
);
return false;
sd_handle
.
hdmatx
=
&
sd_tx_dma
;
}
err
=
HAL_SD_WriteBlocks_BlockNumber_DMA
(
&
sd_handle
,
(
uint32_t
*
)
src
,
block_num
,
SDCARD_BLOCK_SIZE
,
num_blocks
);
if
(
err
==
SD_OK
)
{
// wait for DMA transfer to finish, with a large timeout
// wait for DMA transfer to finish, with a large timeout
status = HAL_SD_CheckWriteOperation(&sd_handle, 100000000);
err
=
HAL_SD_CheckWriteOperation
(
&
sd_handle
,
100000000
);
if (status != SD_OK) {
}
return false;
dma_deinit
(
sd_handle
.
hdmatx
);
sd_handle
.
hdmatx
=
NULL
;
}
else
{
err
=
HAL_SD_WriteBlocks_BlockNumber
(
&
sd_handle
,
(
uint32_t
*
)
src
,
block_num
,
SDCARD_BLOCK_SIZE
,
num_blocks
);
}
}
return
true
;
return
err
;
}
}
#endif
/******************************************************************************/
/******************************************************************************/
// Micro Python bindings
// Micro Python bindings
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment