Takanobu Muraguchi / Mbed 2 deprecated picossd_step1_2cs

Dependencies:   mbed EEPROM USBDevice

RawNAND.cpp

Committer:
muraguchi
Date:
2021-09-15
Revision:
4:2e8b78a74493
Parent:
3:28ceea26c918

File content as of revision 4:2e8b78a74493:

#include "RawNAND.h"

// TODO: Replace wait_us(int) to wait_ns 

RawNAND::RawNAND(PinName ceb0,PinName ceb1, PinName cle,
                 PinName ale, PinName web,
                 PinName reb, PinName wpb,
                 PinName rbb, 
                 PinName io1, PinName io2,
                 PinName io3, PinName io4,
                 PinName io5, PinName io6,
                 PinName io7, PinName io8)
        : _ceb0(ceb0,1),_ceb1(ceb1,1),_cle(cle,1),
          _ale(ale,1),_web(web,1),
          _reb(reb,1),_wpb(wpb,1),
          _rbb(rbb,PullUp),
          _io(io1,io2,io3,io4,io5,io6,io7,io8) {
          _io.mode(PullNone);
          _io.input();
              
}
void RawNAND::reset(uint8_t cs) {
    // wait ready
    while(_rbb==0){
        __NOP();    
    }
    // RESET COMMAND (0xff)
    if(cs==0) {
        _ceb0 = 0;
    } else if (cs==1) {
        _ceb1 = 1;
    }
    _cle = 1;
    _ale = 0;
    _web = 0;
    _io=0xff;
    _io.output();
    // wait setup time : max(tCS,tCLS,tALS,tDS,tWP)
    wait_us(tCS_US);
    _web = 1;
    // wait hold time : max(tCLH,tALH,tDH,tWH,tWB,tCH)
    wait_us(tWB_US);
    // check tRBB;
    while (_rbb==0){
        __NOP();
    }
    if(cs==0) {
        _ceb0 = 1;
    } else if (cs==1) {
        _ceb1 = 1;
    }
}
void RawNAND::idRead(uint8_t cs, uint8_t * readData) {
    // ID READ COMMAND (0x90)
    if(cs==0) {
        _ceb0 = 0;
    } else if (cs==1) {
        _ceb1 = 0;
    }
    _cle = 1;
    _ale = 0;
    _web = 0;
    _io=0x90;
    _io.output();
    // wait setup time : max(tCS,tCLS,tALS,tDS,tWP)
    wait_us(tCS_US);
    _web = 1;
    // wait hold time : max(tCLH,tALH,tDH,tWH)
    wait_us(tWH_US);
    
    // IO READ ADDRESS  (0x00)
    _cle=0;
    _ale=1;
    _web=0;
    _io=0x00;
    // wait setup time : max(tCLS,tALS,tDS,tWP)
    wait_us(tCLS_US);
    _web=1;
    // wait hold time : max(tCLH,tALH,tDH,tWH)
    wait_us(tWH_US);

    // ALE low and IO input
    _ale=0;
    _io.input();
    // ALE low to tREB low : tAR
    wait_us(tAR_US);

    // IO READ read data
    for (int l=0;l<5;l++) {
        _reb = 0;
        // wait max(tREA,tRP)
        wait_us(tREA_US);
        *(readData+l)=_io;
        _reb = 1;
        // wait tREH
        wait_us(tREH_US);
    }
    // wait io hiz
    if(cs==0) {
        _ceb0 = 1;
    } else if (cs==1) {
        _ceb1 = 1;
    }
    wait_us(tCHZ_US);
}
uint8_t RawNAND::statusRead(uint8_t cs) {
    uint8_t status;
    // wait ready
    while(_rbb==0){
        __NOP();    
    }

    // STATUS READ COMMAND (0x70)
    if(cs==0) {
        _ceb0 = 0;
    } else if (cs==1) {
        _ceb1 = 0;
    }
    _cle = 1;
    _ale = 0;
    _web = 0;
    _io=0x70;
    _io.output();
    // wait setup time : max(tCS,tCLS,tALS,tDS,tWP)
    wait_us(tCS_US);
    _web = 1;
    // wait hold time : max(tCLH,tDH,tWH)
    wait_us(tWH_US);
    _cle = 0;
    _io.input();
    // wait max(tWHR-tWH,tCLR-tWH)
    wait_us(tWHR_US-tWH_US);
    _reb = 0;
    // wait max(tREA,tRP)
    wait_us(tREA_US);
    status = _io;
    _reb = 1;
    // wait tREH
    wait_us(tREH_US);
    if(cs==0) {
        _ceb0 = 1;
    } else if (cs==1) {
        _ceb1 = 1;
    }
    wait_us(tCHZ_US);
    // wait io hiz
    return status;
}

