From 1048eb7e2c9c70e47fd47926bc07066ed02cc314 Mon Sep 17 00:00:00 2001 From: Brian Webb Date: Sat, 28 Apr 2012 19:29:25 -0700 Subject: [PATCH] Added pios_eeprom for saving settings. --- flight/PiOS/Common/pios_crc.c | 127 ++++++++++++++++++++++- flight/PiOS/STM32F10x/pios_eeprom.c | 155 ++++++++++++++++++++++++++++ flight/PiOS/inc/pios_crc.h | 6 ++ flight/PiOS/inc/pios_eeprom.h | 50 +++++++++ 4 files changed, 337 insertions(+), 1 deletion(-) create mode 100644 flight/PiOS/STM32F10x/pios_eeprom.c create mode 100644 flight/PiOS/inc/pios_eeprom.h diff --git a/flight/PiOS/Common/pios_crc.c b/flight/PiOS/Common/pios_crc.c index 548ba2648..dcd8c80c7 100644 --- a/flight/PiOS/Common/pios_crc.c +++ b/flight/PiOS/Common/pios_crc.c @@ -29,6 +29,76 @@ static const uint8_t crc_table[256] = { 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 }; +static const uint16_t CRC_Table16[] = { // HDLC polynomial + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +static const uint32_t CRC_Table32[] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 + }; + /** * Update the crc value with new data. * @@ -52,7 +122,7 @@ uint8_t PIOS_CRC_updateByte(uint8_t crc, const uint8_t data) return crc_table[crc ^ data]; } -/* +/** * @brief Update a CRC with a data buffer * @param[in] crc Starting CRC value * @param[in] data Data buffer @@ -72,3 +142,58 @@ uint8_t PIOS_CRC_updateCRC(uint8_t crc, const uint8_t* data, int32_t length) return crc8; } +/** + * Update the crc value with new data. + * \param crc The current crc value. + * \param data Pointer to a buffer of \a data_len bytes. + * \param length Number of bytes in the \a data buffer. + * \return The updated crc value. + */ +uint16_t PIOS_CRC16_updateByte(uint16_t crc, const uint8_t data) +{ + return ((crc >> 8) ^ CRC_Table16[(crc & 0xff) ^ data]); +} + +/** + * @brief Update a CRC with a data buffer + * @param[in] crc Starting CRC value + * @param[in] data Data buffer + * @param[in] length Number of bytes to process + * @returns Updated CRC + */ +uint16_t PIOS_CRC16_updateCRC(uint16_t crc, const uint8_t* data, int32_t length) +{ + register uint8_t *p = (uint8_t *)data; + register uint16_t _crc = crc; + for (register uint32_t i = length; i > 0; i--) + _crc = (_crc >> 8) ^ CRC_Table16[(_crc ^ *p++) & 0xff]; + return _crc; +} + +/** + * Update the crc value with new data. + * \param crc The current crc value. + * \param data Pointer to a buffer of \a data_len bytes. + * \param length Number of bytes in the \a data buffer. + * \return The updated crc value. + */ +uint32_t PIOS_CRC32_updateByte(uint32_t crc, const uint8_t data) +{ + return ((crc << 8) ^ CRC_Table32[(crc >> 24) ^ data]); +} + +/** + * @brief Update a CRC with a data buffer + * @param[in] crc Starting CRC value + * @param[in] data Data buffer + * @param[in] length Number of bytes to process + * @returns Updated CRC + */ +uint32_t PIOS_CRC32_updateCRC(uint32_t crc, const uint8_t* data, int32_t length) +{ + register uint8_t *p = (uint8_t *)data; + register uint32_t _crc = crc; + for (register uint32_t i = length; i > 0; i--) + _crc = (_crc << 8) ^ CRC_Table32[(_crc >> 24) ^ *p++]; + return _crc; +} diff --git a/flight/PiOS/STM32F10x/pios_eeprom.c b/flight/PiOS/STM32F10x/pios_eeprom.c new file mode 100644 index 000000000..ef2b24e7e --- /dev/null +++ b/flight/PiOS/STM32F10x/pios_eeprom.c @@ -0,0 +1,155 @@ +/** +****************************************************************************** +* @addtogroup PIOS PIOS Core hardware abstraction layer +* @{ +* @addtogroup PIOS_EEPROM EEPROM reading/writing functions +* @brief PIOS EEPROM reading/writing functions +* @{ +* +* @file pios_eeprom.c +* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. +* @brief COM layer functions +* @see The GNU Public License (GPL) Version 3 +* +*****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Project Includes */ +#include +#include +#include +#include + +#include + +static struct pios_eeprom_cfg config; + +/** + * Initialize the flash eeprom device + * \param cfg The configuration structure. + */ +void PIOS_EEPROM_Init(const struct pios_eeprom_cfg *cfg) +{ + config = *cfg; +} + +/** + * Save a block of data to the flash eeprom device. + * \param data A pointer to the data to write. + * \param len The length of data to write. + * \return 0 on sucess + */ +int32_t PIOS_EEPROM_Save(uint8_t *data, uint32_t len) +{ + + // We need to write 32 bit words, so extend the length to be an even multiple of 4 bytes, + // and include 4 bytes for the 32 bit CRC. + uint32_t nwords = (len / 4) + 1 + (len % 4 ? 1 : 0); + uint32_t size = nwords * 4; + + // Ensure that the length is not longer than the max size. + if (size > config.max_size) + return -1; + + // Calculate a 32 bit CRC of the data. + uint32_t crc = PIOS_CRC32_updateCRC(0xffffffff, data, len); + + // Unlock the Flash Program Erase controller + FLASH_Unlock(); + + // See if we have to write the data. + if ((memcmp(data, (uint8_t*)config.base_address, len) == 0) && + (memcmp((uint8_t*)crc, (uint8_t*)config.base_address + size - 4, 4) == 0)) + return 0; + + // TODO: Check that the area isn't already erased + + // Erase page + FLASH_Status fs = FLASH_ErasePage(config.base_address); + if (fs != FLASH_COMPLETE) + { // error + FLASH_Lock(); + return -2; + } + + // write 4 bytes at a time into program flash area (emulated EEPROM area) + uint8_t *p1 = data; + uint32_t *p3 = (uint32_t *)config.base_address; + for (int32_t i = 0; i < size; p3++) + { + uint32_t value = 0; + + if (i == (size - 4)) + { + // write the CRC. + value = crc; + i += 4; + } + else + { + if (i < len) value |= (uint32_t)*p1++ << 0; else value |= 0x000000ff; i++; + if (i < len) value |= (uint32_t)*p1++ << 8; else value |= 0x0000ff00; i++; + if (i < len) value |= (uint32_t)*p1++ << 16; else value |= 0x00ff0000; i++; + if (i < len) value |= (uint32_t)*p1++ << 24; else value |= 0xff000000; i++; + } + + // write a 32-bit value + fs = FLASH_ProgramWord((uint32_t)p3, value); + if (fs != FLASH_COMPLETE) + { + FLASH_Lock(); + return -3; + } + } + + // Lock the Flash Program Erase controller + FLASH_Lock(); + + return 0; +} + +/** + * Reads a block of data from the flash eeprom device. + * \param data A pointer to the output data buffer. + * \param len The length of data to read. + * \return 0 on sucess + */ +int32_t PIOS_EEPROM_Load(uint8_t *data, uint32_t len) +{ + + // We need to write 32 bit words, so the length should have been extended + // to an even multiple of 4 bytes, and should include 4 bytes for the 32 bit CRC. + uint32_t nwords = (len / 4) + 1 + (len % 4 ? 1 : 0); + uint32_t size = nwords * 4; + + // Ensure that the length is not longer than the max size. + if (size > config.max_size) + return -1; + + // Read the data from flash. + memcpy(data, (uint8_t*)config.base_address, len); + + // Read the CRC. + uint32_t crc_flash = *((uint32_t*)(config.base_address + size - 4)); + + // Calculate a 32 bit CRC of the data. + uint32_t crc = PIOS_CRC32_updateCRC(0xffffffff, data, len); + if(crc != crc_flash) + return -2; + + return 0; +} diff --git a/flight/PiOS/inc/pios_crc.h b/flight/PiOS/inc/pios_crc.h index 3a64f8bab..612c89e49 100644 --- a/flight/PiOS/inc/pios_crc.h +++ b/flight/PiOS/inc/pios_crc.h @@ -29,3 +29,9 @@ uint8_t PIOS_CRC_updateByte(uint8_t crc, const uint8_t data); uint8_t PIOS_CRC_updateCRC(uint8_t crc, const uint8_t* data, int32_t length); + +uint16_t PIOS_CRC16_updateByte(uint16_t crc, const uint8_t data); +uint16_t PIOS_CRC16_updateCRC(uint16_t crc, const uint8_t* data, int32_t length); + +uint32_t PIOS_CRC32_updateByte(uint32_t crc, const uint8_t data); +uint32_t PIOS_CRC32_updateCRC(uint32_t crc, const uint8_t* data, int32_t length); diff --git a/flight/PiOS/inc/pios_eeprom.h b/flight/PiOS/inc/pios_eeprom.h new file mode 100644 index 000000000..14acc595e --- /dev/null +++ b/flight/PiOS/inc/pios_eeprom.h @@ -0,0 +1,50 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_EEPROM EEPROM reading/writing functions + * @brief PIOS EEPROM reading/writing functions + * @{ + * + * @file pios_eeprom.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @brief COM layer functions + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PIOS_EEPROM_H +#define PIOS_EEPROM_H + +/* Public Structures */ +struct pios_eeprom_cfg { + uint32_t base_address; + uint32_t max_size; +}; + +/* Public Functions */ +extern void PIOS_EEPROM_Init(const struct pios_eeprom_cfg *cfg); +extern int32_t PIOS_EEPROM_Save(uint8_t *data, uint32_t len); +extern int32_t PIOS_EEPROM_Load(uint8_t *data, uint32_t len); + +#endif /* PIOS_EEPROM_H */ + +/** + * @} + * @} + */