mirror of
https://github.com/laanwj/k210-sdk-stuff.git
synced 2024-11-22 01:16:20 +04:00
rust: sdcard read/write sectors using DMA
This commit is contained in:
parent
ed91b43e2a
commit
0dcbeda646
@ -1,5 +1,4 @@
|
||||
//! SD card slot access (in SPI mode) on Maix Go
|
||||
// TODO: actually use the DMA channel that is claimed…
|
||||
use core::convert::TryInto;
|
||||
|
||||
use crate::soc::dmac::{dma_channel, DMAC};
|
||||
@ -189,6 +188,22 @@ impl<'a, X: SPI> SDCard<'a, X> {
|
||||
self.spi.send_data(self.spi_cs, data);
|
||||
}
|
||||
|
||||
fn write_data_dma(&self, data: &[u32]) {
|
||||
self.spi.configure(
|
||||
work_mode::MODE0,
|
||||
frame_format::STANDARD,
|
||||
8, /* data bits */
|
||||
0, /* endian */
|
||||
0, /*instruction length*/
|
||||
0, /*address length*/
|
||||
0, /*wait cycles*/
|
||||
aitm::STANDARD,
|
||||
tmod::TRANS,
|
||||
);
|
||||
self.spi
|
||||
.send_data_dma(self.dmac, self.channel, self.spi_cs, data);
|
||||
}
|
||||
|
||||
fn read_data(&self, data: &mut [u8]) {
|
||||
self.spi.configure(
|
||||
work_mode::MODE0,
|
||||
@ -204,6 +219,22 @@ impl<'a, X: SPI> SDCard<'a, X> {
|
||||
self.spi.recv_data(self.spi_cs, data);
|
||||
}
|
||||
|
||||
fn read_data_dma(&self, data: &mut [u32]) {
|
||||
self.spi.configure(
|
||||
work_mode::MODE0,
|
||||
frame_format::STANDARD,
|
||||
8, /* data bits */
|
||||
0, /* endian */
|
||||
0, /*instruction length*/
|
||||
0, /*address length*/
|
||||
0, /*wait cycles*/
|
||||
aitm::STANDARD,
|
||||
tmod::RECV,
|
||||
);
|
||||
self.spi
|
||||
.recv_data_dma(self.dmac, self.channel, self.spi_cs, data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send 5 bytes command to the SD card.
|
||||
* @param cmd: The user expected command to send to SD card.
|
||||
@ -554,13 +585,18 @@ impl<'a, X: SPI> SDCard<'a, X> {
|
||||
return Err(());
|
||||
}
|
||||
let mut error = false;
|
||||
let mut dma_chunk = [0u32; SEC_LEN];
|
||||
for chunk in data_buf.chunks_mut(SEC_LEN) {
|
||||
if self.get_response() != SD_START_DATA_SINGLE_BLOCK_READ {
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
/* Read the SD block data : read NumByteToRead data */
|
||||
self.read_data(chunk);
|
||||
self.read_data_dma(&mut dma_chunk);
|
||||
/* Place the data received as u32 units from DMA into the u8 target buffer */
|
||||
for (a, b) in chunk.iter_mut().zip(dma_chunk.iter()) {
|
||||
*a = (b & 0xff) as u8;
|
||||
}
|
||||
/* Get CRC bytes (not really needed by us, but required by SD) */
|
||||
let mut frame = [0u8; 2];
|
||||
self.read_data(&mut frame);
|
||||
@ -610,11 +646,15 @@ impl<'a, X: SPI> SDCard<'a, X> {
|
||||
self.end_cmd();
|
||||
return Err(());
|
||||
}
|
||||
let mut dma_chunk = [0u32; SEC_LEN];
|
||||
for chunk in data_buf.chunks(SEC_LEN) {
|
||||
/* Send the data token to signify the start of the data */
|
||||
self.write_data(&frame);
|
||||
/* Write the block data to SD : write count data by block */
|
||||
self.write_data(chunk);
|
||||
for (a, &b) in dma_chunk.iter_mut().zip(chunk.iter()) {
|
||||
*a = b.into();
|
||||
}
|
||||
self.write_data_dma(&mut dma_chunk);
|
||||
/* Put dummy CRC bytes */
|
||||
self.write_data(&[0xff, 0xff]);
|
||||
/* Read data response */
|
||||
|
@ -75,6 +75,7 @@ pub trait SPI {
|
||||
);
|
||||
fn set_clk_rate(&self, spi_clk: u32) -> u32;
|
||||
fn recv_data<X: TruncU32>(&self, chip_select: u32, rx: &mut [X]);
|
||||
fn recv_data_dma(&self, dmac: &DMAC, channel_num: dma_channel, chip_select: u32, rx: &mut [u32]);
|
||||
fn send_data<X: Into<u32> + Copy>(&self, chip_select: u32, tx: &[X]);
|
||||
fn send_data_dma(&self, dmac: &DMAC, channel_num: dma_channel, chip_select: u32, tx: &[u32]);
|
||||
fn fill_data(&self, chip_select: u32, value: u32, tx_len: usize);
|
||||
@ -193,6 +194,30 @@ impl<IF: SPI01> SPI for SPIImpl<IF> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Receive 32-bit data using DMA.
|
||||
// make sure to set tmod to tmod::RECV
|
||||
fn recv_data_dma(&self, dmac: &DMAC, channel_num: dma_channel, chip_select: u32, rx: &mut [u32]) {
|
||||
if rx.len() == 0 {
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
self.spi.ctrlr1.write(|w| w.bits((rx.len() - 1).try_into().unwrap()));
|
||||
self.spi.ssienr.write(|w| w.bits(0x01));
|
||||
self.spi.dmacr.write(|w| w.bits(0x3)); /*enable dma receive */
|
||||
|
||||
sysctl::dma_select(channel_num, IF::DMA_RX);
|
||||
dmac.set_single_mode(channel_num, self.spi.dr.as_ptr() as u64, rx.as_ptr() as u64,
|
||||
address_increment::NOCHANGE, address_increment::INCREMENT,
|
||||
burst_length::LENGTH_1, transfer_width::WIDTH_32, rx.len() as u32);
|
||||
self.spi.dr[0].write(|w| w.bits(0xffffffff));
|
||||
self.spi.ser.write(|w| w.bits(1 << chip_select));
|
||||
dmac.wait_done(channel_num);
|
||||
|
||||
self.spi.ser.write(|w| w.bits(0x00));
|
||||
self.spi.ssienr.write(|w| w.bits(0x00));
|
||||
}
|
||||
}
|
||||
|
||||
/// Send arbitrary data
|
||||
fn send_data<X: Into<u32> + Copy>(&self, chip_select: u32, tx: &[X]) {
|
||||
unsafe {
|
||||
|
Loading…
Reference in New Issue
Block a user