void RawNAND::setWriteProtect(uint8_t writeProtect){
    _wpb = writeProtect;
    // wait tWW
    wait_us(tWW_US);
}

void RawNAND::pageRead(uint8_t cs, uint8_t * readData,uint16_t blockAddress,uint8_t pageAddress,uint16_t columnAddress,uint16_t beats){
    // wait ready
    while(_rbb==0){
        __NOP();    
    }

    // 1ST READ COMMAND (0x00)
    if(cs==0) {
        _ceb0 = 0;
    } else if (cs==1) {
        _ceb1 = 0;
    }
    _cle = 1;
    _ale = 0;
    _web = 0;
    _io=0x00;
    _io.output();
    // wait setup time : max(tCS,tCLS,tALS,tDS,tWP)
    wait_us(tCS_US);

    _web = 1;
    // wait hold time : max(tCLH,tDH,tWH)
    wait_us(tWH_US);

    // 1st address column [7:0]
    _cle = 0;
    _ale = 1;
    _web = 0;
    _io  = columnAddress & 0xff;
    // wait setup time : max(tALS,tCLS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tCLH,tDH,tWH)
    wait_us(tWH_US);   

    // 2nd address column [11:8]
    _web = 0;
    _io  = (columnAddress>>8) & 0x0f;            
    // wait setup time : max(tALS,tCLS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tCLH,tDH,tWH)
    wait_us(tWH_US);
    
    // 3rd address  {blockAddress[1:0],pageAddress[5:0]}
    _web = 0;
    _io  = ((blockAddress<<6) | pageAddress) ;            
    // wait setup time : max(tALS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tALH,tDH,tWH)
    wait_us(tWH_US);
    
    // 4th address  blockAddress[9:2]
    _web = 0;
    _io  = (blockAddress>>2) ;   
    // wait setup time : max(tALS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tALH,tDH,tWH)
    wait_us(tWH_US);

    // 2ND READ COMMAND (0x30)
    _cle = 1;
    _ale = 0;
    _web = 0;
    _io  = 0x30;
    // wait setup time : max(tALS,tCLS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tALH,tDH,tWH,tWB)
    wait_us(tWB_US);

    _cle = 0;
    _io.input();

    // wait ready
    while(_rbb==0){
        __NOP();    
    }

    // wait tRR  ( RBB to REB Low )
    wait_us(tRR_US);

    // read sequence
    for (int b=0;b<beats;b++){
        _reb = 0;
        // wait max(tREA,tRP)
        wait_us(tREA_US);
         *(readData + b)= _io;
        _reb = 1;
        // wait tREH
        wait_us(tREH_US);
    }

    if(cs==0) {
        _ceb0 = 1;
    } else if (cs==1) {
        _ceb1 = 1;
    }
    // wait io hiz
    wait_us(tCHZ_US);

}


