--- /dev/null
+/**************************************************************************/
+/*!
+ @file as1115.c
+ @author K. Townsend (microBuilder.eu)
+
+ @brief Drivers for the AS1115 I2C LED/segment-display driver
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2012, microBuilder SARL
+ 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+#include "as1115.h"
+#include "core/systick/systick.h"
+
+extern volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
+extern volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
+extern volatile uint32_t I2CReadLength, I2CWriteLength;
+
+static bool _as1115Initialised = false;
+
+/**************************************************************************/
+/*!
+ @brief Sends a single command byte over I2C to the specified address
+*/
+/**************************************************************************/
+as1115Error_t as1115WriteCmd (uint8_t address, uint8_t cmd)
+{
+ // Clear write buffers
+ uint32_t i;
+ for ( i = 0; i < I2C_BUFSIZE; i++ )
+ {
+ I2CMasterBuffer[i] = 0x00;
+ }
+
+ // ToDo: Add real I2C error checking
+ I2CWriteLength = 2;
+ I2CReadLength = 0;
+ I2CMasterBuffer[0] = address; // device sub address
+ I2CMasterBuffer[1] = cmd; // Command register
+ i2cEngine();
+ return AS1115_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes an command byte followed by a data byte over I2C
+*/
+/**************************************************************************/
+as1115Error_t as1115WriteCmdData (uint8_t address, uint8_t cmd, uint8_t data)
+{
+ // Clear write buffers
+ uint32_t i;
+ for ( i = 0; i < I2C_BUFSIZE; i++ )
+ {
+ I2CMasterBuffer[i] = 0x00;
+ }
+
+ // ToDo: Add real I2C error checking
+ I2CWriteLength = 3;
+ I2CReadLength = 0;
+ I2CMasterBuffer[0] = address; // I2C device address
+ I2CMasterBuffer[1] = cmd; // Command register
+ I2CMasterBuffer[2] = data; // Value to write
+ i2cEngine();
+ return AS1115_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads a single byte over I2C
+*/
+/**************************************************************************/
+as1115Error_t as1115Read8(uint8_t address, uint8_t *value)
+{
+ // Clear write buffers
+ uint32_t i;
+ for ( i = 0; i < I2C_BUFSIZE; i++ )
+ {
+ I2CMasterBuffer[i] = 0x00;
+ }
+
+ // ToDo: Add real I2C error checking
+ I2CWriteLength = 0;
+ I2CReadLength = 1;
+ I2CMasterBuffer[0] = address | AS1115_READBIT;
+ i2cEngine();
+
+ *value = I2CSlaveBuffer[0];
+
+ return AS1115_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Initialises the I2C block
+*/
+/**************************************************************************/
+as1115Error_t as1115Init(void)
+{
+ // Initialise I2C
+ if (i2cInit(I2CMASTER) == false)
+ {
+ return AS1115_ERROR_I2CINIT; /* Fatal error */
+ }
+
+ // Reset AS1115 to normal operation with default settings
+ as1115WriteCmdData(AS1115_ADDRESS, AS1115_SHUTDOWN, 0x01);
+
+ // Use user-set I2C address (000000 + address pins)
+ as1115WriteCmdData(AS1115_ADDRESS, AS1115_SELFADDR, 0x01);
+
+ systickDelay(20);
+
+ // Use hex decoding
+ as1115SetDecodeMode(0);
+
+ // Set the brightness to the maximum value (0x0F)
+ as1115SetBrightness(0xF);
+
+ // Turn on all digits by default (0..7)
+ as1115WriteCmdData(AS1115_SUBADDRESS, AS1115_SCANLIMIT, 0x07);
+
+ _as1115Initialised = true;
+
+ return AS1115_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Send test command
+*/
+/**************************************************************************/
+as1115Error_t as1115Test(void)
+{
+ as1115Error_t error = AS1115_ERROR_OK;
+ uint8_t results;
+
+ if (!_as1115Initialised) as1115Init();
+
+ // Use test register to detect LED status
+ error = as1115WriteCmd(AS1115_SUBADDRESS, AS1115_DISPTEST);
+ if (error) return error;
+
+ error = as1115Read8(AS1115_SUBADDRESS, &results);
+ if (error) return error;
+
+ // Throw an error since something is wrong with the wiring (use 'results' to check)
+ if ((results & 0xF8) != 0x80)
+ {
+ return AS1115_ERROR_UNEXPECTEDRESPONSE;
+ }
+
+ // Turn everything on
+ error = as1115WriteCmdData(AS1115_SUBADDRESS, AS1115_DISPTEST, 0x01);
+ if (error) return error;
+ systickDelay(1000);
+
+ // Turn everything off
+ error = as1115WriteCmdData(AS1115_SUBADDRESS, AS1115_DISPTEST, 0x00);
+ if (error) return error;
+
+ return error;
+}
+
+/**************************************************************************/
+/*!
+ @brief Sets the decode enable register to indicate if BCD or HEX
+ decoding should be used. Set to 0 for no BCD on all digits.
+*/
+/**************************************************************************/
+as1115Error_t as1115SetDecodeMode(uint8_t x)
+{
+ as1115Error_t error = AS1115_ERROR_OK;
+
+ error = as1115WriteCmdData(AS1115_SUBADDRESS, AS1115_DECODEMODE, x);
+ return error;
+}
+
+/**************************************************************************/
+/*!
+ @brief Sets the intensity control register (0..15 or 0x00..0x0F)
+*/
+/**************************************************************************/
+as1115Error_t as1115SetBrightness(uint8_t x)
+{
+ as1115Error_t error = AS1115_ERROR_OK;
+
+ if (x > 0xF) x = 0xF;
+
+ error = as1115WriteCmdData(AS1115_SUBADDRESS, AS1115_INTENSITY, x);
+ return error;
+}
+
+/**************************************************************************/
+/*!
+ @brief Sets the feature bit (controls blinking, clock source, etc.)
+*/
+/**************************************************************************/
+as1115Error_t as1115SetFeature(uint8_t feature)
+{
+ as1115Error_t error = AS1115_ERROR_OK;
+
+ error = as1115WriteCmdData(AS1115_SUBADDRESS, AS1115_FEATURE, feature);
+ return error;
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes an 8-bit buffer to the display
+*/
+/**************************************************************************/
+as1115Error_t as1115WriteBuffer(uint8_t *buffer)
+{
+ as1115Error_t error = AS1115_ERROR_OK;
+ uint32_t i;
+
+ if (!_as1115Initialised) as1115Init();
+
+ // Clear write buffers
+ for ( i = 0; i < I2C_BUFSIZE; i++ )
+ {
+ I2CMasterBuffer[i] = 0x00;
+ }
+
+ // Update individual digits
+ for ( i = 0; i < 8; i++ )
+ {
+ I2CWriteLength = 3;
+ I2CReadLength = 0;
+ I2CMasterBuffer[0] = AS1115_SUBADDRESS; // I2C device address
+ I2CMasterBuffer[1] = i+1; // Digit register
+ I2CMasterBuffer[2] = buffer[i]; // Value
+ i2cEngine();
+ }
+
+ return AS1115_ERROR_OK;
+}
+
--- /dev/null
+/**************************************************************************/
+/*!
+ @file as1115.h
+ @author K. Townsend (microBuilder.eu)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2012, microBuilder SARL
+ 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+
+#ifndef _AS1115_H_
+#define _AS1115_H_
+
+#include "projectconfig.h"
+#include "core/i2c/i2c.h"
+
+#define AS1115_ADDRESS (0x00 << 1)
+#define AS1115_SUBADDRESS (0x03 << 1)
+#define AS1115_READBIT (0x01)
+
+// Individual digit registers
+#define AS1115_DIGIT0 (0x01)
+#define AS1115_DIGIT1 (0x02)
+#define AS1115_DIGIT2 (0x03)
+#define AS1115_DIGIT3 (0x04)
+#define AS1115_DIGIT4 (0x05)
+#define AS1115_DIGIT5 (0x06)
+#define AS1115_DIGIT6 (0x07)
+#define AS1115_DIGIT7 (0x08)
+
+// Command registers
+#define AS1115_DECODEMODE (0x09)
+#define AS1115_INTENSITY (0x0A)
+#define AS1115_SCANLIMIT (0x0B)
+#define AS1115_SHUTDOWN (0x0C)
+#define AS1115_SELFADDR (0x2D)
+#define AS1115_FEATURE (0x0E)
+#define AS1115_DISPTEST (0x0F)
+
+// Bit definitions for AS1115_FEATURE
+#define AS1115_FEATURE_CLOCKENABLE (0x01) // 0 = Internal oscillator, 1 = Use pin CLK for sys clock input
+#define AS1115_FEATURE_RESETREGISTERS (0x02) // 0 = reset disabled, 1 = reset all ctrl registers to default state except function register
+#define AS1115_FEATURE_DECODESEL (0x04) // 0 = Enable BCD decoding, 1 = HEX decoding
+#define AS1115_FEATURE_BLINKENABLE (0x10) // 0 = Disable blinking, 1 = Enable blinking
+#define AS1115_FEATURE_BLINKFREQSEL (0x20) // 0 = 0.5s+0.5s on/off, 1 = 1s+1s on/off
+#define AS1115_FEATURE_SYNC (0x40) // Syncs blinking on rising edge of pin LD/CS
+#define AS1115_FEATURE_BLINKSTART (0x80) // 0 = blinking starts off, 1 = blinking starts on
+
+typedef enum
+{
+ AS1115_ERROR_OK = 0, // Everything executed normally
+ AS1115_ERROR_I2CINIT, // Unable to initialise I2C
+ AS1115_ERROR_I2CBUSY, // I2C already in use
+ AS1115_ERROR_UNEXPECTEDRESPONSE, // Didn't get 0x80 after AS1115_DISPTEST
+ AS1115_ERROR_LAST
+}
+as1115Error_t;
+
+as1115Error_t as1115Init(void);
+as1115Error_t as1115Test(void);
+as1115Error_t as1115SetDecodeMode(uint8_t x);
+as1115Error_t as1115SetBrightness(uint8_t x);
+as1115Error_t as1115SetFeature(uint8_t feature);
+as1115Error_t as1115WriteBuffer(uint8_t *buffer);
+
+#endif
+
+
--- /dev/null
+Segment/LED Displays
+====================
+
+This folder contains drivers for LED-based segment displays
+
+AS1115 AS1115 segment-display driver
+++ /dev/null
-/**************************************************************************/
-/*!
- @file at25040.c
- @author K. Townsend (microBuilder.eu)
- @date 22 March 2010
- @version 0.10
-
- @section DESCRIPTION
-
- Driver for Atmel's AT25010a/AT25020a/AT25040a 1K/2K/4K serial EEPROM.
-
- @note The AT25xxx has an 8-byte buffer, including 1 command byte
- and one address offset byte, meaning that a maximum of 6
- bytes can be read or written in one operation. An error
- will be returned if a value greater than 6 is passed in
- for bufferLength with the eepromRead and eepromWrite
- methods.
-
- @section Example
-
- @code
- #include "core/cpu/cpu.h"
- #include "drivers/eeprom/at25040/at25040.h"
-
- int main(void)
- {
- cpuInit();
- at25Init();
-
- // Set read and write buffers
- uint8_t wBuffer[1];
- uint8_t rBuffer[1];
-
- // Instantiate error message placeholder
- at25Error_e error = AT25_ERROR_OK;
-
- // Write 0xAA to EEPROM at address 0x0000
- wBuffer[0] = 0xAA;
- error = at25Write(0x0000, wBuffer, 1);
- if (error)
- {
- // Log the error message or take appropriate actions
- switch (error)
- {
- case (AT25_ERROR_TIMEOUT_WFINISH):
- // EEPROM timed out waiting for the write to finish
- break;
- case (AT25_ERROR_TIMEOUT_WE):
- // EEPROM timed out waiting for write-enable
- break;
- case (AT25_ERROR_ADDRERR):
- // Address is out of range
- break;
- }
- }
-
- // Read the EEPROM at address 0x0000
- at25Read(0x0000, rBuffer, 1);
- ...
- }
- @endcode
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2010, microBuilder SARL
- 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
-*/
-/**************************************************************************/
-
-#include "at25040.h"
-#include "core/ssp/ssp.h"
-#include "core/gpio/gpio.h"
-
-#define AT25_SELECT() gpioSetValue(0, 2, 0)
-#define AT25_DESELECT() gpioSetValue(0, 2, 1)
-
-uint32_t i, timeout;
-uint8_t src_addr[SSP_FIFOSIZE];
-uint8_t dest_addr[SSP_FIFOSIZE];
-
-/**************************************************************************/
-/*!
- @brief Sends the write enable command (WREN/0x06)
-*/
-/**************************************************************************/
-void at25WriteEnable()
-{
- AT25_SELECT();
- src_addr[0] = AT25_WREN;
- sspSend(0, (uint8_t *)src_addr, 1);
- AT25_DESELECT();
-
- // Delay for at least 250nS (1nS @ 72MHz = ~0.0072 ticks)
- for (i = 0; i < 100; i++);
-}
-
-/**************************************************************************/
-/*!
- @brief Gets the value of the Read Status Register (RDSR/0x05)
-
- @return The 8-bit value returned by the Read Status Register
-*/
-/**************************************************************************/
-uint8_t at25GetRSR()
-{
- AT25_SELECT();
- src_addr[0] = AT25_RDSR;
- sspSend(0, (uint8_t *)src_addr, 1);
- sspReceive(0, (uint8_t *)dest_addr, 1);
- AT25_DESELECT();
- return dest_addr[0] & (AT25_RDSR_WEN | AT25_RDSR_RDY);
-}
-
-/**************************************************************************/
-/*!
- @brief Initialises the SPI block (CLK set low when inactive, trigger
- on leading edge).
-*/
-/**************************************************************************/
-void at25Init (void)
-{
- sspInit(0, sspClockPolarity_Low, sspClockPhase_RisingEdge);
-}
-
-/**************************************************************************/
-/*!
- @brief Reads the specified number of bytes from the supplied address.
-
- This function will read one or more bytes starting at the supplied
- address.
-
- @param[in] address
- The 16-bit address where the read will start. The maximum
- value for the address depends on the size of the EEPROM
- @param[in] *buffer
- Pointer to the buffer that will store the read results
- @param[in] bufferLength
- Length of the buffer
-*/
-/**************************************************************************/
-at25Error_e at25Read (uint16_t address, uint8_t *buffer, uint32_t bufferLength)
-{
- if (address >= AT25_MAXADDRESS)
- {
- return AT25_ERROR_ADDRERR;
- }
-
- if (bufferLength > 6)
- {
- return AT25_ERROR_BUFFEROVERFLOW;
- }
-
- timeout = 0;
- while ( timeout < SSP_MAX_TIMEOUT )
- {
- // Wait until the device is ready
- uint8_t status = at25GetRSR() & AT25_RDSR_RDY;
- if (status == 0)
- {
- break;
- }
- timeout++;
- }
- if ( timeout == SSP_MAX_TIMEOUT )
- {
- return AT25_ERROR_TIMEOUT_WE;
- }
-
- AT25_SELECT();
- // Read command (0x03), append A8 if > addr 256 bytes
- src_addr[0] = address > 0xFF ? AT25_READ | AT25_A8 : AT25_READ;
- src_addr[1] = (address);
- sspSend(0, (uint8_t *)src_addr, 2);
- sspReceive(0, (uint8_t *)&dest_addr[2], bufferLength);
- AT25_DESELECT();
-
- // Fill response buffer
- for (i = 0; i < bufferLength; i++)
- {
- buffer[i] = dest_addr[i + 2];
- }
-
- return AT25_ERROR_OK;
-}
-
-/**************************************************************************/
-/*!
- @brief Writes the supplied bytes at a specified address.
-
- This function will write one or more bytes starting at the supplied
- address.
-
- @param[in] address
- The 16-bit address where the write will start. The
- maximum value for the address depends on the size of the
- EEPROM
- @param[in] *buffer
- Pointer to the buffer that contains the values to write.
- @param[in] bufferLength
- Length of the buffer
-*/
-/**************************************************************************/
-at25Error_e at25Write (uint16_t address, uint8_t *buffer, uint32_t bufferLength)
-{
- if (address >= AT25_MAXADDRESS)
- {
- return AT25_ERROR_ADDRERR;
- }
-
- if (bufferLength > 6)
- {
- return AT25_ERROR_BUFFEROVERFLOW;
- }
-
- // Set write enable latch
- at25WriteEnable();
-
- timeout = 0;
- while ( timeout < SSP_MAX_TIMEOUT )
- {
- // Wait until the device is write enabled
- if (at25GetRSR() == AT25_RDSR_WEN)
- {
- break;
- }
- timeout++;
- }
- if ( timeout == SSP_MAX_TIMEOUT )
- {
- return AT25_ERROR_TIMEOUT_WE;
- }
-
- for (i = 0; i < bufferLength; i++) // Init RD and WR buffer
- {
- src_addr[i+2] = buffer[i]; // leave two bytes for cmd and offset(8 bits)
- dest_addr[i] = 0;
- }
-
- AT25_SELECT();
- // Write command (0x02), append A8 if addr > 256 bytes
- src_addr[0] = address > 0xFF ? AT25_WRITE | AT25_A8 : AT25_WRITE;
- src_addr[1] = (address);
- sspSend(0, (uint8_t *)src_addr, bufferLength + 2);
- AT25_DESELECT();
-
- // Wait at least 3ms
- for (i = 0; i < ((CFG_CPU_CCLK / 1000) * 3); i++);
-
- timeout = 0;
- while ( timeout < SSP_MAX_TIMEOUT )
- {
- // Check status to see if write cycle is done or not
- AT25_SELECT();
- src_addr[0] = AT25_RDSR;
- sspSend(0, (uint8_t *)src_addr, 1);
- sspReceive(0, (uint8_t *)dest_addr, 1);
- AT25_DESELECT();
- // Wait until device is ready
- if ((dest_addr[0] & AT25_RDSR_RDY) == 0x00)
- {
- break;
- }
- timeout++;
- }
- if ( timeout == SSP_MAX_TIMEOUT )
- {
- return AT25_ERROR_TIMEOUT_WFINISH;
- }
-
- for (i = 0; i < 300; i++); // Wait at least 250ns
-
- return AT25_ERROR_OK;
-}
+++ /dev/null
-/**************************************************************************/
-/*!
- @file at25040.h
- @author K. Townsend (microBuilder.eu)
- @date 22 March 2010
- @version 0.10
-
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2010, microBuilder SARL
- 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
-*/
-/**************************************************************************/
-
-#ifndef _AT25040_H_
-#define _AT25040_H_
-
-#include "projectconfig.h"
-
-#define AT25_RDSR_RDY 0x01
-#define AT25_RDSR_WEN 0x02
-#define AT25_A8 0x08 // For addresses > 0xFF (AT25040 only) A8 must be added to R/W commands
-#define AT25_MAXADDRESS 0x0200 // AT25040 = 0X0200, AT25020 = 0x100, AT25010 = 0x80
-
-/**************************************************************************/
-/*!
- AT25040 Commands
-*/
-/**************************************************************************/
-typedef enum
-{
- AT25_WREN = 0x06,
- AT25_WRDI = 0x04,
- AT25_RDSR = 0x05,
- AT25_WRSR = 0x01,
- AT25_READ = 0x03,
- AT25_WRITE = 0x02
-} at25_Commands_e;
-
-/**************************************************************************/
-/*!
- Error messages
-*/
-/**************************************************************************/
-typedef enum
-{
- AT25_ERROR_OK = 0, // Everything executed normally
- AT25_ERROR_TIMEOUT_WE, // Timed out waiting for write enable status
- AT25_ERROR_TIMEOUT_WFINISH, // Timed out waiting for write to finish
- AT25_ERROR_ADDRERR, // Address out of range
- AT25_ERROR_BUFFEROVERFLOW, // Max 6 bytes can be read/written in one operation
- AT2_ERROR_LAST
-}
-at25Error_e;
-
-void at25Init (void);
-at25Error_e at25Read (uint16_t address, uint8_t *buffer, uint32_t bufferLength);
-at25Error_e at25Write (uint16_t address, uint8_t *buffer, uint32_t bufferLength);
-
-#endif
+++ /dev/null
-/**************************************************************************/
-/*!
- @file eeprom.c
- @author K. Townsend (microBuilder.eu)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2010, microBuilder SARL
- 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
-*/
-/**************************************************************************/
-#include <string.h>
-
-#include "projectconfig.h"
-#include "eeprom.h"
-
-// Currently only the MCP24AA I2C EEPROM is used
-#include "drivers/eeprom/mcp24aa/mcp24aa.h"
-
-static uint8_t buf[32];
-
-/**************************************************************************/
-/*!
- @brief Checks whether the supplied address is within the valid range
-
- @param[in] addr
- The 16-bit address to check
-
- @return Zero if the address is valid, otherwise 1
-*/
-/**************************************************************************/
-bool eepromCheckAddress(uint16_t addr)
-{
- // Check for invalid values
- return addr <= MCP24AA_MAXADDR ? FALSE : TRUE;
-}
-
-/**************************************************************************/
-/*!
- @brief Reads 1 byte from EEPROM
-
- @param[in] addr
- The 16-bit address to read from in EEPROM
-
- @return An unsigned 8-bit value (uint8_t)
-*/
-/**************************************************************************/
-uint8_t eepromReadU8(uint16_t addr)
-{
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaReadBuffer(addr, buf, sizeof(uint8_t));
-
- // ToDo: Handle any errors
- if (error) { };
-
- return buf[0];
-}
-
-/**************************************************************************/
-/*!
- @brief Reads 1 byte from EEPROM
-
- @param[in] addr
- The 16-bit address to read from in EEPROM
-
- @return A signed 8-bit value (int8_t)
-*/
-/**************************************************************************/
-int8_t eepromReadS8(uint16_t addr)
-{
- int8_t results;
-
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaReadBuffer(addr, buf, sizeof(int8_t));
-
- // ToDo: Handle any errors
- if (error) { };
-
- memcpy(&results, buf, sizeof(int8_t));
- return results;
-}
-
-/**************************************************************************/
-/*!
- @brief Reads 2 bytes from EEPROM
-
- @param[in] addr
- The 16-bit address to read from in EEPROM
-
- @return A unsigned 16-bit value (uint16_t)
-*/
-/**************************************************************************/
-uint16_t eepromReadU16(uint16_t addr)
-{
- uint16_t results;
-
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaReadBuffer(addr, buf, sizeof(uint16_t));
-
- // ToDo: Handle any errors
- if (error) { };
-
- memcpy(&results, buf, sizeof(uint16_t));
-
- return results;
-}
-
-/**************************************************************************/
-/*!
- @brief Reads 2 bytes from EEPROM
-
- @param[in] addr
- The 16-bit address to read from in EEPROM
-
- @return A signed 16-bit value (int16_t)
-*/
-/**************************************************************************/
-int16_t eepromReadS16(uint16_t addr)
-{
- int16_t results;
-
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaReadBuffer(addr, buf, sizeof(int16_t));
-
- // ToDo: Handle any errors
- if (error) { };
-
- memcpy(&results, buf, sizeof(int16_t));
- return results;
-}
-
-/**************************************************************************/
-/*!
- @brief Reads 4 bytes from EEPROM
-
- @param[in] addr
- The 16-bit address to read from in EEPROM
-
- @return A unsigned 32-bit value (uint32_t)
-*/
-/**************************************************************************/
-uint32_t eepromReadU32(uint16_t addr)
-{
- uint32_t results;
-
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaReadBuffer(addr, buf, sizeof(uint32_t));
-
- // ToDo: Handle any errors
- if (error) { };
-
- memcpy(&results, buf, sizeof(uint32_t));
- return results;
-}
-
-/**************************************************************************/
-/*!
- @brief Reads 4 bytes from EEPROM
-
- @param[in] addr
- The 16-bit address to read from in EEPROM
-
- @return A signed 32-bit value (int32_t)
-*/
-/**************************************************************************/
-int32_t eepromReadS32(uint16_t addr)
-{
- int32_t results;
-
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaReadBuffer(addr, buf, sizeof(int32_t));
-
- // ToDo: Handle any errors
- if (error) { };
-
- memcpy(&results, buf, sizeof(int32_t));
- return results;
-}
-
-/**************************************************************************/
-/*!
- @brief Reads 8 bytes from EEPROM
-
- @param[in] addr
- The 16-bit address to read from in EEPROM
-
- @return A unsigned 64-bit value (uint64_t)
-*/
-/**************************************************************************/
-uint64_t eepromReadU64(uint16_t addr)
-{
- uint64_t results;
-
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaReadBuffer(addr, buf, sizeof(uint64_t));
-
- // ToDo: Handle any errors
- if (error) { };
-
- memcpy(&results, buf, sizeof(uint64_t));
- return results;
-}
-
-/**************************************************************************/
-/*!
- @brief Reads 8 bytes from EEPROM
-
- @param[in] addr
- The 16-bit address to read from in EEPROM
-
- @return A signed 64-bit value (int64_t)
-*/
-/**************************************************************************/
-int64_t eepromReadS64(uint16_t addr)
-{
- int64_t results;
-
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaReadBuffer(addr, buf, sizeof(int64_t));
-
- // ToDo: Handle any errors
- if (error) { };
-
- memcpy(&results, buf, sizeof(int64_t));
- return results;
-}
-
-/**************************************************************************/
-/*!
- @brief Reads a variabls length buffer from EEPROM
-
- @param[in] addr
- The 16-bit address to write to in EEPROM
- @param[out] buffer
- Pointer to the buffer that will store any retrieved bytes
- @param[in] bufferLength
- The number of bytes to read
-*/
-/**************************************************************************/
-void eepromReadBuffer(uint16_t addr, uint8_t *buffer, uint32_t bufferLength)
-{
- // Instantiate error message placeholder
- mcp24aaError_e error = MCP24AA_ERROR_OK;
-
- // Read the contents of address
- error = mcp24aaReadBuffer(addr, buffer, bufferLength);
-
- // ToDo: Handle any errors
- if (error) { };
-}
-
-/**************************************************************************/
-/*!
- @brief Writes 1 byte to EEPROM
-
- @param[in] addr
- The 16-bit address to write to in EEPROM
-*/
-/**************************************************************************/
-void eepromWriteU8(uint16_t addr, uint8_t value)
-{
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
-
- // ToDo: Handle any errors
- if (error) { };
-}
-
-/**************************************************************************/
-/*!
- @brief Writes 1 signed byte to EEPROM
-
- @param[in] addr
- The 16-bit address to write to in EEPROM
-*/
-/**************************************************************************/
-void eepromWriteS8(uint16_t addr, int8_t value)
-{
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
-
- // ToDo: Handle any errors
- if (error) { };
-}
-
-/**************************************************************************/
-/*!
- @brief Writes an unsigned 16-bit integer to EEPROM
-
- @param[in] addr
- The 16-bit address to write to in EEPROM
-*/
-/**************************************************************************/
-void eepromWriteU16(uint16_t addr, uint16_t value)
-{
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
-
- // ToDo: Handle any errors
- if (error) { };
-}
-
-/**************************************************************************/
-/*!
- @brief Writes a signed 16-bit integer to EEPROM
-
- @param[in] addr
- The 16-bit address to write to in EEPROM
-*/
-/**************************************************************************/
-void eepromWriteS16(uint16_t addr, int16_t value)
-{
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
-
- // ToDo: Handle any errors
- if (error) { };
-}
-
-/**************************************************************************/
-/*!
- @brief Writes an unsigned 32-bit integer to EEPROM
-
- @param[in] addr
- The 16-bit address to write to in EEPROM
-*/
-/**************************************************************************/
-void eepromWriteU32(uint16_t addr, uint32_t value)
-{
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
-
- // ToDo: Handle any errors
- if (error) { };
-}
-
-/**************************************************************************/
-/*!
- @brief Writes a signed 32-bit integer to EEPROM
-
- @param[in] addr
- The 16-bit address to write to in EEPROM
-*/
-/**************************************************************************/
-void eepromWriteS32(uint16_t addr, int32_t value)
-{
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
-
- // ToDo: Handle any errors
- if (error) { };
-}
-
-/**************************************************************************/
-/*!
- @brief Writes an unsigned 64-bit integer to EEPROM
-
- @param[in] addr
- The 16-bit address to write to in EEPROM
-*/
-/**************************************************************************/
-void eepromWriteU64(uint16_t addr, uint64_t value)
-{
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
-
- // ToDo: Handle any errors
- if (error) { };
-}
-
-/**************************************************************************/
-/*!
- @brief Writes a signed 64-bit integer to EEPROM
-
- @param[in] addr
- The 16-bit address to write to in EEPROM
-*/
-/**************************************************************************/
-void eepromWriteS64(uint16_t addr, int64_t value)
-{
- mcp24aaError_e error = MCP24AA_ERROR_OK;
- error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
-
- // ToDo: Handle any errors
- if (error) { };
-}
+++ /dev/null
-/**************************************************************************/
-/*!
- @file eeprom.h
- @author K. Townsend (microBuilder.eu)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2010, microBuilder SARL
- 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
-*/
-/**************************************************************************/
-#ifndef __EEPROM_H__
-#define __EEPROM_H__
-
-#include "projectconfig.h"
-
-// Method Prototypes
-bool eepromCheckAddress ( uint16_t addr );
-uint8_t eepromReadU8 ( uint16_t addr );
-int8_t eepromReadS8 ( uint16_t addr );
-uint16_t eepromReadU16 ( uint16_t addr );
-int16_t eepromReadS16 ( uint16_t addr );
-uint32_t eepromReadU32 ( uint16_t addr );
-int32_t eepromReadS32 ( uint16_t addr );
-uint64_t eepromReadU64 ( uint16_t addr );
-int64_t eepromReadS64 ( uint16_t addr );
-void eepromReadBuffer ( uint16_t addr, uint8_t *buffer, uint32_t bufferLength);
-void eepromWriteU8 ( uint16_t addr, uint8_t value );
-void eepromWriteS8 ( uint16_t addr, int8_t value );
-void eepromWriteU16 ( uint16_t addr, uint16_t value );
-void eepromWriteS16 ( uint16_t addr, int16_t value );
-void eepromWriteU32 ( uint16_t addr, uint32_t value );
-void eepromWriteS32 ( uint16_t addr, int32_t value );
-void eepromWriteU64 ( uint16_t addr, uint64_t value );
-void eepromWriteS64 ( uint16_t addr, int64_t value );
-
-#endif
+++ /dev/null
-/**************************************************************************/
-/*!
- @file mcp24aa.c
- @author K. Townsend (microBuilder.eu)
- @date 22 March 2010
- @version 0.10
-
- @section DESCRIPTION
-
- Driver for Microchip's 24AA32AF serial EEPROM. This driver assumes
- that the address is set to 1010 000.
-
- @section Example
-
- @code
- #include "core/cpu/cpu.h"
- #include "drivers/eeprom/mcp24aa/mcp24aa.h"
-
- int main(void)
- {
- cpuInit();
-
- mcp24aaInit();
-
- // Instantiate error message placeholder
- mcp24aaError_e error = MCP24AA_ERROR_OK;
-
- // Create read buffer (1 byte)
- uint8_t buffer[1] = { 0x00 };
-
- // Write 0xCC at address 0x125
- error = mcp24aaWriteByte(0x0125, 0xCC);
- if (error)
- {
- // Handle any errors
- switch (error)
- {
- case (MCP24AA_ERROR_I2CINIT):
- // Unable to initialise I2C
- break;
- case (MCP24AA_ERROR_ADDRERR):
- // Address out of range
- break;
- default:
- break;
- }
- }
-
- // Read the contents of address 0x0125
- error = MCP24AA_ERROR_OK;
- error = mcp24aaReadByte(0x0125, buffer);
- if (error)
- {
- // Handle any errors
- switch (error)
- {
- case (MCP24AA_ERROR_I2CINIT):
- // Unable to initialise I2C
- break;
- case (MCP24AA_ERROR_ADDRERR):
- // Address out of range
- break;
- default:
- break;
- }
- }
-
- uint8_t results = buffer[0];
- }
- @endcode
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2010, microBuilder SARL
- 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
-*/
-/**************************************************************************/
-
-#include "mcp24aa.h"
-#include "core/systick/systick.h"
-#include "core/i2c/i2c.h"
-
-extern volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
-extern volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
-extern volatile uint32_t I2CReadLength, I2CWriteLength;
-
-static bool _mcp24aaInitialised = false;
-
-/**************************************************************************/
-/*!
- @brief Initialises the I2C block
-*/
-/**************************************************************************/
-mcp24aaError_e mcp24aaInit()
-{
- // Initialise I2C
- if (i2cInit(I2CMASTER) == false)
- {
- return MCP24AA_ERROR_I2CINIT; /* Fatal error */
- }
-
- // Set initialisation flag
- _mcp24aaInitialised = true;
-
- return MCP24AA_ERROR_OK;
-}
-
-/**************************************************************************/
-/*!
- @brief Reads the specified number of bytes from the supplied address.
-
- This function will read one or more bytes starting at the supplied
- address. A maximum of 8 bytes can be read in one operation.
-
- @param[in] address
- The 16-bit address where the read will start. The maximum
- value for the address depends on the size of the EEPROM
- @param[in] *buffer
- Pointer to the buffer that will store the read results
- @param[in] bufferLength
- Length of the buffer
-*/
-/**************************************************************************/
-mcp24aaError_e mcp24aaReadBuffer (uint16_t address, uint8_t *buffer, uint32_t bufferLength)
-{
- if (!_mcp24aaInitialised) mcp24aaInit();
-
- if (address >= MCP24AA_MAXADDR)
- {
- return MCP24AA_ERROR_ADDRERR;
- }
-
- if (bufferLength > 8)
- {
- return MCP24AA_ERROR_BUFFEROVERFLOW;
- }
-
- // ToDo: Check if I2C is ready
-
- // Clear buffers
- uint32_t i;
- for ( i = 0; i < I2C_BUFSIZE; i++ )
- {
- I2CMasterBuffer[i] = 0x00;
- I2CSlaveBuffer[i] = 0x00;
- }
-
- // Write address bits to enable random read
- I2CWriteLength = 3;
- I2CReadLength = bufferLength;
- I2CMasterBuffer[0] = MCP24AA_ADDR; // I2C device address
- I2CMasterBuffer[1] = (address >> 8); // Address (high byte)
- I2CMasterBuffer[2] = (address & 0xFF); // Address (low byte)
- // If you wish to read, you need to append the address w/read bit, though this
- // needs to be placed one bit higher than the size of I2CWriteLength which
- // may be unexpected
- I2CMasterBuffer[3] = MCP24AA_ADDR | MCP24AA_READBIT;
-
- // Transmit command
- i2cEngine();
-
- // Fill response buffer
- for (i = 0; i < bufferLength; i++)
- {
- buffer[i] = I2CSlaveBuffer[i];
- }
-
- return MCP24AA_ERROR_OK;
-}
-
-/**************************************************************************/
-/*!
- @brief Writes the supplied bytes at a specified address.
-
- This function will write one or more bytes starting at the supplied
- address. A maximum of 8 bytes can be written in one operation.
-
- @param[in] address
- The 16-bit address where the write will start. The
- maximum value for the address depends on the size of the
- EEPROM
- @param[in] *buffer
- Pointer to the buffer that contains the values to write.
- @param[in] bufferLength
- Length of the buffer
-*/
-/**************************************************************************/
-mcp24aaError_e mcp24aaWriteBuffer (uint16_t address, uint8_t *buffer, uint32_t bufferLength)
-{
- if (!_mcp24aaInitialised) mcp24aaInit();
-
- if (address >= MCP24AA_MAXADDR)
- {
- return MCP24AA_ERROR_ADDRERR;
- }
-
- if (bufferLength > 8)
- {
- return MCP24AA_ERROR_BUFFEROVERFLOW;
- }
-
- // ToDo: Check if I2C is ready
-
- // Clear write buffer
- uint32_t i;
- for ( i = 0; i < I2C_BUFSIZE; i++ )
- {
- I2CMasterBuffer[i] = 0x00;
- }
-
- // Write address bits and data to the master buffer
- I2CWriteLength = 3 + bufferLength;
- I2CReadLength = 0;
- I2CMasterBuffer[0] = MCP24AA_ADDR; // I2C device address
- I2CMasterBuffer[1] = (address >> 8); // Address (high byte)
- I2CMasterBuffer[2] = (address & 0xFF); // Address (low byte)
- for (i = 0; i < bufferLength; i++)
- {
- I2CMasterBuffer[i+3] = buffer[i];
- }
-
- // Transmit command
- i2cEngine();
-
- // Wait at least 10ms
- systickDelay(10);
-
- return MCP24AA_ERROR_OK;
-}
-
-/**************************************************************************/
-/*!
- @brief Reads one byte from the supplied address.
-
- This function will read one byte starting at the supplied address.
-
- @param[in] address
- The 16-bit address where the read will start. The maximum
- value for the address depends on the size of the EEPROM
- @param[in] *buffer
- Pointer to the buffer that will store the read results
-
- @code
- #include "core/cpu/cpu/h"
- #include "drivers/eeprom/mcp24aa/mcp24aa.h"
- ...
- cpuInit();
- mcp24aaInit();
-
- // Create read buffer (1 byte)
- uint8_t buffer[1] = { 0x00 };
-
- // Write 0xEE and address 0x0120
- mcp24aaWriteByte(0x0120, 0xEE);
-
- // Populate buffer with contents of 0x0120
- mcp24aaReadByte(0x0120, buffer);
-
- // results should equal 0xEE
- uint8_t results = buffer[0];
- @endcode
-*/
-/**************************************************************************/
-mcp24aaError_e mcp24aaReadByte (uint16_t address, uint8_t *buffer)
-{
- if (!_mcp24aaInitialised) mcp24aaInit();
-
- return mcp24aaReadBuffer(address, buffer, 1);
-}
-
-/**************************************************************************/
-/*!
- @brief Writes one byte to the supplied address.
-
- This function will write one byte at the supplied address.
-
- @param[in] address
- The 16-bit address where the write will start. The maximum
- value for the address depends on the size of the EEPROM
- @param[in] value
- The data to be written to the EEPROM
-
- @code
- #include "core/cpu/cpu/h"
- #include "drivers/eeprom/mcp24aa/mcp24aa.h"
- ...
- cpuInit();
- mcp24aaInit();
-
- // Create read buffer (1 byte)
- uint8_t buffer[1] = { 0x00 };
-
- // Write 0xEE and address 0x0120
- mcp24aaWriteByte(0x0120, 0xEE);
-
- // Populate buffer with contents of 0x0120
- mcp24aaReadByte(0x0120, buffer);
-
- // results should equal 0xEE
- uint8_t results = buffer[0];
- @endcode
-*/
-/**************************************************************************/
-mcp24aaError_e mcp24aaWriteByte (uint16_t address, uint8_t value)
-{
- if (!_mcp24aaInitialised) mcp24aaInit();
-
- // Set read buffer
- uint8_t wBuffer[1];
-
- // Write byte to EEPROM at specified address
- wBuffer[0] = value;
- return mcp24aaWriteBuffer(address, wBuffer, 1);
-}
-
+++ /dev/null
-/**************************************************************************/
-/*!
- @file mcp24aa.h
- @author K. Townsend (microBuilder.eu)
- @date 22 March 2010
- @version 0.10
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2010, microBuilder SARL
- 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
-*/
-/**************************************************************************/
-
-#ifndef _MCP24AA_H_
-#define _MCP24AA_H_
-
-#include "projectconfig.h"
-
-#define MCP24AA_ADDR 0xA0 // 10100000
-#define MCP24AA_RW 0x01
-#define MCP24AA_READBIT 0x01
-#define MCP24AA_MAXADDR 0xFFF // 4K = 4096
-
-typedef enum
-{
- MCP24AA_ERROR_OK = 0, // Everything executed normally
- MCP24AA_ERROR_I2CINIT, // Unable to initialise I2C
- MCP24AA_ERROR_I2CBUSY, // I2C already in use
- MCP24AA_ERROR_ADDRERR, // Address out of range
- MCP24AA_ERROR_BUFFEROVERFLOW, // Max 8 bytes can be read/written in one operation
- MCP24AA_ERROR_LAST
-}
-mcp24aaError_e;
-
-mcp24aaError_e mcp24aaInit (void);
-mcp24aaError_e mcp24aaReadBuffer (uint16_t address, uint8_t *buffer, uint32_t bufferLength);
-mcp24aaError_e mcp24aaWriteBuffer (uint16_t address, uint8_t *buffer, uint32_t bufferLength);
-mcp24aaError_e mcp24aaReadByte (uint16_t address, uint8_t *buffer);
-mcp24aaError_e mcp24aaWriteByte (uint16_t address, uint8_t value);
-
-
-#endif
+++ /dev/null
-/**************************************************************************/
-/*!
- @file spiflash.h
- @author K. Townsend (microBuilder.eu)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2010, microBuilder SARL
- 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
-*/
-/**************************************************************************/
-
-#ifndef _SPIFLASH_H_
-#define _SPIFLASH_H_
-
-#include "projectconfig.h"
-
-/**************************************************************************/
-/*!
- @brief Error messages
-*/
-/**************************************************************************/
-typedef enum
-{
- SPIFLASH_ERROR_OK = 0, // Everything executed normally
- SPIFLASH_ERROR_ADDROUTOFRANGE = 1, // Address out of range
- SPIFLASH_ERROR_TIMEOUT_READY = 2, // Timeout waiting for ready status
- SPIFLASH_ERROR_WRITEERR = 3, // Write Error
- SPIFLASH_ERROR_PROTECTIONERR = 4, // Write Protection Error
- SPIFLASH_ERROR_ADDROVERFLOW = 5, // Address overflow during read/write
- SPIFLASH_ERROR_UNEXPECTEDID = 6, // The manufacturer and/or device ID are different than expected
- SPIFLASH_ERROR_NOTSTARTOFPAGE = 7, // The supplied address is not the start of a new page
- SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE = 9, // When writing page data, you can't exceed page size
- SPIFLASH_ERROR_PAGEWRITEOVERFLOW = 10, // Page data will overflow beause (start address + len) > page size
- SPIFLASH_ERROR_LAST
-}
-spiflashError_e;
-
-/**************************************************************************/
-/*!
- @brief Describes the storage capacity of the SPI flash, including the
- size of the minimum HW write (page) and erase (sector) units.
-*/
-/**************************************************************************/
-typedef struct
-{
- uint32_t pageSize; // Page size to write data (in bytes)
- uint32_t pageCount; // Number of pages
- uint32_t sectorSize; // Sector size to erase data (in bytes)
- uint32_t sectorCount; // Number of sectors
-}
-spiflashSizeInfo_t;
-
-/**************************************************************************/
-/*!
- @brief Tries to initialise the flash device, and sets up any HW
- required by the SPI flash
-*/
-/**************************************************************************/
-void spiflashInit (void);
-
-/**************************************************************************/
-/*!
- @brief Gets an instance of spiflashSizeInfo_t that describes the
- storage limits of the SPI flash like page size (minimum write
- size) and sector size (minimum erase size).
-*/
-/**************************************************************************/
-spiflashSizeInfo_t spiflashGetSizeInfo(void);
-
-/**************************************************************************/
-/*!
- @brief Gets the 8-bit manufacturer ID and device ID for the flash
-
- @param[out] *manufID
- Pointer to the uint8_t that will store the manufacturer ID
- @param[out] *deviceID
- Pointer to the uint8_t that will store the device ID
-*/
-/**************************************************************************/
-void spiflashGetManufacturerInfo (uint8_t *manufID, uint8_t *deviceID);
-
-/**************************************************************************/
-/*!
- @brief Sets the write flag on the SPI flash, and if required puts the
- WP pin in an appropriate state
-
- @param[in] enable
- True (1) to enable writing, false (0) to disable it
-*/
-/**************************************************************************/
-void spiflashWriteEnable (bool enable);
-
-/**************************************************************************/
-/*!
- @brief Reads the specified number of bytes from the supplied address.
-
- This function will read one or more bytes starting at the supplied
- address. Please note that bufferLength is zero-based, meaning you
- should supply '0' to read a single byte, '3' to read 4 bytes of data,
- etc.
-
- @param[in] address
- The 24-bit address where the read will start.
- @param[out] *buffer
- Pointer to the buffer that will store the read results
- @param[in] len
- Length of the buffer.
-
- @section EXAMPLE
-
- @code
- uint8_t buffer[64];
- spiflashError_e error;
- error = spiflashReadBuffer (0, buffer, 64);
- if (error)
- {
- // Check what went wrong
- switch (error)
- {
- case SPIFLASH_ERROR_ADDROUTOFRANGE:
- // Specified starting address is out of range
- break;
- case SPIFLASH_ERROR_TIMEOUT_READY:
- // Timed out waiting for flash to return ready state
- break;
- case SPIFLASH_ERROR_ADDROVERFLOW:
- // Ran over the upper address during read
- break;
- }
- }
- @endcode
-*/
-/**************************************************************************/
-spiflashError_e spiflashReadBuffer (uint32_t address, uint8_t *buffer, uint32_t len);
-
-/**************************************************************************/
-/*!
- @brief Erases the contents of a single sector
-
- @param[in] sectorNumber
- The sector number to erase (zero-based).
-
- @section EXAMPLE
-
- @code
- spiflashError_e error;
- error = spiflashEraseSector(0);
- if (error)
- {
- // Check what went wrong
- switch (error)
- {
- case SPIFLASH_ERROR_ADDROUTOFRANGE:
- // Specified starting address is out of range
- break;
- case SPIFLASH_ERROR_PROTECTIONERR:
- // Couldn't set the write enable bit
- break;
- case SPIFLASH_ERROR_TIMEOUT_READY:
- // Timed out waiting for flash to return ready state
- break;
- }
- }
- @endcode
-*/
-/**************************************************************************/
-spiflashError_e spiflashEraseSector (uint32_t sectorNumber);
-
-/**************************************************************************/
-/*!
- @brief Erases the entire flash chip
-
- @section EXAMPLE
-
- @code
- spiflashError_e error;
- error = spiflashEraseChip();
- if (error)
- {
- // Check what went wrong
- switch (error)
- {
- case SPIFLASH_ERROR_PROTECTIONERR:
- // Couldn't set the write enable bit
- break;
- case SPIFLASH_ERROR_TIMEOUT_READY:
- // Timed out waiting for flash to return ready state
- break;
- }
- }
- @endcode
-*/
-/**************************************************************************/
-spiflashError_e spiflashEraseChip (void);
-
-/**************************************************************************/
-/*!
- @brief Writes up to 256 bytes of data to the specified page.
-
- @note Before writing data to a page, make sure that the 4K sector
- containing the specific page has been erased, otherwise the
- data will be meaningless.
-
- @param[in] address
- The 24-bit address where the write will start.
- @param[out] *buffer
- Pointer to the buffer that will store the read results
- @param[in] len
- Length of the buffer. Valid values are from 1 to 256,
- within the limits of the starting address and page length.
-
- @section EXAMPLE
-
- @code
- spiflashError_e error;
- uint8_t buffer[256];
-
- buffer[0] = 0x12;
- buffer[1] = 0x34;
- buffer[2] = 0x56;
- buffer[3] = 0x78;
- buffer[4] = 0xDE;
- buffer[5] = 0xAD;
- buffer[6] = 0xC0;
- buffer[7] = 0xDE;
-
- error = spiflashWritePage (0, buffer, 8);
- if (error)
- {
- // Check what went wrong
- switch (error)
- {
- case SPIFLASH_ERROR_ADDROUTOFRANGE:
- // Specified starting address is out of range
- break;
- case SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE:
- // Supplied data exceeds max page size
- break;
- case SPIFLASH_ERROR_PAGEWRITEOVERFLOW:
- // The data length plus the start address offset exceeeds page limits
- break;
- case SPIFLASH_ERROR_TIMEOUT_READY:
- // Timeout waiting for ready status (can be pre or post write)
- break;
- case SPIFLASH_ERROR_PROTECTIONERR:
- // Unable to set write latch
- break;
- }
- }
- @endcode
-*/
-/**************************************************************************/
-spiflashError_e spiflashWritePage (uint32_t address, uint8_t *buffer, uint32_t len);
-
-/**************************************************************************/
-/*!
- @brief Writes a continuous stream of data that will automatically
- cross page boundaries.
-
- @note Before writing data, make sure that the appropriate sectors
- have been erased, otherwise the data will be meaningless.
-
- @param[in] address
- The 24-bit address where the write will start.
- @param[out] *buffer
- Pointer to the buffer that will store the read results
- @param[in] len
- Length of the buffer, within the limits of the starting
- address and size of the flash device.
-
- @section EXAMPLE
-
- @code
- spiflashError_e error;
- uint8_t buffer[256];
-
- buffer[0] = 0x12;
- buffer[1] = 0x34;
- buffer[2] = 0x56;
- buffer[3] = 0x78;
- buffer[4] = 0xDE;
- buffer[5] = 0xAD;
- buffer[6] = 0xC0;
- buffer[7] = 0xDE;
-
- error = spiflashWrite (0, buffer, 8);
- if (error)
- {
- // Check what went wrong
- switch (error)
- {
- case SPIFLASH_ERROR_ADDROUTOFRANGE:
- // Specified starting address is out of range
- break;
- case SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE:
- // Supplied data exceeds max page size
- break;
- case SPIFLASH_ERROR_PAGEWRITEOVERFLOW:
- // The data length plus the start address offset exceeeds page limits
- break;
- case SPIFLASH_ERROR_TIMEOUT_READY:
- // Timeout waiting for ready status (can be pre or post write)
- break;
- case SPIFLASH_ERROR_PROTECTIONERR:
- // Unable to set write latch
- break;
- }
- }
- @endcode
-*/
-/**************************************************************************/
-spiflashError_e spiflashWrite (uint32_t address, uint8_t *buffer, uint32_t len);
-
-#endif
+++ /dev/null
-/**************************************************************************/
-/*!
- @file w25q16bv.c
- @author K. Townsend (microBuilder.eu)
-
- @section DESCRIPTION
-
- Driver for Winbond's 16 MBit SPI/Quad-SPI Flash (W25Q16BV)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2010, microBuilder SARL
- 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
-*/
-/**************************************************************************/
-
-#include "w25q16bv.h"
-#include "../spiflash.h"
-#include "core/ssp/ssp.h"
-#include "core/gpio/gpio.h"
-#include "core/systick/systick.h"
-
-// Macros to toggle the CS/SSEL line on the SPI bus
-#define W25Q16BV_SELECT() gpioSetValue(0, 2, 0)
-#define W25Q16BV_DESELECT() gpioSetValue(0, 2, 1)
-
-// Flag to indicate whether the SPI flash has been initialised or not
-static bool _w25q16bvInitialised = false;
-
-/**************************************************************************/
-/* HW Specific Functions */
-/* ------------------------------------------------------------------- */
-/* These functions are specific to the chip being used, and are */
-/* seperate from the 'generic' functions defined in spiflash.h */
-/* */
-/**************************************************************************/
-
-/**************************************************************************/
-/*!
- This function both reads and writes data. For write operations, include data
- to be written as argument. For read ops, use dummy data as arg. Returned
- data is read byte val.
-*/
-/**************************************************************************/
-uint8_t w25q16bv_TransferByte(uint8_t data)
-{
- /* Move on only if NOT busy and TX FIFO not full */
- while ((SSP_SSP0SR & (SSP_SSP0SR_TNF_MASK | SSP_SSP0SR_BSY_MASK)) != SSP_SSP0SR_TNF_NOTFULL);
- SSP_SSP0DR = data;
-
- /* Wait until the busy bit is cleared and receive buffer is not empty */
- while ((SSP_SSP0SR & (SSP_SSP0SR_BSY_MASK | SSP_SSP0SR_RNE_MASK)) != SSP_SSP0SR_RNE_NOTEMPTY);
-
- // Read the queue
- return SSP_SSP0DR;
-}
-
-/**************************************************************************/
-/*!
- @brief Gets the value of the Read Status Register (0x05)
-
- @return The 8-bit value returned by the Read Status Register
-*/
-/**************************************************************************/
-uint8_t w25q16bvGetStatus()
-{
- uint8_t status;
-
- W25Q16BV_SELECT();
- w25q16bv_TransferByte(W25Q16BV_CMD_READSTAT1); // Send read status 1 cmd
- status = w25q16bv_TransferByte(0xFF); // Dummy write
- W25Q16BV_DESELECT();
-
- return status & (W25Q16BV_STAT1_BUSY | W25Q16BV_STAT1_WRTEN);
-}
-
-/**************************************************************************/
-/*!
- @brief Waits for the SPI flash to indicate that it is ready (not
- busy) or until a timeout occurs.
-
- @return An error message indicating that a timeoout occured
- (SPIFLASH_ERROR_TIMEOUT_READY) or an OK signal to indicate that
- the SPI flash is ready (SPIFLASH_ERROR_OK)
-*/
-/**************************************************************************/
-spiflashError_e w25q16bvWaitForReady()
-{
- uint32_t timeout = 0;
- uint8_t status;
-
- while ( timeout < SSP_MAX_TIMEOUT )
- {
- status = w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY;
- if (status == 0)
- {
- break;
- }
- timeout++;
- }
- if ( timeout == SSP_MAX_TIMEOUT )
- {
- return SPIFLASH_ERROR_TIMEOUT_READY;
- }
-
- return SPIFLASH_ERROR_OK;
-}
-
-/**************************************************************************/
-/*!
- @brief Gets the unique 64-bit ID assigned to this IC (useful for
- security purposes to detect if the flash was changed, etc.)
-
- @param[out] *buffer
- Pointer to the uint8_t buffer that will store the 8 byte
- long unique ID
-
- @note The unique ID is return in bit order 63..0
-*/
-/**************************************************************************/
-void w25q16bvGetUniqueID(uint8_t *buffer)
-{
- uint8_t i;
-
- W25Q16BV_SELECT();
- w25q16bv_TransferByte(W25Q16BV_CMD_READUNIQUEID); // Unique ID cmd
- w25q16bv_TransferByte(0xFF); // Dummy write
- w25q16bv_TransferByte(0xFF); // Dummy write
- w25q16bv_TransferByte(0xFF); // Dummy write
- w25q16bv_TransferByte(0xFF); // Dummy write
- // Read 8 bytes worth of data
- for (i = 0; i < 8; i++)
- {
- buffer[i] = w25q16bv_TransferByte(0xFF);
- }
- W25Q16BV_DESELECT();
-}
-
-/**************************************************************************/
-/* Generic spiflash.h Functions */
-/* ------------------------------------------------------------------- */
-/* These functions are part of the common interface defined in */
-/* spiflash.h and must be implemented by any spi flash device */
-/* */
-/**************************************************************************/
-
-/**************************************************************************/
-/*!
- @brief Tries to initialise the flash device, and setups any HW
- required by the SPI flash
-*/
-/**************************************************************************/
-void spiflashInit (void)
-{
- // Initialise the SPI bus
- sspInit(0, sspClockPolarity_Low, sspClockPhase_RisingEdge);
-
- // ToDo: Set the WP, Hold, etc. pins to an appropriate state
-
- _w25q16bvInitialised = TRUE;
-}
-
-/**************************************************************************/
-/*!
- @brief Gets an instance of spiflashSizeInfo_t that describes the
- storage limits of the SPI flash like page size (minimum write
- size) and sector size (minimum erase size).
-*/
-/**************************************************************************/
-spiflashSizeInfo_t spiflashGetSizeInfo(void)
-{
- spiflashSizeInfo_t size;
- size.pageSize = W25Q16BV_PAGESIZE;
- size.pageCount = W25Q16BV_PAGES;
- size.sectorSize = W25Q16BV_SECTORSIZE;
- size.sectorCount = W25Q16BV_SECTORS;
- return size;
-}
-
-/**************************************************************************/
-/*!
- @brief Gets the 8-bit manufacturer ID and device ID for the flash
-
- @param[out] *manufID
- Pointer to the uint8_t that will store the manufacturer ID
- @param[out] *deviceID
- Pointer to the uint8_t that will store the device ID
-*/
-/**************************************************************************/
-void spiflashGetManufacturerInfo (uint8_t *manufID, uint8_t *deviceID)
-{
- if (!_w25q16bvInitialised) spiflashInit();
-
- // W25Q16BV_CMD_MANUFDEVID (0x90) provides both the JEDEC manufacturer
- // ID and the device ID
-
- W25Q16BV_SELECT();
- w25q16bv_TransferByte(W25Q16BV_CMD_MANUFDEVID);
- w25q16bv_TransferByte(0x00); // Dummy write
- w25q16bv_TransferByte(0x00); // Dummy write
- w25q16bv_TransferByte(0x00); // Dummy write
- *manufID = w25q16bv_TransferByte(0xFF);
- *deviceID = w25q16bv_TransferByte(0xFF);
- W25Q16BV_DESELECT();
-}
-
-/**************************************************************************/
-/*!
- @brief Sets the write flag on the SPI flash, and if required puts the
- WP pin in an appropriate state
-
- @param[in] enable
- True (1) to enable writing, false (0) to disable it
-*/
-/**************************************************************************/
-void spiflashWriteEnable (bool enable)
-{
- if (!_w25q16bvInitialised) spiflashInit();
-
- // ToDo: Put the WP pin in an appropriate state if required
-
- W25Q16BV_SELECT();
- w25q16bv_TransferByte(enable ? W25Q16BV_CMD_WRITEENABLE : W25Q16BV_CMD_WRITEDISABLE);
- W25Q16BV_DESELECT();
-}
-
-/**************************************************************************/
-/*!
- @brief Reads the specified number of bytes from the supplied address.
-
- This function will read one or more bytes starting at the supplied
- address. Please note that bufferLength is zero-based, meaning you
- should supply '0' to read a single byte, '3' to read 4 bytes of data,
- etc.
-
- @param[in] address
- The 24-bit address where the read will start.
- @param[out] *buffer
- Pointer to the buffer that will store the read results
- @param[in] len
- Length of the buffer.
-
- @section EXAMPLE
-
- @code
- uint8_t buffer[64];
- spiflashError_e error;
- error = spiflashReadBuffer (0, buffer, 64);
- if (error)
- {
- // Check what went wrong
- switch (error)
- {
- case SPIFLASH_ERROR_ADDROUTOFRANGE:
- // Specified starting address is out of range
- break;
- case SPIFLASH_ERROR_TIMEOUT_READY:
- // Timed out waiting for flash to return ready state
- break;
- case SPIFLASH_ERROR_ADDROVERFLOW:
- // Ran over the upper address during read
- break;
- }
- }
- @endcode
-*/
-/**************************************************************************/
-spiflashError_e spiflashReadBuffer (uint32_t address, uint8_t *buffer, uint32_t len)
-{
- if (!_w25q16bvInitialised) spiflashInit();
-
- uint32_t a, i;
- a = i = 0;
-
- // Make sure the address is valid
- if (address >= W25Q16BV_MAXADDRESS)
- {
- return SPIFLASH_ERROR_ADDROUTOFRANGE;
- }
-
- // Wait until the device is ready or a timeout occurs
- if (w25q16bvWaitForReady())
- return SPIFLASH_ERROR_TIMEOUT_READY;
-
- // Send the read data command
- W25Q16BV_SELECT();
- w25q16bv_TransferByte(W25Q16BV_CMD_READDATA); // 0x03
- w25q16bv_TransferByte((address >> 16) & 0xFF); // address upper 8
- w25q16bv_TransferByte((address >> 8) & 0xFF); // address mid 8
- w25q16bv_TransferByte(address & 0xFF); // address lower 8
- // Fill response buffer
- for (a = address; a < address + len; a++, i++)
- {
- if (a > W25Q16BV_MAXADDRESS)
- {
- // Oops ... we're at the end of the flash memory
- return SPIFLASH_ERROR_ADDROVERFLOW;
- }
- buffer[i] = w25q16bv_TransferByte(0xFF);
- }
- W25Q16BV_DESELECT();
-
- return SPIFLASH_ERROR_OK;
-}
-
-/**************************************************************************/
-/*!
- @brief Erases the contents of a single sector
-
- @param[in] sectorNumber
- The sector number to erase (zero-based).
-
- @section EXAMPLE
-
- @code
- spiflashError_e error;
- error = spiflashEraseSector(0);
- if (error)
- {
- // Check what went wrong
- switch (error)
- {
- case SPIFLASH_ERROR_ADDROUTOFRANGE:
- // Specified starting address is out of range
- break;
- case SPIFLASH_ERROR_PROTECTIONERR:
- // Couldn't set the write enable bit
- break;
- case SPIFLASH_ERROR_TIMEOUT_READY:
- // Timed out waiting for flash to return ready state
- break;
- }
- }
- @endcode
-*/
-/**************************************************************************/
-spiflashError_e spiflashEraseSector (uint32_t sectorNumber)
-{
- if (!_w25q16bvInitialised) spiflashInit();
-
- // Make sure the address is valid
- if (sectorNumber >= W25Q16BV_SECTORS)
- {
- return SPIFLASH_ERROR_ADDROUTOFRANGE;
- }
-
- // Wait until the device is ready or a timeout occurs
- if (w25q16bvWaitForReady())
- return SPIFLASH_ERROR_TIMEOUT_READY;
-
- // Make sure the chip is write enabled
- spiflashWriteEnable (TRUE);
-
- // Make sure the write enable latch is actually set
- uint8_t status;
- status = w25q16bvGetStatus();
- if (!(status & W25Q16BV_STAT1_WRTEN))
- {
- // Throw a write protection error (write enable latch not set)
- return SPIFLASH_ERROR_PROTECTIONERR;
- }
-
- // Send the erase sector command
- uint32_t address = sectorNumber * W25Q16BV_SECTORSIZE;
- W25Q16BV_SELECT();
- w25q16bv_TransferByte(W25Q16BV_CMD_SECTERASE4);
- w25q16bv_TransferByte((address >> 16) & 0xFF); // address upper 8
- w25q16bv_TransferByte((address >> 8) & 0xFF); // address mid 8
- w25q16bv_TransferByte(address & 0xFF); // address lower 8
- W25Q16BV_DESELECT();
-
- // Wait until the busy bit is cleared before exiting
- // This can take up to 400ms according to the datasheet
- while (w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY);
-
- return SPIFLASH_ERROR_OK;
-}
-
-/**************************************************************************/
-/*!
- @brief Erases the entire flash chip
-
- @section EXAMPLE
-
- @code
- spiflashError_e error;
- error = spiflashEraseChip();
- if (error)
- {
- // Check what went wrong
- switch (error)
- {
- case SPIFLASH_ERROR_PROTECTIONERR:
- // Couldn't set the write enable bit
- break;
- case SPIFLASH_ERROR_TIMEOUT_READY:
- // Timed out waiting for flash to return ready state
- break;
- }
- }
- @endcode
-*/
-/**************************************************************************/
-spiflashError_e spiflashEraseChip (void)
-{
- if (!_w25q16bvInitialised) spiflashInit();
-
- // Wait until the device is ready or a timeout occurs
- if (w25q16bvWaitForReady())
- return SPIFLASH_ERROR_TIMEOUT_READY;
-
- // Make sure the chip is write enabled
- spiflashWriteEnable (TRUE);
-
- // Make sure the write enable latch is actually set
- uint8_t status;
- status = w25q16bvGetStatus();
- if (!(status & W25Q16BV_STAT1_WRTEN))
- {
- // Throw a write protection error (write enable latch not set)
- return SPIFLASH_ERROR_PROTECTIONERR;
- }
-
- // Send the erase chip command
- W25Q16BV_SELECT();
- w25q16bv_TransferByte(W25Q16BV_CMD_CHIPERASE);
- W25Q16BV_DESELECT();
-
- // Wait until the busy bit is cleared before exiting
- // This can take up to 10 seconds according to the datasheet!
- while (w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY);
-
- return SPIFLASH_ERROR_OK;
-}
-
-/**************************************************************************/
-/*!
- @brief Writes up to 256 bytes of data to the specified page.
-
- @note Before writing data to a page, make sure that the 4K sector
- containing the specific page has been erased, otherwise the
- data will be meaningless.
-
- @param[in] address
- The 24-bit address where the write will start.
- @param[out] *buffer
- Pointer to the buffer that will store the read results
- @param[in] len
- Length of the buffer. Valid values are from 1 to 256,
- within the limits of the starting address and page length.
-
- @section EXAMPLE
-
- @code
- spiflashError_e error;
- uint8_t buffer[256];
-
- buffer[0] = 0x12;
- buffer[1] = 0x34;
- buffer[2] = 0x56;
- buffer[3] = 0x78;
- buffer[4] = 0xDE;
- buffer[5] = 0xAD;
- buffer[6] = 0xC0;
- buffer[7] = 0xDE;
-
- error = spiflashWritePage (0, buffer, 8);
- if (error)
- {
- // Check what went wrong
- switch (error)
- {
- case SPIFLASH_ERROR_ADDROUTOFRANGE:
- // Specified starting address is out of range
- break;
- case SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE:
- // Supplied data exceeds max page size
- break;
- case SPIFLASH_ERROR_PAGEWRITEOVERFLOW:
- // The data length plus the start address offset exceeeds page limits
- break;
- case SPIFLASH_ERROR_TIMEOUT_READY:
- // Timeout waiting for ready status (can be pre or post write)
- break;
- case SPIFLASH_ERROR_PROTECTIONERR:
- // Unable to set write latch
- break;
- }
- }
- @endcode
-*/
-/**************************************************************************/
-spiflashError_e spiflashWritePage (uint32_t address, uint8_t *buffer, uint32_t len)
-{
- uint8_t status;
- uint32_t i;
-
- if (!_w25q16bvInitialised) spiflashInit();
-
- // Make sure the address is valid
- if (address >= W25Q16BV_MAXADDRESS)
- {
- return SPIFLASH_ERROR_ADDROUTOFRANGE;
- }
-
- // Make sure that the supplied data is no larger than the page size
- if (len > W25Q16BV_PAGESIZE)
- {
- return SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE;
- }
-
- // Make sure that the data won't wrap around to the beginning of the sector
- if ((address % W25Q16BV_PAGESIZE) + len > W25Q16BV_PAGESIZE)
- {
- // If you try to write to a page beyond the last byte, it will
- // wrap around to the start of the page, almost certainly
- // messing up your data
- return SPIFLASH_ERROR_PAGEWRITEOVERFLOW;
- }
-
- // Wait until the device is ready or a timeout occurs
- if (w25q16bvWaitForReady())
- return SPIFLASH_ERROR_TIMEOUT_READY;
-
- // Make sure the chip is write enabled
- spiflashWriteEnable (TRUE);
-
- // Make sure the write enable latch is actually set
- status = w25q16bvGetStatus();
- if (!(status & W25Q16BV_STAT1_WRTEN))
- {
- // Throw a write protection error (write enable latch not set)
- return SPIFLASH_ERROR_PROTECTIONERR;
- }
-
- // Send page write command (0x02) plus 24-bit address
- W25Q16BV_SELECT();
- w25q16bv_TransferByte(W25Q16BV_CMD_PAGEPROG); // 0x02
- w25q16bv_TransferByte((address >> 16) & 0xFF); // address upper 8
- w25q16bv_TransferByte((address >> 8) & 0xFF); // address mid 8
- if (len == 256)
- {
- // If len = 256 bytes, lower 8 bits must be 0 (see datasheet 11.2.17)
- w25q16bv_TransferByte(0);
- }
- else
- {
- w25q16bv_TransferByte(address & 0xFF); // address lower 8
- }
- // Transfer data
- for (i = 0; i < len; i++)
- {
- w25q16bv_TransferByte(buffer[i]);
- }
- // Write only occurs after the CS line is de-asserted
- W25Q16BV_DESELECT();
-
- // Wait at least 3ms (max page program time according to datasheet)
- systickDelay(3);
-
- // Wait until the device is ready or a timeout occurs
- if (w25q16bvWaitForReady())
- return SPIFLASH_ERROR_TIMEOUT_READY;
-
- return SPIFLASH_ERROR_OK;
-}
-
-/**************************************************************************/
-/*!
- @brief Writes a continuous stream of data that will automatically
- cross page boundaries.
-
- @note Before writing data, make sure that the appropriate sectors
- have been erased, otherwise the data will be meaningless.
-
- @param[in] address
- The 24-bit address where the write will start.
- @param[out] *buffer
- Pointer to the buffer that will store the read results
- @param[in] len
- Length of the buffer, within the limits of the starting
- address and size of the flash device.
-
- @section EXAMPLE
-
- @code
- spiflashError_e error;
- uint8_t buffer[256];
-
- buffer[0] = 0x12;
- buffer[1] = 0x34;
- buffer[2] = 0x56;
- buffer[3] = 0x78;
- buffer[4] = 0xDE;
- buffer[5] = 0xAD;
- buffer[6] = 0xC0;
- buffer[7] = 0xDE;
-
- error = spiflashWrite (0, buffer, 8);
- if (error)
- {
- // Check what went wrong
- switch (error)
- {
- case SPIFLASH_ERROR_ADDROUTOFRANGE:
- // Specified starting address is out of range
- break;
- case SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE:
- // Supplied data exceeds max page size
- break;
- case SPIFLASH_ERROR_PAGEWRITEOVERFLOW:
- // The data length plus the start address offset exceeeds page limits
- break;
- case SPIFLASH_ERROR_TIMEOUT_READY:
- // Timeout waiting for ready status (can be pre or post write)
- break;
- case SPIFLASH_ERROR_PROTECTIONERR:
- // Unable to set write latch
- break;
- }
- }
- @endcode
-*/
-/**************************************************************************/
-spiflashError_e spiflashWrite (uint32_t address, uint8_t *buffer, uint32_t len)
-{
- uint32_t bytestowrite;
- uint32_t bufferoffset;
- spiflashError_e error;
-
- // There's no point duplicating most error checks here since they will all be
- // done in the underlying call to spiflashWritePage
-
- // If the data is only on one page we can take a shortcut
- if ((address % W25Q16BV_PAGESIZE) + len <= W25Q16BV_PAGESIZE)
- {
- // Only one page ... write and be done with it
- return spiflashWritePage(address, buffer, len);
- }
-
- // Block spans multiple pages
- bufferoffset = 0;
- while(len)
- {
- // Figure out how many bytes need to be written to this page
- bytestowrite = W25Q16BV_PAGESIZE - (address % W25Q16BV_PAGESIZE);
- // Write the current page
- error = spiflashWritePage(address, buffer+bufferoffset, bytestowrite);
- // Abort if we returned an error
- if (error)
- return error;
- // Adjust address and len, and buffer offset
- address += bytestowrite;
- len -= bytestowrite;
- bufferoffset+=bytestowrite;
- // If the next page is the last one, write it and exit
- // otherwise stay in the the loop and keep writing
- if (len <= W25Q16BV_PAGESIZE)
- {
- // Write the last frame and then quit
- error = spiflashWritePage(address, buffer+bufferoffset, len);
- // Abort if we returned an error
- if (error)
- return error;
- // set len to zero to gracefully exit loop
- len = 0;
- }
- }
-
- return SPIFLASH_ERROR_OK;
-}
-
-
+++ /dev/null
-/**************************************************************************/
-/*!
- @file w25q16bv.h
- @author K. Townsend (microBuilder.eu)
-
- @section LICENSE
-
- Software License Agreement (BSD License)
-
- Copyright (c) 2010, microBuilder SARL
- 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
-*/
-/**************************************************************************/
-
-#ifndef _W25Q16BV_H_
-#define _W25Q16BV_H_
-
-#include "projectconfig.h"
-
-#define W25Q16BV_MAXADDRESS 0x1FFFFF
-#define W25Q16BV_PAGESIZE 256 // 256 bytes per programmable page
-#define W25Q16BV_PAGES 8192 // 2,097,152 Bytes / 256 bytes per page
-#define W25Q16BV_SECTORSIZE 4096 // 1 erase sector = 4096 bytes
-#define W25Q16BV_SECTORS 512 // 2,097,152 Bytes / 4096 bytes per sector
-#define W25Q16BV_MANUFACTURERID 0xEF // Used to validate read data
-#define W25Q16BV_DEVICEID 0x14 // Used to validate read data
-
-#define W25Q16BV_STAT1_BUSY 0x01 // Erase/Write in Progress
-#define W25Q16BV_STAT1_WRTEN 0x02 // Write Enable Latch
-#define W25Q16BV_STAT2_QUADENBL 0x02 // Quad Enable
-#define W25Q16BV_STAT2_SSPNDSTAT 0x80 // Suspend Status
-
-/**************************************************************************/
-/*!
- W25Q16BV Commands
-*/
-/**************************************************************************/
-typedef enum
-{
- // Erase/Program Instructions
- W25Q16BV_CMD_WRITEENABLE = 0x06, // Write Enabled
- W25Q16BV_CMD_WRITEDISABLE = 0x04, // Write Disabled
- W25Q16BV_CMD_READSTAT1 = 0x05, // Read Status Register 1
- W25Q16BV_CMD_READSTAT2 = 0x35, // Read Status Register 2
- W25Q16BV_CMD_WRITESTAT = 0x01, // Write Status Register
- W25Q16BV_CMD_PAGEPROG = 0x02, // Page Program
- W25Q16BV_CMD_QUADPAGEPROG = 0x32, // Quad Page Program
- W25Q16BV_CMD_SECTERASE4 = 0x20, // Sector Erase (4KB)
- W25Q16BV_CMD_BLOCKERASE32 = 0x52, // Block Erase (32KB)
- W25Q16BV_CMD_BLOCKERASE64 = 0xD8, // Block Erase (64KB)
- W25Q16BV_CMD_CHIPERASE = 0x60, // Chip Erase
- W25Q16BV_CMD_ERASESUSPEND = 0x75, // Erase Suspend
- W25Q16BV_CMD_ERASERESUME = 0x7A, // Erase Resume
- W25Q16BV_CMD_POWERDOWN = 0xB9, // Power Down
- W25Q16BV_CMD_CRMR = 0xFF, // Continuous Read Mode Reset
- // Read Instructions
- W25Q16BV_CMD_READDATA = 0x03, // Read Data
- W25Q16BV_CMD_FREAD = 0x0B, // Fast Read
- W25Q16BV_CMD_FREADDUALOUT = 0x3B, // Fast Read Dual Output
- W25Q16BV_CMD_FREADDUALIO = 0xBB, // Fast Read Dual I/O
- W25Q16BV_CMD_FREADQUADOUT = 0x6B, // Fast Read Quad Output
- W25Q16BV_CMD_FREADQUADIO = 0xEB, // Fast Read Quad I/O
- W25Q16BV_CMD_WREADQUADIO = 0xE7, // Word Read Quad I/O
- W25Q16BV_CMD_OWREADQUADIO = 0xE3, // Octal Word Read Quad I/O
- // ID/Security Instructions
- W25Q16BV_CMD_RPWRDDEVID = 0xAB, // Release Power Down/Device ID
- W25Q16BV_CMD_MANUFDEVID = 0x90, // Manufacturer/Device ID
- W25Q16BV_CMD_MANUFDEVID2 = 0x92, // Manufacturer/Device ID by Dual I/O
- W25Q16BV_CMD_MANUFDEVID4 = 0x94, // Manufacturer/Device ID by Quad I/O
- W25Q16BV_CMD_JEDECID = 0x9F, // JEDEC ID
- W25Q16BV_CMD_READUNIQUEID = 0x4B // Read Unique ID
-} w25q16bv_Commands_e;
-
-#endif
--- /dev/null
+/**************************************************************************/
+/*!
+ @file at25040.c
+ @author K. Townsend (microBuilder.eu)
+ @date 22 March 2010
+ @version 0.10
+
+ @section DESCRIPTION
+
+ Driver for Atmel's AT25010a/AT25020a/AT25040a 1K/2K/4K serial EEPROM.
+
+ @note The AT25xxx has an 8-byte buffer, including 1 command byte
+ and one address offset byte, meaning that a maximum of 6
+ bytes can be read or written in one operation. An error
+ will be returned if a value greater than 6 is passed in
+ for bufferLength with the eepromRead and eepromWrite
+ methods.
+
+ @section Example
+
+ @code
+ #include "core/cpu/cpu.h"
+ #include "drivers/storage/eeprom/at25040/at25040.h"
+
+ int main(void)
+ {
+ cpuInit();
+ at25Init();
+
+ // Set read and write buffers
+ uint8_t wBuffer[1];
+ uint8_t rBuffer[1];
+
+ // Instantiate error message placeholder
+ at25Error_e error = AT25_ERROR_OK;
+
+ // Write 0xAA to EEPROM at address 0x0000
+ wBuffer[0] = 0xAA;
+ error = at25Write(0x0000, wBuffer, 1);
+ if (error)
+ {
+ // Log the error message or take appropriate actions
+ switch (error)
+ {
+ case (AT25_ERROR_TIMEOUT_WFINISH):
+ // EEPROM timed out waiting for the write to finish
+ break;
+ case (AT25_ERROR_TIMEOUT_WE):
+ // EEPROM timed out waiting for write-enable
+ break;
+ case (AT25_ERROR_ADDRERR):
+ // Address is out of range
+ break;
+ }
+ }
+
+ // Read the EEPROM at address 0x0000
+ at25Read(0x0000, rBuffer, 1);
+ ...
+ }
+ @endcode
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2010, microBuilder SARL
+ 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+
+#include "at25040.h"
+#include "core/ssp/ssp.h"
+#include "core/gpio/gpio.h"
+
+#define AT25_SELECT() gpioSetValue(0, 2, 0)
+#define AT25_DESELECT() gpioSetValue(0, 2, 1)
+
+uint32_t i, timeout;
+uint8_t src_addr[SSP_FIFOSIZE];
+uint8_t dest_addr[SSP_FIFOSIZE];
+
+/**************************************************************************/
+/*!
+ @brief Sends the write enable command (WREN/0x06)
+*/
+/**************************************************************************/
+void at25WriteEnable()
+{
+ AT25_SELECT();
+ src_addr[0] = AT25_WREN;
+ sspSend(0, (uint8_t *)src_addr, 1);
+ AT25_DESELECT();
+
+ // Delay for at least 250nS (1nS @ 72MHz = ~0.0072 ticks)
+ for (i = 0; i < 100; i++);
+}
+
+/**************************************************************************/
+/*!
+ @brief Gets the value of the Read Status Register (RDSR/0x05)
+
+ @return The 8-bit value returned by the Read Status Register
+*/
+/**************************************************************************/
+uint8_t at25GetRSR()
+{
+ AT25_SELECT();
+ src_addr[0] = AT25_RDSR;
+ sspSend(0, (uint8_t *)src_addr, 1);
+ sspReceive(0, (uint8_t *)dest_addr, 1);
+ AT25_DESELECT();
+ return dest_addr[0] & (AT25_RDSR_WEN | AT25_RDSR_RDY);
+}
+
+/**************************************************************************/
+/*!
+ @brief Initialises the SPI block (CLK set low when inactive, trigger
+ on leading edge).
+*/
+/**************************************************************************/
+void at25Init (void)
+{
+ sspInit(0, sspClockPolarity_Low, sspClockPhase_RisingEdge);
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads the specified number of bytes from the supplied address.
+
+ This function will read one or more bytes starting at the supplied
+ address.
+
+ @param[in] address
+ The 16-bit address where the read will start. The maximum
+ value for the address depends on the size of the EEPROM
+ @param[in] *buffer
+ Pointer to the buffer that will store the read results
+ @param[in] bufferLength
+ Length of the buffer
+*/
+/**************************************************************************/
+at25Error_e at25Read (uint16_t address, uint8_t *buffer, uint32_t bufferLength)
+{
+ if (address >= AT25_MAXADDRESS)
+ {
+ return AT25_ERROR_ADDRERR;
+ }
+
+ if (bufferLength > 6)
+ {
+ return AT25_ERROR_BUFFEROVERFLOW;
+ }
+
+ timeout = 0;
+ while ( timeout < SSP_MAX_TIMEOUT )
+ {
+ // Wait until the device is ready
+ uint8_t status = at25GetRSR() & AT25_RDSR_RDY;
+ if (status == 0)
+ {
+ break;
+ }
+ timeout++;
+ }
+ if ( timeout == SSP_MAX_TIMEOUT )
+ {
+ return AT25_ERROR_TIMEOUT_WE;
+ }
+
+ AT25_SELECT();
+ // Read command (0x03), append A8 if > addr 256 bytes
+ src_addr[0] = address > 0xFF ? AT25_READ | AT25_A8 : AT25_READ;
+ src_addr[1] = (address);
+ sspSend(0, (uint8_t *)src_addr, 2);
+ sspReceive(0, (uint8_t *)&dest_addr[2], bufferLength);
+ AT25_DESELECT();
+
+ // Fill response buffer
+ for (i = 0; i < bufferLength; i++)
+ {
+ buffer[i] = dest_addr[i + 2];
+ }
+
+ return AT25_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes the supplied bytes at a specified address.
+
+ This function will write one or more bytes starting at the supplied
+ address.
+
+ @param[in] address
+ The 16-bit address where the write will start. The
+ maximum value for the address depends on the size of the
+ EEPROM
+ @param[in] *buffer
+ Pointer to the buffer that contains the values to write.
+ @param[in] bufferLength
+ Length of the buffer
+*/
+/**************************************************************************/
+at25Error_e at25Write (uint16_t address, uint8_t *buffer, uint32_t bufferLength)
+{
+ if (address >= AT25_MAXADDRESS)
+ {
+ return AT25_ERROR_ADDRERR;
+ }
+
+ if (bufferLength > 6)
+ {
+ return AT25_ERROR_BUFFEROVERFLOW;
+ }
+
+ // Set write enable latch
+ at25WriteEnable();
+
+ timeout = 0;
+ while ( timeout < SSP_MAX_TIMEOUT )
+ {
+ // Wait until the device is write enabled
+ if (at25GetRSR() == AT25_RDSR_WEN)
+ {
+ break;
+ }
+ timeout++;
+ }
+ if ( timeout == SSP_MAX_TIMEOUT )
+ {
+ return AT25_ERROR_TIMEOUT_WE;
+ }
+
+ for (i = 0; i < bufferLength; i++) // Init RD and WR buffer
+ {
+ src_addr[i+2] = buffer[i]; // leave two bytes for cmd and offset(8 bits)
+ dest_addr[i] = 0;
+ }
+
+ AT25_SELECT();
+ // Write command (0x02), append A8 if addr > 256 bytes
+ src_addr[0] = address > 0xFF ? AT25_WRITE | AT25_A8 : AT25_WRITE;
+ src_addr[1] = (address);
+ sspSend(0, (uint8_t *)src_addr, bufferLength + 2);
+ AT25_DESELECT();
+
+ // Wait at least 3ms
+ for (i = 0; i < ((CFG_CPU_CCLK / 1000) * 3); i++);
+
+ timeout = 0;
+ while ( timeout < SSP_MAX_TIMEOUT )
+ {
+ // Check status to see if write cycle is done or not
+ AT25_SELECT();
+ src_addr[0] = AT25_RDSR;
+ sspSend(0, (uint8_t *)src_addr, 1);
+ sspReceive(0, (uint8_t *)dest_addr, 1);
+ AT25_DESELECT();
+ // Wait until device is ready
+ if ((dest_addr[0] & AT25_RDSR_RDY) == 0x00)
+ {
+ break;
+ }
+ timeout++;
+ }
+ if ( timeout == SSP_MAX_TIMEOUT )
+ {
+ return AT25_ERROR_TIMEOUT_WFINISH;
+ }
+
+ for (i = 0; i < 300; i++); // Wait at least 250ns
+
+ return AT25_ERROR_OK;
+}
--- /dev/null
+/**************************************************************************/
+/*!
+ @file at25040.h
+ @author K. Townsend (microBuilder.eu)
+ @date 22 March 2010
+ @version 0.10
+
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2010, microBuilder SARL
+ 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+
+#ifndef _AT25040_H_
+#define _AT25040_H_
+
+#include "projectconfig.h"
+
+#define AT25_RDSR_RDY 0x01
+#define AT25_RDSR_WEN 0x02
+#define AT25_A8 0x08 // For addresses > 0xFF (AT25040 only) A8 must be added to R/W commands
+#define AT25_MAXADDRESS 0x0200 // AT25040 = 0X0200, AT25020 = 0x100, AT25010 = 0x80
+
+/**************************************************************************/
+/*!
+ AT25040 Commands
+*/
+/**************************************************************************/
+typedef enum
+{
+ AT25_WREN = 0x06,
+ AT25_WRDI = 0x04,
+ AT25_RDSR = 0x05,
+ AT25_WRSR = 0x01,
+ AT25_READ = 0x03,
+ AT25_WRITE = 0x02
+} at25_Commands_e;
+
+/**************************************************************************/
+/*!
+ Error messages
+*/
+/**************************************************************************/
+typedef enum
+{
+ AT25_ERROR_OK = 0, // Everything executed normally
+ AT25_ERROR_TIMEOUT_WE, // Timed out waiting for write enable status
+ AT25_ERROR_TIMEOUT_WFINISH, // Timed out waiting for write to finish
+ AT25_ERROR_ADDRERR, // Address out of range
+ AT25_ERROR_BUFFEROVERFLOW, // Max 6 bytes can be read/written in one operation
+ AT2_ERROR_LAST
+}
+at25Error_e;
+
+void at25Init (void);
+at25Error_e at25Read (uint16_t address, uint8_t *buffer, uint32_t bufferLength);
+at25Error_e at25Write (uint16_t address, uint8_t *buffer, uint32_t bufferLength);
+
+#endif
--- /dev/null
+/**************************************************************************/
+/*!
+ @file eeprom.c
+ @author K. Townsend (microBuilder.eu)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2010, microBuilder SARL
+ 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+#include <string.h>
+
+#include "projectconfig.h"
+#include "eeprom.h"
+
+// Currently only the MCP24AA I2C EEPROM is used
+#include "drivers/storage/eeprom/mcp24aa/mcp24aa.h"
+
+static uint8_t buf[32];
+
+/**************************************************************************/
+/*!
+ @brief Checks whether the supplied address is within the valid range
+
+ @param[in] addr
+ The 16-bit address to check
+
+ @return Zero if the address is valid, otherwise 1
+*/
+/**************************************************************************/
+bool eepromCheckAddress(uint16_t addr)
+{
+ // Check for invalid values
+ return addr <= MCP24AA_MAXADDR ? FALSE : TRUE;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads 1 byte from EEPROM
+
+ @param[in] addr
+ The 16-bit address to read from in EEPROM
+
+ @return An unsigned 8-bit value (uint8_t)
+*/
+/**************************************************************************/
+uint8_t eepromReadU8(uint16_t addr)
+{
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaReadBuffer(addr, buf, sizeof(uint8_t));
+
+ // ToDo: Handle any errors
+ if (error) { };
+
+ return buf[0];
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads 1 byte from EEPROM
+
+ @param[in] addr
+ The 16-bit address to read from in EEPROM
+
+ @return A signed 8-bit value (int8_t)
+*/
+/**************************************************************************/
+int8_t eepromReadS8(uint16_t addr)
+{
+ int8_t results;
+
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaReadBuffer(addr, buf, sizeof(int8_t));
+
+ // ToDo: Handle any errors
+ if (error) { };
+
+ memcpy(&results, buf, sizeof(int8_t));
+ return results;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads 2 bytes from EEPROM
+
+ @param[in] addr
+ The 16-bit address to read from in EEPROM
+
+ @return A unsigned 16-bit value (uint16_t)
+*/
+/**************************************************************************/
+uint16_t eepromReadU16(uint16_t addr)
+{
+ uint16_t results;
+
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaReadBuffer(addr, buf, sizeof(uint16_t));
+
+ // ToDo: Handle any errors
+ if (error) { };
+
+ memcpy(&results, buf, sizeof(uint16_t));
+
+ return results;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads 2 bytes from EEPROM
+
+ @param[in] addr
+ The 16-bit address to read from in EEPROM
+
+ @return A signed 16-bit value (int16_t)
+*/
+/**************************************************************************/
+int16_t eepromReadS16(uint16_t addr)
+{
+ int16_t results;
+
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaReadBuffer(addr, buf, sizeof(int16_t));
+
+ // ToDo: Handle any errors
+ if (error) { };
+
+ memcpy(&results, buf, sizeof(int16_t));
+ return results;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads 4 bytes from EEPROM
+
+ @param[in] addr
+ The 16-bit address to read from in EEPROM
+
+ @return A unsigned 32-bit value (uint32_t)
+*/
+/**************************************************************************/
+uint32_t eepromReadU32(uint16_t addr)
+{
+ uint32_t results;
+
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaReadBuffer(addr, buf, sizeof(uint32_t));
+
+ // ToDo: Handle any errors
+ if (error) { };
+
+ memcpy(&results, buf, sizeof(uint32_t));
+ return results;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads 4 bytes from EEPROM
+
+ @param[in] addr
+ The 16-bit address to read from in EEPROM
+
+ @return A signed 32-bit value (int32_t)
+*/
+/**************************************************************************/
+int32_t eepromReadS32(uint16_t addr)
+{
+ int32_t results;
+
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaReadBuffer(addr, buf, sizeof(int32_t));
+
+ // ToDo: Handle any errors
+ if (error) { };
+
+ memcpy(&results, buf, sizeof(int32_t));
+ return results;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads 8 bytes from EEPROM
+
+ @param[in] addr
+ The 16-bit address to read from in EEPROM
+
+ @return A unsigned 64-bit value (uint64_t)
+*/
+/**************************************************************************/
+uint64_t eepromReadU64(uint16_t addr)
+{
+ uint64_t results;
+
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaReadBuffer(addr, buf, sizeof(uint64_t));
+
+ // ToDo: Handle any errors
+ if (error) { };
+
+ memcpy(&results, buf, sizeof(uint64_t));
+ return results;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads 8 bytes from EEPROM
+
+ @param[in] addr
+ The 16-bit address to read from in EEPROM
+
+ @return A signed 64-bit value (int64_t)
+*/
+/**************************************************************************/
+int64_t eepromReadS64(uint16_t addr)
+{
+ int64_t results;
+
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaReadBuffer(addr, buf, sizeof(int64_t));
+
+ // ToDo: Handle any errors
+ if (error) { };
+
+ memcpy(&results, buf, sizeof(int64_t));
+ return results;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads a variabls length buffer from EEPROM
+
+ @param[in] addr
+ The 16-bit address to write to in EEPROM
+ @param[out] buffer
+ Pointer to the buffer that will store any retrieved bytes
+ @param[in] bufferLength
+ The number of bytes to read
+*/
+/**************************************************************************/
+void eepromReadBuffer(uint16_t addr, uint8_t *buffer, uint32_t bufferLength)
+{
+ // Instantiate error message placeholder
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+
+ // Read the contents of address
+ error = mcp24aaReadBuffer(addr, buffer, bufferLength);
+
+ // ToDo: Handle any errors
+ if (error) { };
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes 1 byte to EEPROM
+
+ @param[in] addr
+ The 16-bit address to write to in EEPROM
+*/
+/**************************************************************************/
+void eepromWriteU8(uint16_t addr, uint8_t value)
+{
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
+
+ // ToDo: Handle any errors
+ if (error) { };
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes 1 signed byte to EEPROM
+
+ @param[in] addr
+ The 16-bit address to write to in EEPROM
+*/
+/**************************************************************************/
+void eepromWriteS8(uint16_t addr, int8_t value)
+{
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
+
+ // ToDo: Handle any errors
+ if (error) { };
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes an unsigned 16-bit integer to EEPROM
+
+ @param[in] addr
+ The 16-bit address to write to in EEPROM
+*/
+/**************************************************************************/
+void eepromWriteU16(uint16_t addr, uint16_t value)
+{
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
+
+ // ToDo: Handle any errors
+ if (error) { };
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes a signed 16-bit integer to EEPROM
+
+ @param[in] addr
+ The 16-bit address to write to in EEPROM
+*/
+/**************************************************************************/
+void eepromWriteS16(uint16_t addr, int16_t value)
+{
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
+
+ // ToDo: Handle any errors
+ if (error) { };
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes an unsigned 32-bit integer to EEPROM
+
+ @param[in] addr
+ The 16-bit address to write to in EEPROM
+*/
+/**************************************************************************/
+void eepromWriteU32(uint16_t addr, uint32_t value)
+{
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
+
+ // ToDo: Handle any errors
+ if (error) { };
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes a signed 32-bit integer to EEPROM
+
+ @param[in] addr
+ The 16-bit address to write to in EEPROM
+*/
+/**************************************************************************/
+void eepromWriteS32(uint16_t addr, int32_t value)
+{
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
+
+ // ToDo: Handle any errors
+ if (error) { };
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes an unsigned 64-bit integer to EEPROM
+
+ @param[in] addr
+ The 16-bit address to write to in EEPROM
+*/
+/**************************************************************************/
+void eepromWriteU64(uint16_t addr, uint64_t value)
+{
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
+
+ // ToDo: Handle any errors
+ if (error) { };
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes a signed 64-bit integer to EEPROM
+
+ @param[in] addr
+ The 16-bit address to write to in EEPROM
+*/
+/**************************************************************************/
+void eepromWriteS64(uint16_t addr, int64_t value)
+{
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+ error = mcp24aaWriteBuffer(addr, (uint8_t *)&value, sizeof(value));
+
+ // ToDo: Handle any errors
+ if (error) { };
+}
--- /dev/null
+/**************************************************************************/
+/*!
+ @file eeprom.h
+ @author K. Townsend (microBuilder.eu)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2010, microBuilder SARL
+ 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+#ifndef __EEPROM_H__
+#define __EEPROM_H__
+
+#include "projectconfig.h"
+
+// Method Prototypes
+bool eepromCheckAddress ( uint16_t addr );
+uint8_t eepromReadU8 ( uint16_t addr );
+int8_t eepromReadS8 ( uint16_t addr );
+uint16_t eepromReadU16 ( uint16_t addr );
+int16_t eepromReadS16 ( uint16_t addr );
+uint32_t eepromReadU32 ( uint16_t addr );
+int32_t eepromReadS32 ( uint16_t addr );
+uint64_t eepromReadU64 ( uint16_t addr );
+int64_t eepromReadS64 ( uint16_t addr );
+void eepromReadBuffer ( uint16_t addr, uint8_t *buffer, uint32_t bufferLength);
+void eepromWriteU8 ( uint16_t addr, uint8_t value );
+void eepromWriteS8 ( uint16_t addr, int8_t value );
+void eepromWriteU16 ( uint16_t addr, uint16_t value );
+void eepromWriteS16 ( uint16_t addr, int16_t value );
+void eepromWriteU32 ( uint16_t addr, uint32_t value );
+void eepromWriteS32 ( uint16_t addr, int32_t value );
+void eepromWriteU64 ( uint16_t addr, uint64_t value );
+void eepromWriteS64 ( uint16_t addr, int64_t value );
+
+#endif
--- /dev/null
+/**************************************************************************/
+/*!
+ @file mcp24aa.c
+ @author K. Townsend (microBuilder.eu)
+ @date 22 March 2010
+ @version 0.10
+
+ @section DESCRIPTION
+
+ Driver for Microchip's 24AA32AF serial EEPROM. This driver assumes
+ that the address is set to 1010 000.
+
+ @section Example
+
+ @code
+ #include "core/cpu/cpu.h"
+ #include "drivers/storage/eeprom/mcp24aa/mcp24aa.h"
+
+ int main(void)
+ {
+ cpuInit();
+
+ mcp24aaInit();
+
+ // Instantiate error message placeholder
+ mcp24aaError_e error = MCP24AA_ERROR_OK;
+
+ // Create read buffer (1 byte)
+ uint8_t buffer[1] = { 0x00 };
+
+ // Write 0xCC at address 0x125
+ error = mcp24aaWriteByte(0x0125, 0xCC);
+ if (error)
+ {
+ // Handle any errors
+ switch (error)
+ {
+ case (MCP24AA_ERROR_I2CINIT):
+ // Unable to initialise I2C
+ break;
+ case (MCP24AA_ERROR_ADDRERR):
+ // Address out of range
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Read the contents of address 0x0125
+ error = MCP24AA_ERROR_OK;
+ error = mcp24aaReadByte(0x0125, buffer);
+ if (error)
+ {
+ // Handle any errors
+ switch (error)
+ {
+ case (MCP24AA_ERROR_I2CINIT):
+ // Unable to initialise I2C
+ break;
+ case (MCP24AA_ERROR_ADDRERR):
+ // Address out of range
+ break;
+ default:
+ break;
+ }
+ }
+
+ uint8_t results = buffer[0];
+ }
+ @endcode
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2010, microBuilder SARL
+ 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+
+#include "mcp24aa.h"
+#include "core/systick/systick.h"
+#include "core/i2c/i2c.h"
+
+extern volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
+extern volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
+extern volatile uint32_t I2CReadLength, I2CWriteLength;
+
+static bool _mcp24aaInitialised = false;
+
+/**************************************************************************/
+/*!
+ @brief Initialises the I2C block
+*/
+/**************************************************************************/
+mcp24aaError_e mcp24aaInit()
+{
+ // Initialise I2C
+ if (i2cInit(I2CMASTER) == false)
+ {
+ return MCP24AA_ERROR_I2CINIT; /* Fatal error */
+ }
+
+ // Set initialisation flag
+ _mcp24aaInitialised = true;
+
+ return MCP24AA_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads the specified number of bytes from the supplied address.
+
+ This function will read one or more bytes starting at the supplied
+ address. A maximum of 8 bytes can be read in one operation.
+
+ @param[in] address
+ The 16-bit address where the read will start. The maximum
+ value for the address depends on the size of the EEPROM
+ @param[in] *buffer
+ Pointer to the buffer that will store the read results
+ @param[in] bufferLength
+ Length of the buffer
+*/
+/**************************************************************************/
+mcp24aaError_e mcp24aaReadBuffer (uint16_t address, uint8_t *buffer, uint32_t bufferLength)
+{
+ if (!_mcp24aaInitialised) mcp24aaInit();
+
+ if (address >= MCP24AA_MAXADDR)
+ {
+ return MCP24AA_ERROR_ADDRERR;
+ }
+
+ if (bufferLength > 8)
+ {
+ return MCP24AA_ERROR_BUFFEROVERFLOW;
+ }
+
+ // ToDo: Check if I2C is ready
+
+ // Clear buffers
+ uint32_t i;
+ for ( i = 0; i < I2C_BUFSIZE; i++ )
+ {
+ I2CMasterBuffer[i] = 0x00;
+ I2CSlaveBuffer[i] = 0x00;
+ }
+
+ // Write address bits to enable random read
+ I2CWriteLength = 3;
+ I2CReadLength = bufferLength;
+ I2CMasterBuffer[0] = MCP24AA_ADDR; // I2C device address
+ I2CMasterBuffer[1] = (address >> 8); // Address (high byte)
+ I2CMasterBuffer[2] = (address & 0xFF); // Address (low byte)
+ // If you wish to read, you need to append the address w/read bit, though this
+ // needs to be placed one bit higher than the size of I2CWriteLength which
+ // may be unexpected
+ I2CMasterBuffer[3] = MCP24AA_ADDR | MCP24AA_READBIT;
+
+ // Transmit command
+ i2cEngine();
+
+ // Fill response buffer
+ for (i = 0; i < bufferLength; i++)
+ {
+ buffer[i] = I2CSlaveBuffer[i];
+ }
+
+ return MCP24AA_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes the supplied bytes at a specified address.
+
+ This function will write one or more bytes starting at the supplied
+ address. A maximum of 8 bytes can be written in one operation.
+
+ @param[in] address
+ The 16-bit address where the write will start. The
+ maximum value for the address depends on the size of the
+ EEPROM
+ @param[in] *buffer
+ Pointer to the buffer that contains the values to write.
+ @param[in] bufferLength
+ Length of the buffer
+*/
+/**************************************************************************/
+mcp24aaError_e mcp24aaWriteBuffer (uint16_t address, uint8_t *buffer, uint32_t bufferLength)
+{
+ if (!_mcp24aaInitialised) mcp24aaInit();
+
+ if (address >= MCP24AA_MAXADDR)
+ {
+ return MCP24AA_ERROR_ADDRERR;
+ }
+
+ if (bufferLength > 8)
+ {
+ return MCP24AA_ERROR_BUFFEROVERFLOW;
+ }
+
+ // ToDo: Check if I2C is ready
+
+ // Clear write buffer
+ uint32_t i;
+ for ( i = 0; i < I2C_BUFSIZE; i++ )
+ {
+ I2CMasterBuffer[i] = 0x00;
+ }
+
+ // Write address bits and data to the master buffer
+ I2CWriteLength = 3 + bufferLength;
+ I2CReadLength = 0;
+ I2CMasterBuffer[0] = MCP24AA_ADDR; // I2C device address
+ I2CMasterBuffer[1] = (address >> 8); // Address (high byte)
+ I2CMasterBuffer[2] = (address & 0xFF); // Address (low byte)
+ for (i = 0; i < bufferLength; i++)
+ {
+ I2CMasterBuffer[i+3] = buffer[i];
+ }
+
+ // Transmit command
+ i2cEngine();
+
+ // Wait at least 10ms
+ systickDelay(10);
+
+ return MCP24AA_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads one byte from the supplied address.
+
+ This function will read one byte starting at the supplied address.
+
+ @param[in] address
+ The 16-bit address where the read will start. The maximum
+ value for the address depends on the size of the EEPROM
+ @param[in] *buffer
+ Pointer to the buffer that will store the read results
+
+ @code
+ #include "core/cpu/cpu/h"
+ #include "drivers/storage/eeprom/mcp24aa/mcp24aa.h"
+ ...
+ cpuInit();
+ mcp24aaInit();
+
+ // Create read buffer (1 byte)
+ uint8_t buffer[1] = { 0x00 };
+
+ // Write 0xEE and address 0x0120
+ mcp24aaWriteByte(0x0120, 0xEE);
+
+ // Populate buffer with contents of 0x0120
+ mcp24aaReadByte(0x0120, buffer);
+
+ // results should equal 0xEE
+ uint8_t results = buffer[0];
+ @endcode
+*/
+/**************************************************************************/
+mcp24aaError_e mcp24aaReadByte (uint16_t address, uint8_t *buffer)
+{
+ if (!_mcp24aaInitialised) mcp24aaInit();
+
+ return mcp24aaReadBuffer(address, buffer, 1);
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes one byte to the supplied address.
+
+ This function will write one byte at the supplied address.
+
+ @param[in] address
+ The 16-bit address where the write will start. The maximum
+ value for the address depends on the size of the EEPROM
+ @param[in] value
+ The data to be written to the EEPROM
+
+ @code
+ #include "core/cpu/cpu/h"
+ #include "drivers/storage/eeprom/mcp24aa/mcp24aa.h"
+ ...
+ cpuInit();
+ mcp24aaInit();
+
+ // Create read buffer (1 byte)
+ uint8_t buffer[1] = { 0x00 };
+
+ // Write 0xEE and address 0x0120
+ mcp24aaWriteByte(0x0120, 0xEE);
+
+ // Populate buffer with contents of 0x0120
+ mcp24aaReadByte(0x0120, buffer);
+
+ // results should equal 0xEE
+ uint8_t results = buffer[0];
+ @endcode
+*/
+/**************************************************************************/
+mcp24aaError_e mcp24aaWriteByte (uint16_t address, uint8_t value)
+{
+ if (!_mcp24aaInitialised) mcp24aaInit();
+
+ // Set read buffer
+ uint8_t wBuffer[1];
+
+ // Write byte to EEPROM at specified address
+ wBuffer[0] = value;
+ return mcp24aaWriteBuffer(address, wBuffer, 1);
+}
+
--- /dev/null
+/**************************************************************************/
+/*!
+ @file mcp24aa.h
+ @author K. Townsend (microBuilder.eu)
+ @date 22 March 2010
+ @version 0.10
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2010, microBuilder SARL
+ 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+
+#ifndef _MCP24AA_H_
+#define _MCP24AA_H_
+
+#include "projectconfig.h"
+
+#define MCP24AA_ADDR 0xA0 // 10100000
+#define MCP24AA_RW 0x01
+#define MCP24AA_READBIT 0x01
+#define MCP24AA_MAXADDR 0xFFF // 4K = 4096
+
+typedef enum
+{
+ MCP24AA_ERROR_OK = 0, // Everything executed normally
+ MCP24AA_ERROR_I2CINIT, // Unable to initialise I2C
+ MCP24AA_ERROR_I2CBUSY, // I2C already in use
+ MCP24AA_ERROR_ADDRERR, // Address out of range
+ MCP24AA_ERROR_BUFFEROVERFLOW, // Max 8 bytes can be read/written in one operation
+ MCP24AA_ERROR_LAST
+}
+mcp24aaError_e;
+
+mcp24aaError_e mcp24aaInit (void);
+mcp24aaError_e mcp24aaReadBuffer (uint16_t address, uint8_t *buffer, uint32_t bufferLength);
+mcp24aaError_e mcp24aaWriteBuffer (uint16_t address, uint8_t *buffer, uint32_t bufferLength);
+mcp24aaError_e mcp24aaReadByte (uint16_t address, uint8_t *buffer);
+mcp24aaError_e mcp24aaWriteByte (uint16_t address, uint8_t value);
+
+
+#endif
--- /dev/null
+/**************************************************************************/
+/*!
+ @file spiflash.h
+ @author K. Townsend (microBuilder.eu)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2010, microBuilder SARL
+ 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+
+#ifndef _SPIFLASH_H_
+#define _SPIFLASH_H_
+
+#include "projectconfig.h"
+
+/**************************************************************************/
+/*!
+ @brief Error messages
+*/
+/**************************************************************************/
+typedef enum
+{
+ SPIFLASH_ERROR_OK = 0, // Everything executed normally
+ SPIFLASH_ERROR_ADDROUTOFRANGE = 1, // Address out of range
+ SPIFLASH_ERROR_TIMEOUT_READY = 2, // Timeout waiting for ready status
+ SPIFLASH_ERROR_WRITEERR = 3, // Write Error
+ SPIFLASH_ERROR_PROTECTIONERR = 4, // Write Protection Error
+ SPIFLASH_ERROR_ADDROVERFLOW = 5, // Address overflow during read/write
+ SPIFLASH_ERROR_UNEXPECTEDID = 6, // The manufacturer and/or device ID are different than expected
+ SPIFLASH_ERROR_NOTSTARTOFPAGE = 7, // The supplied address is not the start of a new page
+ SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE = 9, // When writing page data, you can't exceed page size
+ SPIFLASH_ERROR_PAGEWRITEOVERFLOW = 10, // Page data will overflow beause (start address + len) > page size
+ SPIFLASH_ERROR_LAST
+}
+spiflashError_e;
+
+/**************************************************************************/
+/*!
+ @brief Describes the storage capacity of the SPI flash, including the
+ size of the minimum HW write (page) and erase (sector) units.
+*/
+/**************************************************************************/
+typedef struct
+{
+ uint32_t pageSize; // Page size to write data (in bytes)
+ uint32_t pageCount; // Number of pages
+ uint32_t sectorSize; // Sector size to erase data (in bytes)
+ uint32_t sectorCount; // Number of sectors
+}
+spiflashSizeInfo_t;
+
+/**************************************************************************/
+/*!
+ @brief Tries to initialise the flash device, and sets up any HW
+ required by the SPI flash
+*/
+/**************************************************************************/
+void spiflashInit (void);
+
+/**************************************************************************/
+/*!
+ @brief Gets an instance of spiflashSizeInfo_t that describes the
+ storage limits of the SPI flash like page size (minimum write
+ size) and sector size (minimum erase size).
+*/
+/**************************************************************************/
+spiflashSizeInfo_t spiflashGetSizeInfo(void);
+
+/**************************************************************************/
+/*!
+ @brief Gets the 8-bit manufacturer ID and device ID for the flash
+
+ @param[out] *manufID
+ Pointer to the uint8_t that will store the manufacturer ID
+ @param[out] *deviceID
+ Pointer to the uint8_t that will store the device ID
+*/
+/**************************************************************************/
+void spiflashGetManufacturerInfo (uint8_t *manufID, uint8_t *deviceID);
+
+/**************************************************************************/
+/*!
+ @brief Sets the write flag on the SPI flash, and if required puts the
+ WP pin in an appropriate state
+
+ @param[in] enable
+ True (1) to enable writing, false (0) to disable it
+*/
+/**************************************************************************/
+void spiflashWriteEnable (bool enable);
+
+/**************************************************************************/
+/*!
+ @brief Reads the specified number of bytes from the supplied address.
+
+ This function will read one or more bytes starting at the supplied
+ address. Please note that bufferLength is zero-based, meaning you
+ should supply '0' to read a single byte, '3' to read 4 bytes of data,
+ etc.
+
+ @param[in] address
+ The 24-bit address where the read will start.
+ @param[out] *buffer
+ Pointer to the buffer that will store the read results
+ @param[in] len
+ Length of the buffer.
+
+ @section EXAMPLE
+
+ @code
+ uint8_t buffer[64];
+ spiflashError_e error;
+ error = spiflashReadBuffer (0, buffer, 64);
+ if (error)
+ {
+ // Check what went wrong
+ switch (error)
+ {
+ case SPIFLASH_ERROR_ADDROUTOFRANGE:
+ // Specified starting address is out of range
+ break;
+ case SPIFLASH_ERROR_TIMEOUT_READY:
+ // Timed out waiting for flash to return ready state
+ break;
+ case SPIFLASH_ERROR_ADDROVERFLOW:
+ // Ran over the upper address during read
+ break;
+ }
+ }
+ @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashReadBuffer (uint32_t address, uint8_t *buffer, uint32_t len);
+
+/**************************************************************************/
+/*!
+ @brief Erases the contents of a single sector
+
+ @param[in] sectorNumber
+ The sector number to erase (zero-based).
+
+ @section EXAMPLE
+
+ @code
+ spiflashError_e error;
+ error = spiflashEraseSector(0);
+ if (error)
+ {
+ // Check what went wrong
+ switch (error)
+ {
+ case SPIFLASH_ERROR_ADDROUTOFRANGE:
+ // Specified starting address is out of range
+ break;
+ case SPIFLASH_ERROR_PROTECTIONERR:
+ // Couldn't set the write enable bit
+ break;
+ case SPIFLASH_ERROR_TIMEOUT_READY:
+ // Timed out waiting for flash to return ready state
+ break;
+ }
+ }
+ @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashEraseSector (uint32_t sectorNumber);
+
+/**************************************************************************/
+/*!
+ @brief Erases the entire flash chip
+
+ @section EXAMPLE
+
+ @code
+ spiflashError_e error;
+ error = spiflashEraseChip();
+ if (error)
+ {
+ // Check what went wrong
+ switch (error)
+ {
+ case SPIFLASH_ERROR_PROTECTIONERR:
+ // Couldn't set the write enable bit
+ break;
+ case SPIFLASH_ERROR_TIMEOUT_READY:
+ // Timed out waiting for flash to return ready state
+ break;
+ }
+ }
+ @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashEraseChip (void);
+
+/**************************************************************************/
+/*!
+ @brief Writes up to 256 bytes of data to the specified page.
+
+ @note Before writing data to a page, make sure that the 4K sector
+ containing the specific page has been erased, otherwise the
+ data will be meaningless.
+
+ @param[in] address
+ The 24-bit address where the write will start.
+ @param[out] *buffer
+ Pointer to the buffer that will store the read results
+ @param[in] len
+ Length of the buffer. Valid values are from 1 to 256,
+ within the limits of the starting address and page length.
+
+ @section EXAMPLE
+
+ @code
+ spiflashError_e error;
+ uint8_t buffer[256];
+
+ buffer[0] = 0x12;
+ buffer[1] = 0x34;
+ buffer[2] = 0x56;
+ buffer[3] = 0x78;
+ buffer[4] = 0xDE;
+ buffer[5] = 0xAD;
+ buffer[6] = 0xC0;
+ buffer[7] = 0xDE;
+
+ error = spiflashWritePage (0, buffer, 8);
+ if (error)
+ {
+ // Check what went wrong
+ switch (error)
+ {
+ case SPIFLASH_ERROR_ADDROUTOFRANGE:
+ // Specified starting address is out of range
+ break;
+ case SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE:
+ // Supplied data exceeds max page size
+ break;
+ case SPIFLASH_ERROR_PAGEWRITEOVERFLOW:
+ // The data length plus the start address offset exceeeds page limits
+ break;
+ case SPIFLASH_ERROR_TIMEOUT_READY:
+ // Timeout waiting for ready status (can be pre or post write)
+ break;
+ case SPIFLASH_ERROR_PROTECTIONERR:
+ // Unable to set write latch
+ break;
+ }
+ }
+ @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashWritePage (uint32_t address, uint8_t *buffer, uint32_t len);
+
+/**************************************************************************/
+/*!
+ @brief Writes a continuous stream of data that will automatically
+ cross page boundaries.
+
+ @note Before writing data, make sure that the appropriate sectors
+ have been erased, otherwise the data will be meaningless.
+
+ @param[in] address
+ The 24-bit address where the write will start.
+ @param[out] *buffer
+ Pointer to the buffer that will store the read results
+ @param[in] len
+ Length of the buffer, within the limits of the starting
+ address and size of the flash device.
+
+ @section EXAMPLE
+
+ @code
+ spiflashError_e error;
+ uint8_t buffer[256];
+
+ buffer[0] = 0x12;
+ buffer[1] = 0x34;
+ buffer[2] = 0x56;
+ buffer[3] = 0x78;
+ buffer[4] = 0xDE;
+ buffer[5] = 0xAD;
+ buffer[6] = 0xC0;
+ buffer[7] = 0xDE;
+
+ error = spiflashWrite (0, buffer, 8);
+ if (error)
+ {
+ // Check what went wrong
+ switch (error)
+ {
+ case SPIFLASH_ERROR_ADDROUTOFRANGE:
+ // Specified starting address is out of range
+ break;
+ case SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE:
+ // Supplied data exceeds max page size
+ break;
+ case SPIFLASH_ERROR_PAGEWRITEOVERFLOW:
+ // The data length plus the start address offset exceeeds page limits
+ break;
+ case SPIFLASH_ERROR_TIMEOUT_READY:
+ // Timeout waiting for ready status (can be pre or post write)
+ break;
+ case SPIFLASH_ERROR_PROTECTIONERR:
+ // Unable to set write latch
+ break;
+ }
+ }
+ @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashWrite (uint32_t address, uint8_t *buffer, uint32_t len);
+
+#endif
--- /dev/null
+/**************************************************************************/
+/*!
+ @file w25q16bv.c
+ @author K. Townsend (microBuilder.eu)
+
+ @section DESCRIPTION
+
+ Driver for Winbond's 16 MBit SPI/Quad-SPI Flash (W25Q16BV)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2010, microBuilder SARL
+ 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+
+#include "w25q16bv.h"
+#include "../spiflash.h"
+#include "core/ssp/ssp.h"
+#include "core/gpio/gpio.h"
+#include "core/systick/systick.h"
+
+// Macros to toggle the CS/SSEL line on the SPI bus
+#define W25Q16BV_SELECT() gpioSetValue(0, 2, 0)
+#define W25Q16BV_DESELECT() gpioSetValue(0, 2, 1)
+
+// Flag to indicate whether the SPI flash has been initialised or not
+static bool _w25q16bvInitialised = false;
+
+/**************************************************************************/
+/* HW Specific Functions */
+/* ------------------------------------------------------------------- */
+/* These functions are specific to the chip being used, and are */
+/* seperate from the 'generic' functions defined in spiflash.h */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/*!
+ This function both reads and writes data. For write operations, include data
+ to be written as argument. For read ops, use dummy data as arg. Returned
+ data is read byte val.
+*/
+/**************************************************************************/
+uint8_t w25q16bv_TransferByte(uint8_t data)
+{
+ /* Move on only if NOT busy and TX FIFO not full */
+ while ((SSP_SSP0SR & (SSP_SSP0SR_TNF_MASK | SSP_SSP0SR_BSY_MASK)) != SSP_SSP0SR_TNF_NOTFULL);
+ SSP_SSP0DR = data;
+
+ /* Wait until the busy bit is cleared and receive buffer is not empty */
+ while ((SSP_SSP0SR & (SSP_SSP0SR_BSY_MASK | SSP_SSP0SR_RNE_MASK)) != SSP_SSP0SR_RNE_NOTEMPTY);
+
+ // Read the queue
+ return SSP_SSP0DR;
+}
+
+/**************************************************************************/
+/*!
+ @brief Gets the value of the Read Status Register (0x05)
+
+ @return The 8-bit value returned by the Read Status Register
+*/
+/**************************************************************************/
+uint8_t w25q16bvGetStatus()
+{
+ uint8_t status;
+
+ W25Q16BV_SELECT();
+ w25q16bv_TransferByte(W25Q16BV_CMD_READSTAT1); // Send read status 1 cmd
+ status = w25q16bv_TransferByte(0xFF); // Dummy write
+ W25Q16BV_DESELECT();
+
+ return status & (W25Q16BV_STAT1_BUSY | W25Q16BV_STAT1_WRTEN);
+}
+
+/**************************************************************************/
+/*!
+ @brief Waits for the SPI flash to indicate that it is ready (not
+ busy) or until a timeout occurs.
+
+ @return An error message indicating that a timeoout occured
+ (SPIFLASH_ERROR_TIMEOUT_READY) or an OK signal to indicate that
+ the SPI flash is ready (SPIFLASH_ERROR_OK)
+*/
+/**************************************************************************/
+spiflashError_e w25q16bvWaitForReady()
+{
+ uint32_t timeout = 0;
+ uint8_t status;
+
+ while ( timeout < SSP_MAX_TIMEOUT )
+ {
+ status = w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY;
+ if (status == 0)
+ {
+ break;
+ }
+ timeout++;
+ }
+ if ( timeout == SSP_MAX_TIMEOUT )
+ {
+ return SPIFLASH_ERROR_TIMEOUT_READY;
+ }
+
+ return SPIFLASH_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Gets the unique 64-bit ID assigned to this IC (useful for
+ security purposes to detect if the flash was changed, etc.)
+
+ @param[out] *buffer
+ Pointer to the uint8_t buffer that will store the 8 byte
+ long unique ID
+
+ @note The unique ID is return in bit order 63..0
+*/
+/**************************************************************************/
+void w25q16bvGetUniqueID(uint8_t *buffer)
+{
+ uint8_t i;
+
+ W25Q16BV_SELECT();
+ w25q16bv_TransferByte(W25Q16BV_CMD_READUNIQUEID); // Unique ID cmd
+ w25q16bv_TransferByte(0xFF); // Dummy write
+ w25q16bv_TransferByte(0xFF); // Dummy write
+ w25q16bv_TransferByte(0xFF); // Dummy write
+ w25q16bv_TransferByte(0xFF); // Dummy write
+ // Read 8 bytes worth of data
+ for (i = 0; i < 8; i++)
+ {
+ buffer[i] = w25q16bv_TransferByte(0xFF);
+ }
+ W25Q16BV_DESELECT();
+}
+
+/**************************************************************************/
+/* Generic spiflash.h Functions */
+/* ------------------------------------------------------------------- */
+/* These functions are part of the common interface defined in */
+/* spiflash.h and must be implemented by any spi flash device */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/*!
+ @brief Tries to initialise the flash device, and setups any HW
+ required by the SPI flash
+*/
+/**************************************************************************/
+void spiflashInit (void)
+{
+ // Initialise the SPI bus
+ sspInit(0, sspClockPolarity_Low, sspClockPhase_RisingEdge);
+
+ // ToDo: Set the WP, Hold, etc. pins to an appropriate state
+
+ _w25q16bvInitialised = TRUE;
+}
+
+/**************************************************************************/
+/*!
+ @brief Gets an instance of spiflashSizeInfo_t that describes the
+ storage limits of the SPI flash like page size (minimum write
+ size) and sector size (minimum erase size).
+*/
+/**************************************************************************/
+spiflashSizeInfo_t spiflashGetSizeInfo(void)
+{
+ spiflashSizeInfo_t size;
+ size.pageSize = W25Q16BV_PAGESIZE;
+ size.pageCount = W25Q16BV_PAGES;
+ size.sectorSize = W25Q16BV_SECTORSIZE;
+ size.sectorCount = W25Q16BV_SECTORS;
+ return size;
+}
+
+/**************************************************************************/
+/*!
+ @brief Gets the 8-bit manufacturer ID and device ID for the flash
+
+ @param[out] *manufID
+ Pointer to the uint8_t that will store the manufacturer ID
+ @param[out] *deviceID
+ Pointer to the uint8_t that will store the device ID
+*/
+/**************************************************************************/
+void spiflashGetManufacturerInfo (uint8_t *manufID, uint8_t *deviceID)
+{
+ if (!_w25q16bvInitialised) spiflashInit();
+
+ // W25Q16BV_CMD_MANUFDEVID (0x90) provides both the JEDEC manufacturer
+ // ID and the device ID
+
+ W25Q16BV_SELECT();
+ w25q16bv_TransferByte(W25Q16BV_CMD_MANUFDEVID);
+ w25q16bv_TransferByte(0x00); // Dummy write
+ w25q16bv_TransferByte(0x00); // Dummy write
+ w25q16bv_TransferByte(0x00); // Dummy write
+ *manufID = w25q16bv_TransferByte(0xFF);
+ *deviceID = w25q16bv_TransferByte(0xFF);
+ W25Q16BV_DESELECT();
+}
+
+/**************************************************************************/
+/*!
+ @brief Sets the write flag on the SPI flash, and if required puts the
+ WP pin in an appropriate state
+
+ @param[in] enable
+ True (1) to enable writing, false (0) to disable it
+*/
+/**************************************************************************/
+void spiflashWriteEnable (bool enable)
+{
+ if (!_w25q16bvInitialised) spiflashInit();
+
+ // ToDo: Put the WP pin in an appropriate state if required
+
+ W25Q16BV_SELECT();
+ w25q16bv_TransferByte(enable ? W25Q16BV_CMD_WRITEENABLE : W25Q16BV_CMD_WRITEDISABLE);
+ W25Q16BV_DESELECT();
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads the specified number of bytes from the supplied address.
+
+ This function will read one or more bytes starting at the supplied
+ address. Please note that bufferLength is zero-based, meaning you
+ should supply '0' to read a single byte, '3' to read 4 bytes of data,
+ etc.
+
+ @param[in] address
+ The 24-bit address where the read will start.
+ @param[out] *buffer
+ Pointer to the buffer that will store the read results
+ @param[in] len
+ Length of the buffer.
+
+ @section EXAMPLE
+
+ @code
+ uint8_t buffer[64];
+ spiflashError_e error;
+ error = spiflashReadBuffer (0, buffer, 64);
+ if (error)
+ {
+ // Check what went wrong
+ switch (error)
+ {
+ case SPIFLASH_ERROR_ADDROUTOFRANGE:
+ // Specified starting address is out of range
+ break;
+ case SPIFLASH_ERROR_TIMEOUT_READY:
+ // Timed out waiting for flash to return ready state
+ break;
+ case SPIFLASH_ERROR_ADDROVERFLOW:
+ // Ran over the upper address during read
+ break;
+ }
+ }
+ @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashReadBuffer (uint32_t address, uint8_t *buffer, uint32_t len)
+{
+ if (!_w25q16bvInitialised) spiflashInit();
+
+ uint32_t a, i;
+ a = i = 0;
+
+ // Make sure the address is valid
+ if (address >= W25Q16BV_MAXADDRESS)
+ {
+ return SPIFLASH_ERROR_ADDROUTOFRANGE;
+ }
+
+ // Wait until the device is ready or a timeout occurs
+ if (w25q16bvWaitForReady())
+ return SPIFLASH_ERROR_TIMEOUT_READY;
+
+ // Send the read data command
+ W25Q16BV_SELECT();
+ w25q16bv_TransferByte(W25Q16BV_CMD_READDATA); // 0x03
+ w25q16bv_TransferByte((address >> 16) & 0xFF); // address upper 8
+ w25q16bv_TransferByte((address >> 8) & 0xFF); // address mid 8
+ w25q16bv_TransferByte(address & 0xFF); // address lower 8
+ // Fill response buffer
+ for (a = address; a < address + len; a++, i++)
+ {
+ if (a > W25Q16BV_MAXADDRESS)
+ {
+ // Oops ... we're at the end of the flash memory
+ return SPIFLASH_ERROR_ADDROVERFLOW;
+ }
+ buffer[i] = w25q16bv_TransferByte(0xFF);
+ }
+ W25Q16BV_DESELECT();
+
+ return SPIFLASH_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Erases the contents of a single sector
+
+ @param[in] sectorNumber
+ The sector number to erase (zero-based).
+
+ @section EXAMPLE
+
+ @code
+ spiflashError_e error;
+ error = spiflashEraseSector(0);
+ if (error)
+ {
+ // Check what went wrong
+ switch (error)
+ {
+ case SPIFLASH_ERROR_ADDROUTOFRANGE:
+ // Specified starting address is out of range
+ break;
+ case SPIFLASH_ERROR_PROTECTIONERR:
+ // Couldn't set the write enable bit
+ break;
+ case SPIFLASH_ERROR_TIMEOUT_READY:
+ // Timed out waiting for flash to return ready state
+ break;
+ }
+ }
+ @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashEraseSector (uint32_t sectorNumber)
+{
+ if (!_w25q16bvInitialised) spiflashInit();
+
+ // Make sure the address is valid
+ if (sectorNumber >= W25Q16BV_SECTORS)
+ {
+ return SPIFLASH_ERROR_ADDROUTOFRANGE;
+ }
+
+ // Wait until the device is ready or a timeout occurs
+ if (w25q16bvWaitForReady())
+ return SPIFLASH_ERROR_TIMEOUT_READY;
+
+ // Make sure the chip is write enabled
+ spiflashWriteEnable (TRUE);
+
+ // Make sure the write enable latch is actually set
+ uint8_t status;
+ status = w25q16bvGetStatus();
+ if (!(status & W25Q16BV_STAT1_WRTEN))
+ {
+ // Throw a write protection error (write enable latch not set)
+ return SPIFLASH_ERROR_PROTECTIONERR;
+ }
+
+ // Send the erase sector command
+ uint32_t address = sectorNumber * W25Q16BV_SECTORSIZE;
+ W25Q16BV_SELECT();
+ w25q16bv_TransferByte(W25Q16BV_CMD_SECTERASE4);
+ w25q16bv_TransferByte((address >> 16) & 0xFF); // address upper 8
+ w25q16bv_TransferByte((address >> 8) & 0xFF); // address mid 8
+ w25q16bv_TransferByte(address & 0xFF); // address lower 8
+ W25Q16BV_DESELECT();
+
+ // Wait until the busy bit is cleared before exiting
+ // This can take up to 400ms according to the datasheet
+ while (w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY);
+
+ return SPIFLASH_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Erases the entire flash chip
+
+ @section EXAMPLE
+
+ @code
+ spiflashError_e error;
+ error = spiflashEraseChip();
+ if (error)
+ {
+ // Check what went wrong
+ switch (error)
+ {
+ case SPIFLASH_ERROR_PROTECTIONERR:
+ // Couldn't set the write enable bit
+ break;
+ case SPIFLASH_ERROR_TIMEOUT_READY:
+ // Timed out waiting for flash to return ready state
+ break;
+ }
+ }
+ @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashEraseChip (void)
+{
+ if (!_w25q16bvInitialised) spiflashInit();
+
+ // Wait until the device is ready or a timeout occurs
+ if (w25q16bvWaitForReady())
+ return SPIFLASH_ERROR_TIMEOUT_READY;
+
+ // Make sure the chip is write enabled
+ spiflashWriteEnable (TRUE);
+
+ // Make sure the write enable latch is actually set
+ uint8_t status;
+ status = w25q16bvGetStatus();
+ if (!(status & W25Q16BV_STAT1_WRTEN))
+ {
+ // Throw a write protection error (write enable latch not set)
+ return SPIFLASH_ERROR_PROTECTIONERR;
+ }
+
+ // Send the erase chip command
+ W25Q16BV_SELECT();
+ w25q16bv_TransferByte(W25Q16BV_CMD_CHIPERASE);
+ W25Q16BV_DESELECT();
+
+ // Wait until the busy bit is cleared before exiting
+ // This can take up to 10 seconds according to the datasheet!
+ while (w25q16bvGetStatus() & W25Q16BV_STAT1_BUSY);
+
+ return SPIFLASH_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes up to 256 bytes of data to the specified page.
+
+ @note Before writing data to a page, make sure that the 4K sector
+ containing the specific page has been erased, otherwise the
+ data will be meaningless.
+
+ @param[in] address
+ The 24-bit address where the write will start.
+ @param[out] *buffer
+ Pointer to the buffer that will store the read results
+ @param[in] len
+ Length of the buffer. Valid values are from 1 to 256,
+ within the limits of the starting address and page length.
+
+ @section EXAMPLE
+
+ @code
+ spiflashError_e error;
+ uint8_t buffer[256];
+
+ buffer[0] = 0x12;
+ buffer[1] = 0x34;
+ buffer[2] = 0x56;
+ buffer[3] = 0x78;
+ buffer[4] = 0xDE;
+ buffer[5] = 0xAD;
+ buffer[6] = 0xC0;
+ buffer[7] = 0xDE;
+
+ error = spiflashWritePage (0, buffer, 8);
+ if (error)
+ {
+ // Check what went wrong
+ switch (error)
+ {
+ case SPIFLASH_ERROR_ADDROUTOFRANGE:
+ // Specified starting address is out of range
+ break;
+ case SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE:
+ // Supplied data exceeds max page size
+ break;
+ case SPIFLASH_ERROR_PAGEWRITEOVERFLOW:
+ // The data length plus the start address offset exceeeds page limits
+ break;
+ case SPIFLASH_ERROR_TIMEOUT_READY:
+ // Timeout waiting for ready status (can be pre or post write)
+ break;
+ case SPIFLASH_ERROR_PROTECTIONERR:
+ // Unable to set write latch
+ break;
+ }
+ }
+ @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashWritePage (uint32_t address, uint8_t *buffer, uint32_t len)
+{
+ uint8_t status;
+ uint32_t i;
+
+ if (!_w25q16bvInitialised) spiflashInit();
+
+ // Make sure the address is valid
+ if (address >= W25Q16BV_MAXADDRESS)
+ {
+ return SPIFLASH_ERROR_ADDROUTOFRANGE;
+ }
+
+ // Make sure that the supplied data is no larger than the page size
+ if (len > W25Q16BV_PAGESIZE)
+ {
+ return SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE;
+ }
+
+ // Make sure that the data won't wrap around to the beginning of the sector
+ if ((address % W25Q16BV_PAGESIZE) + len > W25Q16BV_PAGESIZE)
+ {
+ // If you try to write to a page beyond the last byte, it will
+ // wrap around to the start of the page, almost certainly
+ // messing up your data
+ return SPIFLASH_ERROR_PAGEWRITEOVERFLOW;
+ }
+
+ // Wait until the device is ready or a timeout occurs
+ if (w25q16bvWaitForReady())
+ return SPIFLASH_ERROR_TIMEOUT_READY;
+
+ // Make sure the chip is write enabled
+ spiflashWriteEnable (TRUE);
+
+ // Make sure the write enable latch is actually set
+ status = w25q16bvGetStatus();
+ if (!(status & W25Q16BV_STAT1_WRTEN))
+ {
+ // Throw a write protection error (write enable latch not set)
+ return SPIFLASH_ERROR_PROTECTIONERR;
+ }
+
+ // Send page write command (0x02) plus 24-bit address
+ W25Q16BV_SELECT();
+ w25q16bv_TransferByte(W25Q16BV_CMD_PAGEPROG); // 0x02
+ w25q16bv_TransferByte((address >> 16) & 0xFF); // address upper 8
+ w25q16bv_TransferByte((address >> 8) & 0xFF); // address mid 8
+ if (len == 256)
+ {
+ // If len = 256 bytes, lower 8 bits must be 0 (see datasheet 11.2.17)
+ w25q16bv_TransferByte(0);
+ }
+ else
+ {
+ w25q16bv_TransferByte(address & 0xFF); // address lower 8
+ }
+ // Transfer data
+ for (i = 0; i < len; i++)
+ {
+ w25q16bv_TransferByte(buffer[i]);
+ }
+ // Write only occurs after the CS line is de-asserted
+ W25Q16BV_DESELECT();
+
+ // Wait at least 3ms (max page program time according to datasheet)
+ systickDelay(3);
+
+ // Wait until the device is ready or a timeout occurs
+ if (w25q16bvWaitForReady())
+ return SPIFLASH_ERROR_TIMEOUT_READY;
+
+ return SPIFLASH_ERROR_OK;
+}
+
+/**************************************************************************/
+/*!
+ @brief Writes a continuous stream of data that will automatically
+ cross page boundaries.
+
+ @note Before writing data, make sure that the appropriate sectors
+ have been erased, otherwise the data will be meaningless.
+
+ @param[in] address
+ The 24-bit address where the write will start.
+ @param[out] *buffer
+ Pointer to the buffer that will store the read results
+ @param[in] len
+ Length of the buffer, within the limits of the starting
+ address and size of the flash device.
+
+ @section EXAMPLE
+
+ @code
+ spiflashError_e error;
+ uint8_t buffer[256];
+
+ buffer[0] = 0x12;
+ buffer[1] = 0x34;
+ buffer[2] = 0x56;
+ buffer[3] = 0x78;
+ buffer[4] = 0xDE;
+ buffer[5] = 0xAD;
+ buffer[6] = 0xC0;
+ buffer[7] = 0xDE;
+
+ error = spiflashWrite (0, buffer, 8);
+ if (error)
+ {
+ // Check what went wrong
+ switch (error)
+ {
+ case SPIFLASH_ERROR_ADDROUTOFRANGE:
+ // Specified starting address is out of range
+ break;
+ case SPIFLASH_ERROR_DATAEXCEEDSPAGESIZE:
+ // Supplied data exceeds max page size
+ break;
+ case SPIFLASH_ERROR_PAGEWRITEOVERFLOW:
+ // The data length plus the start address offset exceeeds page limits
+ break;
+ case SPIFLASH_ERROR_TIMEOUT_READY:
+ // Timeout waiting for ready status (can be pre or post write)
+ break;
+ case SPIFLASH_ERROR_PROTECTIONERR:
+ // Unable to set write latch
+ break;
+ }
+ }
+ @endcode
+*/
+/**************************************************************************/
+spiflashError_e spiflashWrite (uint32_t address, uint8_t *buffer, uint32_t len)
+{
+ uint32_t bytestowrite;
+ uint32_t bufferoffset;
+ spiflashError_e error;
+
+ // There's no point duplicating most error checks here since they will all be
+ // done in the underlying call to spiflashWritePage
+
+ // If the data is only on one page we can take a shortcut
+ if ((address % W25Q16BV_PAGESIZE) + len <= W25Q16BV_PAGESIZE)
+ {
+ // Only one page ... write and be done with it
+ return spiflashWritePage(address, buffer, len);
+ }
+
+ // Block spans multiple pages
+ bufferoffset = 0;
+ while(len)
+ {
+ // Figure out how many bytes need to be written to this page
+ bytestowrite = W25Q16BV_PAGESIZE - (address % W25Q16BV_PAGESIZE);
+ // Write the current page
+ error = spiflashWritePage(address, buffer+bufferoffset, bytestowrite);
+ // Abort if we returned an error
+ if (error)
+ return error;
+ // Adjust address and len, and buffer offset
+ address += bytestowrite;
+ len -= bytestowrite;
+ bufferoffset+=bytestowrite;
+ // If the next page is the last one, write it and exit
+ // otherwise stay in the the loop and keep writing
+ if (len <= W25Q16BV_PAGESIZE)
+ {
+ // Write the last frame and then quit
+ error = spiflashWritePage(address, buffer+bufferoffset, len);
+ // Abort if we returned an error
+ if (error)
+ return error;
+ // set len to zero to gracefully exit loop
+ len = 0;
+ }
+ }
+
+ return SPIFLASH_ERROR_OK;
+}
+
+
--- /dev/null
+/**************************************************************************/
+/*!
+ @file w25q16bv.h
+ @author K. Townsend (microBuilder.eu)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2010, microBuilder SARL
+ 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 copyright holders 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 COPYRIGHT HOLDERS ''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 COPYRIGHT HOLDER 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.
+*/
+/**************************************************************************/
+
+#ifndef _W25Q16BV_H_
+#define _W25Q16BV_H_
+
+#include "projectconfig.h"
+
+#define W25Q16BV_MAXADDRESS 0x1FFFFF
+#define W25Q16BV_PAGESIZE 256 // 256 bytes per programmable page
+#define W25Q16BV_PAGES 8192 // 2,097,152 Bytes / 256 bytes per page
+#define W25Q16BV_SECTORSIZE 4096 // 1 erase sector = 4096 bytes
+#define W25Q16BV_SECTORS 512 // 2,097,152 Bytes / 4096 bytes per sector
+#define W25Q16BV_MANUFACTURERID 0xEF // Used to validate read data
+#define W25Q16BV_DEVICEID 0x14 // Used to validate read data
+
+#define W25Q16BV_STAT1_BUSY 0x01 // Erase/Write in Progress
+#define W25Q16BV_STAT1_WRTEN 0x02 // Write Enable Latch
+#define W25Q16BV_STAT2_QUADENBL 0x02 // Quad Enable
+#define W25Q16BV_STAT2_SSPNDSTAT 0x80 // Suspend Status
+
+/**************************************************************************/
+/*!
+ W25Q16BV Commands
+*/
+/**************************************************************************/
+typedef enum
+{
+ // Erase/Program Instructions
+ W25Q16BV_CMD_WRITEENABLE = 0x06, // Write Enabled
+ W25Q16BV_CMD_WRITEDISABLE = 0x04, // Write Disabled
+ W25Q16BV_CMD_READSTAT1 = 0x05, // Read Status Register 1
+ W25Q16BV_CMD_READSTAT2 = 0x35, // Read Status Register 2
+ W25Q16BV_CMD_WRITESTAT = 0x01, // Write Status Register
+ W25Q16BV_CMD_PAGEPROG = 0x02, // Page Program
+ W25Q16BV_CMD_QUADPAGEPROG = 0x32, // Quad Page Program
+ W25Q16BV_CMD_SECTERASE4 = 0x20, // Sector Erase (4KB)
+ W25Q16BV_CMD_BLOCKERASE32 = 0x52, // Block Erase (32KB)
+ W25Q16BV_CMD_BLOCKERASE64 = 0xD8, // Block Erase (64KB)
+ W25Q16BV_CMD_CHIPERASE = 0x60, // Chip Erase
+ W25Q16BV_CMD_ERASESUSPEND = 0x75, // Erase Suspend
+ W25Q16BV_CMD_ERASERESUME = 0x7A, // Erase Resume
+ W25Q16BV_CMD_POWERDOWN = 0xB9, // Power Down
+ W25Q16BV_CMD_CRMR = 0xFF, // Continuous Read Mode Reset
+ // Read Instructions
+ W25Q16BV_CMD_READDATA = 0x03, // Read Data
+ W25Q16BV_CMD_FREAD = 0x0B, // Fast Read
+ W25Q16BV_CMD_FREADDUALOUT = 0x3B, // Fast Read Dual Output
+ W25Q16BV_CMD_FREADDUALIO = 0xBB, // Fast Read Dual I/O
+ W25Q16BV_CMD_FREADQUADOUT = 0x6B, // Fast Read Quad Output
+ W25Q16BV_CMD_FREADQUADIO = 0xEB, // Fast Read Quad I/O
+ W25Q16BV_CMD_WREADQUADIO = 0xE7, // Word Read Quad I/O
+ W25Q16BV_CMD_OWREADQUADIO = 0xE3, // Octal Word Read Quad I/O
+ // ID/Security Instructions
+ W25Q16BV_CMD_RPWRDDEVID = 0xAB, // Release Power Down/Device ID
+ W25Q16BV_CMD_MANUFDEVID = 0x90, // Manufacturer/Device ID
+ W25Q16BV_CMD_MANUFDEVID2 = 0x92, // Manufacturer/Device ID by Dual I/O
+ W25Q16BV_CMD_MANUFDEVID4 = 0x94, // Manufacturer/Device ID by Quad I/O
+ W25Q16BV_CMD_JEDECID = 0x9F, // JEDEC ID
+ W25Q16BV_CMD_READUNIQUEID = 0x4B // Read Unique ID
+} w25q16bv_Commands_e;
+
+#endif