spimaster

Dependencies:   mbed SDFileSystem

SDspimaster.cpp

Committer:
yutation
Date:
2021-12-05
Revision:
2:6d633bb5c09d
Child:
3:4c39249bcd56

File content as of revision 2:6d633bb5c09d:

#include "SDspimaster.h"
#include "mbed_debug.h"

// Register Address
const uint8_t TRANS_TYPE_REG = 0x2;
const uint8_t TRANS_CTRL_REG =0x3;
const uint8_t TRANS_STS_REG  =0x4;
const uint8_t TRANS_ERROR_REG  =0x5;
const uint8_t RX_FIFO_DATA_REG  =0x10;
const uint8_t TX_FIFO_DATA_REG  =0x20;
const uint8_t ADDR_7_0_REG  =0x7;
const uint8_t ADDR_15_8_REG  =0x8;
const uint8_t ADDR_23_16_REG  =0x9;
const uint8_t ADDR_31_24_REG  =0xa;



// Reg Value states
// TRANS_TYPE_REG
const uint8_t DIRECT_ACCESS =0;
const uint8_t INIT_SD =1;
const uint8_t READ_SD_BLOCK =2;
const uint8_t WRITE_SD_BLOCK =3;

//TRANS_CTRL_REG
const uint8_t TRANS_START =1;

//TRANS_STS_REG
const uint8_t TRANS_BUSY =1;

//TRANS_ERROR_REG
const uint8_t NO_ERROR =0;

//the variable below should be replaced by a specific pin
// the name is the same as the data sheet of spimaster

uint8_t clk_i;
uint8_t address_i;
uint8_t data_i;
uint8_t data_o;
uint8_t write_en;
uint8_t rst_i;



SDspimaster::SDspimaster(const char* name) :
    FATFileSystem(name), _is_initialized(0) {
    rst_i = 1;
    rst_i = 0;

}

void read_reg(uint8_t addr, uint8_t* value){
    clk_i = 1;
    write_en = 0;
    address_i = addr;
    clk_i = 0;
    *value = data_o;
    
}

void write_reg(uint8_t addr, uint8_t value){
    clk_i = 1;
    address_i = addr;
    data_i = value;
    write_en = 1;
    clk_i = 0;
    
}

void write_address(uint32_t addr) {
    write_reg(ADDR_7_0_REG, (addr >> 0) & 0xff);
    write_reg(ADDR_15_8_REG, (addr >> 8) & 0xff);
    write_reg(ADDR_23_16_REG, (addr >> 16) & 0xff);
    write_reg(ADDR_31_24_REG, (addr >> 25) & 0xff);
}

int write_block(uint32_t addr, const uint8_t* buffer) {
    uint8_t state;
    for(uint32_t i = 0; i <= 512; i++) {
        write_reg(TX_FIFO_DATA_REG, buffer[i]);
    }
    write_address(addr);
    write_reg( TRANS_TYPE_REG, WRITE_SD_BLOCK);
    write_reg(TRANS_CTRL_REG, TRANS_START);
    read_reg(TRANS_STS_REG, &state);
    while(state == TRANS_BUSY)
        read_reg(TRANS_STS_REG, &state);
    read_reg(TRANS_ERROR_REG,&state);
    
    if((state>>4) & 0x3 != NO_ERROR)
        return 1;
    
    return 0;
}

int read_block(uint32_t addr, uint8_t* buffer) {
    uint8_t state;
    write_address(addr);
    write_reg( TRANS_TYPE_REG, READ_SD_BLOCK);
    write_reg(TRANS_CTRL_REG, TRANS_START);
    read_reg(TRANS_STS_REG, &state);
    while(state == TRANS_BUSY)
        read_reg(TRANS_STS_REG, &state);
    read_reg(TRANS_ERROR_REG,&state);
    if((state>>2) & 0x3 != NO_ERROR)
        return 1;
        
    for(uint32_t i = 0; i <= 512; i++) {
        read_reg(RX_FIFO_DATA_REG, &buffer[i]);
    }
   
    
    return 0;
}

int SDspimaster::disk_initialize() {
    uint8_t state;
    write_reg( TRANS_TYPE_REG, INIT_SD);
    write_reg(TRANS_CTRL_REG, TRANS_START);
    read_reg(TRANS_STS_REG, &state);
    while(state == TRANS_BUSY)
        read_reg(TRANS_STS_REG, &state);
    read_reg(TRANS_ERROR_REG,&state);
    
    if(state & 0x3 != NO_ERROR)
        return 1;
    
    _is_initialized = 1;
    return 0;
}

int SDspimaster::disk_status() {
    //returns 0 when initialized
    if (_is_initialized) {
        return 0;
    } else {
        return 1;
    }
}

int SDspimaster::disk_write(const uint8_t* buffer, uint32_t block_number, uint32_t count) {
    if (!_is_initialized) {
        return -1;
    }
    
    for (uint32_t b = block_number; b < block_number + count; b++) {
        // set write address for single block (CMD24)
        
        if (write_block(b, buffer) != 0) {
            return 1;
        }
        
        // send the data block
        buffer += 512;
    }
    
    return 0;
}

int SDspimaster::disk_read(uint8_t* buffer, uint32_t block_number, uint32_t count) {
    if (!_is_initialized) {
        return -1;
    }
    
        for (uint32_t b = block_number; b < block_number + count; b++) {
        // set write address for single block (CMD24)
        
        
        if (read_block(b, buffer) != 0) {
            return 1;
        }
        
        // send the data block
        buffer += 512;
    }

    return 0;
}

int SDspimaster::disk_sync() { return 0; }

// Not implement right
uint32_t SDspimaster::disk_sectors() { return -1; }