📄 pageeepromm.nc
字号:
// $Id: PageEEPROMM.nc,v 1.4.2.3 2003/08/18 22:09:49 cssharp Exp $/* tab:4 * "Copyright (c) 2000-2003 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * * Copyright (c) 2002-2003 Intel Corporation * All rights reserved. * * This file is distributed under the terms in the attached INTEL-LICENSE * file. If you do not find these files, copies can be found by writing to * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, * 94704. Attention: Intel License Inquiry. */includes crc;includes PageEEPROM;module PageEEPROMM { provides { interface StdControl; interface PageEEPROM; } uses { interface StdControl as FlashControl; interface SlavePin as FlashSelect; interface FastSPI as FlashSPI; interface Resource as FlashIdle; command bool getCompareStatus(); interface Leds; }}implementation{#define CHECKARGS#if 0 uint8_t work[20]; uint8_t woffset; void wdbg(uint8_t x) { work[woffset++] = x; if (woffset == sizeof work) woffset = 0; }#else#define wdbg(n)#endif enum { // requests IDLE, R_READ, R_READCRC, R_WRITE, R_ERASE, R_SYNC, R_SYNCALL, R_FLUSH, R_FLUSHALL }; uint8_t request; uint8_t *reqBuf; eeprompageoffset_t reqOffset, reqBytes; eeprompage_t reqPage; bool deselectRequested; /* deselect of EEPROM requested (needed between two commands) */ bool broken; // Write failed. Fail all subsequent requests. bool compareOk; enum { P_SEND_CMD, P_READ, P_READCRC, P_WRITE, P_FLUSH, P_FILL, P_ERASE, P_COMPARE, P_COMPARE_CHECK }; uint8_t cmdPhase, waiting; uint8_t *data, cmd[4]; uint8_t cmdCount; eeprompageoffset_t dataCount; uint16_t computedCrc; struct { eeprompage_t page; bool busy : 1; bool clean : 1; bool erased : 1; uint8_t unchecked : 2; } buffer[2]; uint8_t selected; // buffer used by the current op uint8_t checking; bool flashBusy; enum { // commands we're executing (all SPI Mode 0 or 3) C_READ_BUFFER1 = 0xd4, C_READ_BUFFER2 = 0xd6, C_WRITE_BUFFER1 = 0x84, C_WRITE_BUFFER2 = 0x87, C_FILL_BUFFER1 = 0x53, C_FILL_BUFFER2 = 0x55, C_FLUSH_BUFFER1 = 0x83, C_FLUSH_BUFFER2 = 0x86, C_QFLUSH_BUFFER1 = 0x88, C_QFLUSH_BUFFER2 = 0x89, C_COMPARE_BUFFER1 = 0x60, C_COMPARE_BUFFER2 = 0x61, C_REQ_STATUS = 0xd7, C_ERASE_PAGE = 0x81 }; // Select a command for the current buffer#define OPN(n, name) ((n) ? name ## 1 : name ## 2)#define OP(name) OPN(selected, name) command result_t StdControl.init() { request = IDLE; waiting = deselectRequested = FALSE; flashBusy = TRUE; // pretend we're on an invalid non-existent page buffer[0].page = buffer[1].page = TOS_EEPROM_MAX_PAGES; buffer[0].busy = buffer[1].busy = FALSE; buffer[0].clean = buffer[1].clean = TRUE; buffer[0].unchecked = buffer[1].unchecked = 0; buffer[0].erased = buffer[1].erased = FALSE; return call FlashControl.init(); } command result_t StdControl.start() { return call FlashControl.start(); } command result_t StdControl.stop() { return call FlashControl.stop(); } /* Select EEPROM, start a SPI transaction */ void selectFlash() { call FlashSelect.low(); } /* Deselect EEPROM via SlavePin */ void requestDeselect() { deselectRequested = TRUE; call FlashSelect.high(TRUE); } event result_t FlashIdle.available() { if (cmdPhase == P_COMPARE_CHECK) compareOk = call getCompareStatus(); requestDeselect(); return SUCCESS; } void requestFlashStatus() { waiting = TRUE; selectFlash(); wdbg(C_REQ_STATUS); call FlashSPI.txByte(C_REQ_STATUS); if (call FlashIdle.wait() == FAIL) // already done signal FlashIdle.available(); } void sendFlashCommand() { uint8_t in = 0, out = 0; uint8_t *ptr = cmd; eeprompageoffset_t count = cmdCount; uint16_t crc = 0; uint8_t lphase = P_SEND_CMD; /* For a 3% speedup, we could use labels and goto *. But: very gcc-specific. Also, need to do asm ("ijmp" : : "z" (state)) instead of goto *state */ wdbg(cmd[0]); selectFlash(); for (;;) { if (lphase == P_READCRC) { crc = crcByte(crc, in); --count; if (!count) { computedCrc = crc; break; } } else if (lphase == P_SEND_CMD) { out = *ptr++; count--; if (!count) { lphase = cmdPhase; ptr = data; count = dataCount; } } else if (lphase == P_READ) { *ptr++ = in; --count; if (!count) break; } else if (lphase == P_WRITE) { if (!count) break; out = *ptr++; --count; } else /* P_FILL, P_FLUSH, P_ERASE, P_COMPARE */ break; in = call FlashSPI.txByte(out); } requestDeselect(); } void requestDone(result_t result); task void taskSuccess() { requestDone(SUCCESS); } task void taskFail() { requestDone(FAIL); } void handleRWRequest(); void execCommand(bool wait, uint8_t reqCmd, uint8_t dontCare, eeprompage_t page, eeprompageoffset_t offset); void checkBuffer(uint8_t buf) { cmdPhase = P_COMPARE; checking = buf; execCommand(TRUE, OPN(buf, C_COMPARE_BUFFER), 0, buffer[buf].page, 0); } void flushBuffer() { cmdPhase = P_FLUSH; execCommand(TRUE, buffer[selected].erased ? OP(C_QFLUSH_BUFFER) : OP(C_FLUSH_BUFFER), 0, buffer[selected].page, 0); } void flashCommandComplete() { if (waiting) { waiting = flashBusy = buffer[0].busy = buffer[1].busy = FALSE; if (cmdPhase == P_COMPARE_CHECK) { if (compareOk) buffer[checking].unchecked = 0; else if (buffer[checking].unchecked < 2) buffer[checking].clean = FALSE; else { broken = TRUE; // write failed. refuse all further reqs requestDone(FAIL); return; } handleRWRequest(); } else { // Eager compare - this steals the current command#if 1 if ((buffer[0].unchecked || buffer[1].unchecked) && !(cmdPhase == P_COMPARE || cmdPhase == P_COMPARE_CHECK)) checkBuffer(buffer[0].unchecked ? 0 : 1); else#endif sendFlashCommand(); } return; } switch (cmdPhase) { default: // shouldn't happen requestDone(FAIL); break; case P_READ: case P_READCRC: case P_WRITE: requestDone(SUCCESS); break; case P_FLUSH: flashBusy = TRUE; buffer[selected].clean = buffer[selected].busy = TRUE; buffer[selected].unchecked++; buffer[selected].erased = FALSE; handleRWRequest(); break; case P_COMPARE: cmdPhase = P_COMPARE_CHECK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -