diff --git a/rust/k210-shared/src/board/sdcard.rs b/rust/k210-shared/src/board/sdcard.rs index e58f3af..c6ae526 100644 --- a/rust/k210-shared/src/board/sdcard.rs +++ b/rust/k210-shared/src/board/sdcard.rs @@ -1,4 +1,4 @@ -//! SD card slot access on Maix Go +//! SD card slot access (in SPI mode) on Maix Go // TODO: actually use the DMA channel that is claimed… use core::convert::TryInto; @@ -34,7 +34,7 @@ pub const SEC_LEN: usize = 512; /** SD commands */ #[repr(u8)] #[derive(Debug, PartialEq, Eq, Copy, Clone)] -enum CMD { +pub enum CMD { /** Software reset */ CMD0 = 0, /** Check voltage range (SDC V2) */ @@ -67,6 +67,13 @@ enum CMD { CMD59 = 59, } +#[derive(Debug, Copy, Clone)] +pub enum InitError { + CMDFailed(CMD, u8), + CardCapacityStatusNotSet([u8; 4]), + CannotGetCardInfo, +} + /** * Card Specific Data: CSD Register */ @@ -441,15 +448,18 @@ impl<'a, X: SPI> SDCard<'a, X> { } /* - * Initializes the SD/SD communication. + * Initializes the SD/SD communication in SPI mode. * @param None * @retval The SD Response info if succeeeded, otherwise Err */ - pub fn init(&self) -> Result { + pub fn init(&self) -> Result { /* Initialize SD_SPI */ self.lowlevel_init(); /* SD chip select high */ self.CS_HIGH(); + /* NOTE: this reset doesn't always seem to work if the SD access was broken off in the + * middle of an operation: CMDFailed(CMD0, 127). */ + /* Send dummy byte 0xFF, 10 times with CS high */ /* Rise CS and MOSI for 80 clocks cycles */ /* Send dummy byte 0xFF */ @@ -457,15 +467,15 @@ impl<'a, X: SPI> SDCard<'a, X> { /*------------Put SD in SPI mode--------------*/ /* SD initialized and set to SPI mode properly */ + /* Send software reset */ self.send_cmd(CMD::CMD0, 0, 0x95); let result = self.get_response(); self.end_cmd(); if result != 0x01 { - // printf("SD_CMD0 is %X\n", result); - // TODO: better erroring - return Err(()); + return Err(InitError::CMDFailed(CMD::CMD0, result)); } + /* Check voltage range */ self.send_cmd(CMD::CMD8, 0x01AA, 0x87); /* 0x01 or 0x05 */ let result = self.get_response(); @@ -473,17 +483,18 @@ impl<'a, X: SPI> SDCard<'a, X> { self.read_data(&mut frame); self.end_cmd(); if result != 0x01 { - //printf("SD_CMD8 is %X\n", result); - return Err(()); + return Err(InitError::CMDFailed(CMD::CMD8, result)); } let mut index = 255; while index != 0 { + /* */ self.send_cmd(CMD::CMD55, 0, 0); let result = self.get_response(); self.end_cmd(); if result != 0x01 { - return Err(()); + return Err(InitError::CMDFailed(CMD::CMD55, result)); } + /* Initiate SDC initialization process */ self.send_cmd(CMD::ACMD41, 0x40000000, 0); let result = self.get_response(); self.end_cmd(); @@ -493,12 +504,12 @@ impl<'a, X: SPI> SDCard<'a, X> { index -= 1; } if index == 0 { - //printf("SD_CMD55 is %X\n", result); - return Err(()); + return Err(InitError::CMDFailed(CMD::ACMD41, result)); } index = 255; let mut frame = [0u8; 4]; while index != 0 { + /* Read OCR */ self.send_cmd(CMD::CMD58, 0, 1); let result = self.get_response(); self.read_data(&mut frame); @@ -509,20 +520,19 @@ impl<'a, X: SPI> SDCard<'a, X> { index -= 1; } if index == 0 { - // printf("SD_CMD58 is %X\n", result); - return Err(()); + return Err(InitError::CMDFailed(CMD::CMD58, result)); } if (frame[0] & 0x40) == 0 { - return Err(()); + return Err(InitError::CardCapacityStatusNotSet(frame)); } self.HIGH_SPEED_ENABLE(); self.get_cardinfo() + .map_err(|_| InitError::CannotGetCardInfo) } /* * Reads a block of data from the SD. - * @param data_buf: pointer to the buffer that receives the data read from the - * SD. + * @param data_buf: slice that receives the data read from the SD. * @param sector: SD's internal address to read from. * @retval The SD Response: * - `Err(())`: Sequence failed @@ -572,8 +582,7 @@ impl<'a, X: SPI> SDCard<'a, X> { /* * Writes a block to the SD - * @param data_buf: pointer to the buffer containing the data to be written on - * the SD. + * @param data_buf: slice containing the data to be written to the SD. * @param sector: address to write on. * @retval The SD Response: * - `Err(())`: Sequence failed diff --git a/rust/sdlcd/src/main.rs b/rust/sdlcd/src/main.rs index 16436b4..9dd646d 100644 --- a/rust/sdlcd/src/main.rs +++ b/rust/sdlcd/src/main.rs @@ -1,4 +1,6 @@ -/*! Stream raw data from SD card to LCD, bascially a test for using both SPI0 and SPI1 */ +/*! Stream raw data from SD card to LCD, bascially a test for using both SPI0 and SPI1 + * at the same time + */ #![allow(dead_code)] #![allow(non_snake_case)] #![allow(non_camel_case_types)] @@ -9,8 +11,8 @@ use core::convert::TryInto; use k210_hal::prelude::*; use k210_hal::stdout::Stdout; use k210_hal::Peripherals; -use k210_shared::board::def::{io,DISP_WIDTH,DISP_HEIGHT,DISP_PIXELS}; -use k210_shared::board::lcd::{LCD,LCDHL,self}; +use k210_shared::board::def::{io, DISP_HEIGHT, DISP_PIXELS, DISP_WIDTH}; +use k210_shared::board::lcd::{self, LCD, LCDHL}; use k210_shared::board::lcd_colors; use k210_shared::board::sdcard; use k210_shared::soc::dmac::{dma_channel, DMACExt}; @@ -22,7 +24,7 @@ use riscv_rt::entry; /** GPIOHS GPIO number to use for controlling the SD card CS pin */ const SD_CS_GPIONUM: u8 = 7; -/** CS value passed to SPI controller, this is a dummy value as SPI0_CS3 is not mapping to anything +/** CS value passed to SPI controller, this is a dummy value as SPI0_CS3 is not mapped to anything * in the FPIOA */ const SD_CS: u32 = 3; @@ -90,14 +92,17 @@ fn main() -> ! { let mut image: ScreenImage = [0; DISP_PIXELS / 2]; let mut buffer = [0u8; DISP_PIXELS * 2]; while sector < num_sectors { - sd.read_sector(&mut buffer, sector.try_into().unwrap()).unwrap(); + /* Read raw image */ + sd.read_sector(&mut buffer, sector.try_into().unwrap()) + .unwrap(); writeln!(stdout, "sector {} succesfully read", sector).unwrap(); let mut i = buffer.iter(); + /* Combine into u32s, reordering 16-bit halves */ for x in image.iter_mut() { - *x = (u32::from(*i.next().unwrap()) << 0) | - (u32::from(*i.next().unwrap()) << 8) | - (u32::from(*i.next().unwrap()) << 16) | - (u32::from(*i.next().unwrap()) << 24); + *x = (u32::from(*i.next().unwrap()) << 16) + | (u32::from(*i.next().unwrap()) << 24) + | (u32::from(*i.next().unwrap()) << 0) + | (u32::from(*i.next().unwrap()) << 8); } lcd.draw_picture(0, 0, DISP_WIDTH, DISP_HEIGHT, &image);