📄 xmem.c
字号:
/* * Copyright (c) 2006, Swedish Institute of Computer Science * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)$Id: xmem.c,v 1.7 2008/07/03 23:12:10 adamdunkels Exp $ *//** * \file * Device driver for the ST M25P80 40MHz 1Mbyte external memory. * \author * Bj鰎n Gr鰊vall <bg@sics.se> * * Data is written bit inverted (~-operator) to flash so that * unwritten data will read as zeros (UNIX style). */#include <stdio.h>#include <string.h>#include <io.h>#include <signal.h>#include "contiki.h"#include "dev/spi.h"#include "dev/xmem.h"#include "dev/watchdog.h"#if 0#define PRINTF(...) printf(__VA_ARGS__)#else#define PRINTF(...) do {} while (0)#endif#define SPI_FLASH_INS_WREN 0x06#define SPI_FLASH_INS_WRDI 0x04#define SPI_FLASH_INS_RDSR 0x05#define SPI_FLASH_INS_WRSR 0x01#define SPI_FLASH_INS_READ 0x03#define SPI_FLASH_INS_FAST_READ 0x0b#define SPI_FLASH_INS_PP 0x02#define SPI_FLASH_INS_SE 0xd8#define SPI_FLASH_INS_BE 0xc7#define SPI_FLASH_INS_DP 0xb9#define SPI_FLASH_INS_RES 0xab/*---------------------------------------------------------------------------*/static voidspi_tx(unsigned byte){ FASTSPI_TX(byte);}/*---------------------------------------------------------------------------*/static voidwrite_enable(void){ int s; s = splhigh(); SPI_FLASH_ENABLE(); spi_tx(SPI_FLASH_INS_WREN); SPI_FLASH_DISABLE(); splx(s);}/*---------------------------------------------------------------------------*/static unsignedread_status_register(void){ unsigned char u; int s; s = splhigh(); SPI_FLASH_ENABLE(); spi_tx(SPI_FLASH_INS_RDSR); FASTSPI_CLEAR_RX(); FASTSPI_RX(u); SPI_FLASH_DISABLE(); splx(s); return u;}/*---------------------------------------------------------------------------*//* * Wait for a write/erase operation to finish. */static unsignedwait_ready(void){ unsigned u; do { u = read_status_register(); } while(u & 0x01); /* WIP=1, write in progress */ return u;}/*---------------------------------------------------------------------------*//* * Erase 64k bytes of data. It takes about 1s before WIP goes low! */static voiderase_sector(unsigned long offset){ int s; wait_ready(); write_enable(); s = splhigh(); SPI_FLASH_ENABLE(); spi_tx(SPI_FLASH_INS_SE); spi_tx(offset >> 16); /* MSB */ spi_tx(offset >> 8); spi_tx(offset >> 0); /* LSB */ SPI_FLASH_DISABLE(); splx(s);}/*---------------------------------------------------------------------------*//* * Initialize external flash *and* SPI bus! */voidxmem_init(void){ spi_init(); P4DIR |= BV(FLASH_CS) | BV(FLASH_HOLD) | BV(FLASH_PWR); P4OUT |= BV(FLASH_PWR); /* P4.3 Output, turn on power! */ SPI_FLASH_DISABLE(); /* Unselect flash. */ SPI_FLASH_UNHOLD();}/*---------------------------------------------------------------------------*/intxmem_pread(void *_p, int size, unsigned long offset){ unsigned char *p = _p; const unsigned char *end = p + size; int s; wait_ready(); s = splhigh(); SPI_FLASH_ENABLE(); spi_tx(SPI_FLASH_INS_READ); spi_tx(offset >> 16); /* MSB */ spi_tx(offset >> 8); spi_tx(offset >> 0); /* LSB */ FASTSPI_CLEAR_RX(); for(; p < end; p++) { unsigned char u; FASTSPI_RX(u); *p = ~u; } SPI_FLASH_DISABLE(); splx(s); return size;}/*---------------------------------------------------------------------------*/static const char *program_page(unsigned long offset, const unsigned char *p, int nbytes){ const unsigned char *end = p + nbytes; int s; wait_ready(); write_enable(); s = splhigh(); SPI_FLASH_ENABLE(); spi_tx(SPI_FLASH_INS_PP); spi_tx(offset >> 16); /* MSB */ spi_tx(offset >> 8); spi_tx(offset >> 0); /* LSB */ for(; p < end; p++) { spi_tx(~*p); } SPI_FLASH_DISABLE(); splx(s); return p;}/*---------------------------------------------------------------------------*/intxmem_pwrite(const void *_buf, int size, unsigned long addr){ const unsigned char *p = _buf; const unsigned long end = addr + size; unsigned long i, next_page; for(i = addr; i < end;) { next_page = (i | 0xff) + 1; if(next_page > end) { next_page = end; } p = program_page(i, p, next_page - i); i = next_page; } return size;}/*---------------------------------------------------------------------------*/intxmem_erase(long size, unsigned long addr){ unsigned long end = addr + size; if(size % XMEM_ERASE_UNIT_SIZE != 0) { PRINTF("xmem_erase: bad size\n"); return -1; } if(addr % XMEM_ERASE_UNIT_SIZE != 0) { PRINTF("xmem_erase: bad offset\n"); return -1; } watchdog_stop(); for (; addr < end; addr += XMEM_ERASE_UNIT_SIZE) { erase_sector(addr); } watchdog_start(); return size;}/*---------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -