From: Kevin Townsend Date: Sat, 10 Mar 2012 00:29:41 +0000 (+0100) Subject: moved to /storage X-Git-Url: http://git.rohieb.name/hackover2013-badge-firmware.git/commitdiff_plain/e888054f5b6b6a817eb608ee3eb1be9f528156c8?ds=sidebyside moved to /storage --- diff --git a/drivers/displays/segment/as1115/as1115.c b/drivers/displays/segment/as1115/as1115.c new file mode 100644 index 0000000..eb23645 --- /dev/null +++ b/drivers/displays/segment/as1115/as1115.c @@ -0,0 +1,264 @@ +/**************************************************************************/ +/*! + @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; +} + diff --git a/drivers/displays/segment/as1115/as1115.h b/drivers/displays/segment/as1115/as1115.h new file mode 100644 index 0000000..026dbe0 --- /dev/null +++ b/drivers/displays/segment/as1115/as1115.h @@ -0,0 +1,94 @@ +/**************************************************************************/ +/*! + @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 + + diff --git a/drivers/displays/segment/readme.txt b/drivers/displays/segment/readme.txt new file mode 100644 index 0000000..7922b54 --- /dev/null +++ b/drivers/displays/segment/readme.txt @@ -0,0 +1,6 @@ +Segment/LED Displays +==================== + +This folder contains drivers for LED-based segment displays + +AS1115 AS1115 segment-display driver diff --git a/drivers/eeprom/at25040/at25040.c b/drivers/eeprom/at25040/at25040.c deleted file mode 100644 index d84a733..0000000 --- a/drivers/eeprom/at25040/at25040.c +++ /dev/null @@ -1,297 +0,0 @@ -/**************************************************************************/ -/*! - @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; -} diff --git a/drivers/eeprom/at25040/at25040.h b/drivers/eeprom/at25040/at25040.h deleted file mode 100644 index 57a6d6d..0000000 --- a/drivers/eeprom/at25040/at25040.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************/ -/*! - @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 diff --git a/drivers/eeprom/eeprom.c b/drivers/eeprom/eeprom.c deleted file mode 100644 index fda0d9b..0000000 --- a/drivers/eeprom/eeprom.c +++ /dev/null @@ -1,410 +0,0 @@ -/**************************************************************************/ -/*! - @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 - -#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) { }; -} diff --git a/drivers/eeprom/eeprom.h b/drivers/eeprom/eeprom.h deleted file mode 100644 index 71875b7..0000000 --- a/drivers/eeprom/eeprom.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************/ -/*! - @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 diff --git a/drivers/eeprom/mcp24aa/mcp24aa.c b/drivers/eeprom/mcp24aa/mcp24aa.c deleted file mode 100644 index 24d8975..0000000 --- a/drivers/eeprom/mcp24aa/mcp24aa.c +++ /dev/null @@ -1,339 +0,0 @@ -/**************************************************************************/ -/*! - @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); -} - diff --git a/drivers/eeprom/mcp24aa/mcp24aa.h b/drivers/eeprom/mcp24aa/mcp24aa.h deleted file mode 100644 index 3563939..0000000 --- a/drivers/eeprom/mcp24aa/mcp24aa.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************/ -/*! - @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 diff --git a/drivers/spiflash/spiflash.h b/drivers/spiflash/spiflash.h deleted file mode 100644 index bf2ab68..0000000 --- a/drivers/spiflash/spiflash.h +++ /dev/null @@ -1,339 +0,0 @@ -/**************************************************************************/ -/*! - @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 diff --git a/drivers/spiflash/w25q16bv/w25q16bv.c b/drivers/spiflash/w25q16bv/w25q16bv.c deleted file mode 100644 index c99e1dc..0000000 --- a/drivers/spiflash/w25q16bv/w25q16bv.c +++ /dev/null @@ -1,697 +0,0 @@ -/**************************************************************************/ -/*! - @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; -} - - diff --git a/drivers/spiflash/w25q16bv/w25q16bv.h b/drivers/spiflash/w25q16bv/w25q16bv.h deleted file mode 100644 index 15e296d..0000000 --- a/drivers/spiflash/w25q16bv/w25q16bv.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************/ -/*! - @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 diff --git a/drivers/storage/eeprom/at25040/at25040.c b/drivers/storage/eeprom/at25040/at25040.c new file mode 100644 index 0000000..ad98926 --- /dev/null +++ b/drivers/storage/eeprom/at25040/at25040.c @@ -0,0 +1,297 @@ +/**************************************************************************/ +/*! + @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; +} diff --git a/drivers/storage/eeprom/at25040/at25040.h b/drivers/storage/eeprom/at25040/at25040.h new file mode 100644 index 0000000..57a6d6d --- /dev/null +++ b/drivers/storage/eeprom/at25040/at25040.h @@ -0,0 +1,85 @@ +/**************************************************************************/ +/*! + @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 diff --git a/drivers/storage/eeprom/eeprom.c b/drivers/storage/eeprom/eeprom.c new file mode 100644 index 0000000..01b627a --- /dev/null +++ b/drivers/storage/eeprom/eeprom.c @@ -0,0 +1,410 @@ +/**************************************************************************/ +/*! + @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 + +#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) { }; +} diff --git a/drivers/storage/eeprom/eeprom.h b/drivers/storage/eeprom/eeprom.h new file mode 100644 index 0000000..71875b7 --- /dev/null +++ b/drivers/storage/eeprom/eeprom.h @@ -0,0 +1,61 @@ +/**************************************************************************/ +/*! + @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 diff --git a/drivers/storage/eeprom/mcp24aa/mcp24aa.c b/drivers/storage/eeprom/mcp24aa/mcp24aa.c new file mode 100644 index 0000000..e56deb1 --- /dev/null +++ b/drivers/storage/eeprom/mcp24aa/mcp24aa.c @@ -0,0 +1,339 @@ +/**************************************************************************/ +/*! + @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); +} + diff --git a/drivers/storage/eeprom/mcp24aa/mcp24aa.h b/drivers/storage/eeprom/mcp24aa/mcp24aa.h new file mode 100644 index 0000000..3563939 --- /dev/null +++ b/drivers/storage/eeprom/mcp24aa/mcp24aa.h @@ -0,0 +1,67 @@ +/**************************************************************************/ +/*! + @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 diff --git a/drivers/storage/spiflash/spiflash.h b/drivers/storage/spiflash/spiflash.h new file mode 100644 index 0000000..bf2ab68 --- /dev/null +++ b/drivers/storage/spiflash/spiflash.h @@ -0,0 +1,339 @@ +/**************************************************************************/ +/*! + @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 diff --git a/drivers/storage/spiflash/w25q16bv/w25q16bv.c b/drivers/storage/spiflash/w25q16bv/w25q16bv.c new file mode 100644 index 0000000..c99e1dc --- /dev/null +++ b/drivers/storage/spiflash/w25q16bv/w25q16bv.c @@ -0,0 +1,697 @@ +/**************************************************************************/ +/*! + @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; +} + + diff --git a/drivers/storage/spiflash/w25q16bv/w25q16bv.h b/drivers/storage/spiflash/w25q16bv/w25q16bv.h new file mode 100644 index 0000000..15e296d --- /dev/null +++ b/drivers/storage/spiflash/w25q16bv/w25q16bv.h @@ -0,0 +1,96 @@ +/**************************************************************************/ +/*! + @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