[Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/diku/sensinode/tos/platform/micro4/flash FlashAccessC.nc, NONE, 1.1 HPLSTM25P40M.nc, NONE, 1.1 HALSTM25P40M.nc, NONE, 1.1 FlashAccess.nc, NONE, 1.1 FlashAccessM.nc, NONE, 1.1 HALSTM25P40.nc, NONE, 1.1 HPLSTM25P40.nc, NONE, 1.1

Marcus Chang marcus_chang at users.sourceforge.net
Thu Mar 15 07:40:21 PDT 2007


Update of /cvsroot/tinyos/tinyos-1.x/contrib/diku/sensinode/tos/platform/micro4/flash
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv30685/sensinode/tos/platform/micro4/flash

Added Files:
	FlashAccessC.nc HPLSTM25P40M.nc HALSTM25P40M.nc FlashAccess.nc 
	FlashAccessM.nc HALSTM25P40.nc HPLSTM25P40.nc 
Log Message:
* Sensinode Micro.4 platform support
* Hoghtrob Data Collection Application

--- NEW FILE: FlashAccessC.nc ---
/*
  Copyright (C) 2004 Klaus S. Madsen <klaussm at diku.dk>
  Copyright (C) 2006 Marcus Chang <marcus at diku.dk>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/


configuration FlashAccessC {
	provides {
		interface StdControl as FlashControl;
		interface FlashAccess;
	}
}

implementation {
	components FlashAccessM, HALSTM25P40M, HPLSTM25P40M, HPLSpiM, TimerC, BusArbitrationC, StdOutC;

	FlashControl = FlashAccessM.FlashControl;
	FlashAccess = FlashAccessM.FlashAccess;

	FlashAccessM.Flash		->	HALSTM25P40M.Flash;

	HALSTM25P40M.BusArbitration 	->	BusArbitrationC.BusArbitration[unique("BusArbitration")];
	HALSTM25P40M.Timer 				->	TimerC.Timer[unique("Timer")];
	HALSTM25P40M.Spi				->	HPLSpiM.Spi;
	HALSTM25P40M.HPLFlash			->	HPLSTM25P40M.HPLFlash;

	HPLSTM25P40M.Spi		->	HPLSpiM.Spi;
	
	HALSTM25P40M.StdOut	-> StdOutC;
	HPLSTM25P40M.StdOut	-> StdOutC;
}



--- NEW FILE: HPLSTM25P40M.nc ---
/*
  Copyright (C) 2004 Klaus S. Madsen <klaussm at diku.dk>
  Copyright (C) 2006 Marcus Chang <marcus at diku.dk>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/


/*These macros control flash select signal and assume correct bus state*/
#define FLASH_SELECT(x) P3OUT &= ~0x01
#define FLASH_UNSELECT(x) P3OUT |= 0x01

/*Flash control commands*/
#define M25P_WREN 0x06
#define M25P_WRDI 0x04
#define M25P_RDID 0x9F
#define M25P_RDSR 0x05
#define M25P_WRSR 0x01
#define M25P_READ 0x03
#define M25P_FAST_READ 0x0B
#define M25P_PP   0x02
#define M25P_SE   0xD8
#define M25P_BE   0xC7
#define M25P_DP   0xB9
#define M25P_RES  0xAB

/** Flash status register bits */
#define FLASH_SR_SRWD 0x80 /*!< Status register write protect */
#define FLASH_SR_BP2  0x10 /*!< Block protect bit 2*/
#define FLASH_SR_BP1  0x08 /*!< Block protect bit 1*/
#define FLASH_SR_BP0  0x04 /*!< Block protect bit 0*/
#define FLASH_SR_WEL  0x02 /*!< Write enable latch*/
#define FLASH_SR_WIP  0x01 /*!< Write in progress (busy)*/


module HPLSTM25P40M {
	provides {
		interface HPLSTM25P40 as HPLFlash;
	}

	uses {
		interface StdOut;
		interface Spi;
	}
}

implementation {

	bool flashBusy();
	void flashWait();


	/**********************************************************************
	 * Flash read
	 *********************************************************************/
	/**
	 * Read flash block.
	 *
	 *
	 * \param address block address on flash
	 * \param buffer  pointer to buffer
	 * \param length  length of read buffer
	 *
	 * \return SUCCESS
	 * \return FAIL	bus not free or init failed
	 */
	command result_t HPLFlash.read(uint32_t address, uint8_t *buffer, uint16_t length)
	{
		uint16_t i;
		uint8_t * p = buffer;

		/***********************************************
		** Read flash into buffer
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_READ);
		call Spi.write(address >> 16);
		call Spi.write(address >> 8);
		call Spi.write(address);

		for (i = 0; i < length; i++)
		{
			*p++ = call Spi.write(0);
		}
		FLASH_UNSELECT();
		
		return SUCCESS;
	}
	

	/**
	 * Fast Read flash block.
	 *
	 *
	 * \param address block address on flash
	 * \param buffer  pointer to buffer
	 * \param length  length of read buffer
	 *
	 * \return SUCCESS
	 * \return FAIL	bus not free or init failed
	 */
	command result_t HPLFlash.fastRead(uint32_t address, uint8_t *buffer, uint16_t length)
	{
		uint16_t i;
		uint8_t *p = buffer;

		/***********************************************
		** Fast read flash into buffer
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_FAST_READ);
		call Spi.write(address >> 16);
		call Spi.write(address >> 8);
		call Spi.write(address);
		call Spi.write(0);

		for (i = 0; i< length ; i++)
		{
			*p++ = call Spi.write(0);
		}

		FLASH_UNSELECT();

		return SUCCESS;
	}
	

	/**********************************************************************
	 * Flash write
	 *********************************************************************/
	/**
	 * Write flash page. Page size is 256 bytes.
	 * Write address must point at start of page.
	 *
	 * \param address block address on flash
	 * \param buffer  pointer to buffer
	 * \param length  length of read buffer
	 *
	 * \return SUCCESS
	 * \return FAIL		bus not free or buffer too long
	 */
	command result_t HPLFlash.write(uint32_t address, uint8_t *buffer, uint16_t length)
	{
		uint16_t i;
		uint8_t *p = buffer;

		/***********************************************
		** Enable write mode
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_WREN);
		FLASH_UNSELECT();

		TOSH_uwait(10);

		/***********************************************
		** Write buffer to page, starting at address
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_PP);
		call Spi.write(address >> 16);
		call Spi.write(address >> 8);
		call Spi.write(address);

		for (i = 0; i< length ; i++)
		{
			call Spi.write(*p++);
		}
		FLASH_UNSELECT();

		TOSH_uwait(10);

		/***********************************************
		** Disable write mode
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_WRDI);
		FLASH_UNSELECT();

		return SUCCESS;
	}



	/**********************************************************************
	 * Flash erase
	 *********************************************************************/
	/**
	 * Flash sector erase. Sector size is 64 kilobytes.
	 * Address must point at start of sector.
	 *
	 * \param address block address on flash
	 *
	 * \return SUCCESS
	 * \return FAIL		bus not free 
	 */
	command result_t HPLFlash.sectorErase(uint32_t address)
	{

		/***********************************************
		** Enable write mode
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_WREN);
		FLASH_UNSELECT();

		TOSH_uwait(10);

		/***********************************************
		** Erase sector holding address
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_SE);
		call Spi.write(address >> 16);
		call Spi.write(address >> 8);
		call Spi.write(address);
		FLASH_UNSELECT();

		TOSH_uwait(10);

		/***********************************************
		** Disable write mode
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_WRDI);
		FLASH_UNSELECT();


		return SUCCESS;
	}

	/**
	 * Flash bulk erase. 
	 * Erases entire flash
	 *
	 * \return SUCCESS
	 * \return FAIL	bus not free 
	 */
	command result_t HPLFlash.bulkErase()
	{

		/***********************************************
		** Enable write mode
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_WREN);
		FLASH_UNSELECT();

		TOSH_uwait(10);

		/***********************************************
		** Bulk erase
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_BE);
		FLASH_UNSELECT();

		TOSH_uwait(10);

		/***********************************************
		** Disable write mode
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_WRDI);
		FLASH_UNSELECT();

		return SUCCESS;
	}


	/**********************************************************************
	 * Flash power management
	 *********************************************************************/
	/**
	 * Deep Power-down. 
	 *
	 * \return SUCCESS
	 * \return FAIL		bus not free
	 */
	command result_t HPLFlash.sleep()
	{

		/***********************************************
		** Send command to enter deep power-down
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_DP);
		FLASH_UNSELECT();

        TOSH_uwait(10);

		return SUCCESS;
	}

	/**
	 * Flash signature read. Wakes the device up from power down mode.
	 * Signature value should be 0x12 if the flash is present and working.
	 *
	 * \return signature value
	 * \return -1	bus not free
	 */
	command int16_t HPLFlash.wakeUp()
	{
		int16_t retval;

		/***********************************************
		** Read signature
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_RES);
		call Spi.write(0);
		call Spi.write(0);
		call Spi.write(0);
		retval = call Spi.write(0);
		FLASH_UNSELECT();
		
		TOSH_uwait(10);

		return retval;
	}


	/**********************************************************************
	 * Flash services
	 *********************************************************************/
	/**
	 * Flash identification read. 
	 * Only available in chips with Process Technology code X
	 *
	 * \return id value
	 * \return -1	bus not free
	 */
	command int32_t HPLFlash.readIdentification()
	{
		int32_t retval;

		/***********************************************
		** Read identification
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_RDID);
		retval = call Spi.write(0);
		retval = (retval << 8) + call Spi.write(0);
		retval = (retval << 8) + call Spi.write(0);
		FLASH_UNSELECT();

		return retval;
	}

	/**
	 * Flash status register read. 
	 *
	 * \return status register value
	 * \return -1		bus not free
	 */
	command int16_t HPLFlash.readStatus()
	{
		int16_t retval;

		/***********************************************
		** Read status register
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_RDSR);
		retval = call Spi.write(M25P_RDSR);
		FLASH_UNSELECT();

		return retval;
	}

	/**
	 * Flash status register write. 
	 *
	 * \return SUCCESS
	 * \return FAIL		bus not free
	 */
	command result_t HPLFlash.writeStatus(uint8_t value)
	{

		/***********************************************
		** Enable write mode
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_WREN);
		FLASH_UNSELECT();

		TOSH_uwait(10);

		/***********************************************
		** Write status register
		***********************************************/
		FLASH_SELECT();
		call Spi.write(M25P_WRSR);
		call Spi.write(value);
		FLASH_UNSELECT();

		return SUCCESS;
	}



	/**********************************************************************
	 * Checks if flash is writing
	 *********************************************************************/
	command result_t HPLFlash.isFree() {
		uint8_t status;

		FLASH_SELECT();
		call Spi.write(M25P_RDSR);
		status = call Spi.write(0);
		FLASH_UNSELECT();

		TOSH_uwait(10);
	
		if (status & FLASH_SR_WIP) {
			return FAIL;
		} else {
			return SUCCESS;
		}
	}

	async event result_t StdOut.get(uint8_t data) {
		return SUCCESS;
	}

}

--- NEW FILE: HALSTM25P40M.nc ---
/*
  Copyright (C) 2004 Klaus S. Madsen <klaussm at diku.dk>
  Copyright (C) 2006 Marcus Chang <marcus at diku.dk>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/


#include "HPLSpi.h"


module HALSTM25P40M {
	provides {
		interface HALSTM25P40 as Flash;
	}

	uses {
		interface HPLSTM25P40 as HPLFlash;
		interface Timer;
		interface Spi;
		interface BusArbitration;
		interface StdOut;
	}
}

implementation {

#define QUEUE_SIZE 9
#define FLASH_BUSY_BACKOFF 200

	enum
	{
		TASK_READ = 0x01,
		TASK_FAST_READ = 0x02,
		TASK_WRITE = 0x03,
		TASK_SECTOR_ERASE = 0x04,
		TASK_BULK_ERASE = 0x05,
		TASK_SLEEP = 0x06,
		TASK_WAKEUP = 0x07,
		TASK_CHECK_BUSY = 0x08,
	};
		
	task void readTask();
	task void fastReadTask();
	task void writeTask();
	task void sectorEraseTask();
	task void bulkEraseTask();
	task void sleepTask();
	task void wakeupTask();
	task void checkBusyTask();

	bool taskPosted[QUEUE_SIZE];
	uint8_t queue[QUEUE_SIZE];
	uint8_t first, last, currentTask;
    bool timerActive = FALSE, flashTaskPosted = FALSE, postCheckBusyTask = FALSE;
    bool flashOn = FALSE;

    /**********************************************************************
     *********************************************************************/
	bool queuePutBack(uint8_t id) {

		if ( (queue[id] != 0) || (last == id) || (id > QUEUE_SIZE - 1) )
			return FALSE;

		if (first == 0) {
			first = id;
			last = id;
		} else {
			queue[last] = id;	
			last = id;
		}

		return TRUE;
	}

	bool queuePutFront(uint8_t id) {

		if ( (queue[id] != 0) || (last == id) || (id > QUEUE_SIZE - 1) )
			return FALSE;

		if (first == 0) {
			first = id;
			last = id;
		} else {
			queue[id] = first;
			first = id;
		}

		return TRUE;
	}

	uint8_t queueGet() {
		uint8_t retval;
		
		retval = first;
		first = queue[retval];
		queue[retval] = 0;

		if (first == 0) {
			last = 0;
		}
		
		return retval;
	}

	bool queueEmpty() {
		if ( (first == 0) && (flashTaskPosted == FALSE) ) {
			return TRUE;
		} else {
			return FALSE;
		}
	}
	
	void postNextTask() {
		uint8_t id;
		
		id = queueGet();

		switch(id) {           
			case TASK_READ:
				flashTaskPosted = TRUE;
				post readTask();
				break;

			case TASK_FAST_READ:
				flashTaskPosted = TRUE;
				post fastReadTask();
				break;

			case TASK_WRITE:
				flashTaskPosted = TRUE;
				post writeTask();
				break;

			case TASK_SECTOR_ERASE:
				flashTaskPosted = TRUE;
				post sectorEraseTask();
				break;

			case TASK_BULK_ERASE:
				flashTaskPosted = TRUE;
				post bulkEraseTask();
				break;

			case TASK_SLEEP:
				flashTaskPosted = TRUE;
				post sleepTask();
				break;

			case TASK_WAKEUP:
				flashTaskPosted = TRUE;
				post wakeupTask();
				break;

			default:
				break;
		}
	
			
		return;
	}

	/**********************************************************************
	 *********************************************************************/
	event result_t BusArbitration.busFree()
	{
		if (!timerActive && !queueEmpty() && !flashTaskPosted)
		{
			postNextTask();
		}
        else if (!timerActive && queueEmpty() && !flashTaskPosted && flashOn)
        {
            flashTaskPosted = TRUE;
            post sleepTask();
        }        
		else if (postCheckBusyTask == TRUE)
		{
			postCheckBusyTask = FALSE;
			post checkBusyTask();
		}

		return SUCCESS;
	}

	/**********************************************************************
	 *********************************************************************/
	event result_t Timer.fired()
	{
		post checkBusyTask();
		
		return SUCCESS;
	}

	/**********************************************************************
	 * Flash read
	 *********************************************************************/
	/**
	 * Read flash block.
	 *
	 *
	 * \param address block address on flash
	 * \param buffer  pointer to buffer
	 * \param length  length of read buffer
	 *
	 * \return SUCCESS
	 * \return FAIL	bus not free or init failed
	 */
	uint32_t readQueueAddress;
	uint8_t * readQueueBuffer;
	uint16_t readQueueLength;

	command result_t Flash.read(uint32_t address, uint8_t *buffer, uint16_t length)
	{
		if (address > 0x07FFFF) return FAIL;

		if (!taskPosted[TASK_READ]) {
			taskPosted[TASK_READ] = TRUE;
			
			readQueueAddress = address;
			readQueueBuffer = buffer;
			readQueueLength = length;

            /* if the queue is empty no task has been posted and the flash is off */
			if (queueEmpty()) {
				flashTaskPosted = TRUE;

                if (flashOn)
                {
                    post readTask();
                } else
                {
                    post wakeupTask();
                    queuePutBack(TASK_READ);
                }
			} else 
                queuePutBack(TASK_READ);

			return SUCCESS;
		} else {
			return FAIL;
		}
		
	}
	
	task void readTask() {

		if (call BusArbitration.getBus() == FAIL) {
			queuePutFront(TASK_READ);
			return;
		}
		
		/***********************************************
		** select SPI bus and module 1 (micro4)
		***********************************************/
		call Spi.enable(BUS_CLOCK_INVERT + BUS_CLOCK_4MHZ, 1);

		/***********************************************
		** Read flash into buffer
		***********************************************/
		call HPLFlash.read(readQueueAddress, readQueueBuffer, readQueueLength);

		signal Flash.readReady(readQueueAddress, readQueueBuffer, readQueueLength);

		flashTaskPosted = FALSE;
		taskPosted[TASK_READ] = FALSE;

		call Spi.disable();
		call BusArbitration.releaseBus();

		return;
	}
	

	/**
	 * Fast Read flash block.
	 *
	 *
	 * \param address block address on flash
	 * \param buffer  pointer to buffer
	 * \param length  length of read buffer
	 *
	 * \return SUCCESS
	 * \return FAIL	bus not free or init failed
	 */
	uint32_t fastReadQueueAddress;
	uint8_t * fastReadQueueBuffer;
	uint16_t fastReadQueueLength;

	command result_t Flash.fastRead(uint32_t address, uint8_t *buffer, uint16_t length)
	{
		if (address > 0x07FFFF) return FAIL;

		if (!taskPosted[TASK_FAST_READ]) {
			taskPosted[TASK_FAST_READ] = TRUE;
			
			fastReadQueueAddress = address;
			fastReadQueueBuffer = buffer;
			fastReadQueueLength = length;

            /* if the queue is empty no task has been posted and the flash is off */
			if (queueEmpty()) {
				flashTaskPosted = TRUE;

                if (flashOn)
                {
                    post fastReadTask();
                } else
                {
                    post wakeupTask();
                    queuePutBack(TASK_FAST_READ);
                }
			} else
                queuePutBack(TASK_FAST_READ);

			return SUCCESS;
		} else {
			return FAIL;
		}

	}

	task void fastReadTask() {

		if (call BusArbitration.getBus() == FAIL) {
			queuePutFront(TASK_FAST_READ);
			return;
		}
		
		/***********************************************
		** select SPI bus and module 1 (micro4)
		***********************************************/
		call Spi.enable(BUS_CLOCK_INVERT + BUS_CLOCK_4MHZ, 1);

		/***********************************************
		** Fast read flash into buffer
		***********************************************/
		call HPLFlash.fastRead(fastReadQueueAddress, fastReadQueueBuffer, fastReadQueueLength);

		signal Flash.fastReadReady(fastReadQueueAddress, fastReadQueueBuffer, fastReadQueueLength);

		flashTaskPosted = FALSE;
		taskPosted[TASK_FAST_READ] = FALSE;

		call Spi.disable();
		call BusArbitration.releaseBus();

		return;
	}
	

	/**********************************************************************
	 * Flash write
	 *********************************************************************/
	/**
	 * Write flash page. Page size is 256 bytes.
	 * Write address must point at start of page.
	 *
	 * \param address block address on flash
	 * \param buffer  pointer to buffer
	 * \param length  length of read buffer
	 *
	 * \return SUCCESS
	 * \return FAIL		bus not free or buffer too long
	 */
	uint32_t writeQueueAddress;
	uint8_t * writeQueueBuffer;
	uint16_t writeQueueLength;

	command result_t Flash.write(uint32_t address, uint8_t *buffer, uint16_t length)
	{
		if (address > 0x07FFFF) return FAIL;
		if ((length > 256) || (length == 0)) return FAIL;

		if (!taskPosted[TASK_WRITE]) {
			taskPosted[TASK_WRITE] = TRUE;
			
			writeQueueAddress = address;
			writeQueueBuffer = buffer;
			writeQueueLength = length;

            /* if the queue is empty no task has been posted and the flash is off */
			if (queueEmpty()) {
				flashTaskPosted = TRUE;

                if (flashOn)
                {
                    post writeTask();
                } else
                {
                    post wakeupTask();
                    queuePutBack(TASK_WRITE);
                }
			} else
                queuePutBack(TASK_WRITE);

			return SUCCESS;
		} else {
			return FAIL;
		}
	}

	task void writeTask() {

		if (call BusArbitration.getBus() == FAIL) {
			queuePutFront(TASK_WRITE);
			return;
		}
		
		/***********************************************
		** select SPI bus and module 1 (micro4)
		***********************************************/
		call Spi.enable(BUS_CLOCK_INVERT + BUS_CLOCK_4MHZ, 1);

		/***********************************************
		** Write buffer to page, starting at address
		***********************************************/
		call HPLFlash.write(writeQueueAddress, writeQueueBuffer, writeQueueLength);

		/* set timer to post checkBusyTask (signalTask) */
		call Timer.start(TIMER_ONE_SHOT, 20);
		timerActive = TRUE;
		currentTask = TASK_WRITE;

		taskPosted[TASK_WRITE] = FALSE;

		call Spi.disable();
		call BusArbitration.releaseBus();

		return;
	}



	/**********************************************************************
	 * Flash erase
	 *********************************************************************/
	/**
	 * Flash sector erase. Sector size is 64 kilobytes.
	 * Address must point at start of sector.
	 *
	 * \param address block address on flash
	 *
	 * \return SUCCESS
	 * \return FAIL		bus not free 
	 */
	uint32_t sectorEraseQueueAddress;

	command result_t Flash.sectorErase(uint32_t address)
	{
		if (address > 0x07FFFF) return FAIL;

		if (!taskPosted[TASK_SECTOR_ERASE]) {
			taskPosted[TASK_SECTOR_ERASE] = TRUE;
			
			sectorEraseQueueAddress = address;

            /* if the queue is empty no task has been posted and the flash is off */
			if (queueEmpty()) {
				flashTaskPosted = TRUE;
                
                if (flashOn)
                {
                    post sectorEraseTask();
                } else
                {
                    post wakeupTask();
                    queuePutBack(TASK_SECTOR_ERASE);
                }
			} else
                queuePutBack(TASK_SECTOR_ERASE);

			return SUCCESS;
		} else {
			return FAIL;
		}

	}
		
	task void sectorEraseTask() {

		if (call BusArbitration.getBus() == FAIL) {
			queuePutFront(TASK_SECTOR_ERASE);
			return;
		}
		
		/***********************************************
		** select SPI bus and module 1 (micro4)
		***********************************************/
		call Spi.enable(BUS_CLOCK_INVERT + BUS_CLOCK_4MHZ, 1);
		
		/***********************************************
		** Erase sector holding address
		***********************************************/
		call HPLFlash.sectorErase(sectorEraseQueueAddress);

		/* set timer to post checkBusyTask (signalTask) */
		call Timer.start(TIMER_ONE_SHOT, 1000);
		timerActive = TRUE;
		currentTask = TASK_SECTOR_ERASE;

		taskPosted[TASK_SECTOR_ERASE] = FALSE;

		call Spi.disable();
		call BusArbitration.releaseBus();

		return;
	}

	/**
	 * Flash bulk erase. 
	 * Erases entire flash
	 *
	 * \return SUCCESS
	 * \return FAIL	bus not free 
	 */
	command result_t Flash.bulkErase()
	{
		if (!taskPosted[TASK_BULK_ERASE]) {
			taskPosted[TASK_BULK_ERASE] = TRUE;
			
            /* if the queue is empty no task has been posted and the flash is off */
			if (queueEmpty()) {
				flashTaskPosted = TRUE;

                if (flashOn)
                {
                    post bulkEraseTask();
                } else
                {
    				post wakeupTask();
                    queuePutBack(TASK_BULK_ERASE);
                }
			} else
                queuePutBack(TASK_BULK_ERASE);

			return SUCCESS;
		} else {
			return FAIL;
		}
	}

	task void bulkEraseTask() {

		if (call BusArbitration.getBus() == FAIL) {
			queuePutFront(TASK_BULK_ERASE);
			return;
		}
		
		/***********************************************
		** select SPI bus and module 1 (micro4)
		***********************************************/
		call Spi.enable(BUS_CLOCK_INVERT + BUS_CLOCK_4MHZ, 1);

		/***********************************************
		** Bulk erase
		***********************************************/
		call HPLFlash.bulkErase();

		/* set timer to post checkBusyTask (signalTask) */
		call Timer.start(TIMER_ONE_SHOT, 4500);
		timerActive = TRUE;
		currentTask = TASK_BULK_ERASE;

		taskPosted[TASK_BULK_ERASE] = FALSE;

		call Spi.disable();
		call BusArbitration.releaseBus();

		return;
	}


	/**********************************************************************
	 * Flash power management
	 *********************************************************************/
	/**
	 * Deep Power-down. 
	 *
	 * \return SUCCESS
	 * \return FAIL		bus not free
	 */
	command result_t Flash.sleep()
	{
		if (!taskPosted[TASK_SLEEP]) 
        {
			taskPosted[TASK_SLEEP] = TRUE;
			
            /* if the queue is empty no task has been posted and the flash is off */
 			if (queueEmpty()) 
            {
 				flashTaskPosted = TRUE;
                post sleepTask();
   			} else {
                queuePutBack(TASK_SLEEP);                    
            }

			return SUCCESS;
		} else {

			return FAIL;
		}

	}
	
	task void sleepTask() {

		if (call BusArbitration.getBus() == FAIL) {
			queuePutFront(TASK_SLEEP);
			return;
		}
		
		/***********************************************
		** select SPI bus and module 1 (micro4)
		***********************************************/
		call Spi.enable(BUS_CLOCK_INVERT + BUS_CLOCK_4MHZ, 1);

		/***********************************************
		** Send command to enter deep power-down
		***********************************************/
		call HPLFlash.sleep();
        
        call StdOut.print("sleep\r\n");

        flashOn = FALSE;
        flashTaskPosted = FALSE;
		taskPosted[TASK_SLEEP] = FALSE;

		call Spi.disable();
		call BusArbitration.releaseBus();

		return;
	}

	/**
	 * Flash signature read. Wakes the device up from power down mode.
	 * Signature value should be 0x12 if the flash is present and working.
	 *
	 * \return signature value
	 * \return -1	bus not free
	 */
	command result_t Flash.wakeUp()
	{

		if (!taskPosted[TASK_WAKEUP]) 
        {
			taskPosted[TASK_WAKEUP] = TRUE;
			
            /* if the queue is empty no task has been posted and the flash is off */
            if (queueEmpty()) 
            {
                flashTaskPosted = TRUE;
                post wakeupTask();
            } else {
                queuePutBack(TASK_WAKEUP);                    
            }
            
			return SUCCESS;
		} else {

			return FAIL;
		}
	}

	task void wakeupTask() {
		int16_t retval;

		if (call BusArbitration.getBus() == FAIL) {
			queuePutFront(TASK_WAKEUP);
			return;
		}
		
		/***********************************************
		** select SPI bus and module 1 (micro4)
		***********************************************/
		call Spi.enable(BUS_CLOCK_INVERT + BUS_CLOCK_4MHZ, 1);


		/***********************************************
		** Read signature
		***********************************************/
		retval = call HPLFlash.wakeUp();

		call StdOut.print("wakeup: ");
    	call StdOut.printHex(retval);
		call StdOut.print("\r\n");

		/* check if wakeup was successfull */
		if (retval != 0x12) {

			/* flash not ready - repost wakeup task */
			post wakeupTask();
		} else 
		{
			/* wakeup completed */
            flashOn = TRUE;
			flashTaskPosted = FALSE;
			taskPosted[TASK_WAKEUP] = FALSE;
		}

		call Spi.disable();
		call BusArbitration.releaseBus();

		return;
	}



	/**********************************************************************
	 * Checks if flash is writing
	 *********************************************************************/
	task void checkBusyTask() {

		if (call BusArbitration.getBus() == FAIL) {
			postCheckBusyTask = TRUE;
			return;
		}
		
		/***********************************************
		** select SPI bus and module 1 (micro4)
		***********************************************/
		call Spi.enable(BUS_CLOCK_INVERT + BUS_CLOCK_4MHZ, 1);


		/***********************************************
		** Checks if flash is writing
		***********************************************/
		if (call HPLFlash.isFree() == SUCCESS) {
			
			/* signal recent task */
			switch(currentTask) {
				case TASK_WRITE:

					signal Flash.writeDone(writeQueueAddress, writeQueueBuffer, writeQueueLength);
					break;

				case TASK_SECTOR_ERASE:

					signal Flash.sectorEraseDone(sectorEraseQueueAddress);
					break;

				case TASK_BULK_ERASE:

					signal Flash.bulkEraseDone();
					break;

				default:
					break;
			}

			currentTask = 0;
			
			/* post - if any - next task */
			flashTaskPosted = FALSE;
			timerActive = FALSE;
			postNextTask();

		} else {

			call Timer.start(TIMER_ONE_SHOT, FLASH_BUSY_BACKOFF);
		}

		call Spi.disable();
		call BusArbitration.releaseBus();

		return;
	}


	async event result_t StdOut.get(uint8_t data) {
		return SUCCESS;
	}
}

--- NEW FILE: FlashAccess.nc ---
/*
  Interface for accessing flash with the page abstraction.

  Copyright (C) 2004 Klaus S. Madsen <klaussm at diku.dk>
  Copyright (C) 2006 Marcus Chang <marcus at diku.dk>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/



interface FlashAccess {

  command uint16_t firstUsablePage();
  command uint16_t lastUsablePage();

  /**
   * Read a page from the flash. 
   *
   * @param page_no The page to read from.
   * @param page    A buffer to hold the page bring read.
   * @return SUCCESS, the page could be read
   */
	command result_t read(uint16_t page_no, void *page);
	event void readReady(uint16_t page_no, void *page, uint16_t length);

  /**
   * Erase the sector holding the page in the flash.
   *
   * @param page_no The page inside the sector.
   * @return SUCCESS, the sector was erased.
   */
  command result_t erase(uint16_t page_no);
  event void eraseDone(uint16_t page_no);

  /**
   * Erase the entire flash.
   *
   * @return SUCCESS, the flash was erased.
   */
  command result_t eraseAll();
  event void eraseAllDone();

  /**
   * Write a page to the flash
   *
   * <p>Note this function does not clear the page before the
   * write. This must be done by calling erase</p>
   *
   * @param page_no The page to write
   * @param page    A buffer containing the contents to write
   * @result SUCCESS, the self-programming has successfully finished.
   */
  command result_t write(uint16_t page_no, void *page); 
  event void writeDone(uint16_t page_no, void *page);

}

--- NEW FILE: FlashAccessM.nc ---
/*
  Copyright (C) 2004 Klaus S. Madsen <klaussm at diku.dk>
  Copyright (C) 2006 Marcus Chang <marcus at diku.dk>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/


module FlashAccessM
{
	provides {
		interface StdControl as FlashControl;
		interface FlashAccess;
	}
	uses interface HALSTM25P40 as Flash;
}

implementation
{

#define FIRST_PAGE 0x0000
#define LAST_PAGE 0x07FF
#define PAGE_SIZE 0x0100

	command result_t FlashControl.init()
	{
		result_t r1, r2;
		
		r1 = call Flash.wakeUp();
		r2 = call Flash.sleep();
		
		return rcombine(r1, r2);
	}

	command result_t FlashControl.start()
	{
		return call Flash.wakeUp();
	}

	command result_t FlashControl.stop()
	{
		return call Flash.sleep();
	}

	command uint16_t FlashAccess.firstUsablePage() {
	
		return FIRST_PAGE;
	}
	
	command uint16_t FlashAccess.lastUsablePage() {
	
		return LAST_PAGE;
	}

	/**
	* Read a page from the flash. 
	*
	* @param page_no The page to read from.
	* @param page    A buffer to hold the page bring read.
	* @return SUCCESS, the page could be read
	*/
	command result_t FlashAccess.read(uint16_t page_no, void *page) {
	
		uint32_t address;

		if ( (FIRST_PAGE <= page_no) && (page_no <= LAST_PAGE) ) {
			address = page_no;
			address = address << 8;
	
			return call Flash.read(address, (uint8_t *) page, PAGE_SIZE);

		} else {
			return FAIL;
		}
	}

	event void Flash.readReady(uint32_t address, uint8_t *buffer, uint16_t length) {
		
		signal FlashAccess.readReady(address >> 8, buffer, length);
		
		return;
	}

	event void Flash.fastReadReady(uint32_t address, uint8_t *buffer, uint16_t length) {
		return;
	}

	/**
	* Erase the sector holding the page in the flash.
	*
	* @param page_no The page inside the sector.
	* @return SUCCESS, the sector was erased.
	*/
	command result_t FlashAccess.erase(uint16_t page_no) {
	
		uint32_t address;

		if ( (FIRST_PAGE <= page_no) && (page_no <= LAST_PAGE) ) {
			address = page_no;
			address = address << 8;
	
			return call Flash.sectorErase(address);

		} else {
			return FAIL;
		}
	} 
	
	event void Flash.sectorEraseDone(uint32_t address)
	{
		signal FlashAccess.eraseDone(address >> 8);
	}

	/**
	* Erase the sector holding the page in the flash.
	*
	* @param page_no The page inside the sector.
	* @return SUCCESS, the sector was erased.
	*/
	command result_t FlashAccess.eraseAll() {
	
		return call Flash.bulkErase();
	} 
	
	event void Flash.bulkEraseDone()
	{
		signal FlashAccess.eraseAllDone();
	}

	/**
	* Write a page to the flash
	*
	* <p>Note this function does not clear the page before the
	* write. This must be done by calling erase</p>
	*
	* @param page_no The page to write
	* @param page    A buffer containing the contents to write
	* @result SUCCESS, the self-programming has successfully finished.
	*/
	command result_t FlashAccess.write(uint16_t page_no, void *page) { 

		uint32_t address;

		if ( (FIRST_PAGE <= page_no) && (page_no <= LAST_PAGE) ) {
			address = page_no;
			address = address << 8;
	
			return call Flash.write(address, (uint8_t *) page, PAGE_SIZE);
			
		} else {
			return FAIL;
		}
	}
	
	event void Flash.writeDone(uint32_t address, uint8_t *buffer, uint16_t length)
	{
		signal FlashAccess.writeDone(address >> 8, buffer);
	}

}


--- NEW FILE: HALSTM25P40.nc ---
/*
  Copyright (C) 2004 Klaus S. Madsen <klaussm at diku.dk>
  Copyright (C) 2006 Marcus Chang <marcus at diku.dk>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/


interface HALSTM25P40 {

	/**
	 * Read flash block.
	 *
	 *
	 * \param address block address on flash
	 * \param buffer  pointer to buffer
	 * \param length  length of read buffer
	 *
	 * \return SUCCESS
	 * \return FAIL	bus not free or init failed
	 */
	command result_t read(uint32_t address, uint8_t *buffer, uint16_t length);
	event void readReady(uint32_t address, uint8_t *buffer, uint16_t length);

	/**
	 * Fast Read flash block.
	 *
	 *
	 * \param address block address on flash
	 * \param buffer  pointer to buffer
	 * \param length  length of read buffer
	 *
	 * \return SUCCESS
	 * \return FAIL	bus not free or init failed
	 */
	command result_t fastRead(uint32_t address, uint8_t *buffer, uint16_t length);
	event void fastReadReady(uint32_t address, uint8_t *buffer, uint16_t length);

	/**
	 * Write flash page. Page size is 256 bytes.
	 * Write address must point at start of page.
	 *
	 * \param address block address on flash
	 * \param buffer  pointer to buffer
	 * \param length  length of read buffer
	 *
	 * \return SUCCESS
	 * \return FAIL		bus not free or buffer too long
	 */
	command result_t write(uint32_t address, uint8_t *buffer, uint16_t length);
	event void writeDone(uint32_t address, uint8_t *buffer, uint16_t length);

	/**
	 * Flash sector erase. Sector size is 64 kilobytes.
	 * Address must point at start of or within sector.
	 *
	 * \param address block address on flash
	 *
	 * \return SUCCESS
	 * \return FAIL		bus not free 
	 */
	command result_t sectorErase(uint32_t address);
	event void sectorEraseDone(uint32_t address);

	/**
	 * Flash bulk erase. 
	 * Erases entire flash
	 *
	 * \return SUCCESS
	 * \return FAIL	bus not free 
	 */
	command result_t bulkErase();
	event void bulkEraseDone();

	/**
	 * Deep Power-down. 
	 *
	 * \return SUCCESS
	 * \return FAIL		bus not free
	 */
	command result_t sleep();

	/**
	 * Flash signature read. Wakes the device up from power down mode.
	 * Signature value should be 0x12 if the flash is present and working.
	 *
	 * \return signature value
	 * \return -1	bus not free
	 */
	command result_t wakeUp();

}

--- NEW FILE: HPLSTM25P40.nc ---
/*
  Copyright (C) 2004 Klaus S. Madsen <klaussm at diku.dk>
  Copyright (C) 2006 Marcus Chang <marcus at diku.dk>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/


interface HPLSTM25P40 {

	/**
	 * Read flash block.
	 *
	 *
	 * \param address block address on flash
	 * \param buffer  pointer to buffer
	 * \param length  length of read buffer
	 *
	 * \return SUCCESS
	 */
	command result_t read(uint32_t address, uint8_t *buffer, uint16_t length);

	/**
	 * Fast Read flash block.
	 *
	 *
	 * \param address block address on flash
	 * \param buffer  pointer to buffer
	 * \param length  length of read buffer
	 *
	 * \return SUCCESS
	 */
	command result_t fastRead(uint32_t address, uint8_t *buffer, uint16_t length);

	/**
	 * Write flash page. Page size is 256 bytes.
	 * Write address must point at start of page.
	 *
	 * \param address block address on flash
	 * \param buffer  pointer to buffer
	 * \param length  length of read buffer
	 *
	 * \return SUCCESS
	 */
	command result_t write(uint32_t address, uint8_t *buffer, uint16_t length);

	/**
	 * Flash sector erase. Sector size is 64 kilobytes.
	 * Address must point at start of or within sector.
	 *
	 * \param address block address on flash
	 *
	 * \return SUCCESS
	 */
	command result_t sectorErase(uint32_t address);

	/**
	 * Flash bulk erase. 
	 * Erases entire flash
	 *
	 * \return SUCCESS
	 */
	command result_t bulkErase();

	/**
	 * Deep Power-down. 
	 *
	 * \return SUCCESS
	 */
	command result_t sleep();

	/**
	 * Flash signature read. Wakes the device up from power down mode.
	 * Signature value should be 0x12 if the flash is present and working.
	 *
	 * \return signature value
	 */
	command int16_t wakeUp();

	/**
	 * Flash identification read. 
	 * Only available in chips with Process Technology code X
	 *
	 * \return id value
	 */
	command int32_t readIdentification();

	/**
	 * Flash status register read. 
	 *
	 * \return status register value
	 */
	command int16_t readStatus();

	/**
	 * Flash status register write. 
	 *
	 * \return SUCCESS
	 */
	command result_t writeStatus(uint8_t value);

	/**
	 * Flash write status. 
	 *
	 * \return SUCCESS
	 * \return FAIL		write in progress
	 */
	command result_t isFree();

}



More information about the Tinyos-contrib-commits mailing list