|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
-
-
- #include "SerialFlash.h"
- #include "util/SerialFlash_directwrite.h"
-
- #define CSASSERT() DIRECT_WRITE_LOW(cspin_basereg, cspin_bitmask)
- #define CSRELEASE() DIRECT_WRITE_HIGH(cspin_basereg, cspin_bitmask)
- #define SPICONFIG SPISettings(50000000, MSBFIRST, SPI_MODE0)
-
- uint16_t SerialFlashChip::dirindex = 0;
- uint8_t SerialFlashChip::flags = 0;
- uint8_t SerialFlashChip::busy = 0;
-
- static volatile IO_REG_TYPE *cspin_basereg;
- static IO_REG_TYPE cspin_bitmask;
-
- static SPIClass& SPIPORT = SPI;
-
- #define FLAG_32BIT_ADDR 0x01
- #define FLAG_STATUS_CMD70 0x02
- #define FLAG_DIFF_SUSPEND 0x04
- #define FLAG_MULTI_DIE 0x08
- #define FLAG_256K_BLOCKS 0x10
- #define FLAG_DIE_MASK 0xC0
-
- void SerialFlashChip::wait(void)
- {
- uint32_t status;
-
- while (1) {
- SPIPORT.beginTransaction(SPICONFIG);
- CSASSERT();
- if (flags & FLAG_STATUS_CMD70) {
-
-
- SPIPORT.transfer(0x70);
- status = SPIPORT.transfer(0);
- CSRELEASE();
- SPIPORT.endTransaction();
-
- if ((status & 0x80)) break;
- } else {
-
- SPIPORT.transfer(0x05);
- status = SPIPORT.transfer(0);
- CSRELEASE();
- SPIPORT.endTransaction();
-
- if (!(status & 1)) break;
- }
- }
- busy = 0;
-
- }
-
- void SerialFlashChip::read(uint32_t addr, void *buf, uint32_t len)
- {
- uint8_t *p = (uint8_t *)buf;
- uint8_t b, f, status, cmd;
-
- memset(p, 0, len);
- f = flags;
- SPIPORT.beginTransaction(SPICONFIG);
- b = busy;
- if (b) {
-
- CSASSERT();
- if (flags & FLAG_STATUS_CMD70) {
- SPIPORT.transfer(0x70);
- status = SPIPORT.transfer(0);
- if ((status & 0x80)) b = 0;
- } else {
- SPIPORT.transfer(0x05);
- status = SPIPORT.transfer(0);
- if (!(status & 1)) b = 0;
- }
- CSRELEASE();
- if (b == 0) {
-
- busy = 0;
- } else if (b < 3) {
-
-
-
- CSASSERT();
- SPIPORT.transfer(0x06);
- CSRELEASE();
- delayMicroseconds(1);
- cmd = 0x75;
-
- if ((f & FLAG_DIFF_SUSPEND) && (b == 1)) cmd = 0x85;
- CSASSERT();
- SPIPORT.transfer(cmd);
- CSRELEASE();
- if (f & FLAG_STATUS_CMD70) {
-
- CSASSERT();
- SPIPORT.transfer(0x70);
- do {
- status = SPIPORT.transfer(0);
- } while (!(status & 0x80));
- CSRELEASE();
- } else {
- CSASSERT();
- SPIPORT.transfer(0x05);
- do {
- status = SPIPORT.transfer(0);
- } while ((status & 0x01));
- CSRELEASE();
- }
- } else {
-
- SPIPORT.endTransaction();
- wait();
- b = 0;
- SPIPORT.beginTransaction(SPICONFIG);
- }
- }
- do {
- uint32_t rdlen = len;
- if (f & FLAG_MULTI_DIE) {
- if ((addr & 0xFE000000) != ((addr + len - 1) & 0xFE000000)) {
- rdlen = 0x2000000 - (addr & 0x1FFFFFF);
- }
- }
- CSASSERT();
-
- if (f & FLAG_32BIT_ADDR) {
- SPIPORT.transfer(0x03);
- SPIPORT.transfer16(addr >> 16);
- SPIPORT.transfer16(addr);
- } else {
- SPIPORT.transfer16(0x0300 | ((addr >> 16) & 255));
- SPIPORT.transfer16(addr);
- }
- SPIPORT.transfer(p, rdlen);
- CSRELEASE();
- p += rdlen;
- addr += rdlen;
- len -= rdlen;
- } while (len > 0);
- if (b) {
- CSASSERT();
- SPIPORT.transfer(0x06);
- CSRELEASE();
- delayMicroseconds(1);
- cmd = 0x7A;
- if ((f & FLAG_DIFF_SUSPEND) && (b == 1)) cmd = 0x8A;
- CSASSERT();
- SPIPORT.transfer(cmd);
- CSRELEASE();
- }
- SPIPORT.endTransaction();
- }
-
- void SerialFlashChip::write(uint32_t addr, const void *buf, uint32_t len)
- {
- const uint8_t *p = (const uint8_t *)buf;
- uint32_t max, pagelen;
-
-
- do {
- if (busy) wait();
- SPIPORT.beginTransaction(SPICONFIG);
- CSASSERT();
-
- SPIPORT.transfer(0x06);
- CSRELEASE();
- max = 256 - (addr & 0xFF);
- pagelen = (len <= max) ? len : max;
-
- delayMicroseconds(1);
- CSASSERT();
- if (flags & FLAG_32BIT_ADDR) {
- SPIPORT.transfer(0x02);
- SPIPORT.transfer16(addr >> 16);
- SPIPORT.transfer16(addr);
- } else {
- SPIPORT.transfer16(0x0200 | ((addr >> 16) & 255));
- SPIPORT.transfer16(addr);
- }
- addr += pagelen;
- len -= pagelen;
- do {
- SPIPORT.transfer(*p++);
- } while (--pagelen > 0);
- CSRELEASE();
- busy = 4;
- SPIPORT.endTransaction();
- } while (len > 0);
- }
-
- void SerialFlashChip::eraseAll()
- {
- if (busy) wait();
- uint8_t id[5];
- readID(id);
-
- if (id[0] == 0x20 && id[2] >= 0x20 && id[2] <= 0x22) {
-
-
-
-
- uint8_t die_count = 2;
- if (id[2] == 0x21) die_count = 4;
- uint8_t die_index = flags >> 6;
-
- flags &= 0x3F;
- if (die_index >= die_count) return;
- uint8_t die_size = 2;
- if (id[2] == 0x22) die_size = 8;
- SPIPORT.beginTransaction(SPICONFIG);
- CSASSERT();
- SPIPORT.transfer(0x06);
- CSRELEASE();
- delayMicroseconds(1);
- CSASSERT();
-
- SPIPORT.transfer(0xC4);
- SPIPORT.transfer16((die_index * die_size) << 8);
- SPIPORT.transfer16(0x0000);
- CSRELEASE();
-
- flags |= (die_index + 1) << 6;
- } else {
-
- SPIPORT.beginTransaction(SPICONFIG);
- CSASSERT();
-
- SPIPORT.transfer(0x06);
- CSRELEASE();
- delayMicroseconds(1);
- CSASSERT();
-
- SPIPORT.transfer(0xC7);
- CSRELEASE();
- SPIPORT.endTransaction();
- }
- busy = 3;
- }
-
- void SerialFlashChip::eraseBlock(uint32_t addr)
- {
- uint8_t f = flags;
- if (busy) wait();
- SPIPORT.beginTransaction(SPICONFIG);
- CSASSERT();
- SPIPORT.transfer(0x06);
- CSRELEASE();
- delayMicroseconds(1);
- CSASSERT();
- if (f & FLAG_32BIT_ADDR) {
- SPIPORT.transfer(0xD8);
- SPIPORT.transfer16(addr >> 16);
- SPIPORT.transfer16(addr);
- } else {
- SPIPORT.transfer16(0xD800 | ((addr >> 16) & 255));
- SPIPORT.transfer16(addr);
- }
- CSRELEASE();
- SPIPORT.endTransaction();
- busy = 2;
- }
-
-
- bool SerialFlashChip::ready()
- {
- uint32_t status;
- if (!busy) return true;
- SPIPORT.beginTransaction(SPICONFIG);
- CSASSERT();
- if (flags & FLAG_STATUS_CMD70) {
-
-
- SPIPORT.transfer(0x70);
- status = SPIPORT.transfer(0);
- CSRELEASE();
- SPIPORT.endTransaction();
-
- if ((status & 0x80) == 0) return false;
- } else {
-
- SPIPORT.transfer(0x05);
- status = SPIPORT.transfer(0);
- CSRELEASE();
- SPIPORT.endTransaction();
-
- if ((status & 1)) return false;
- }
- busy = 0;
- if (flags & 0xC0) {
-
- eraseAll();
- return false;
- }
- return true;
- }
-
-
- #define ID0_WINBOND 0xEF
- #define ID0_SPANSION 0x01
- #define ID0_MICRON 0x20
- #define ID0_MACRONIX 0xC2
- #define ID0_SST 0xBF
-
-
-
-
-
-
- bool SerialFlashChip::begin(SPIClass& device, uint8_t pin)
- {
- SPIPORT = device;
- return begin(pin);
- }
-
- bool SerialFlashChip::begin(uint8_t pin)
- {
- uint8_t id[5];
- uint8_t f;
- uint32_t size;
-
- cspin_basereg = PIN_TO_BASEREG(pin);
- cspin_bitmask = PIN_TO_BITMASK(pin);
- SPIPORT.begin();
- pinMode(pin, OUTPUT);
- CSRELEASE();
- readID(id);
- f = 0;
- size = capacity(id);
- if (size > 16777216) {
-
- f |= FLAG_32BIT_ADDR;
- SPIPORT.beginTransaction(SPICONFIG);
- if (id[0] == ID0_SPANSION) {
-
- CSASSERT();
- SPIPORT.transfer16(0x1780);
- CSRELEASE();
- } else {
-
- CSASSERT();
- SPIPORT.transfer(0x06);
- CSRELEASE();
- delayMicroseconds(1);
- CSASSERT();
- SPIPORT.transfer(0xB7);
- CSRELEASE();
- }
- SPIPORT.endTransaction();
- if (id[0] == ID0_MICRON) f |= FLAG_MULTI_DIE;
- }
- if (id[0] == ID0_SPANSION) {
-
- f |= FLAG_DIFF_SUSPEND;
- if (!id[4]) {
-
- f |= FLAG_256K_BLOCKS;
- }
- }
- if (id[0] == ID0_MICRON) {
-
- f |= FLAG_STATUS_CMD70;
- }
- flags = f;
- readID(id);
- return true;
- }
-
-
-
- void SerialFlashChip::sleep()
- {
- if (busy) wait();
- SPIPORT.beginTransaction(SPICONFIG);
- CSASSERT();
- SPIPORT.transfer(0xB9);
- CSRELEASE();
- }
-
- void SerialFlashChip::wakeup()
- {
- SPIPORT.beginTransaction(SPICONFIG);
- CSASSERT();
- SPIPORT.transfer(0xAB);
- CSRELEASE();
- }
-
- void SerialFlashChip::readID(uint8_t *buf)
- {
- if (busy) wait();
- SPIPORT.beginTransaction(SPICONFIG);
- CSASSERT();
- SPIPORT.transfer(0x9F);
- buf[0] = SPIPORT.transfer(0);
- buf[1] = SPIPORT.transfer(0);
- buf[2] = SPIPORT.transfer(0);
- if (buf[0] == ID0_SPANSION) {
- buf[3] = SPIPORT.transfer(0);
- buf[4] = SPIPORT.transfer(0);
- }
- CSRELEASE();
- SPIPORT.endTransaction();
-
- }
-
- void SerialFlashChip::readSerialNumber(uint8_t *buf)
- {
- if (busy) wait();
- SPIPORT.beginTransaction(SPICONFIG);
- CSASSERT();
- SPIPORT.transfer(0x4B);
- SPIPORT.transfer16(0);
- SPIPORT.transfer16(0);
- for (int i=0; i<8; i++) {
- buf[i] = SPIPORT.transfer(0);
- }
- CSRELEASE();
- SPIPORT.endTransaction();
-
- }
-
- uint32_t SerialFlashChip::capacity(const uint8_t *id)
- {
- uint32_t n = 1048576;
-
- if (id[2] >= 16 && id[2] <= 31) {
- n = 1ul << id[2];
- } else
- if (id[2] >= 32 && id[2] <= 37) {
- n = 1ul << (id[2] - 6);
- } else
- if ((id[0]==0 && id[1]==0 && id[2]==0) ||
- (id[0]==255 && id[1]==255 && id[2]==255)) {
- n = 0;
- }
-
- return n;
- }
-
- uint32_t SerialFlashChip::blockSize()
- {
-
- if (flags & FLAG_256K_BLOCKS) return 262144;
-
- return 65536;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SerialFlashChip SerialFlash;
|