📄 hplat45dbbytec.nc
字号:
/*
* Copyright (c) 2005-2006 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.
*/
/**
* Generic byte-at-a-time implementation of the AT45DB HPL.
*
* Each platform must provide its own HPL implementation for its AT45DB
* flash chip. To simplify this task, this component can easily be used to
* build an AT45DB HPL by connecting it to a byte-at-a-time SPI interface,
* and an HplAt45dbByte interface.
*
* @param The number of bits needed to represent a sector size, e.g., 9
* for the AT45DB041B.
*
* @author David Gay
*/
generic module HplAt45dbByteC(int sectorSizeLog2) @safe() {
provides interface HplAt45db;
uses {
interface Resource;
interface SpiByte as FlashSpi;
interface HplAt45dbByte;
}
}
implementation
{
enum {
P_IDLE,
P_SEND_CMD,
P_READ,
P_READ_CRC,
P_WRITE,
P_WAIT_IDLE,
P_WAIT_COMPARE,
P_WAIT_COMPARE_OK,
P_FILL,
P_FLUSH,
P_COMPARE,
P_ERASE
};
uint8_t status = P_IDLE;
uint8_t flashCmd[9];
at45pageoffset_t dataCount;
uint8_t * COUNT_NOK(dataCount) data;
uint8_t dontCare;
void complete(uint16_t crc) {
uint8_t s = status;
status = P_IDLE;
switch (s)
{
default: break;
case P_READ_CRC:
signal HplAt45db.crcDone(crc);
break;
case P_FILL:
signal HplAt45db.fillDone();
break;
case P_FLUSH:
signal HplAt45db.flushDone();
break;
case P_COMPARE:
signal HplAt45db.compareDone();
break;
case P_ERASE:
signal HplAt45db.eraseDone();
break;
case P_READ:
signal HplAt45db.readDone();
break;
case P_WRITE:
signal HplAt45db.writeDone();
break;
}
}
void requestFlashStatus() {
call HplAt45dbByte.select();
call FlashSpi.write(AT45_C_REQ_STATUS);
call HplAt45dbByte.waitIdle();
}
void doCommand() {
uint8_t in = 0, out = 0;
uint8_t *ptr;
at45pageoffset_t count;
uint8_t lphase;
uint16_t crc = (uint16_t)data;
if (dataCount) // skip 0-byte ops
{
/* 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
*/
ptr = flashCmd;
lphase = P_SEND_CMD;
count = 4 + dontCare;
call HplAt45dbByte.select();
for (;;)
{
if (lphase == P_READ_CRC)
{
crc = crcByte(crc, in);
--count;
if (!count)
break;
}
else if (lphase == P_SEND_CMD)
{
// Note: the dontCare bytes are read after the end of cmd...
out = *ptr++;
count--;
if (!count)
{
lphase = status;
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_COMMAND */
break;
in = call FlashSpi.write(out);
}
call HplAt45dbByte.deselect();
}
call Resource.release();
complete(crc);
}
event void Resource.granted() {
switch (status)
{
case P_WAIT_COMPARE: case P_WAIT_IDLE:
requestFlashStatus();
break;
default:
doCommand();
break;
}
}
void execCommand(uint8_t op, uint8_t reqCmd, uint8_t reqDontCare,
at45page_t reqPage, at45pageoffset_t reqOffset,
uint8_t * COUNT_NOK(reqCount) reqData, at45pageoffset_t reqCount) {
status = op;
// page (2 bytes) and highest bit of offset
flashCmd[0] = reqCmd;
flashCmd[1] = reqPage >> (16 - sectorSizeLog2);
flashCmd[2] = reqPage << (sectorSizeLog2 - 8) | reqOffset >> 8;
flashCmd[3] = reqOffset; // low-order 8 bits
data = NULL;
dataCount = reqCount;
data = reqData;
dontCare = reqDontCare;
call Resource.request();
}
command void HplAt45db.waitIdle() {
status = P_WAIT_IDLE;
call Resource.request();
}
command void HplAt45db.waitCompare() {
status = P_WAIT_COMPARE;
call Resource.request();
}
event void HplAt45dbByte.idle() {
if (status == P_WAIT_COMPARE)
{
bool cstatus = call HplAt45dbByte.getCompareStatus();
call HplAt45dbByte.deselect();
call Resource.release();
signal HplAt45db.waitCompareDone(cstatus);
}
else
{
call HplAt45dbByte.deselect();
call Resource.release();
signal HplAt45db.waitIdleDone();
}
}
command void HplAt45db.fill(uint8_t cmd, at45page_t page) {
execCommand(P_FILL, cmd, 0, page, 0, NULL, 1);
}
command void HplAt45db.flush(uint8_t cmd, at45page_t page) {
execCommand(P_FLUSH, cmd, 0, page, 0, NULL, 1);
}
command void HplAt45db.compare(uint8_t cmd, at45page_t page) {
execCommand(P_COMPARE, cmd, 0, page, 0, NULL, 1);
}
command void HplAt45db.erase(uint8_t cmd, at45page_t page) {
execCommand(P_ERASE, cmd, 0, page, 0, NULL, 1);
}
command void HplAt45db.read(uint8_t cmd,
at45page_t page, at45pageoffset_t offset,
uint8_t *pdata, at45pageoffset_t count) {
execCommand(P_READ, cmd, 5, page, offset, pdata, count);
}
command void HplAt45db.readBuffer(uint8_t cmd, at45pageoffset_t offset,
uint8_t *pdata, at45pageoffset_t count) {
execCommand(P_READ, cmd, 2, 0, offset, pdata, count);
}
command void HplAt45db.crc(uint8_t cmd,
at45page_t page, at45pageoffset_t offset,
at45pageoffset_t count,
uint16_t baseCrc) {
execCommand(P_READ_CRC, cmd, 2, page, offset, TCAST(uint8_t * COUNT(count), baseCrc), count);
}
command void HplAt45db.write(uint8_t cmd,
at45page_t page, at45pageoffset_t offset,
uint8_t *pdata, at45pageoffset_t count) {
execCommand(P_WRITE, cmd, 0, page, offset, pdata, count);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -