Merge branch 'main' into fix/kstack-leak

This commit is contained in:
Yifan Wu 2023-02-08 11:08:27 +08:00 committed by GitHub
commit 2dc89534a4
106 changed files with 3974 additions and 2260 deletions

View file

@ -1,7 +1,5 @@
mod sdcard;
mod virtio_blk;
pub use sdcard::SDCardWrapper;
pub use virtio_blk::VirtIOBlock;
use crate::board::BlockDeviceImpl;

View file

@ -1,767 +0,0 @@
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(unused)]
use super::BlockDevice;
use crate::sync::UPIntrFreeCell;
use core::convert::TryInto;
use k210_hal::prelude::*;
use k210_pac::{Peripherals, SPI0};
use k210_soc::{
fpioa::{self, io},
//dmac::{dma_channel, DMAC, DMACExt},
gpio,
gpiohs,
sleep::usleep,
spi::{aitm, frame_format, tmod, work_mode, SPIExt, SPIImpl, SPI},
sysctl,
};
use lazy_static::*;
pub struct SDCard<SPI> {
spi: SPI,
spi_cs: u32,
cs_gpionum: u8,
//dmac: &'a DMAC,
//channel: dma_channel,
}
/*
* Start Data tokens:
* Tokens (necessary because at nop/idle (and CS active) only 0xff is
* on the data/command line)
*/
/** Data token start byte, Start Single Block Read */
pub const SD_START_DATA_SINGLE_BLOCK_READ: u8 = 0xFE;
/** Data token start byte, Start Multiple Block Read */
pub const SD_START_DATA_MULTIPLE_BLOCK_READ: u8 = 0xFE;
/** Data token start byte, Start Single Block Write */
pub const SD_START_DATA_SINGLE_BLOCK_WRITE: u8 = 0xFE;
/** Data token start byte, Start Multiple Block Write */
pub const SD_START_DATA_MULTIPLE_BLOCK_WRITE: u8 = 0xFC;
pub const SEC_LEN: usize = 512;
/** SD commands */
#[repr(u8)]
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[allow(unused)]
pub enum CMD {
/** Software reset */
CMD0 = 0,
/** Check voltage range (SDC V2) */
CMD8 = 8,
/** Read CSD register */
CMD9 = 9,
/** Read CID register */
CMD10 = 10,
/** Stop to read data */
CMD12 = 12,
/** Change R/W block size */
CMD16 = 16,
/** Read block */
CMD17 = 17,
/** Read multiple blocks */
CMD18 = 18,
/** Number of blocks to erase (SDC) */
ACMD23 = 23,
/** Write a block */
CMD24 = 24,
/** Write multiple blocks */
CMD25 = 25,
/** Initiate initialization process (SDC) */
ACMD41 = 41,
/** Leading command for ACMD* */
CMD55 = 55,
/** Read OCR */
CMD58 = 58,
/** Enable/disable CRC check */
CMD59 = 59,
}
#[allow(unused)]
#[derive(Debug, Copy, Clone)]
pub enum InitError {
CMDFailed(CMD, u8),
CardCapacityStatusNotSet([u8; 4]),
CannotGetCardInfo,
}
/**
* Card Specific Data: CSD Register
*/
#[derive(Debug, Copy, Clone)]
pub struct SDCardCSD {
pub CSDStruct: u8, /* CSD structure */
pub SysSpecVersion: u8, /* System specification version */
pub Reserved1: u8, /* Reserved */
pub TAAC: u8, /* Data read access-time 1 */
pub NSAC: u8, /* Data read access-time 2 in CLK cycles */
pub MaxBusClkFrec: u8, /* Max. bus clock frequency */
pub CardComdClasses: u16, /* Card command classes */
pub RdBlockLen: u8, /* Max. read data block length */
pub PartBlockRead: u8, /* Partial blocks for read allowed */
pub WrBlockMisalign: u8, /* Write block misalignment */
pub RdBlockMisalign: u8, /* Read block misalignment */
pub DSRImpl: u8, /* DSR implemented */
pub Reserved2: u8, /* Reserved */
pub DeviceSize: u32, /* Device Size */
//MaxRdCurrentVDDMin: u8, /* Max. read current @ VDD min */
//MaxRdCurrentVDDMax: u8, /* Max. read current @ VDD max */
//MaxWrCurrentVDDMin: u8, /* Max. write current @ VDD min */
//MaxWrCurrentVDDMax: u8, /* Max. write current @ VDD max */
//DeviceSizeMul: u8, /* Device size multiplier */
pub EraseGrSize: u8, /* Erase group size */
pub EraseGrMul: u8, /* Erase group size multiplier */
pub WrProtectGrSize: u8, /* Write protect group size */
pub WrProtectGrEnable: u8, /* Write protect group enable */
pub ManDeflECC: u8, /* Manufacturer default ECC */
pub WrSpeedFact: u8, /* Write speed factor */
pub MaxWrBlockLen: u8, /* Max. write data block length */
pub WriteBlockPaPartial: u8, /* Partial blocks for write allowed */
pub Reserved3: u8, /* Reserded */
pub ContentProtectAppli: u8, /* Content protection application */
pub FileFormatGroup: u8, /* File format group */
pub CopyFlag: u8, /* Copy flag (OTP) */
pub PermWrProtect: u8, /* Permanent write protection */
pub TempWrProtect: u8, /* Temporary write protection */
pub FileFormat: u8, /* File Format */
pub ECC: u8, /* ECC code */
pub CSD_CRC: u8, /* CSD CRC */
pub Reserved4: u8, /* always 1*/
}
/**
* Card Identification Data: CID Register
*/
#[derive(Debug, Copy, Clone)]
pub struct SDCardCID {
pub ManufacturerID: u8, /* ManufacturerID */
pub OEM_AppliID: u16, /* OEM/Application ID */
pub ProdName1: u32, /* Product Name part1 */
pub ProdName2: u8, /* Product Name part2*/
pub ProdRev: u8, /* Product Revision */
pub ProdSN: u32, /* Product Serial Number */
pub Reserved1: u8, /* Reserved1 */
pub ManufactDate: u16, /* Manufacturing Date */
pub CID_CRC: u8, /* CID CRC */
pub Reserved2: u8, /* always 1 */
}
/**
* Card information
*/
#[derive(Debug, Copy, Clone)]
pub struct SDCardInfo {
pub SD_csd: SDCardCSD,
pub SD_cid: SDCardCID,
pub CardCapacity: u64, /* Card Capacity */
pub CardBlockSize: u64, /* Card Block Size */
}
impl</*'a,*/ X: SPI> SDCard</*'a,*/ X> {
pub fn new(
spi: X,
spi_cs: u32,
cs_gpionum: u8, /*, dmac: &'a DMAC, channel: dma_channel*/
) -> Self {
Self {
spi,
spi_cs,
cs_gpionum,
/*
dmac,
channel,
*/
}
}
fn CS_HIGH(&self) {
gpiohs::set_pin(self.cs_gpionum, true);
}
fn CS_LOW(&self) {
gpiohs::set_pin(self.cs_gpionum, false);
}
fn HIGH_SPEED_ENABLE(&self) {
self.spi.set_clk_rate(10000000);
}
fn lowlevel_init(&self) {
gpiohs::set_direction(self.cs_gpionum, gpio::direction::OUTPUT);
self.spi.set_clk_rate(200000);
}
fn write_data(&self, data: &[u8]) {
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(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,
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(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.
* @param arg: The command argument.
* @param crc: The CRC.
* @retval None
*/
fn send_cmd(&self, cmd: CMD, arg: u32, crc: u8) {
/* SD chip select low */
self.CS_LOW();
/* Send the Cmd bytes */
self.write_data(&[
/* Construct byte 1 */
((cmd as u8) | 0x40),
/* Construct byte 2 */
(arg >> 24) as u8,
/* Construct byte 3 */
((arg >> 16) & 0xff) as u8,
/* Construct byte 4 */
((arg >> 8) & 0xff) as u8,
/* Construct byte 5 */
(arg & 0xff) as u8,
/* Construct CRC: byte 6 */
crc,
]);
}
/* Send end-command sequence to SD card */
fn end_cmd(&self) {
/* SD chip select high */
self.CS_HIGH();
/* Send the cmd byte */
self.write_data(&[0xff]);
}
/*
* Returns the SD response.
* @param None
* @retval The SD Response:
* - 0xFF: Sequence failed
* - 0: Sequence succeed
*/
fn get_response(&self) -> u8 {
let result = &mut [0u8];
let mut timeout = 0x0FFF;
/* Check if response is got or a timeout is happen */
while timeout != 0 {
self.read_data(result);
/* Right response got */
if result[0] != 0xFF {
return result[0];
}
timeout -= 1;
}
/* After time out */
0xFF
}
/*
* Get SD card data response.
* @param None
* @retval The SD status: Read data response xxx0<status>1
* - status 010: Data accepted
* - status 101: Data rejected due to a crc error
* - status 110: Data rejected due to a Write error.
* - status 111: Data rejected due to other error.
*/
fn get_dataresponse(&self) -> u8 {
let response = &mut [0u8];
/* Read response */
self.read_data(response);
/* Mask unused bits */
response[0] &= 0x1F;
if response[0] != 0x05 {
return 0xFF;
}
/* Wait null data */
self.read_data(response);
while response[0] == 0 {
self.read_data(response);
}
/* Return response */
0
}
/*
* Read the CSD card register
* Reading the contents of the CSD register in SPI mode is a simple
* read-block transaction.
* @param SD_csd: pointer on an SCD register structure
* @retval The SD Response:
* - `Err()`: Sequence failed
* - `Ok(info)`: Sequence succeed
*/
fn get_csdregister(&self) -> Result<SDCardCSD, ()> {
let mut csd_tab = [0u8; 18];
/* Send CMD9 (CSD register) */
self.send_cmd(CMD::CMD9, 0, 0);
/* Wait for response in the R1 format (0x00 is no errors) */
if self.get_response() != 0x00 {
self.end_cmd();
return Err(());
}
if self.get_response() != SD_START_DATA_SINGLE_BLOCK_READ {
self.end_cmd();
return Err(());
}
/* Store CSD register value on csd_tab */
/* Get CRC bytes (not really needed by us, but required by SD) */
self.read_data(&mut csd_tab);
self.end_cmd();
/* see also: https://cdn-shop.adafruit.com/datasheets/TS16GUSDHC6.pdf */
Ok(SDCardCSD {
/* Byte 0 */
CSDStruct: (csd_tab[0] & 0xC0) >> 6,
SysSpecVersion: (csd_tab[0] & 0x3C) >> 2,
Reserved1: csd_tab[0] & 0x03,
/* Byte 1 */
TAAC: csd_tab[1],
/* Byte 2 */
NSAC: csd_tab[2],
/* Byte 3 */
MaxBusClkFrec: csd_tab[3],
/* Byte 4, 5 */
CardComdClasses: (u16::from(csd_tab[4]) << 4) | ((u16::from(csd_tab[5]) & 0xF0) >> 4),
/* Byte 5 */
RdBlockLen: csd_tab[5] & 0x0F,
/* Byte 6 */
PartBlockRead: (csd_tab[6] & 0x80) >> 7,
WrBlockMisalign: (csd_tab[6] & 0x40) >> 6,
RdBlockMisalign: (csd_tab[6] & 0x20) >> 5,
DSRImpl: (csd_tab[6] & 0x10) >> 4,
Reserved2: 0,
// DeviceSize: (csd_tab[6] & 0x03) << 10,
/* Byte 7, 8, 9 */
DeviceSize: ((u32::from(csd_tab[7]) & 0x3F) << 16)
| (u32::from(csd_tab[8]) << 8)
| u32::from(csd_tab[9]),
/* Byte 10 */
EraseGrSize: (csd_tab[10] & 0x40) >> 6,
/* Byte 10, 11 */
EraseGrMul: ((csd_tab[10] & 0x3F) << 1) | ((csd_tab[11] & 0x80) >> 7),
/* Byte 11 */
WrProtectGrSize: (csd_tab[11] & 0x7F),
/* Byte 12 */
WrProtectGrEnable: (csd_tab[12] & 0x80) >> 7,
ManDeflECC: (csd_tab[12] & 0x60) >> 5,
WrSpeedFact: (csd_tab[12] & 0x1C) >> 2,
/* Byte 12,13 */
MaxWrBlockLen: ((csd_tab[12] & 0x03) << 2) | ((csd_tab[13] & 0xC0) >> 6),
/* Byte 13 */
WriteBlockPaPartial: (csd_tab[13] & 0x20) >> 5,
Reserved3: 0,
ContentProtectAppli: (csd_tab[13] & 0x01),
/* Byte 14 */
FileFormatGroup: (csd_tab[14] & 0x80) >> 7,
CopyFlag: (csd_tab[14] & 0x40) >> 6,
PermWrProtect: (csd_tab[14] & 0x20) >> 5,
TempWrProtect: (csd_tab[14] & 0x10) >> 4,
FileFormat: (csd_tab[14] & 0x0C) >> 2,
ECC: (csd_tab[14] & 0x03),
/* Byte 15 */
CSD_CRC: (csd_tab[15] & 0xFE) >> 1,
Reserved4: 1,
/* Return the response */
})
}
/*
* Read the CID card register.
* Reading the contents of the CID register in SPI mode is a simple
* read-block transaction.
* @param SD_cid: pointer on an CID register structure
* @retval The SD Response:
* - `Err()`: Sequence failed
* - `Ok(info)`: Sequence succeed
*/
fn get_cidregister(&self) -> Result<SDCardCID, ()> {
let mut cid_tab = [0u8; 18];
/* Send CMD10 (CID register) */
self.send_cmd(CMD::CMD10, 0, 0);
/* Wait for response in the R1 format (0x00 is no errors) */
if self.get_response() != 0x00 {
self.end_cmd();
return Err(());
}
if self.get_response() != SD_START_DATA_SINGLE_BLOCK_READ {
self.end_cmd();
return Err(());
}
/* Store CID register value on cid_tab */
/* Get CRC bytes (not really needed by us, but required by SD) */
self.read_data(&mut cid_tab);
self.end_cmd();
Ok(SDCardCID {
/* Byte 0 */
ManufacturerID: cid_tab[0],
/* Byte 1, 2 */
OEM_AppliID: (u16::from(cid_tab[1]) << 8) | u16::from(cid_tab[2]),
/* Byte 3, 4, 5, 6 */
ProdName1: (u32::from(cid_tab[3]) << 24)
| (u32::from(cid_tab[4]) << 16)
| (u32::from(cid_tab[5]) << 8)
| u32::from(cid_tab[6]),
/* Byte 7 */
ProdName2: cid_tab[7],
/* Byte 8 */
ProdRev: cid_tab[8],
/* Byte 9, 10, 11, 12 */
ProdSN: (u32::from(cid_tab[9]) << 24)
| (u32::from(cid_tab[10]) << 16)
| (u32::from(cid_tab[11]) << 8)
| u32::from(cid_tab[12]),
/* Byte 13, 14 */
Reserved1: (cid_tab[13] & 0xF0) >> 4,
ManufactDate: ((u16::from(cid_tab[13]) & 0x0F) << 8) | u16::from(cid_tab[14]),
/* Byte 15 */
CID_CRC: (cid_tab[15] & 0xFE) >> 1,
Reserved2: 1,
})
}
/*
* Returns information about specific card.
* @param cardinfo: pointer to a SD_CardInfo structure that contains all SD
* card information.
* @retval The SD Response:
* - `Err(())`: Sequence failed
* - `Ok(info)`: Sequence succeed
*/
fn get_cardinfo(&self) -> Result<SDCardInfo, ()> {
let mut info = SDCardInfo {
SD_csd: self.get_csdregister()?,
SD_cid: self.get_cidregister()?,
CardCapacity: 0,
CardBlockSize: 0,
};
info.CardBlockSize = 1 << u64::from(info.SD_csd.RdBlockLen);
info.CardCapacity = (u64::from(info.SD_csd.DeviceSize) + 1) * 1024 * info.CardBlockSize;
Ok(info)
}
/*
* Initializes the SD/SD communication in SPI mode.
* @param None
* @retval The SD Response info if succeeeded, otherwise Err
*/
pub fn init(&self) -> Result<SDCardInfo, InitError> {
/* 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 */
self.write_data(&[0xff; 10]);
/*------------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 {
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();
let mut frame = [0u8; 4];
self.read_data(&mut frame);
self.end_cmd();
if result != 0x01 {
return Err(InitError::CMDFailed(CMD::CMD8, result));
}
let mut index = 255;
while index != 0 {
/* <ACMD> */
self.send_cmd(CMD::CMD55, 0, 0);
let result = self.get_response();
self.end_cmd();
if result != 0x01 {
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();
if result == 0x00 {
break;
}
index -= 1;
}
if index == 0 {
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);
self.end_cmd();
if result == 0 {
break;
}
index -= 1;
}
if index == 0 {
return Err(InitError::CMDFailed(CMD::CMD58, result));
}
if (frame[0] & 0x40) == 0 {
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: 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
* - `Ok(())`: Sequence succeed
*/
pub fn read_sector(&self, data_buf: &mut [u8], sector: u32) -> Result<(), ()> {
assert!(data_buf.len() >= SEC_LEN && (data_buf.len() % SEC_LEN) == 0);
/* Send CMD17 to read one block, or CMD18 for multiple */
let flag = if data_buf.len() == SEC_LEN {
self.send_cmd(CMD::CMD17, sector, 0);
false
} else {
self.send_cmd(CMD::CMD18, sector, 0);
true
};
/* Check if the SD acknowledged the read block command: R1 response (0x00: no errors) */
if self.get_response() != 0x00 {
self.end_cmd();
return Err(());
}
let mut error = false;
//let mut dma_chunk = [0u32; SEC_LEN];
let mut tmp_chunk = [0u8; 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_dma(&mut dma_chunk);
self.read_data(&mut tmp_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*/ tmp_chunk.iter()) {
//*a = (b & 0xff) as u8;
*a = *b;
}
/* Get CRC bytes (not really needed by us, but required by SD) */
let mut frame = [0u8; 2];
self.read_data(&mut frame);
}
self.end_cmd();
if flag {
self.send_cmd(CMD::CMD12, 0, 0);
self.get_response();
self.end_cmd();
self.end_cmd();
}
/* It is an error if not everything requested was read */
if error {
Err(())
} else {
Ok(())
}
}
/*
* Writes a block to 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
* - `Ok(())`: Sequence succeed
*/
pub fn write_sector(&self, data_buf: &[u8], sector: u32) -> Result<(), ()> {
assert!(data_buf.len() >= SEC_LEN && (data_buf.len() % SEC_LEN) == 0);
let mut frame = [0xff, 0x00];
if data_buf.len() == SEC_LEN {
frame[1] = SD_START_DATA_SINGLE_BLOCK_WRITE;
self.send_cmd(CMD::CMD24, sector, 0);
} else {
frame[1] = SD_START_DATA_MULTIPLE_BLOCK_WRITE;
self.send_cmd(
CMD::ACMD23,
(data_buf.len() / SEC_LEN).try_into().unwrap(),
0,
);
self.get_response();
self.end_cmd();
self.send_cmd(CMD::CMD25, sector, 0);
}
/* Check if the SD acknowledged the write block command: R1 response (0x00: no errors) */
if self.get_response() != 0x00 {
self.end_cmd();
return Err(());
}
//let mut dma_chunk = [0u32; SEC_LEN];
let mut tmp_chunk = [0u8; 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 */
for (a, &b) in /*dma_chunk*/ tmp_chunk.iter_mut().zip(chunk.iter()) {
//*a = b.into();
*a = b;
}
//self.write_data_dma(&mut dma_chunk);
self.write_data(&tmp_chunk);
/* Put dummy CRC bytes */
self.write_data(&[0xff, 0xff]);
/* Read data response */
if self.get_dataresponse() != 0x00 {
self.end_cmd();
return Err(());
}
}
self.end_cmd();
self.end_cmd();
Ok(())
}
}
/** 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
* in the FPIOA */
const SD_CS: u32 = 3;
/** Connect pins to internal functions */
fn io_init() {
fpioa::set_function(io::SPI0_SCLK, fpioa::function::SPI0_SCLK);
fpioa::set_function(io::SPI0_MOSI, fpioa::function::SPI0_D0);
fpioa::set_function(io::SPI0_MISO, fpioa::function::SPI0_D1);
fpioa::set_function(io::SPI0_CS0, fpioa::function::gpiohs(SD_CS_GPIONUM));
fpioa::set_io_pull(io::SPI0_CS0, fpioa::pull::DOWN); // GPIO output=pull down
}
lazy_static! {
static ref PERIPHERALS: UPIntrFreeCell<Peripherals> =
unsafe { UPIntrFreeCell::new(Peripherals::take().unwrap()) };
}
fn init_sdcard() -> SDCard<SPIImpl<SPI0>> {
// wait previous output
usleep(100000);
let peripherals = unsafe { Peripherals::steal() };
sysctl::pll_set_freq(sysctl::pll::PLL0, 800_000_000).unwrap();
sysctl::pll_set_freq(sysctl::pll::PLL1, 300_000_000).unwrap();
sysctl::pll_set_freq(sysctl::pll::PLL2, 45_158_400).unwrap();
let clocks = k210_hal::clock::Clocks::new();
peripherals.UARTHS.configure(115_200.bps(), &clocks);
io_init();
let spi = peripherals.SPI0.constrain();
let sd = SDCard::new(spi, SD_CS, SD_CS_GPIONUM);
let info = sd.init().unwrap();
let num_sectors = info.CardCapacity / 512;
assert!(num_sectors > 0);
println!("init sdcard!");
sd
}
pub struct SDCardWrapper(UPIntrFreeCell<SDCard<SPIImpl<SPI0>>>);
impl SDCardWrapper {
pub fn new() -> Self {
unsafe { Self(UPIntrFreeCell::new(init_sdcard())) }
}
}
impl BlockDevice for SDCardWrapper {
fn read_block(&self, block_id: usize, buf: &mut [u8]) {
self.0
.exclusive_access()
.read_sector(buf, block_id as u32)
.unwrap();
}
fn write_block(&self, block_id: usize, buf: &[u8]) {
self.0
.exclusive_access()
.write_sector(buf, block_id as u32)
.unwrap();
}
fn handle_irq(&self) {
unimplemented!();
}
}

View file

@ -1,4 +1,5 @@
use super::BlockDevice;
use crate::drivers::bus::virtio::VirtioHal;
use crate::sync::{Condvar, UPIntrFreeCell};
use crate::task::schedule;
use crate::DEV_NON_BLOCKING_ACCESS;
@ -69,7 +70,9 @@ impl BlockDevice for VirtIOBlock {
impl VirtIOBlock {
pub fn new() -> Self {
let virtio_blk = unsafe {
UPIntrFreeCell::new(VirtIOBlk::<VirtioHal>::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap())
UPIntrFreeCell::new(
VirtIOBlk::<VirtioHal>::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap(),
)
};
let mut condvars = BTreeMap::new();
let channels = virtio_blk.exclusive_access().virt_queue_size();
@ -83,4 +86,3 @@ impl VirtIOBlock {
}
}
}

View file

@ -1 +1 @@
pub mod virtio;
pub mod virtio;

View file

@ -1,9 +1,9 @@
use alloc::vec::Vec;
use crate::mm::{
frame_alloc, frame_dealloc, kernel_token, FrameTracker, PageTable, PhysAddr, PhysPageNum,
StepByOne, VirtAddr,
StepByOne, VirtAddr, frame_alloc_more,
};
use crate::sync::UPIntrFreeCell;
use alloc::vec::Vec;
use lazy_static::*;
use virtio_drivers::Hal;
@ -16,15 +16,9 @@ pub struct VirtioHal;
impl Hal for VirtioHal {
fn dma_alloc(pages: usize) -> usize {
let mut ppn_base = PhysPageNum(0);
for i in 0..pages {
let frame = frame_alloc().unwrap();
if i == 0 {
ppn_base = frame.ppn;
}
assert_eq!(frame.ppn.0, ppn_base.0 + i);
QUEUE_FRAMES.exclusive_access().push(frame);
}
let trakcers = frame_alloc_more(pages);
let ppn_base = trakcers.as_ref().unwrap().last().unwrap().ppn;
QUEUE_FRAMES.exclusive_access().append(&mut trakcers.unwrap());
let pa: PhysAddr = ppn_base.into();
pa.0
}
@ -49,4 +43,4 @@ impl Hal for VirtioHal {
.unwrap()
.0
}
}
}

View file

@ -1,17 +1,17 @@
mod ns16550a;
#[cfg(feature = "board_qemu")]
use crate::board::CharDeviceImpl;
use alloc::sync::Arc;
use lazy_static::*;
pub use ns16550a::NS16550a;
pub trait CharDevice {
fn init(&self);
fn read(&self) -> u8;
fn write(&self, ch: u8);
fn handle_irq(&self);
}
#[cfg(feature = "board_qemu")]
lazy_static! {
pub static ref UART: Arc<CharDeviceImpl> = Arc::new(CharDeviceImpl::new());
}

View file

@ -131,19 +131,30 @@ pub struct NS16550a<const BASE_ADDR: usize> {
impl<const BASE_ADDR: usize> NS16550a<BASE_ADDR> {
pub fn new() -> Self {
let mut inner = NS16550aInner {
let inner = NS16550aInner {
ns16550a: NS16550aRaw::new(BASE_ADDR),
read_buffer: VecDeque::new(),
};
inner.ns16550a.init();
//inner.ns16550a.init();
Self {
inner: unsafe { UPIntrFreeCell::new(inner) },
condvar: Condvar::new(),
}
}
pub fn read_buffer_is_empty(&self) -> bool {
self.inner
.exclusive_session(|inner| inner.read_buffer.is_empty())
}
}
impl<const BASE_ADDR: usize> CharDevice for NS16550a<BASE_ADDR> {
fn init(&self) {
let mut inner = self.inner.exclusive_access();
inner.ns16550a.init();
drop(inner);
}
fn read(&self) -> u8 {
loop {
let mut inner = self.inner.exclusive_access();

View file

@ -1,3 +1,4 @@
use crate::drivers::bus::virtio::VirtioHal;
use crate::sync::UPIntrFreeCell;
use alloc::{sync::Arc, vec::Vec};
use core::any::Any;
@ -6,25 +7,26 @@ use tinybmp::Bmp;
use virtio_drivers::{VirtIOGpu, VirtIOHeader};
use crate::drivers::bus::virtio::VirtioHal;
const VIRTIO7: usize = 0x10007000;
pub trait GPUDevice: Send + Sync + Any {
pub trait GpuDevice: Send + Sync + Any {
fn update_cursor(&self);
fn getfreambuffer(&self) -> &mut [u8];
fn get_framebuffer(&self) -> &mut [u8];
fn flush(&self);
}
lazy_static::lazy_static!(
pub static ref GPU_DEVICE: Arc<dyn GPUDevice> = Arc::new(VirtIOGPU::new());
pub static ref GPU_DEVICE: Arc<dyn GpuDevice> = Arc::new(VirtIOGpuWrapper::new());
);
pub struct VirtIOGPU {
pub struct VirtIOGpuWrapper {
gpu: UPIntrFreeCell<VirtIOGpu<'static, VirtioHal>>,
fb: &'static [u8],
}
static BMP_DATA: &[u8] = include_bytes!("../../assert/mouse.bmp");
impl VirtIOGPU {
impl VirtIOGpuWrapper {
pub fn new() -> Self {
unsafe {
let mut virtio = VirtIOGpu::<VirtioHal>::new(&mut *(VIRTIO7 as *mut VirtIOHeader)).unwrap();
let mut virtio =
VirtIOGpu::<VirtioHal>::new(&mut *(VIRTIO7 as *mut VirtIOHeader)).unwrap();
let fbuffer = virtio.setup_framebuffer().unwrap();
let len = fbuffer.len();
@ -53,11 +55,11 @@ impl VirtIOGPU {
}
}
impl GPUDevice for VirtIOGPU {
impl GpuDevice for VirtIOGpuWrapper {
fn flush(&self) {
self.gpu.exclusive_access().flush().unwrap();
}
fn getfreambuffer(&self) -> &mut [u8] {
fn get_framebuffer(&self) -> &mut [u8] {
unsafe {
let ptr = self.fb.as_ptr() as *const _ as *mut u8;
core::slice::from_raw_parts_mut(ptr, self.fb.len())

View file

@ -1,75 +1,83 @@
use crate::{
gui::{Button, Component},
sync::UPIntrFreeCell,
syscall::PAD,
};
use alloc::{string::ToString, sync::Arc};
use core::any::Any;
use embedded_graphics::{
prelude::{Point, Size},
text::Text,
};
use k210_hal::cache::Uncache;
use virtio_drivers::{VirtIOHeader, VirtIOInput};
use crate::drivers::bus::virtio::VirtioHal;
use virtio_input_decoder::{Decoder, Key, KeyType};
use super::GPU_DEVICE;
use crate::sync::{Condvar, UPIntrFreeCell};
use crate::task::schedule;
use alloc::collections::VecDeque;
use alloc::sync::Arc;
use core::any::Any;
use virtio_drivers::{VirtIOHeader, VirtIOInput};
const VIRTIO5: usize = 0x10005000;
const VIRTIO6: usize = 0x10006000;
struct VirtIOINPUT(UPIntrFreeCell<VirtIOInput<'static, VirtioHal>>);
struct VirtIOInputInner {
virtio_input: VirtIOInput<'static, VirtioHal>,
events: VecDeque<u64>,
}
pub trait INPUTDevice: Send + Sync + Any {
struct VirtIOInputWrapper {
inner: UPIntrFreeCell<VirtIOInputInner>,
condvar: Condvar,
}
pub trait InputDevice: Send + Sync + Any {
fn read_event(&self) -> u64;
fn handle_irq(&self);
fn is_empty(&self) -> bool;
}
lazy_static::lazy_static!(
pub static ref KEYBOARD_DEVICE: Arc<dyn INPUTDevice> = Arc::new(VirtIOINPUT::new(VIRTIO5));
pub static ref MOUSE_DEVICE: Arc<dyn INPUTDevice> = Arc::new(VirtIOINPUT::new(VIRTIO6));
pub static ref KEYBOARD_DEVICE: Arc<dyn InputDevice> = Arc::new(VirtIOInputWrapper::new(VIRTIO5));
pub static ref MOUSE_DEVICE: Arc<dyn InputDevice> = Arc::new(VirtIOInputWrapper::new(VIRTIO6));
);
impl VirtIOINPUT {
impl VirtIOInputWrapper {
pub fn new(addr: usize) -> Self {
Self(unsafe {
UPIntrFreeCell::new(VirtIOInput::<VirtioHal>::new(&mut *(addr as *mut VirtIOHeader)).unwrap())
})
}
}
impl INPUTDevice for VirtIOINPUT {
fn handle_irq(&self) {
let mut input = self.0.exclusive_access();
input.ack_interrupt();
let event = input.pop_pending_event().unwrap();
let dtype = match Decoder::decode(
event.event_type as usize,
event.code as usize,
event.value as usize,
) {
Ok(dtype) => dtype,
Err(_) => return,
let inner = VirtIOInputInner {
virtio_input: unsafe {
VirtIOInput::<VirtioHal>::new(&mut *(addr as *mut VirtIOHeader)).unwrap()
},
events: VecDeque::new(),
};
match dtype {
virtio_input_decoder::DecodeType::Key(key, r#type) => {
println!("{:?} {:?}", key, r#type);
if r#type == KeyType::Press {
let mut inner = PAD.exclusive_access();
let a = inner.as_ref().unwrap();
match key.to_char() {
Ok(mut k) => {
if k == '\r' {
a.repaint(k.to_string() + "\n")
} else {
a.repaint(k.to_string())
}
}
Err(_) => {}
}
}
}
virtio_input_decoder::DecodeType::Mouse(mouse) => println!("{:?}", mouse),
Self {
inner: unsafe { UPIntrFreeCell::new(inner) },
condvar: Condvar::new(),
}
}
}
impl InputDevice for VirtIOInputWrapper {
fn is_empty(&self) -> bool {
self.inner.exclusive_access().events.is_empty()
}
fn read_event(&self) -> u64 {
loop {
let mut inner = self.inner.exclusive_access();
if let Some(event) = inner.events.pop_front() {
return event;
} else {
let task_cx_ptr = self.condvar.wait_no_sched();
drop(inner);
schedule(task_cx_ptr);
}
}
}
fn handle_irq(&self) {
let mut count = 0;
let mut result = 0;
self.inner.exclusive_session(|inner| {
inner.virtio_input.ack_interrupt();
while let Some(event) = inner.virtio_input.pop_pending_event() {
count += 1;
result = (event.event_type as u64) << 48
| (event.code as u64) << 32
| (event.value) as u64;
inner.events.push_back(result);
}
});
if count > 0 {
self.condvar.signal();
};
}
}

View file

@ -1,18 +1,14 @@
pub mod block;
pub mod chardev;
#[cfg(feature = "board_qemu")]
pub mod gpu;
#[cfg(feature = "board_qemu")]
pub mod input;
#[cfg(feature = "board_qemu")]
pub mod bus;
pub mod chardev;
pub mod gpu;
pub mod input;
pub mod net;
pub mod plic;
pub use block::BLOCK_DEVICE;
#[cfg(feature = "board_qemu")]
pub use chardev::UART;
#[cfg(feature = "board_qemu")]
pub use gpu::*;
#[cfg(feature = "board_qemu")]
pub use input::*;
#[cfg(feature = "board_qemu")]
pub use bus::*;
pub use chardev::UART;
pub use gpu::*;
pub use input::*;
pub use net::*;

41
os/src/drivers/net/mod.rs Normal file
View file

@ -0,0 +1,41 @@
use core::any::Any;
use alloc::sync::Arc;
use lazy_static::*;
use virtio_drivers::{VirtIONet, VirtIOHeader};
use crate::drivers::virtio::VirtioHal;
use crate::sync::UPIntrFreeCell;
const VIRTIO8: usize = 0x10004000;
lazy_static! {
pub static ref NET_DEVICE: Arc<dyn NetDevice> = Arc::new(VirtIONetWrapper::new());
}
pub trait NetDevice: Send + Sync + Any {
fn transmit(&self, data: &[u8]);
fn receive(&self, data: &mut [u8]) -> usize;
}
pub struct VirtIONetWrapper(UPIntrFreeCell<VirtIONet<'static, VirtioHal>>);
impl NetDevice for VirtIONetWrapper {
fn transmit(&self, data: &[u8]) {
self.0.exclusive_access().send(data).expect("can't send data")
}
fn receive(&self, data: &mut [u8]) -> usize {
self.0.exclusive_access().recv(data).expect("can't receive data")
}
}
impl VirtIONetWrapper {
pub fn new() -> Self {
unsafe {
let virtio =
VirtIONet::<VirtioHal>::new(&mut *(VIRTIO8 as *mut VirtIOHeader))
.expect("can't create net device by virtio");
VirtIONetWrapper(UPIntrFreeCell::new(virtio))
}
}
}