uint8_t RawNAND::erase(uint8_t cs, uint16_t blockAddress){
    // wait ready
    while(_rbb==0){
        __NOP();    
    }

    // 1ST ERASE COMMAND (0x60)
    if(cs==0) {
        _ceb0 = 0;
    } else if (cs==1) {
        _ceb1 = 0;
    }
    _cle = 1;
    _ale = 0;
    _web = 0;
    _io=0x60;
    _io.output();
    // wait setup time : max(tCS,tCLS,tALS,tDS,tWP)
    wait_us(tCS_US);

    _web = 1;
    // wait hold time : max(tCLH,tDH,tWH)
    wait_us(tWH_US);


    // 1st page address  {blockAddress[1:0],pageAddress[5:0]}
    _cle = 0;
    _ale = 1;
    _web = 0;
    _io  = (blockAddress<<6) ;            
    // wait setup time : max(tALS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tALH,tDH,tWH)
    wait_us(tWH_US);
    
    // 2nd page address  blockAddress[9:2]
    _web = 0;
    _io  = (blockAddress>>2) ;   
    // wait setup time : max(tALS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tALH,tDH,tWH)
    wait_us(tWH_US);

    // 2ND ERASE COMMAND (0xD0)
    _cle = 1;
    _ale = 0;
    _web = 0;
    _io  = 0xD0;
    // wait setup time : max(tALS,tCLS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tALH,tDH,tWH,tWB)
    wait_us(tWB_US);

    _cle = 0;
    _io.input();

    // wait ready
    while(_rbb==0){
        __NOP();    
    }

    return statusRead(cs);
}

uint8_t RawNAND::pageProgram(uint8_t cs, const uint8_t * writeData,uint16_t blockAddress,uint8_t pageAddress,uint16_t columnAddress,uint16_t beats){
    // wait ready
    while(_rbb==0){
        __NOP();    
    }

    // 1ST PROGRAM COMMAND (0x80)
    if(cs==0) {
        _ceb0 = 0;
    } else if (cs==1) {
        _ceb1 = 0;
    }
    _cle = 1;
    _ale = 0;
    _web = 0;
    _io  = 0x80;
    _io.output();
    // wait setup time : max(tCS,tCLS,tALS,tDS,tWP)
    wait_us(tCS_US);

    _web = 1;
    // wait hold time : max(tCLH,tDH,tWH)
    wait_us(tWH_US);

    // 1st address column [7:0]
    _cle = 0;
    _ale = 1;
    _web = 0;
    _io  = columnAddress & 0xff;
    // wait setup time : max(tALS,tCLS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tCLH,tDH,tWH)
    wait_us(tWH_US);   

    // 2nd address column [11:8]
    _web = 0;
    _io  = (columnAddress>>8) & 0x0f;            
    // wait setup time : max(tALS,tCLS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tCLH,tDH,tWH)
    wait_us(tWH_US);
    
    // 3rd address  {blockAddress[1:0],pageAddress[5:0]}
    _web = 0;
    _io  = ((blockAddress<<6) | pageAddress) ;            
    // wait setup time : max(tALS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tALH,tDH,tWH)
    wait_us(tWH_US);
    
    // 4th address  blockAddress[9:2]
    _web = 0;
    _io  = (blockAddress>>2) ;   
    // wait setup time : max(tALS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tALH,tDH,tWH)
    wait_us(tWH_US);

    // datain
    _ale = 0;
    for (int b=0;b<beats;b++) {
        _io = *(writeData+b);
        _web = 0;
        // setup
        // wait setup time : max(tALS,tCLS,tDS,tWP)
        wait_us(tWP_US);
        
        _web = 1;
        // hold
        // wait hold time : max(tALH,tDH,tWH)
        wait_us(tWH_US);        
    }

    // 2ND PROGRAM COMMAND (0x10)
    _cle = 1;
    _ale = 0;
    _io  = 0x10;
    _web = 0;
    // wait setup time : max(tALS,tCLS,tDS,tWP)
    wait_us(tWP_US);

    _web = 1;
    // wait hold time : max(tCLH,tDH,tWH,tWB)
    wait_us(tWB_US);
    
    _cle = 0;
    _io.input();
    
    // wait ready
    while(_rbb==0){
        __NOP();    
    }
    
    return statusRead(cs);
}