TRC 630401

Files at this revision

API Documentation at this revision

Comitter:
supawat
Date:
Thu Apr 02 03:41:57 2020 +0000
Commit message:
VMS3GTRC vers. 630401

Changed in this revision

at45db161e.cpp Show annotated file Show diff for this revision Revisions of this file
at45db161e.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 0b6c94a21953 at45db161e.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/at45db161e.cpp	Thu Apr 02 03:41:57 2020 +0000
@@ -0,0 +1,522 @@
+#include "at45db161e.h"
+
+//extern Serial debug_pc;
+
+ATD45DB161E::ATD45DB161E(PinName mosi, PinName miso, PinName clk, PinName cs)  
+           : _spi(mosi, miso, clk), _cs(cs) {}
+
+ATD45DB161E::ATD45DB161E(SPI &spi, PinName cs)
+            : _spi(spi), _cs(cs) {}
+/** Setup SPI **/
+void ATD45DB161E::initial_chip(void)
+{
+    _spi.format(8,0); 
+    _spi.frequency(16000000);
+    _set_pageszie_to_binary();
+    _wake_flag = true;
+    _deepsleep_flag = false;
+    _udeepsleep_flag = false;
+}
+
+void ATD45DB161E::_select() { 
+    // ensure that the SPI port is set up correctly still 
+    // This allows SPI channel sharing 
+    _spi.format(8,0); 
+    _spi.frequency(16000000); 
+    _cs = 0;     
+} 
+
+/*  
+ * Deselect simply returns nCS to high 
+ */ 
+void ATD45DB161E::_deselect() { 
+    _cs = 1; 
+}
+
+/* 
+ * Sends the three lest significant bytes of the supplied address 
+ */ 
+ 
+void ATD45DB161E::_sendaddr (unsigned int address) { 
+     _spi.write(address >> 16); 
+     _spi.write(address >> 8); 
+     _spi.write(address);       
+}
+
+/**
+ * Set page size of the flash chip into deep power down mode.
+ **/
+void ATD45DB161E::_set_pageszie_to_binary(void)
+{
+    _pollbusy();    // make sure flash isn't already in busy.  
+    _select(); 
+    _spi.write(0x3d);
+    _spi.write(0x2a);
+    _spi.write(0x80);
+    _spi.write(0xa6); 
+    _deselect();
+    _pollbusy();    // waitting for the operation complete.
+}
+
+
+/* 
+ * return the Status 
+ */ 
+ 
+int ATD45DB161E::ReadStatusRegister(void) {  
+    int status = 0; 
+    _select(); 
+    _spi.write(0xd7); 
+    status = _spi.write(0x00);  
+    _deselect();             
+    return status;  
+}
+
+/* 
+ * Make sure the Flash isnt already doing something 
+ */ 
+void ATD45DB161E::_pollbusy() { 
+    volatile int busy = 1;   
+    while (busy) {
+        if(!_wake_flag)
+        {
+            if(_deepsleep_flag) DeepPowerDown(false);
+            else if(_udeepsleep_flag) UltraDeepPowerDown(false);
+        }
+        // if bit 7 is set, we can proceed 
+        if ( ReadStatusRegister() & 0x80 ) { 
+            busy = 0;} 
+    } 
+}
+
+void ATD45DB161E::pollbusy() { 
+    _pollbusy(); 
+}
+
+/** 
+ * Read Manufacturer and Device ID 
+ * @note if id.extendedInfoLength is not equal to zero,
+ *       successive calls to spi_transfer(0xff) will return
+ *       the extended device information string bytes.
+ * @param id Pointer to the ID structure to initialize
+ **/
+void ATD45DB161E::ReadManufacturerAndDeviceID(struct flash_id *id)
+{
+    _pollbusy();    // make sure flash isn't already in busy.
+    _select(); 
+    /* Send status read command */
+    _spi.write(0x9f);
+    /* Manufacturer ID */
+    id->manufacturer = _spi.write(0x00);
+    /* Device ID (part 1) */
+    id->device[0] = _spi.write(0x00);
+    /* Device ID (part 2) */
+    id->device[1] = _spi.write(0x00);
+    /* Extended Device Information String Length */
+    id->extendedInfoLength = _spi.write(0x00);
+    _deselect();
+}
+
+/** 
+ * Main Memory Page Read. 
+ * A main memory page read allows the user to read data directly from
+ * any one of the 4096 pages in the main memory, bypassing both of the
+ * data buffers and leaving the contents of the buffers unchanged.
+ *
+ * @param page: Page of the main memory to read
+ * @param offset: Starting byte address within the page
+ * @param *data: Data buffer to be return the value in flash memory
+ * @param len: Lenght of data that you want to read
+ * Note: When the end of a page in main memory is reached,
+         the device will continue reading back at the beginning 
+         of the same page.
+ **/
+void ATD45DB161E::PageRead(unsigned int page,unsigned int offset,unsigned char *data,unsigned int len)
+{   
+    unsigned int address,i;
+    
+    address = (page<<9)|offset;
+    
+    _pollbusy();    // make sure flash isn't already in busy.
+    _select();
+
+    /* Send opcode */
+    _spi.write(0xd2);
+        
+    _sendaddr(address);  // send three address byte
+    
+    /* 4 "don't care" bytes */
+    _spi.write(0x00);
+    _spi.write(0x00);
+    _spi.write(0x00);
+    _spi.write(0x00);
+    
+    for(i=0;i<len;i++)
+    {
+        *data++ = _spi.write(0x00);
+    }
+    _deselect();
+}
+
+/** 
+ * Continuous Array Read in low power mode. 
+ * Continuous Array Read in low power mode allows the user to read data 
+ * directly from any address in the main memory, bypassing both of the
+ * data buffers and leaving the contents of the buffers unchanged.
+ *
+ * @param page: Page of the main memory to read
+ * @param addr_st: Starting byte address within the main memory
+ * @param *data: Data buffer to be return the value in flash memory
+ * @param len: Lenght of data that you want to read
+ * Note: When the end of a page in main memory is reached, the device will 
+         continue reading at the beginning of the next page with no delays 
+         incurred during the page boundary crossover.
+ **/
+void ATD45DB161E::ContinuousArrayRead(unsigned int addr_st,unsigned char *data,unsigned int len)
+{   
+    unsigned int i;
+     
+    _pollbusy();    // make sure flash isn't already in busy.
+    _select();
+
+    /* Send opcode */
+    _spi.write(0x01);
+        
+    _sendaddr(addr_st);  // send three address byte
+    
+    for(i=0;i<len;i++)
+    {
+        *data++ = _spi.write(0x00);
+    }
+    _deselect();
+}
+
+/** 
+ * Erase the entire chip memory. Sectors proteced or locked down will
+ * not be erased.
+ **/
+void ATD45DB161E::ChipErase(void)
+{
+    _pollbusy(); // make sure flash isn't already in busy.
+
+    // There are errata on this. For now, do itthe long way :-( 
+    _select(); 
+    // 4 byte command sequence 
+    _spi.write(0xc7); 
+    _spi.write(0x94); 
+    _spi.write(0x80); 
+    _spi.write(0x9a); 
+    _deselect();   
+ 
+    _pollbusy(); // waiting for chip erase 
+}
+
+/** 
+ * Erase a page in the main memory array.
+ * @param page: Number of page that you want to erase
+ **/
+void ATD45DB161E::PageErase(unsigned int page)
+{   
+    unsigned int address;
+    
+    address = page<<9;
+
+    _pollbusy(); // make sure flash isn't already in busy.
+
+    // There are errata on this. For now, do itthe long way :-( 
+    _select();
+    _spi.write(0x81);   //  Command for page erase
+    _sendaddr(address);    //  Send 3 address bytes
+    _deselect();
+    
+    _pollbusy(); // waiting for page erase
+}
+
+/**
+ * This is a combination of Buffer Write and Buffer to Page with
+ * Built-in Erase.
+ * @param page Page where the content of the buffer will transfered
+ * @param offset Starting byte address within the buffer
+ * @param bufferNum Buffer to use (1 or 2)
+ * @param *data: Data that you want to write into flash memory
+ * @param len: Lenght of data that you want to write
+ * Note: If the end of the buffer is reached, the device will
+         wrap around back to the beginning of the buffer.
+ **/
+void ATD45DB161E::PageWriteThroughBuffer(unsigned int page, unsigned int offset, unsigned char bufferNum,unsigned char *data,unsigned int len)
+{
+    unsigned int address,i;
+    unsigned char opcode;
+    
+    address = (page<<9)|offset;
+    // select opcode which buffer have been used
+    if (bufferNum == 1) 
+        opcode = 0x82;
+    else
+        opcode = 0x85; 
+    
+    _pollbusy(); // make sure flash isn't already in busy. 
+    _select();
+    
+    /* Send opcode */
+    _spi.write(opcode);
+    
+    /* Address */
+    _sendaddr(address);  // send three address byte
+    for(i=0;i<len;i++)
+    {
+        _spi.write(*data++);
+    }
+    _deselect();
+    _pollbusy(); // waiting for programming from buffer into main memory
+}
+
+/**
+ * This is a combination of the Main Memory Page to Buffer Transfer, Buffer Write, 
+ * and Buffer to Main Memory Page Program with Built-in Erase commands.
+ * @param addr_st Starting byte address of the flash chip
+ * @param bufferNum Buffer to use (1 or 2)
+ * @param *data: Data that you want to write into flash memory
+ * @param len: Lenght of data that you want to write
+ * Note: If the end of the buffer is reached, the device will
+         wrap around back to the beginning of the buffer.
+ **/
+void ATD45DB161E::ContinuousWriteThroughBuffer(unsigned int addr_st, unsigned char bufferNum,unsigned char *data,unsigned int len)
+{
+    unsigned int i,data_len;
+    unsigned int page_start,page_end;
+    unsigned int page_count,dif_page;
+    unsigned char opcode;
+    
+    page_start = addr_st>>9;
+    page_end = (addr_st+len)>>9;
+    dif_page = page_end - page_start;
+        
+    // select opcode which buffer have been used
+    if (bufferNum == 1) 
+        opcode = 0x58;
+    else
+        opcode = 0x59; 
+    
+    for(page_count=0;page_count<=dif_page;page_count++)
+    {
+        if(512-(addr_st&0x1ff)<len) data_len = 512-(addr_st&0x1ff);
+        else data_len = len;
+        _pollbusy(); // make sure flash isn't already in busy. 
+        _select();        
+        _spi.write(opcode); /* Send opcode */
+        _sendaddr(addr_st);  // send three address byte
+        for(i=0;i<data_len;i++)
+        {
+            _spi.write(*data++);
+        }
+        _deselect();
+        _pollbusy(); // waiting for programming from buffer into main memory
+        addr_st = addr_st + data_len;
+        len = len - data_len;
+    }
+}
+
+/** 
+ * Read the content of one of the SRAM data buffers (in low or high speed mode).
+ * @param bufferNum Buffer to read (1 or 2)
+ * @param offset Starting byte within the buffer
+ * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false).
+ * @param *data: Data that you want to read from flash memory
+ * @param len: Lenght of data that you want to read
+ **/
+void ATD45DB161E::BufferRead(unsigned char bufferNum, unsigned int offset, unsigned char low,unsigned char *data,unsigned int len)
+{
+    unsigned int i;
+    unsigned char opcode;
+
+    /* Send opcode */
+    if(bufferNum == 1)
+    {
+        if(low)
+            opcode = 0xd1;    // opcode for read buffer 1 in low speed
+        else
+            opcode = 0xd4;    // opcode for read buffer 1
+    }
+    else
+    {
+        if(low)
+            opcode = 0xd3;    // opcode for read buffer 1 in low speed
+        else
+            opcode = 0xd6;  // opcode for read buffer 2
+    }
+    _pollbusy();    // make sure flash isn't already in busy.
+    _select();
+    /* Send opcode */
+    _spi.write(opcode);    
+    _sendaddr(offset);  // send three address byte
+    if(!low)
+        _spi.write(0x00); // send dummy byte
+    for(i=0;i<len;i++)
+    {
+        *data++ = _spi.write(0x00);
+    }
+    _deselect();
+}
+
+/** 
+ * Write data to one of the SRAM data buffers. Any further call to
+ * spi_tranfer will return bytes contained in the data buffer until
+ * a low-to-high transition is detected on the CS pin. If the end of
+ * the data buffer is reached, the device will wrap around back to the
+ * beginning of the buffer. 
+ * @param bufferNum Buffer to read (1 or 2)
+ * @param offset Starting byte within the buffer
+ * @param *data: Data that you want to write into flash memory
+ * @param len: Lenght of data that you want to write
+ **/
+void ATD45DB161E::BufferWrite(unsigned char bufferNum, unsigned int offset,unsigned char *data,unsigned int len)
+{
+    unsigned int i;
+    unsigned char opcode;
+    
+    if (bufferNum == 1) 
+        opcode = 0x84;
+    else
+        opcode = 0x87;
+    _pollbusy();    // make sure flash isn't already in busy.
+    _select();
+    
+    /* Send opcode */
+    _spi.write(opcode);
+    _sendaddr(offset);  // send three address byte
+    for(i=0;i<len;i++)
+    {
+        _spi.write(*data++);
+    }
+    _deselect();
+    _pollbusy();    // waiting for operation complete.
+}
+
+/**
+ * Transfer data from buffer 1 or 2 to main memory page.
+ * @param bufferNum Buffer to use (1 or 2)
+ * @param page Page where the content of the buffer will transfered
+ * @param erase If set the page will be first erased before the buffer transfer.
+ * @note If erase is equal to zero, the page must have been previously erased using one of the erase command (Page or Block Erase).
+ **/
+void ATD45DB161E::BufferToPage(unsigned char bufferNum, unsigned int page, unsigned char erase)
+{
+    unsigned int address;
+    unsigned char opcode;
+    
+    address = page<<9;
+    if(erase)
+    {
+        if (bufferNum == 1) 
+        opcode = 0x83;
+        else
+        opcode = 0x86;
+    }
+    else
+    {
+        if (bufferNum == 1) 
+        opcode = 0x88;
+        else
+        opcode = 0x89;
+    }
+    
+    _pollbusy(); // make sure flash isn't already in busy.
+    _select();
+    
+    /* Send opcode */
+    _spi.write(opcode);
+    _sendaddr(address);  // send three address byte
+    _deselect();
+    
+    _pollbusy(); // Wait for buffer write to main memory page
+}
+
+/**
+ * Transfer data from main memory page to buffer 1 or 2.
+ * @param page Page where the content of the main memory page will transfered
+ * @param bufferNum Buffer to use (1 or 2) 
+ **/
+void ATD45DB161E::PageToBuffer(unsigned int page, unsigned char bufferNum)
+{
+    unsigned int address;
+    unsigned char opcode;
+    
+    address = page<<9;
+    
+    if (bufferNum == 1) opcode = 0x53;
+    else opcode = 0x55;
+    
+    _pollbusy(); // make sure flash isn't already in busy.
+    _select();
+    
+    /* Send opcode */
+    _spi.write(opcode);
+    _sendaddr(address);  // send three address byte
+    _deselect();
+    
+    _pollbusy(); // Wait for buffer write to main memory page
+}
+
+/**
+ * Enter the chip into deep power down mode.
+ * @param deep_down_onoff: If set the chip will be entered into deep power down mode. Otherwise, wake up command will be sent to the chip.
+ **/
+void ATD45DB161E::DeepPowerDown(unsigned char deep_down_onoff)
+{
+    if(deep_down_onoff)
+    {
+        _pollbusy();    // make sure flash isn't already in busy.
+        _select();
+        _spi.write(0xb9);
+        _deselect();
+        _wake_flag = false;
+        _deepsleep_flag = true;
+        wait_us(2);        
+    }
+    else
+    {
+        _select();
+        _spi.write(0xab);
+        _deselect();
+        _wake_flag = true;
+        _deepsleep_flag = false;
+        wait_us(35);
+    }    
+}
+
+/**
+ * Enter the chip into ultra deep power down mode.
+ * @param ultra_deep_down_onoff: If set the chip will be entered into ultra deep power down mode. Otherwise, CS pin will be asseeted for wake up the chip.
+ **/
+void ATD45DB161E::UltraDeepPowerDown(unsigned char  ultra_deep_down_onoff)
+{
+    if(ultra_deep_down_onoff)
+    {
+        _pollbusy();    // make sure flash isn't already in busy.
+        _select();
+        _spi.write(0x79);
+        _deselect();
+        _wake_flag = false;
+        _udeepsleep_flag = true;
+        wait_us(4);        
+    }
+    else
+    {
+        _select();
+        wait_us(1);
+        _deselect();
+        wait_us(180);
+        _wake_flag = true;
+        _udeepsleep_flag = false;  
+    }    
+}
+
+/**
+ * Check the chip is wake up.
+ * Return true if the chip is wake up. Otherwise, the chip is entered in deep power down or ultra deep power down mode mode.
+ **/
+bool ATD45DB161E::is_it_awake(void)
+{
+    return _wake_flag;
+}
diff -r 000000000000 -r 0b6c94a21953 at45db161e.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/at45db161e.h	Thu Apr 02 03:41:57 2020 +0000
@@ -0,0 +1,75 @@
+/**
+ * @file at45db161e.h
+ * @brief AT45DB161E module
+ **/
+#ifndef AT45DB161E_H
+#define AT45DB161E_H
+
+#include "mbed.h"
+
+/** 
+          * @brief ID structure 
+          * This structure contains various informations about the
+          * dataflash chip being used.
+          **/
+        struct flash_id
+        {
+            unsigned char manufacturer;       /**< Manufacturer id                           **/
+            unsigned char device[1];          /**< Device id                                 **/
+            unsigned char extendedInfoLength; /**< Extended device information string length **/
+        };
+
+class ATD45DB161E
+{
+    
+    // Public functions
+    public:
+        
+        ATD45DB161E(PinName mosi, PinName miso, PinName clk, PinName cs);
+        ATD45DB161E(SPI &spi, PinName cs);
+        
+        void initial_chip(void);
+        void pollbusy (void);
+        int  ReadStatusRegister(void);
+        void ReadManufacturerAndDeviceID(struct flash_id *id);
+        
+        void PageRead(unsigned int,unsigned int,unsigned char *,unsigned int);
+        void ContinuousArrayRead(unsigned int,unsigned char *,unsigned int);
+        
+        void ChipErase(void);
+        void PageErase(unsigned int);
+        
+        void PageWriteThroughBuffer(unsigned int, unsigned int, unsigned char ,unsigned char *,unsigned int);
+        void ContinuousWriteThroughBuffer(unsigned int, unsigned char ,unsigned char *,unsigned int);
+        
+				void BufferRead(unsigned char, unsigned int, unsigned char, unsigned char *, unsigned int);
+        void BufferWrite(unsigned char, unsigned,unsigned char *,unsigned int);
+        void BufferToPage(unsigned char, unsigned int, unsigned char);
+        void PageToBuffer(unsigned int, unsigned char);
+        
+        void DeepPowerDown(unsigned char);
+        void UltraDeepPowerDown(unsigned char);
+        bool is_it_awake(void);
+        
+    // Private variables    
+    private:
+        SPI _spi;
+        DigitalOut _cs;
+        bool _wake_flag;
+        bool _deepsleep_flag;
+        bool _udeepsleep_flag;
+        
+        void _set_pageszie_to_binary(void);
+        void _select(); 
+        void _deselect();
+        void _pollbusy (void);
+                
+        // Send 3 byte address 
+        void _sendaddr (unsigned int address);
+};
+
+/**
+ * @}
+ **/
+
+#endif /* AT45DB161E_H */