From 20921e48ca2c0905cdb39dc967310692974a3ff4 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 2 Dec 2012 03:25:17 -0500 Subject: [PATCH 01/33] flashfs: define the API to the FLASHFS subsystem --- flight/PiOS/inc/pios_flashfs.h | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 flight/PiOS/inc/pios_flashfs.h diff --git a/flight/PiOS/inc/pios_flashfs.h b/flight/PiOS/inc/pios_flashfs.h new file mode 100644 index 000000000..914ee6db2 --- /dev/null +++ b/flight/PiOS/inc/pios_flashfs.h @@ -0,0 +1,38 @@ +/** + ****************************************************************************** + * @file pios_flashfs.h + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_FLASHFS Flash Filesystem API Definition + * @{ + * @brief Flash Filesystem API Definition + *****************************************************************************/ +/* + * 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_FLASHFS_H_ +#define PIOS_FLASHFS_H_ + +#include +#include "uavobjectmanager.h" /* UAVObjHandle */ + +int32_t PIOS_FLASHFS_Format(); +int32_t PIOS_FLASHFS_ObjSave(UAVObjHandle obj, uint16_t instId, uint8_t * data); +int32_t PIOS_FLASHFS_ObjLoad(UAVObjHandle obj, uint16_t instId, uint8_t * data); +int32_t PIOS_FLASHFS_ObjDelete(UAVObjHandle obj, uint16_t instId); + +#endif /* PIOS_FLASHFS_H_ */ From 5ef098813799be5e3a200b0f5846fabdbe2d39ff Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Tue, 11 Dec 2012 22:36:18 -0500 Subject: [PATCH 02/33] logfs+flash: add log structured filesystem for PiOS A new flash driver abstraction is also provided to allow for future support of other types of flash device under the filesystem. Conflicts: flight/PiOS/Common/pios_flash_jedec.c --- flight/PiOS/Common/pios_flash_jedec.c | 293 +++--- flight/PiOS/Common/pios_flashfs_logfs.c | 990 ++++++++++++++++++ flight/PiOS/inc/pios_flash.h | 47 + ..._flash_jedec.h => pios_flash_jedec_priv.h} | 49 +- flight/PiOS/inc/pios_flashfs_logfs_priv.h | 46 + flight/PiOS/pios.h | 5 +- 6 files changed, 1280 insertions(+), 150 deletions(-) create mode 100644 flight/PiOS/Common/pios_flashfs_logfs.c create mode 100644 flight/PiOS/inc/pios_flash.h rename flight/PiOS/inc/{pios_flash_jedec.h => pios_flash_jedec_priv.h} (56%) create mode 100644 flight/PiOS/inc/pios_flashfs_logfs_priv.h diff --git a/flight/PiOS/Common/pios_flash_jedec.c b/flight/PiOS/Common/pios_flash_jedec.c index 6c012112c..cf614259b 100644 --- a/flight/PiOS/Common/pios_flash_jedec.c +++ b/flight/PiOS/Common/pios_flash_jedec.c @@ -8,6 +8,7 @@ * * @file pios_flash_w25x.c * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 * @brief Driver for talking to W25X flash chip (and most JEDEC chips) * @see The GNU Public License (GPL) Version 3 * @@ -28,6 +29,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "pios.h" +#include "pios_flash_jedec_priv.h" #define JEDEC_WRITE_ENABLE 0x06 #define JEDEC_WRITE_DISABLE 0x04 @@ -67,58 +69,78 @@ struct jedec_flash_dev { enum pios_jedec_dev_magic magic; }; -//! Global structure for this flash device -struct jedec_flash_dev * flash_dev; - //! Private functions -static int32_t PIOS_Flash_Jedec_Validate(struct jedec_flash_dev * dev); +static int32_t PIOS_Flash_Jedec_Validate(struct jedec_flash_dev * flash_dev); static struct jedec_flash_dev * PIOS_Flash_Jedec_alloc(void); -static int32_t PIOS_Flash_Jedec_ClaimBus(); -static int32_t PIOS_Flash_Jedec_ReleaseBus(); -static int32_t PIOS_Flash_Jedec_WriteEnable(); -static int32_t PIOS_Flash_Jedec_Busy() ; +static int32_t PIOS_Flash_Jedec_ReadID(struct jedec_flash_dev * flash_dev); +static int32_t PIOS_Flash_Jedec_ReadStatus(struct jedec_flash_dev * flash_dev); +static int32_t PIOS_Flash_Jedec_ClaimBus(struct jedec_flash_dev * flash_dev); +static int32_t PIOS_Flash_Jedec_ReleaseBus(struct jedec_flash_dev * flash_dev); +static int32_t PIOS_Flash_Jedec_WriteEnable(struct jedec_flash_dev * flash_dev); +static int32_t PIOS_Flash_Jedec_Busy(struct jedec_flash_dev * flash_dev); /** * @brief Allocate a new device */ static struct jedec_flash_dev * PIOS_Flash_Jedec_alloc(void) { - struct jedec_flash_dev * jedec_dev; + struct jedec_flash_dev * flash_dev; - jedec_dev = (struct jedec_flash_dev *)pvPortMalloc(sizeof(*jedec_dev)); - if (!jedec_dev) return (NULL); + flash_dev = (struct jedec_flash_dev *)pvPortMalloc(sizeof(*flash_dev)); + if (!flash_dev) return (NULL); - jedec_dev->claimed = false; - jedec_dev->magic = PIOS_JEDEC_DEV_MAGIC; + flash_dev->claimed = false; + flash_dev->magic = PIOS_JEDEC_DEV_MAGIC; #if defined(FLASH_FREERTOS) - jedec_dev->transaction_lock = xSemaphoreCreateMutex(); + flash_dev->transaction_lock = xSemaphoreCreateMutex(); #endif - return(jedec_dev); + return(flash_dev); } /** * @brief Validate the handle to the spi device */ -static int32_t PIOS_Flash_Jedec_Validate(struct jedec_flash_dev * dev) { - if (dev == NULL) +static int32_t PIOS_Flash_Jedec_Validate(struct jedec_flash_dev * flash_dev) { + if (flash_dev == NULL) return -1; - if (dev->magic != PIOS_JEDEC_DEV_MAGIC) + if (flash_dev->magic != PIOS_JEDEC_DEV_MAGIC) return -2; - if (dev->spi_id == 0) + if (flash_dev->spi_id == 0) return -3; return 0; } +/** + * @brief Initialize the flash device and enable write access + */ +int32_t PIOS_Flash_Jedec_Init(uint32_t * flash_id, uint32_t spi_id, uint32_t slave_num, const struct pios_flash_jedec_cfg * cfg) +{ + struct jedec_flash_dev * flash_dev = PIOS_Flash_Jedec_alloc(); + if (flash_dev == NULL) + return -1; + + flash_dev->spi_id = spi_id; + flash_dev->slave_num = slave_num; + flash_dev->cfg = cfg; + + device_type = PIOS_Flash_Jedec_ReadID(flash_dev); + if (device_type == 0) + return -1; + + /* Give back a handle to this flash device */ + *flash_id = (uint32_t) flash_dev; + + return 0; +} + + /** * @brief Claim the SPI bus for flash use and assert CS pin * @return 0 for sucess, -1 for failure to get semaphore */ -static int32_t PIOS_Flash_Jedec_ClaimBus() +static int32_t PIOS_Flash_Jedec_ClaimBus(struct jedec_flash_dev * flash_dev) { - if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) - return -1; - if(PIOS_SPI_ClaimBus(flash_dev->spi_id) < 0) return -1; @@ -131,10 +153,8 @@ static int32_t PIOS_Flash_Jedec_ClaimBus() /** * @brief Release the SPI bus sempahore and ensure flash chip not using bus */ -static int32_t PIOS_Flash_Jedec_ReleaseBus() +static int32_t PIOS_Flash_Jedec_ReleaseBus(struct jedec_flash_dev * flash_dev) { - if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) - return -1; PIOS_SPI_RC_PinSet(flash_dev->spi_id, flash_dev->slave_num, 1); PIOS_SPI_ReleaseBus(flash_dev->spi_id); flash_dev->claimed = false; @@ -145,9 +165,9 @@ static int32_t PIOS_Flash_Jedec_ReleaseBus() * @brief Returns if the flash chip is busy * @returns -1 for failure, 0 for not busy, 1 for busy */ -static int32_t PIOS_Flash_Jedec_Busy() +static int32_t PIOS_Flash_Jedec_Busy(struct jedec_flash_dev * flash_dev) { - int32_t status = PIOS_Flash_Jedec_ReadStatus(); + int32_t status = PIOS_Flash_Jedec_ReadStatus(flash_dev); if (status < 0) return -1; return status & JEDEC_STATUS_BUSY; @@ -157,52 +177,87 @@ static int32_t PIOS_Flash_Jedec_Busy() * @brief Execute the write enable instruction and returns the status * @returns 0 if successful, -1 if unable to claim bus */ -static int32_t PIOS_Flash_Jedec_WriteEnable() +static int32_t PIOS_Flash_Jedec_WriteEnable(struct jedec_flash_dev * flash_dev) { - if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) + if (PIOS_Flash_Jedec_ClaimBus(flash_dev) != 0) return -1; uint8_t out[] = {JEDEC_WRITE_ENABLE}; - if(PIOS_Flash_Jedec_ClaimBus() != 0) - return -1; PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL); - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); + return 0; } + +/** + * @brief Read the status register from flash chip and return it + */ +static int32_t PIOS_Flash_Jedec_ReadStatus(struct jedec_flash_dev * flash_dev) +{ + if (PIOS_Flash_Jedec_ClaimBus(flash_dev) < 0) + return -1; + + uint8_t out[2] = {JEDEC_READ_STATUS, 0}; + uint8_t in[2] = {0,0}; + if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,in,sizeof(out),NULL) < 0) { + PIOS_Flash_Jedec_ReleaseBus(flash_dev); + return -2; + } + + PIOS_Flash_Jedec_ReleaseBus(flash_dev); + + return in[1]; +} + /** - * @brief Initialize the flash device and enable write access + * @brief Read the status register from flash chip and return it */ -int32_t PIOS_Flash_Jedec_Init(uint32_t spi_id, uint32_t slave_num, const struct pios_flash_jedec_cfg * cfg) +static int32_t PIOS_Flash_Jedec_ReadID(struct jedec_flash_dev * flash_dev) { - flash_dev = PIOS_Flash_Jedec_alloc(); - if(flash_dev == NULL) - return -1; + if (PIOS_Flash_Jedec_ClaimBus(flash_dev) < 0) + return -2; - flash_dev->spi_id = spi_id; - flash_dev->slave_num = slave_num; - flash_dev->cfg = cfg; + uint8_t out[] = {JEDEC_DEVICE_ID, 0, 0, 0}; + uint8_t in[4]; + if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,in,sizeof(out),NULL) < 0) { + PIOS_Flash_Jedec_ReleaseBus(flash_dev); + return -3; + } - device_type = PIOS_Flash_Jedec_ReadID(); - if(device_type == 0) - return -1; + PIOS_Flash_Jedec_ReleaseBus(flash_dev); - return 0; + flash_dev->device_type = in[1]; + flash_dev->capacity = in[3]; + + return in[1]; } +/********************************** + * + * Provide a PIOS flash driver API + * + *********************************/ +#include "pios_flash.h" + +#if FLASH_USE_FREERTOS_LOCKS + /** * @brief Grab the semaphore to perform a transaction * @return 0 for success, -1 for timeout */ -int32_t PIOS_Flash_Jedec_StartTransaction() +static int32_t PIOS_Flash_Jedec_StartTransaction(uint32_t flash_id) { -#if defined(FLASH_FREERTOS) + struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; + if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; +#if defined(PIOS_INCLUDE_FREERTOS) if(xSemaphoreTake(flash_dev->transaction_lock, portMAX_DELAY) != pdTRUE) - return -1; + return -2; #endif + return 0; } @@ -210,60 +265,34 @@ int32_t PIOS_Flash_Jedec_StartTransaction() * @brief Release the semaphore to perform a transaction * @return 0 for success, -1 for timeout */ -int32_t PIOS_Flash_Jedec_EndTransaction() +static int32_t PIOS_Flash_Jedec_EndTransaction(uint32_t flash_id) { -#if defined(FLASH_FREERTOS) + struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; + if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; +#if defined(PIOS_INCLUDE_FREERTOS) if(xSemaphoreGive(flash_dev->transaction_lock) != pdTRUE) - return -1; + return -2; #endif + return 0; } -/** - * @brief Read the status register from flash chip and return it - */ -int32_t PIOS_Flash_Jedec_ReadStatus() -{ - if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) - return -1; +#else /* FLASH_USE_FREERTOS_LOCKS */ - uint8_t out[2] = {JEDEC_READ_STATUS, 0}; - uint8_t in[2] = {0,0}; - if(PIOS_Flash_Jedec_ClaimBus() < 0) - return -1; - - if(PIOS_SPI_TransferBlock(flash_dev->spi_id,out,in,sizeof(out),NULL) < 0) { - PIOS_Flash_Jedec_ReleaseBus(); - return -2; +static int32_t PIOS_Flash_Jedec_StartTransaction(uint32_t flash_id) +{ + return 0; } - PIOS_Flash_Jedec_ReleaseBus(); - return in[1]; -} - -/** - * @brief Read the status register from flash chip and return it - */ -int32_t PIOS_Flash_Jedec_ReadID() +static int32_t PIOS_Flash_Jedec_EndTransaction(uint32_t flash_id) { - uint8_t out[] = {JEDEC_DEVICE_ID, 0, 0, 0}; - uint8_t in[4]; - if (PIOS_Flash_Jedec_ClaimBus() < 0) - return -1; - - if(PIOS_SPI_TransferBlock(flash_dev->spi_id,out,in,sizeof(out),NULL) < 0) { - PIOS_Flash_Jedec_ReleaseBus(); - return -2; + return 0; } - PIOS_Flash_Jedec_ReleaseBus(); - flash_dev->device_type = in[1]; - flash_dev->capacity = in[3]; - return in[1]; -} +#endif /* FLASH_USE_FREERTOS_LOCKS */ /** * @brief Erase a sector on the flash chip @@ -272,29 +301,31 @@ int32_t PIOS_Flash_Jedec_ReadID() * @retval -1 if unable to claim bus * @retval */ -int32_t PIOS_Flash_Jedec_EraseSector(uint32_t addr) +static int32_t PIOS_Flash_Jedec_EraseSector(uint32_t flash_id, uint32_t addr) { + struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; + if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; uint8_t ret; uint8_t out[] = {flash_dev->cfg->sector_erase, (addr >> 16) & 0xff, (addr >> 8) & 0xff , addr & 0xff}; - if((ret = PIOS_Flash_Jedec_WriteEnable()) != 0) + if ((ret = PIOS_Flash_Jedec_WriteEnable(flash_dev)) != 0) return ret; - if(PIOS_Flash_Jedec_ClaimBus() != 0) + if (PIOS_Flash_Jedec_ClaimBus(flash_dev) != 0) return -1; if(PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -2; } - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); // Keep polling when bus is busy too - while(PIOS_Flash_Jedec_Busy() != 0) { + while (PIOS_Flash_Jedec_Busy(flash_dev) != 0) { #if defined(FLASH_FREERTOS) vTaskDelay(1); #endif @@ -307,30 +338,32 @@ int32_t PIOS_Flash_Jedec_EraseSector(uint32_t addr) * @brief Execute the whole chip * @returns 0 if successful, -1 if unable to claim bus */ -int32_t PIOS_Flash_Jedec_EraseChip() +static int32_t PIOS_Flash_Jedec_EraseChip(uint32_t flash_id) { + struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; + if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; uint8_t ret; uint8_t out[] = {flash_dev->cfg->chip_erase}; - if((ret = PIOS_Flash_Jedec_WriteEnable()) != 0) + if ((ret = PIOS_Flash_Jedec_WriteEnable(flash_dev)) != 0) return ret; - if(PIOS_Flash_Jedec_ClaimBus() != 0) + if (PIOS_Flash_Jedec_ClaimBus(flash_dev) != 0) return -1; if(PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -2; } - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); // Keep polling when bus is busy too int i = 0; - while(PIOS_Flash_Jedec_Busy() != 0) { + while (PIOS_Flash_Jedec_Busy(flash_dev) != 0) { #if defined(FLASH_FREERTOS) vTaskDelay(1); if ((i++) % 100 == 0) @@ -356,8 +389,10 @@ int32_t PIOS_Flash_Jedec_EraseChip() * @retval -2 Size exceeds 256 bytes * @retval -3 Length to write would wrap around page boundary */ -int32_t PIOS_Flash_Jedec_WriteData(uint32_t addr, uint8_t * data, uint16_t len) +static int32_t PIOS_Flash_Jedec_WriteData(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) { + struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; + if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; @@ -372,41 +407,41 @@ int32_t PIOS_Flash_Jedec_WriteData(uint32_t addr, uint8_t * data, uint16_t len) if(((addr & 0xff) + len) > 0x100) return -3; - if((ret = PIOS_Flash_Jedec_WriteEnable()) != 0) + if ((ret = PIOS_Flash_Jedec_WriteEnable(flash_dev)) != 0) return ret; /* Execute write page command and clock in address. Keep CS asserted */ - if(PIOS_Flash_Jedec_ClaimBus() != 0) + if (PIOS_Flash_Jedec_ClaimBus(flash_dev) != 0) return -1; if(PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -1; } /* Clock out data to flash */ if(PIOS_SPI_TransferBlock(flash_dev->spi_id,data,NULL,len,NULL) < 0) { - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -1; } - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); // Keep polling when bus is busy too #if defined(FLASH_FREERTOS) - while(PIOS_Flash_Jedec_Busy() != 0) { + while (PIOS_Flash_Jedec_Busy(flash_dev) != 0) { vTaskDelay(1); } #else // Query status this way to prevent accel chip locking us out - if(PIOS_Flash_Jedec_ClaimBus() < 0) + if (PIOS_Flash_Jedec_ClaimBus(flash_dev) < 0) return -1; PIOS_SPI_TransferByte(flash_dev->spi_id, JEDEC_READ_STATUS); while(PIOS_SPI_TransferByte(flash_dev->spi_id, JEDEC_READ_STATUS) & JEDEC_STATUS_BUSY); - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); #endif return 0; @@ -422,8 +457,10 @@ int32_t PIOS_Flash_Jedec_WriteData(uint32_t addr, uint8_t * data, uint16_t len) * @retval -2 Size exceeds 256 bytes * @retval -3 Length to write would wrap around page boundary */ -int32_t PIOS_Flash_Jedec_WriteChunks(uint32_t addr, struct pios_flash_chunk * p_chunk, uint32_t num) +static int32_t PIOS_Flash_Jedec_WriteChunks(uint32_t flash_id, uint32_t addr, struct pios_flash_chunk chunks[], uint32_t num) { + struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; + if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; @@ -433,7 +470,7 @@ int32_t PIOS_Flash_Jedec_WriteChunks(uint32_t addr, struct pios_flash_chunk * p_ /* Can only write one page at a time */ uint32_t len = 0; for(uint32_t i = 0; i < num; i++) - len += p_chunk[i].len; + len += chunks[i].len; if(len > 0x100) return -2; @@ -442,29 +479,29 @@ int32_t PIOS_Flash_Jedec_WriteChunks(uint32_t addr, struct pios_flash_chunk * p_ if(((addr & 0xff) + len) > 0x100) return -3; - if((ret = PIOS_Flash_Jedec_WriteEnable()) != 0) + if ((ret = PIOS_Flash_Jedec_WriteEnable(flash_dev)) != 0) return ret; /* Execute write page command and clock in address. Keep CS asserted */ - if(PIOS_Flash_Jedec_ClaimBus() != 0) + if (PIOS_Flash_Jedec_ClaimBus(flash_dev) != 0) return -1; if(PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -1; } for(uint32_t i = 0; i < num; i++) { - struct pios_flash_chunk * chunk = &p_chunk[i]; + struct pios_flash_chunk * chunk = &chunks[i]; /* Clock out data to flash */ if(PIOS_SPI_TransferBlock(flash_dev->spi_id,chunk->addr,NULL,chunk->len,NULL) < 0) { - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -1; } } - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); // Skip checking for busy with this to get OS running again fast @@ -479,29 +516,43 @@ int32_t PIOS_Flash_Jedec_WriteChunks(uint32_t addr, struct pios_flash_chunk * p_ * @return Zero if success or error code * @retval -1 Unable to claim SPI bus */ -int32_t PIOS_Flash_Jedec_ReadData(uint32_t addr, uint8_t * data, uint16_t len) +static int32_t PIOS_Flash_Jedec_ReadData(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) { + struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; + if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; - if(PIOS_Flash_Jedec_ClaimBus() == -1) + if (PIOS_Flash_Jedec_ClaimBus(flash_dev) == -1) return -1; /* Execute read command and clock in address. Keep CS asserted */ uint8_t out[] = {JEDEC_READ_DATA, (addr >> 16) & 0xff, (addr >> 8) & 0xff , addr & 0xff}; if(PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -2; } /* Copy the transfer data to the buffer */ if(PIOS_SPI_TransferBlock(flash_dev->spi_id,NULL,data,len,NULL) < 0) { - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -3; } - PIOS_Flash_Jedec_ReleaseBus(); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); return 0; } + +/* Provide a flash driver to external drivers */ +const struct pios_flash_driver pios_jedec_flash_driver = { + .start_transaction = PIOS_Flash_Jedec_StartTransaction, + .end_transaction = PIOS_Flash_Jedec_EndTransaction, + .erase_chip = PIOS_Flash_Jedec_EraseChip, + .erase_sector = PIOS_Flash_Jedec_EraseSector, + .write_chunks = PIOS_Flash_Jedec_WriteChunks, + .write_data = PIOS_Flash_Jedec_WriteData, + .read_data = PIOS_Flash_Jedec_ReadData, +}; + diff --git a/flight/PiOS/Common/pios_flashfs_logfs.c b/flight/PiOS/Common/pios_flashfs_logfs.c new file mode 100644 index 000000000..2dbe8e8e1 --- /dev/null +++ b/flight/PiOS/Common/pios_flashfs_logfs.c @@ -0,0 +1,990 @@ +/** + ****************************************************************************** + * @file pios_flashfs_logfs.c + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_FLASHFS Flash Filesystem Function + * @{ + * @brief Log Structured Filesystem for internal or external NOR Flash + *****************************************************************************/ +/* + * 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 + */ + +#include "openpilot.h" +#include "uavobjectmanager.h" /* UAVObjHandle, UAVObj* */ + +#include "pios_flashfs.h" /* API for flash filesystem */ +#include "pios_flashfs_logfs_priv.h" + +#define MIN(x,y) ((x) < (y) ? (x) : (y)) + +/* + * Filesystem state data tracked in RAM + */ + +struct logfs_state { + const struct flashfs_logfs_cfg * cfg; + bool mounted; + uint8_t active_arena_id; + + /* NOTE: num_active_slots + num_free_slots will not typically add + * up to the number of slots in the arena since some of the + * slots will be obsolete or otherwise invalidated + */ + uint16_t num_free_slots; /* slots in free state */ + uint16_t num_active_slots; /* slots in active state */ + + /* Underlying flash driver glue */ + const struct pios_flash_driver * driver; + uint32_t flash_id; +}; + +static struct logfs_state logfs; + +/* + * Internal Utility functions + */ + +/** + * @brief Return the offset in flash of a particular slot within an arena + * @return address of the requested slot + */ +static uintptr_t logfs_get_addr(uint8_t arena_id, uint16_t slot_id) +{ + PIOS_Assert(arena_id < (logfs.cfg->total_fs_size / logfs.cfg->arena_size)); + PIOS_Assert(slot_id < (logfs.cfg->arena_size / logfs.cfg->slot_size)); + + return (logfs.cfg->start_offset + + (arena_id * logfs.cfg->arena_size) + + (slot_id * logfs.cfg->slot_size)); +} + +/* + * The bits within these enum values must progress ONLY + * from 1 -> 0 so that we can write later ones on top + * of earlier ones in NOR flash without an erase cycle. + */ +enum arena_state { + ARENA_STATE_ERASED = 0xEEEEEEEE, + ARENA_STATE_RESERVED = 0xE6E6E6E6, + ARENA_STATE_ACTIVE = 0x66666666, + ARENA_STATE_OBSOLETE = 0x44444444, +}; + +struct arena_header { + uint32_t magic; + enum arena_state state; +} __attribute__((packed)); + + +/**************************************** + * Arena life-cycle transition functions + ****************************************/ + +/** + * @brief Erases all sectors within the given arena and sets arena to erased state. + * @return 0 if success, < 0 on failure + * @note Must be called while holding the flash transaction lock + */ +static int32_t logfs_erase_arena(uint8_t arena_id) +{ + uintptr_t arena_addr = logfs_get_addr (arena_id, 0); + + /* Erase all of the sectors in the arena */ + for (uint8_t sector_id = 0; + sector_id < (logfs.cfg->arena_size / logfs.cfg->sector_size); + sector_id++) { + if (logfs.driver->erase_sector(logfs.flash_id, + arena_addr + (sector_id * logfs.cfg->sector_size))) { + return -1; + } + } + + /* Mark this arena as fully erased */ + struct arena_header arena_hdr = { + .magic = logfs.cfg->fs_magic, + .state = ARENA_STATE_ERASED, + }; + + if (logfs.driver->write_data(logfs.flash_id, + arena_addr, + (uint8_t *)&arena_hdr, + sizeof(arena_hdr)) != 0) { + return -2; + } + + /* Arena is ready to be activated */ + return 0; +} + +/** + * @brief Marks the given arena as reserved so it can be filled. + * @return 0 if success, < 0 on failure + * @note Arena must have been previously erased before calling this + * @note Must be called while holding the flash transaction lock + */ +static int32_t logfs_reserve_arena (uint8_t arena_id) +{ + uintptr_t arena_addr = logfs_get_addr (arena_id, 0); + + /* Read in the current arena header */ + struct arena_header arena_hdr; + if (logfs.driver->read_data(logfs.flash_id, + arena_addr, + (uint8_t *)&arena_hdr, + sizeof(arena_hdr)) != 0) { + return -1; + } + if (arena_hdr.state != ARENA_STATE_ERASED) { + /* Arena was not erased, can't reserve it */ + return -2; + } + + /* Set the arena state to reserved */ + arena_hdr.state = ARENA_STATE_RESERVED; + + /* Write the arena header back to flash */ + if (logfs.driver->write_data(logfs.flash_id, + arena_addr, + (uint8_t *)&arena_hdr, + sizeof(arena_hdr)) != 0) { + return -3; + } + + /* Arena is ready to be filled */ + return 0; +} + +/** + * @brief Erases all arenas available to this filesystem instance + * @return 0 if success, < 0 on failure + * @note Must be called while holding the flash transaction lock + */ +static int32_t logfs_erase_all_arenas() +{ + uint16_t num_arenas = logfs.cfg->total_fs_size / logfs.cfg->arena_size; + + for (uint16_t arena = 0; arena < num_arenas; arena++) { + if (logfs_erase_arena(arena) != 0) + return -1; + } + + return 0; +} + +/** + * @brief Marks the given arena as active so it can be mounted. + * @return 0 if success, < 0 on failure + * @note Arena must have been previously erased or reserved before calling this + * @note Must be called while holding the flash transaction lock + */ +static int32_t logfs_activate_arena(uint8_t arena_id) +{ + uintptr_t arena_addr = logfs_get_addr(arena_id, 0); + + /* Make sure this arena has been previously erased */ + struct arena_header arena_hdr; + if (logfs.driver->read_data(logfs.flash_id, + arena_addr, + (uint8_t *)&arena_hdr, + sizeof (arena_hdr)) != 0) { + /* Failed to read arena header */ + return -1; + } + if ((arena_hdr.state != ARENA_STATE_RESERVED) && + (arena_hdr.state != ARENA_STATE_ERASED)) { + /* Arena was not erased or reserved, can't activate it */ + return -2; + } + + /* Mark this arena as active */ + arena_hdr.state = ARENA_STATE_ACTIVE; + if (logfs.driver->write_data(logfs.flash_id, + arena_addr, + (uint8_t *)&arena_hdr, + sizeof(arena_hdr)) != 0) { + return -3; + } + + /* The arena is now activated and the log may be mounted */ + return 0; +} + +/** + * @brief Marks the given arena as obsolete. + * @return 0 if success, < 0 on failure + * @note Arena must have been previously active before calling this + * @note Must be called while holding the flash transaction lock + */ +static int32_t logfs_obsolete_arena(uint8_t arena_id) +{ + uintptr_t arena_addr = logfs_get_addr (arena_id, 0); + + /* We shouldn't be retiring the currently active arena */ + PIOS_Assert(!logfs.mounted); + + /* Make sure this arena was previously active */ + struct arena_header arena_hdr; + if (logfs.driver->read_data(logfs.flash_id, + arena_addr, + (uint8_t *)&arena_hdr, + sizeof (arena_hdr)) != 0) { + /* Failed to read arena header */ + return -1; + } + + if (arena_hdr.state != ARENA_STATE_ACTIVE) { + /* Arena was not previously active, can't obsolete it */ + return -2; + } + + /* Mark this arena as obsolete */ + arena_hdr.state = ARENA_STATE_OBSOLETE; + if (logfs.driver->write_data(logfs.flash_id, + arena_addr, + (uint8_t *)&arena_hdr, + sizeof(arena_hdr)) != 0) { + return -3; + } + + /* Arena is now obsoleted */ + return 0; +} + +/** + * @brief Find the first active arena in flash + * @return arena_id (>=0) of first active arena + * @return -1 if no active arena is found + * @return -2 if failed to read arena header + * @note Must be called while holding the flash transaction lock + */ +static int32_t logfs_find_active_arena() +{ + /* Search for the lowest numbered active arena */ + for (uint8_t arena_id = 0; + arena_id < logfs.cfg->total_fs_size / logfs.cfg->arena_size; + arena_id++) { + uintptr_t arena_addr = logfs_get_addr (arena_id, 0); + /* Load the arena header */ + struct arena_header arena_hdr; + if (logfs.driver->read_data(logfs.flash_id, + arena_addr, + (uint8_t *)&arena_hdr, + sizeof (arena_hdr)) != 0) { + return -2; + } + if ((arena_hdr.state == ARENA_STATE_ACTIVE) && + (arena_hdr.magic == logfs.cfg->fs_magic)) { + /* This is the first active arena */ + return arena_id; + } + } + + /* Didn't find an active arena */ + return -1; +} + +/* + * The bits within these enum values must progress ONLY + * from 1 -> 0 so that we can write later ones on top + * of earlier ones in NOR flash without an erase cycle. + */ +enum slot_state { + SLOT_STATE_EMPTY = 0xFFFFFFFF, + SLOT_STATE_RESERVED = 0xFAFAFAFA, + SLOT_STATE_ACTIVE = 0xAAAAAAAA, + SLOT_STATE_OBSOLETE = 0x88888888, +}; + +struct slot_header { + enum slot_state state; + uint32_t objid; + uint16_t instid; + uint16_t size; +} __attribute__((packed)); + +/* NOTE: Must be called while holding the flash transaction lock */ +static int32_t logfs_raw_copy_bytes (uintptr_t src_addr, uint16_t src_size, uintptr_t dst_addr) +{ +#define RAW_COPY_BLOCK_SIZE 16 + uint8_t data_block[RAW_COPY_BLOCK_SIZE]; + + while (src_size) { + uint16_t blk_size; + if (src_size >= RAW_COPY_BLOCK_SIZE) { + /* Copy a full block */ + blk_size = RAW_COPY_BLOCK_SIZE; + } else { + /* Copy the remainder */ + blk_size = src_size; + } + + /* Read a block of data from source */ + if (logfs.driver->read_data(logfs.flash_id, + src_addr, + data_block, + blk_size) != 0) { + /* Failed to read next chunk from source */ + return -1; + } + + /* Write a block of data to destination */ + if (logfs.driver->write_data(logfs.flash_id, + dst_addr, + data_block, + blk_size) != 0) { + /* Failed to write chunk to destination */ + return -2; + } + + /* Update the src/dst pointers */ + src_size -= blk_size; + src_addr += blk_size; + dst_addr += blk_size; + } + + return 0; +} + +/* + * Is the entire filesystem full? + * true = all slots in the arena are in the ACTIVE state (ie. garbage collection won't free anything) + * false = some slots in the arena are either currently free or could be free'd by garbage collection + */ +static bool logfs_fs_is_full(void) +{ + return (logfs.num_active_slots == (logfs.cfg->arena_size / logfs.cfg->slot_size)); +} + +/* + * Is the log full? + * true = there are no unwritten slots left in the log (garbage collection may or may not help) + * false = there are still some entirely unused slots left in the log + */ +static bool logfs_log_is_full(void) +{ + return (logfs.num_free_slots == 0); +} + +static int32_t logfs_unmount_log(void) +{ + PIOS_Assert (logfs.mounted); + + logfs.num_active_slots = 0; + logfs.num_free_slots = 0; + logfs.mounted = false; + + return 0; +} + +static int32_t logfs_mount_log(uint8_t arena_id) +{ + PIOS_Assert (!logfs.mounted); + + logfs.num_active_slots = 0; + logfs.num_free_slots = 0; + logfs.active_arena_id = arena_id; + + /* Scan the log to find out how full it is */ + for (uint16_t slot_id = 1; + slot_id < (logfs.cfg->arena_size / logfs.cfg->slot_size); + slot_id++) { + struct slot_header slot_hdr; + uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, slot_id); + if (logfs.driver->read_data(logfs.flash_id, + slot_addr, + (uint8_t *)&slot_hdr, + sizeof (slot_hdr)) != 0) { + return -1; + } + + /* + * Empty slots must be in a continguous block at the + * end of the arena. + */ + PIOS_Assert (slot_hdr.state == SLOT_STATE_EMPTY || + logfs.num_free_slots == 0); + + switch (slot_hdr.state) { + case SLOT_STATE_EMPTY: + logfs.num_free_slots++; + break; + case SLOT_STATE_ACTIVE: + logfs.num_active_slots++; + break; + case SLOT_STATE_RESERVED: + case SLOT_STATE_OBSOLETE: + break; + } + } + + /* Scan is complete, mark the arena mounted */ + logfs.active_arena_id = arena_id; + logfs.mounted = true; + + return 0; +} + +/** + * @brief Initialize the flash object setting FS + * @return 0 if success, -1 if failure + */ +int32_t PIOS_FLASHFS_Logfs_Init(uint32_t * fs_id, const struct flashfs_logfs_cfg * cfg, const struct pios_flash_driver * driver, uint32_t flash_id) +{ + PIOS_Assert(cfg); + PIOS_Assert(fs_id); + PIOS_Assert(driver); + + /* We must have at least 2 arenas for garbage collection to work */ + PIOS_Assert((cfg->total_fs_size / cfg->arena_size > 1)); + + /* Make sure the underlying flash driver provides the minimal set of required methods */ + PIOS_Assert(driver->start_transaction); + PIOS_Assert(driver->end_transaction); + PIOS_Assert(driver->erase_sector); + PIOS_Assert(driver->write_data); + PIOS_Assert(driver->read_data); + + /* Bind configuration parameters to this filesystem instance */ + logfs.cfg = cfg; /* filesystem configuration */ + logfs.driver = driver; /* lower-level flash driver */ + logfs.flash_id = flash_id; /* lower-level flash device id */ + logfs.mounted = false; + + int8_t rc; + + if (logfs.driver->start_transaction(logfs.flash_id) != 0) { + rc = -1; + goto out_exit; + } + + bool found = false; + int32_t arena_id; + for (uint8_t try = 0; !found && try < 2; try++) { + /* Find the active arena */ + arena_id = logfs_find_active_arena(); + if (arena_id >= 0) { + /* Found the active arena */ + found = true; + break; + } else { + /* No active arena found, erase and activate arena 0 */ + if (logfs_erase_arena(0) != 0) + break; + if (logfs_activate_arena(0) != 0) + break; + } + } + + if (!found) { + /* Still no active arena, something is broken */ + rc = -2; + goto out_end_trans; + } + + /* We've found an active arena, mount it */ + if (logfs_mount_log(arena_id) != 0) { + /* Failed to mount the log, something is broken */ + rc = -3; + goto out_end_trans; + } + + /* Log has been mounted */ + rc = 0; + + *fs_id = (uint32_t) &logfs; + +out_end_trans: + logfs.driver->end_transaction(logfs.flash_id); + +out_exit: + return rc; +} + +/* NOTE: Must be called while holding the flash transaction lock */ +static int32_t logfs_garbage_collect (void) { + PIOS_Assert (logfs.mounted); + + /* Source arena is the active arena */ + uint8_t src_arena_id = logfs.active_arena_id; + + /* Compute destination arena */ + uint8_t dst_arena_id = (logfs.active_arena_id + 1) % (logfs.cfg->total_fs_size / logfs.cfg->arena_size); + + /* Erase destination arena */ + if (logfs_erase_arena (dst_arena_id) != 0) { + return -1; + } + + /* Reserve the destination arena so we can start filling it */ + if (logfs_reserve_arena (dst_arena_id) != 0) { + /* Unable to reserve the arena */ + return -2; + } + + /* Copy active slots from active arena to destination arena */ + uint16_t dst_slot_id = 1; + for (uint16_t src_slot_id = 1; + src_slot_id < (logfs.cfg->arena_size / logfs.cfg->slot_size); + src_slot_id++) { + struct slot_header slot_hdr; + uintptr_t src_addr = logfs_get_addr (src_arena_id, src_slot_id); + if (logfs.driver->read_data(logfs.flash_id, + src_addr, + (uint8_t *)&slot_hdr, + sizeof (slot_hdr)) != 0) { + return -3; + } + + if (slot_hdr.state == SLOT_STATE_ACTIVE) { + uintptr_t dst_addr = logfs_get_addr (dst_arena_id, dst_slot_id); + if (logfs_raw_copy_bytes(src_addr, + sizeof(slot_hdr) + slot_hdr.size, + dst_addr) != 0) { + /* Failed to copy all bytes */ + return -4; + } + dst_slot_id++; + } + } + + /* Activate the destination arena */ + if (logfs_activate_arena (dst_arena_id) != 0) { + return -5; + } + + /* Unmount the source arena */ + if (logfs_unmount_log () != 0) { + return -6; + } + + /* Obsolete the source arena */ + if (logfs_obsolete_arena (src_arena_id) != 0) { + return -7; + } + + /* Mount the new arena */ + if (logfs_mount_log (dst_arena_id) != 0) { + return -8; + } + + return 0; +} + +/* NOTE: Must be called while holding the flash transaction lock */ +static int16_t logfs_object_find_next (struct slot_header * slot_hdr, uint16_t * curr_slot, uint32_t objid, uint16_t instid) +{ + PIOS_Assert(slot_hdr); + PIOS_Assert(curr_slot); + + /* First slot in the arena is reserved for arena header, skip it. */ + if (*curr_slot == 0) *curr_slot = 1; + + for (uint16_t slot_id = *curr_slot; + slot_id < (logfs.cfg->arena_size / logfs.cfg->slot_size); + slot_id++) { + uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, slot_id); + + if (logfs.driver->read_data(logfs.flash_id, + slot_addr, + (uint8_t *)slot_hdr, + sizeof (*slot_hdr)) != 0) { + return -2; + } + if (slot_hdr->state == SLOT_STATE_EMPTY) { + /* We hit the end of the log */ + break; + } + if (slot_hdr->state == SLOT_STATE_ACTIVE && + slot_hdr->objid == objid && + slot_hdr->instid == instid) { + /* Found what we were looking for */ + *curr_slot = slot_id; + return 0; + } + } + + /* No matching entry was found */ + return -1; +} + +/* NOTE: Must be called while holding the flash transaction lock */ +/* OPTIMIZE: could trust that there is at most one active version of every object and terminate the search when we find one */ +static int8_t logfs_delete_object (uint32_t objid, uint16_t instid) +{ + int8_t rc; + + bool more = true; + uint16_t curr_slot_id = 0; + do { + struct slot_header slot_hdr; + switch (logfs_object_find_next (&slot_hdr, &curr_slot_id, objid, instid)) { + case 0: + /* Found a matching slot. Obsolete it. */ + slot_hdr.state = SLOT_STATE_OBSOLETE; + uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, curr_slot_id); + + if (logfs.driver->write_data(logfs.flash_id, + slot_addr, + (uint8_t *)&slot_hdr, + sizeof(slot_hdr)) != 0) { + rc = -2; + goto out_exit; + } + break; + case -1: + /* Search completed, object not found */ + more = false; + rc = 0; + break; + default: + /* Error occurred during search */ + rc = -1; + goto out_exit; + } + } while (more); + +out_exit: + return rc; +} + +/* NOTE: Must be called while holding the flash transaction lock */ +static int8_t logfs_reserve_free_slot (uint16_t * slot_id, struct slot_header * slot_hdr, uint32_t objid, uint16_t instid, uint16_t objsize) +{ + PIOS_Assert(slot_id); + PIOS_Assert(slot_hdr); + + if (logfs.num_free_slots < 1) { + /* No free slots to allocate */ + return -1; + } + + if (objsize > (logfs.cfg->slot_size - sizeof (slot_hdr))) { + /* This object is too big for the slot */ + return -2; + } + + uint16_t candidate_slot_id = (logfs.cfg->arena_size / logfs.cfg->slot_size) - logfs.num_free_slots; + PIOS_Assert(candidate_slot_id > 0); + + uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, candidate_slot_id); + + if (logfs.driver->read_data(logfs.flash_id, + slot_addr, + (uint8_t *)slot_hdr, + sizeof (*slot_hdr)) != 0) { + /* Failed to read slot header for candidate slot */ + return -3; + } + + if (slot_hdr->state != SLOT_STATE_EMPTY) { + /* Candidate slot isn't empty! Something is broken. */ + PIOS_DEBUG_Assert(0); + return -4; + } + + /* Mark this slot as RESERVED */ + slot_hdr->state = SLOT_STATE_RESERVED; + slot_hdr->objid = objid; + slot_hdr->instid = instid; + slot_hdr->size = objsize; + + if (logfs.driver->write_data(logfs.flash_id, + slot_addr, + (uint8_t *)slot_hdr, + sizeof(*slot_hdr)) != 0) { + /* Failed to write the slot header */ + return -5; + } + + /* FIXME: If the header write (above) failed, may have partially written data, thus corrupting that slot but we would have missed decrementing this counter */ + logfs.num_free_slots--; + + *slot_id = candidate_slot_id; + return 0; +} + +/* NOTE: Must be called while holding the flash transaction lock */ +static int8_t logfs_append_to_log (uint32_t objid, uint16_t instid, uint8_t * data, uint16_t data_len) +{ + /* Reserve a free slot for our new object */ + uint16_t free_slot_id; + struct slot_header slot_hdr; + if (logfs_reserve_free_slot (&free_slot_id, &slot_hdr, objid, instid, data_len) != 0) { + /* Failed to reserve a free slot */ + return -1; + } + + /* Compute slot address */ + uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, free_slot_id); + + /* Write the data into the reserved slot, starting after the slot header */ + uintptr_t slot_offset = sizeof(slot_hdr); + while (data_len > 0) { + /* Individual writes must fit entirely within a single page buffer. */ + uint16_t page_remaining = logfs.cfg->page_size - (slot_offset % logfs.cfg->page_size); + uint16_t write_size = MIN(data_len, page_remaining); + if (logfs.driver->write_data (logfs.flash_id, + slot_addr + slot_offset, + data, + write_size) != 0) { + /* Failed to write the object data to the slot */ + return -2; + } + + /* Update our accounting */ + data += write_size; + slot_offset += write_size; + data_len -= write_size; + } + + /* Mark this slot active in one atomic step */ + slot_hdr.state = SLOT_STATE_ACTIVE; + if (logfs.driver->write_data (logfs.flash_id, + slot_addr, + (uint8_t *)&slot_hdr, + sizeof(slot_hdr)) != 0) { + /* Failed to mark the slot active */ + return -4; + } + + /* Object has been successfully written to the slot */ + logfs.num_active_slots++; + return 0; +} + +/** + * @brief Saves one object instance per sector + * @param[in] obj UAVObjHandle the object to save + * @param[in] instId The instance of the object to save + * @return 0 if success or -1 if failure + */ +int32_t PIOS_FLASHFS_ObjSave(UAVObjHandle obj, uint16_t instid, uint8_t * data) +{ + int8_t rc; + + uint32_t objid = UAVObjGetID(obj); + uint16_t objsize = UAVObjGetNumBytes(obj); + + PIOS_Assert(objsize <= (logfs.cfg->slot_size - sizeof(struct slot_header))); + + if (logfs.driver->start_transaction(logfs.flash_id) != 0) { + rc = -1; + goto out_exit; + } + + if (logfs_delete_object (objid, instid) != 0) { + rc = -2; + goto out_end_trans; + } + + /* + * All old versions of this object + instance have been invalidated. + * Write the new object. + */ + + /* Check if the arena is entirely full. */ + if (logfs_fs_is_full()) { + /* Note: Filesystem Full means we're full of *active* records so gc won't help at all. */ + rc = -3; + goto out_end_trans; + } + + /* Is garbage collection required? */ + if (logfs_log_is_full()) { + /* Note: Log Full means the log is full but may contain obsolete slots so gc may free some space */ + if (logfs_garbage_collect() != 0) { + rc = -4; + goto out_end_trans; + } + /* Check one more time just to be sure we actually free'd some space */ + if (logfs_log_is_full()) { + /* + * Log is still full even after gc! + * NOTE: This should not happen since the filesystem wasn't full + * when we checked above so gc should have helped. + */ + PIOS_DEBUG_Assert(0); + rc = -5; + goto out_end_trans; + } + } + + /* We have room for our new object. Append it to the log. */ + if (logfs_append_to_log(objid, instid, data, objsize) != 0) { + /* Error during append */ + rc = -6; + goto out_end_trans; + } + + /* Object successfully written to the log */ + rc = 0; + +out_end_trans: + logfs.driver->end_transaction(logfs.flash_id); + +out_exit: + return rc; +} + +/** + * @brief Load one object instance per sector + * @param[in] obj UAVObjHandle the object to save + * @param[in] instId The instance of the object to save + * @return 0 if success or error code + * @retval -1 if object not in file table + * @retval -2 if unable to retrieve object header + * @retval -3 if loaded data instId or objId don't match + * @retval -4 if unable to retrieve instance data + * @retval -5 if unable to read CRC + * @retval -6 if CRC doesn't match + */ +int32_t PIOS_FLASHFS_ObjLoad(UAVObjHandle obj, uint16_t instid, uint8_t * data) +{ + int8_t rc; + + uint32_t objid = UAVObjGetID(obj); + uint16_t objsize = UAVObjGetNumBytes(obj); + + PIOS_Assert(objsize <= (logfs.cfg->slot_size - sizeof(struct slot_header))); + + if (logfs.driver->start_transaction(logfs.flash_id) != 0) { + rc = -1; + goto out_exit; + } + + /* Find the object in the log */ + uint16_t slot_id = 0; + struct slot_header slot_hdr; + if (logfs_object_find_next (&slot_hdr, &slot_id, objid, instid) != 0) { + /* Object does not exist in fs */ + rc = -2; + goto out_end_trans; + } + + /* Sanity check what we've found */ + if (slot_hdr.size != objsize) { + /* Object sizes don't match. Not safe to copy contents. */ + rc = -3; + goto out_end_trans; + } + + /* Read the contents of the object from the log */ + uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, slot_id); + if (logfs.driver->read_data(logfs.flash_id, + slot_addr + sizeof(slot_hdr), + (uint8_t *)data, + objsize) != 0) { + /* Failed to read object data from the log */ + rc = -4; + goto out_end_trans; + } + + /* Object successfully loaded */ + rc = 0; + +out_end_trans: + logfs.driver->end_transaction(logfs.flash_id); + +out_exit: + return rc; +} + +/** + * @brief Delete object from flash + * @param[in] obj UAVObjHandle the object to save + * @param[in] instId The instance of the object to save + * @return 0 if success or error code + * @retval -1 if object not in file table + * @retval -2 Erase failed + * @note To avoid buffering the file table (1k ram!) the entry in the file table + * remains but destination sector is erased. This will make the load fail as the + * file header won't match the object. At next save it goes back there. + */ +int32_t PIOS_FLASHFS_ObjDelete(UAVObjHandle obj, uint16_t instid) +{ + int8_t rc; + + uint32_t objid = UAVObjGetID(obj); + uint16_t objsize = UAVObjGetNumBytes(obj); + + PIOS_Assert(objsize <= (logfs.cfg->slot_size - sizeof(struct slot_header))); + + if (logfs.driver->start_transaction(logfs.flash_id) != 0) { + rc = -1; + goto out_exit; + } + + if (logfs_delete_object (objid, instid) != 0) { + rc = -2; + goto out_end_trans; + } + + /* Object successfully deleted from the log */ + rc = 0; + +out_end_trans: + logfs.driver->end_transaction(logfs.flash_id); + +out_exit: + return rc; +} + +int32_t PIOS_FLASHFS_Format() +{ + int32_t rc; + + if (logfs.mounted) { + logfs_unmount_log(); + } + + if (logfs.driver->start_transaction(logfs.flash_id) != 0) { + rc = -1; + goto out_exit; + } + + if (logfs_erase_all_arenas() != 0) { + rc = -2; + goto out_end_trans; + } + + /* Reinitialize arena 0 */ + if (logfs_activate_arena(0) != 0) { + rc = -3; + goto out_end_trans; + } + + /* Mount arena 0 */ + if (logfs_mount_log(0) != 0) { + rc = -4; + goto out_end_trans; + } + + /* Chip erased and log remounted successfully */ + rc = 0; + +out_end_trans: + logfs.driver->end_transaction(logfs.flash_id); + +out_exit: + return rc; +} + +/** + * @} + * @} + */ diff --git a/flight/PiOS/inc/pios_flash.h b/flight/PiOS/inc/pios_flash.h new file mode 100644 index 000000000..7ea28398b --- /dev/null +++ b/flight/PiOS/inc/pios_flash.h @@ -0,0 +1,47 @@ +/** + ****************************************************************************** + * @file pios_flash.h + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_FLASH Flash Driver API Definition + * @{ + * @brief Flash Driver API Definition + *****************************************************************************/ +/* + * 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_FLASH_H_ +#define PIOS_FLASH_H_ + +#include + +struct pios_flash_chunk { + uint8_t * addr; + uint32_t len; +}; + +struct pios_flash_driver { + int32_t (*start_transaction)(uint32_t flash_id); + int32_t (*end_transaction)(uint32_t flash_id); + int32_t (*erase_chip)(uint32_t flash_id); + int32_t (*erase_sector)(uint32_t flash_id, uint32_t addr); + int32_t (*write_data)(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len); + int32_t (*write_chunks)(uint32_t flash_id, uint32_t addr, struct pios_flash_chunk chunks[], uint32_t num_chunks); + int32_t (*read_data)(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len); +}; + +#endif /* PIOS_FLASH_H_ */ diff --git a/flight/PiOS/inc/pios_flash_jedec.h b/flight/PiOS/inc/pios_flash_jedec_priv.h similarity index 56% rename from flight/PiOS/inc/pios_flash_jedec.h rename to flight/PiOS/inc/pios_flash_jedec_priv.h index 4fc5d2fdf..180e929bc 100644 --- a/flight/PiOS/inc/pios_flash_jedec.h +++ b/flight/PiOS/inc/pios_flash_jedec_priv.h @@ -6,45 +6,40 @@ * @addtogroup PIOS_FLASH Flash device handler * @{ * - * @file pios_flash_w25x.h + * @file pios_flash_jedec_priv.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Driver for talking to W25X flash chip (and most JEDEC chips) + * @brief Driver for talking to most JEDEC flash chips * @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 +/* + * 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 + * + * 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., + * + * 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_FLASH_JEDEC_H_ +#define PIOS_FLASH_JEDEC_H_ + +#include "pios_flash.h" /* API definition for flash drivers */ + +extern const struct pios_flash_driver pios_jedec_flash_driver; + struct pios_flash_jedec_cfg { uint32_t sector_erase; uint32_t chip_erase; }; -struct pios_flash_chunk { - uint8_t * addr; - uint32_t len; -}; +int32_t PIOS_Flash_Jedec_Init(uint32_t * flash_id, uint32_t spi_id, uint32_t slave_num, const struct pios_flash_jedec_cfg * cfg); -int32_t PIOS_Flash_Jedec_Init(uint32_t spi_id, uint32_t slave_num, const struct pios_flash_jedec_cfg * cfg); -int32_t PIOS_Flash_Jedec_ReadStatus(); -int32_t PIOS_Flash_Jedec_ReadID(); -int32_t PIOS_Flash_Jedec_EraseChip(); -int32_t PIOS_Flash_Jedec_EraseSector(uint32_t add); -int32_t PIOS_Flash_Jedec_WriteData(uint32_t addr, uint8_t * data, uint16_t len); -int32_t PIOS_Flash_Jedec_ReadData(uint32_t addr, uint8_t * data, uint16_t len); -int32_t PIOS_Flash_Jedec_WriteChunks(uint32_t addr, struct pios_flash_chunk * p_chunk, uint32_t num); -int32_t PIOS_Flash_Jedec_StartTransaction(); -int32_t PIOS_Flash_Jedec_EndTransaction(); +#endif /* PIOS_FLASH_JEDEC_H_ */ diff --git a/flight/PiOS/inc/pios_flashfs_logfs_priv.h b/flight/PiOS/inc/pios_flashfs_logfs_priv.h new file mode 100644 index 000000000..ba1acdf1f --- /dev/null +++ b/flight/PiOS/inc/pios_flashfs_logfs_priv.h @@ -0,0 +1,46 @@ +/** + ****************************************************************************** + * @file pios_flashfs_logfs_priv.h + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_FLASHFS Flash Filesystem Function + * @{ + * @brief Log Structured Filesystem for internal or external NOR Flash + *****************************************************************************/ +/* + * 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_FLASHFS_LOGFS_PRIV_H_ +#define PIOS_FLASHFS_LOGFS_PRIV_H_ + +#include +#include "pios_flash.h" /* struct pios_flash_driver */ + +struct flashfs_logfs_cfg { + uint32_t fs_magic; + uint32_t total_fs_size; /* Total size of all generations of the filesystem */ + uint32_t arena_size; /* Max size of one generation of the filesystem */ + uint32_t slot_size; /* Max size of a "file" */ + + uint32_t start_offset; /* Offset into flash where this filesystem starts */ + uint32_t sector_size; /* Size of a flash erase block */ + uint32_t page_size; /* Maximum flash burst write size */ +}; + +int32_t PIOS_FLASHFS_Logfs_Init(uint32_t * fs_id, const struct flashfs_logfs_cfg * cfg, const struct pios_flash_driver * driver, uint32_t flash_id); + +#endif /* PIOS_FLASHFS_LOGFS_PRIV_H_ */ diff --git a/flight/PiOS/pios.h b/flight/PiOS/pios.h index 2ce7e80ec..4f6a274fd 100644 --- a/flight/PiOS/pios.h +++ b/flight/PiOS/pios.h @@ -3,6 +3,7 @@ * * @file pios.h * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 * @brief Main PiOS header. * - Central header for the project. * @see The GNU Public License (GPL) Version 3 @@ -156,8 +157,8 @@ #endif #if defined(PIOS_INCLUDE_FLASH) -#include -#include +#include +#include #endif #if defined(PIOS_INCLUDE_BL_HELPER) From bcb66764e2f80b021b89dbc824f453d0f3192f29 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Tue, 11 Dec 2012 23:44:12 -0500 Subject: [PATCH 03/33] logfs: use logfs on all targets that have serial flash Conflicts: flight/targets/FlyingF4/Makefile flight/targets/FlyingF4/System/pios_board.c flight/targets/Freedom/Makefile flight/targets/Freedom/System/pios_board.c flight/targets/Quanton/Makefile flight/targets/Quanton/System/pios_board.c flight/targets/board_hw_defs/flyingf4/board_hw_defs.c flight/targets/board_hw_defs/freedom/board_hw_defs.c flight/targets/board_hw_defs/quanton/board_hw_defs.c --- flight/targets/CopterControl/Makefile | 50 ++++++++++--------- .../targets/CopterControl/System/pios_board.c | 49 ++++-------------- flight/targets/RevoMini/Makefile | 22 ++++---- flight/targets/RevoMini/System/pios_board.c | 34 ++++--------- flight/targets/Revolution/Makefile | 22 ++++---- flight/targets/Revolution/System/pios_board.c | 42 ++++++---------- .../coptercontrol/board_hw_defs.c | 50 ++++++++++++++++--- .../board_hw_defs/revolution/board_hw_defs.c | 32 +++++++++--- .../board_hw_defs/revomini/board_hw_defs.c | 32 +++++++++--- 9 files changed, 182 insertions(+), 151 deletions(-) diff --git a/flight/targets/CopterControl/Makefile b/flight/targets/CopterControl/Makefile index a532ce927..2749e6950 100644 --- a/flight/targets/CopterControl/Makefile +++ b/flight/targets/CopterControl/Makefile @@ -1,26 +1,28 @@ - ##### - # Project: OpenPilot - # - # - # Makefile for OpenPilot project build PiOS and the AP. - # - # The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2009. - # - # - # 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 - ##### +############################################################################### +# @file Makefile +# @author The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2009. +# @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 +# @addtogroup +# @{ +# @addtogroup +# @{ +# @brief Makefile to build firmware for the CopterControl board. +############################################################################### +# +# 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 +# WHEREAMI := $(dir $(lastword $(MAKEFILE_LIST))) TOP := $(realpath $(WHEREAMI)/../../../) @@ -253,7 +255,7 @@ SRC += $(PIOSCOMMON)/pios_usb_util.c ## PIOS Hardware (Common) SRC += $(PIOSCOMMON)/pios_crc.c -SRC += $(PIOSCOMMON)/pios_flashfs_objlist.c +SRC += $(PIOSCOMMON)/pios_flashfs_logfs.c SRC += $(PIOSCOMMON)/pios_flash_jedec.c SRC += $(PIOSCOMMON)/pios_adxl345.c SRC += $(PIOSCOMMON)/pios_mpu6000.c diff --git a/flight/targets/CopterControl/System/pios_board.c b/flight/targets/CopterControl/System/pios_board.c index ab624825b..9072f1e84 100644 --- a/flight/targets/CopterControl/System/pios_board.c +++ b/flight/targets/CopterControl/System/pios_board.c @@ -1,15 +1,13 @@ /** - ****************************************************************************** + ***************************************************************************** + * @file pios_board.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 * @addtogroup OpenPilotSystem OpenPilot System * @{ * @addtogroup OpenPilotCore OpenPilot Core * @{ - * - * @file pios_board.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Defines board specific static initializers for hardware for the OpenPilot board. - * @see The GNU Public License (GPL) Version 3 - * + * @brief Defines board specific static initializers for hardware for the CopterControl board. *****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify @@ -124,33 +122,6 @@ static const struct pios_mpu6000_cfg pios_mpu6000_cfg = { }; #endif /* PIOS_INCLUDE_MPU6000 */ -static const struct flashfs_cfg flashfs_w25x_cfg = { - .table_magic = 0x85FB3C35, - .obj_magic = 0x3015AE71, - .obj_table_start = 0x00000010, - .obj_table_end = 0x00001000, - .sector_size = 0x00001000, - .chip_size = 0x00080000, -}; - -static const struct pios_flash_jedec_cfg flash_w25x_cfg = { - .sector_erase = 0x20, - .chip_erase = 0x60 -}; - -static const struct flashfs_cfg flashfs_m25p_cfg = { - .table_magic = 0x85FB3D35, - .obj_magic = 0x3015A371, - .obj_table_start = 0x00000010, - .obj_table_end = 0x00010000, - .sector_size = 0x00010000, - .chip_size = 0x00200000, -}; - -static const struct pios_flash_jedec_cfg flash_m25p_cfg = { - .sector_erase = 0xD8, - .chip_erase = 0xC7 -}; #include /** * PIOS_Board_Init() @@ -191,14 +162,16 @@ void PIOS_Board_Init(void) { #endif + uint32_t flash_id; + uint32_t fs_id; switch(bdinfo->board_rev) { case BOARD_REVISION_CC: - PIOS_Flash_Jedec_Init(pios_spi_flash_accel_id, 1, &flash_w25x_cfg); - PIOS_FLASHFS_Init(&flashfs_w25x_cfg); + PIOS_Flash_Jedec_Init(&flash_id, pios_spi_flash_accel_id, 1, &flash_w25x_cfg); + PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_w25x_cfg, &pios_jedec_flash_driver, flash_id); break; case BOARD_REVISION_CC3D: - PIOS_Flash_Jedec_Init(pios_spi_flash_accel_id, 0, &flash_m25p_cfg); - PIOS_FLASHFS_Init(&flashfs_m25p_cfg); + PIOS_Flash_Jedec_Init(&flash_id, pios_spi_flash_accel_id, 0, &flash_m25p_cfg); + PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_m25p_cfg, &pios_jedec_flash_driver, flash_id); break; default: PIOS_DEBUG_Assert(0); diff --git a/flight/targets/RevoMini/Makefile b/flight/targets/RevoMini/Makefile index 4b54cdd73..964eb27be 100644 --- a/flight/targets/RevoMini/Makefile +++ b/flight/targets/RevoMini/Makefile @@ -1,11 +1,13 @@ -##### -# Project: OpenPilot RevoMini -# -# -# Makefile for OpenPilot RevoMini project -# -# The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2012. -# +############################################################################### +# @file Makefile +# @author The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2012. +# @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 +# @addtogroup +# @{ +# @addtogroup +# @{ +# @brief Makefile to build firmware for the RevoMini board. +############################################################################### # # 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 @@ -20,7 +22,7 @@ # 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 -##### +# WHEREAMI := $(dir $(lastword $(MAKEFILE_LIST))) TOP := $(realpath $(WHEREAMI)/../../../) @@ -163,7 +165,7 @@ SRC += $(PIOSCOMMON)/pios_rfm22b.c SRC += $(PIOSCOMMON)/pios_rcvr.c SRC += $(PIOSCOMMON)/pios_sbus.c SRC += $(PIOSCOMMON)/pios_flash_jedec.c -SRC += $(PIOSCOMMON)/pios_flashfs_objlist.c +SRC += $(PIOSCOMMON)/pios_flashfs_logfs.c SRC += $(PIOSCOMMON)/printf-stdarg.c SRC += $(PIOSCOMMON)/pios_usb_desc_hid_cdc.c SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c diff --git a/flight/targets/RevoMini/System/pios_board.c b/flight/targets/RevoMini/System/pios_board.c index 5e065c348..965b32b36 100644 --- a/flight/targets/RevoMini/System/pios_board.c +++ b/flight/targets/RevoMini/System/pios_board.c @@ -1,15 +1,13 @@ /** ****************************************************************************** - * @addtogroup Revolution Revolution configuration files - * @{ - * @brief Configures the revolution board - * @{ - * * @file pios_board.c * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2011. - * @brief Defines board specific static initializers for hardware for the Revolution board. - * @see The GNU Public License (GPL) Version 3 - * + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @{ + * @brief Defines board specific static initializers for hardware for the revomini board. *****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify @@ -188,20 +186,6 @@ static const struct pios_mpu6000_cfg pios_mpu6000_cfg = { }; #endif /* PIOS_INCLUDE_MPU6000 */ -static const struct flashfs_cfg flashfs_m25p_cfg = { - .table_magic = 0x85FB3D35, - .obj_magic = 0x3015A371, - .obj_table_start = 0x00000010, - .obj_table_end = 0x00010000, - .sector_size = 0x00010000, - .chip_size = 0x00200000, -}; - -static const struct pios_flash_jedec_cfg flash_m25p_cfg = { - .sector_erase = 0xD8, - .chip_erase = 0xC7 -}; - /* One slot per selectable receiver group. * eg. PWM, PPM, GCS, SPEKTRUM1, SPEKTRUM2, SBUS * NOTE: No slot in this map for NONE. @@ -317,8 +301,10 @@ void PIOS_Board_Init(void) { #if defined(PIOS_INCLUDE_FLASH) /* Connect flash to the approrpiate interface and configure it */ - PIOS_Flash_Jedec_Init(pios_spi_telem_flash_id, 1, &flash_m25p_cfg); - PIOS_FLASHFS_Init(&flashfs_m25p_cfg); + uint32_t flash_id; + PIOS_Flash_Jedec_Init(&flash_id, pios_spi_telem_flash_id, 1, &flash_m25p_cfg); + uint32_t fs_id; + PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_m25p_cfg, &pios_jedec_flash_driver, flash_id); #endif /* Initialize UAVObject libraries */ diff --git a/flight/targets/Revolution/Makefile b/flight/targets/Revolution/Makefile index 3d8a8ad1e..9e6c28044 100644 --- a/flight/targets/Revolution/Makefile +++ b/flight/targets/Revolution/Makefile @@ -1,11 +1,13 @@ -##### -# Project: OpenPilot INS -# -# -# Makefile for OpenPilot INS project -# -# The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2009. -# +############################################################################### +# @file Makefile +# @author The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2009. +# @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 +# @addtogroup +# @{ +# @addtogroup +# @{ +# @brief Makefile to build firmware for the Revolution board. +############################################################################### # # 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 @@ -20,7 +22,7 @@ # 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 -##### +# WHEREAMI := $(dir $(lastword $(MAKEFILE_LIST))) TOP := $(realpath $(WHEREAMI)/../../../) @@ -177,7 +179,7 @@ SRC += $(PIOSCOMMON)/pios_com.c SRC += $(PIOSCOMMON)/pios_rcvr.c SRC += $(PIOSCOMMON)/pios_sbus.c SRC += $(PIOSCOMMON)/pios_flash_jedec.c -SRC += $(PIOSCOMMON)/pios_flashfs_objlist.c +SRC += $(PIOSCOMMON)/pios_flashfs_logfs.c SRC += $(PIOSCOMMON)/printf-stdarg.c SRC += $(PIOSCOMMON)/pios_usb_desc_hid_cdc.c SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c diff --git a/flight/targets/Revolution/System/pios_board.c b/flight/targets/Revolution/System/pios_board.c index 37c9810b3..18a49bdd7 100644 --- a/flight/targets/Revolution/System/pios_board.c +++ b/flight/targets/Revolution/System/pios_board.c @@ -1,15 +1,13 @@ /** - ****************************************************************************** - * @addtogroup Revolution Revolution configuration files - * @{ - * @brief Configures the revolution board - * @{ - * + ***************************************************************************** * @file pios_board.c * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2011. - * @brief Defines board specific static initializers for hardware for the Revolution board. - * @see The GNU Public License (GPL) Version 3 - * + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotCore OpenPilot Core + * @{ + * @brief Defines board specific static initializers for hardware for the revolution board. *****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify @@ -271,21 +269,6 @@ static const struct pios_l3gd20_cfg pios_l3gd20_cfg = { }; #endif /* PIOS_INCLUDE_L3GD20 */ - -static const struct flashfs_cfg flashfs_m25p_cfg = { - .table_magic = 0x85FB3D35, - .obj_magic = 0x3015A371, - .obj_table_start = 0x00000010, - .obj_table_end = 0x00010000, - .sector_size = 0x00010000, - .chip_size = 0x00200000, -}; - -static const struct pios_flash_jedec_cfg flash_m25p_cfg = { - .sector_erase = 0xD8, - .chip_erase = 0xC7 -}; - /* One slot per selectable receiver group. * eg. PWM, PPM, GCS, SPEKTRUM1, SPEKTRUM2, SBUS * NOTE: No slot in this map for NONE. @@ -398,11 +381,16 @@ void PIOS_Board_Init(void) { if (PIOS_SPI_Init(&pios_spi_flash_id, &pios_spi_flash_cfg)) { PIOS_DEBUG_Assert(0); } - PIOS_Flash_Jedec_Init(pios_spi_flash_id, 0, &flash_m25p_cfg); + /* Connect flash to the approrpiate interface and configure it */ + uint32_t flash_id; + PIOS_Flash_Jedec_Init(&flash_id, pios_spi_flash_id, 0, &flash_m25p_cfg); #else - PIOS_Flash_Jedec_Init(pios_spi_accel_id, 1, &flash_m25p_cfg); + /* Connect flash to the approrpiate interface and configure it */ + uint32_t flash_id; + PIOS_Flash_Jedec_Init(&flash_id, pios_spi_accel_id, 1, &flash_m25p_cfg); #endif - PIOS_FLASHFS_Init(&flashfs_m25p_cfg); + uint32_t fs_id; + PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_m25p_cfg, &pios_jedec_flash_driver, flash_id); /* Initialize UAVObject libraries */ EventDispatcherInitialize(); diff --git a/flight/targets/board_hw_defs/coptercontrol/board_hw_defs.c b/flight/targets/board_hw_defs/coptercontrol/board_hw_defs.c index 403657199..fdd95a1e5 100644 --- a/flight/targets/board_hw_defs/coptercontrol/board_hw_defs.c +++ b/flight/targets/board_hw_defs/coptercontrol/board_hw_defs.c @@ -1,15 +1,13 @@ /** ****************************************************************************** + * @file board_hw_defs.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 * @addtogroup OpenPilotSystem OpenPilot System * @{ * @addtogroup OpenPilotCore OpenPilot Core * @{ - * - * @file board_hw_defs.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. - * @brief Defines board specific static initializers for hardware for the OpenPilot board. - * @see The GNU Public License (GPL) Version 3 - * + * @brief Defines board specific static initializers for hardware for the CopterControl board. *****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify @@ -401,6 +399,46 @@ void PIOS_SPI_flash_accel_irq_handler(void) #endif /* PIOS_INCLUDE_SPI */ +#if defined(PIOS_INCLUDE_FLASH) +#include "pios_flashfs_logfs_priv.h" +#include "pios_flash_jedec_priv.h" + +static const struct flashfs_logfs_cfg flashfs_w25x_cfg = { + .fs_magic = 0x89abcdef, + .total_fs_size = 0x00080000, /* 512K bytes (128 sectors = entire chip) */ + .arena_size = 0x00010000, /* 256 * slot size */ + .slot_size = 0x00000100, /* 256 bytes */ + + .start_offset = 0, /* start at the beginning of the chip */ + .sector_size = 0x00001000, /* 4K bytes */ + .page_size = 0x00000100, /* 256 bytes */ +}; + +static const struct pios_flash_jedec_cfg flash_w25x_cfg = { + .sector_erase = 0x20, + .chip_erase = 0x60 +}; + +static const struct flashfs_logfs_cfg flashfs_m25p_cfg = { + .fs_magic = 0x89abceef, + .total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */ + .arena_size = 0x00010000, /* 256 * slot size */ + .slot_size = 0x00000100, /* 256 bytes */ + + .start_offset = 0, /* start at the beginning of the chip */ + .sector_size = 0x00010000, /* 64K bytes */ + .page_size = 0x00000100, /* 256 bytes */ +}; + +static const struct pios_flash_jedec_cfg flash_m25p_cfg = { + .sector_erase = 0xD8, + .chip_erase = 0xC7 +}; + +#include "pios_flash.h" + +#endif /* PIOS_INCLUDE_FLASH */ + /* * ADC system */ diff --git a/flight/targets/board_hw_defs/revolution/board_hw_defs.c b/flight/targets/board_hw_defs/revolution/board_hw_defs.c index 7df06e4e9..f6d3560ca 100644 --- a/flight/targets/board_hw_defs/revolution/board_hw_defs.c +++ b/flight/targets/board_hw_defs/revolution/board_hw_defs.c @@ -1,15 +1,13 @@ /** ****************************************************************************** + * @file board_hw_defs.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 * @addtogroup OpenPilotSystem OpenPilot System * @{ * @addtogroup OpenPilotCore OpenPilot Core * @{ - * - * @file board_hw_defs.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. - * @brief Defines board specific static initializers for hardware for the OpenPilot board. - * @see The GNU Public License (GPL) Version 3 - * + * @brief Defines board specific static initializers for hardware for the Revolution board. *****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify @@ -449,6 +447,28 @@ void PIOS_SPI_flash_irq_handler(void) #endif /* PIOS_INCLUDE_SPI */ +#if defined(PIOS_INCLUDE_FLASH) +#include "pios_flashfs_logfs_priv.h" +#include "pios_flash_jedec_priv.h" + +static const struct flashfs_logfs_cfg flashfs_m25p_cfg = { + .fs_magic = 0x89abceef, + .total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */ + .arena_size = 0x00010000, /* 256 * slot size */ + .slot_size = 0x00000100, /* 256 bytes */ + + .start_offset = 0, /* start at the beginning of the chip */ + .sector_size = 0x00010000, /* 64K bytes */ + .page_size = 0x00000100, /* 256 bytes */ +}; + +static const struct pios_flash_jedec_cfg flash_m25p_cfg = { + .sector_erase = 0xD8, + .chip_erase = 0xC7 +}; + +#endif /* PIOS_INCLUDE_FLASH */ + #if defined(PIOS_OVERO_SPI) /* SPI3 Interface * - Used for flash communications diff --git a/flight/targets/board_hw_defs/revomini/board_hw_defs.c b/flight/targets/board_hw_defs/revomini/board_hw_defs.c index bb65069cf..41a56894b 100644 --- a/flight/targets/board_hw_defs/revomini/board_hw_defs.c +++ b/flight/targets/board_hw_defs/revomini/board_hw_defs.c @@ -1,15 +1,13 @@ /** ****************************************************************************** + * @file board_hw_defs.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 * @addtogroup OpenPilotSystem OpenPilot System * @{ * @addtogroup OpenPilotCore OpenPilot Core * @{ - * - * @file board_hw_defs.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012. - * @brief Defines board specific static initializers for hardware for the OpenPilot board. - * @see The GNU Public License (GPL) Version 3 - * + * @brief Defines board specific static initializers for hardware for the RevoMini board. *****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify @@ -564,6 +562,28 @@ const struct pios_rfm22b_cfg * PIOS_BOARD_HW_DEFS_GetRfm22Cfg (uint32_t board_re #endif /* PIOS_INCLUDE_SPI */ +#if defined(PIOS_INCLUDE_FLASH) +#include "pios_flashfs_logfs_priv.h" +#include "pios_flash_jedec_priv.h" + +static const struct flashfs_logfs_cfg flashfs_m25p_cfg = { + .fs_magic = 0x89abceef, + .total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */ + .arena_size = 0x00010000, /* 256 * slot size */ + .slot_size = 0x00000100, /* 256 bytes */ + + .start_offset = 0, /* start at the beginning of the chip */ + .sector_size = 0x00010000, /* 64K bytes */ + .page_size = 0x00000100, /* 256 bytes */ +}; + +static const struct pios_flash_jedec_cfg flash_m25p_cfg = { + .sector_erase = 0xD8, + .chip_erase = 0xC7 +}; + +#endif /* PIOS_INCLUDE_FLASH */ + #include #ifdef PIOS_INCLUDE_COM_TELEM From d89a9b1b6cd9372eac1a20cb23fd9de144d125eb Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 2 Dec 2012 03:29:15 -0500 Subject: [PATCH 04/33] objlist: remove now unused objlist flash filesystem Conflicts: flight/PiOS/inc/pios_flashfs_objlist.h --- flight/PiOS/Common/pios_flashfs_objlist.c | 402 ---------------------- flight/PiOS/inc/pios_flashfs_objlist.h | 47 --- 2 files changed, 449 deletions(-) delete mode 100644 flight/PiOS/Common/pios_flashfs_objlist.c delete mode 100644 flight/PiOS/inc/pios_flashfs_objlist.h diff --git a/flight/PiOS/Common/pios_flashfs_objlist.c b/flight/PiOS/Common/pios_flashfs_objlist.c deleted file mode 100644 index 4111eb029..000000000 --- a/flight/PiOS/Common/pios_flashfs_objlist.c +++ /dev/null @@ -1,402 +0,0 @@ -/** - ****************************************************************************** - * - * @addtogroup PIOS PIOS Core hardware abstraction layer - * @{ - * @addtogroup PIOS_FLASHFS_OBJLIST Object list based flash filesystem (low ram) - * @{ - * - * @file pios_flashfs_objlist.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief A file system for storing UAVObject in flash chip - * @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 - */ - - -#include "openpilot.h" -#include "uavobjectmanager.h" - -// Private functions -static int32_t PIOS_FLASHFS_ClearObjectTableHeader(); -static int32_t PIOS_FLASHFS_GetObjAddress(uint32_t objId, uint16_t instId); -static int32_t PIOS_FLASHFS_GetNewAddress(uint32_t objId, uint16_t instId); - -// Private variables -static int32_t numObjects = -1; - -// Private structures -// Header for objects in the file system table -struct objectHeader { - uint32_t objMagic; - uint32_t objId; - uint32_t instId; - uint32_t address; -} __attribute__((packed));; - -struct fileHeader { - uint32_t id; - uint16_t instId; - uint16_t size; -} __attribute__((packed)); - - -#define MAX_BADMAGIC 1000 - -static const struct flashfs_cfg * cfg; -/** - * @brief Initialize the flash object setting FS - * @return 0 if success, -1 if failure - */ -int32_t PIOS_FLASHFS_Init(const struct flashfs_cfg * new_cfg) -{ - cfg = new_cfg; - - // Check for valid object table or create one - uint32_t object_table_magic; - uint32_t magic_fail_count = 0; - bool magic_good = false; - - while(!magic_good) { - if (PIOS_Flash_Jedec_ReadData(0, (uint8_t *)&object_table_magic, sizeof(object_table_magic)) != 0) - return -1; - if(object_table_magic != new_cfg->table_magic) { - if(magic_fail_count++ > MAX_BADMAGIC) { - if(PIOS_FLASHFS_Format() != 0) - return -1; -#if defined(PIOS_LED_HEARTBEAT) - PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); -#endif /* PIOS_LED_HEARTBEAT */ - magic_fail_count = 0; - magic_good = true; - } else { - PIOS_DELAY_WaituS(1000); - } - } - else { - magic_good = true; - } - - } - - int32_t addr = cfg->obj_table_start; - struct objectHeader header; - numObjects = 0; - - // Loop through header area while objects detect to count how many saved - while(addr < cfg->obj_table_end) { - // Read the instance data - if (PIOS_Flash_Jedec_ReadData(addr, (uint8_t *)&header, sizeof(header)) != 0) - return -1; - - // Counting number of valid headers - if(header.objMagic != cfg->obj_magic) - break; - - numObjects++; - addr += sizeof(header); - } - - return 0; -} - -/** - * @brief Erase the whole flash chip and create the file system - * @return 0 if successful, -1 if not - */ -int32_t PIOS_FLASHFS_Format() -{ - if(PIOS_Flash_Jedec_EraseChip() != 0) - return -1; - if(PIOS_FLASHFS_ClearObjectTableHeader() != 0) - return -1; - return 0; -} - -/** - * @brief Erase the headers for all objects in the flash chip - * @return 0 if successful, -1 if not - */ -static int32_t PIOS_FLASHFS_ClearObjectTableHeader() -{ - if(PIOS_Flash_Jedec_EraseSector(0) != 0) - return -1; - - if (PIOS_Flash_Jedec_WriteData(0, (uint8_t *)&cfg->table_magic, sizeof(cfg->table_magic)) != 0) - return -1; - - uint32_t object_table_magic; - PIOS_Flash_Jedec_ReadData(0, (uint8_t *)&object_table_magic, sizeof(object_table_magic)); - if(object_table_magic != cfg->table_magic) - return -1; - - return 0; -} - -/** - * @brief Get the address of an object - * @param obj UAVObjHandle for that object - * @parma instId Instance id for that object - * @return address if successful, -1 if not found - */ -static int32_t PIOS_FLASHFS_GetObjAddress(uint32_t objId, uint16_t instId) -{ - int32_t addr = cfg->obj_table_start; - struct objectHeader header; - - // Loop through header area while objects detect to count how many saved - while(addr < cfg->obj_table_end) { - // Read the instance data - if (PIOS_Flash_Jedec_ReadData(addr, (uint8_t *) &header, sizeof(header)) != 0) - return -1; - if(header.objMagic != cfg->obj_magic) - break; // stop searching once hit first non-object header - else if (header.objId == objId && header.instId == instId) - break; - addr += sizeof(header); - } - - if (header.objId == objId && header.instId == instId) - return header.address; - - return -1; -} - -/** - * @brief Returns an address for a new object and creates entry into object table - * @param[in] obj Object handle for object to be saved - * @param[in] instId The instance id of object to be saved - * @return 0 if success or error code - * @retval -1 Object not found - * @retval -2 No room in object table - * @retval -3 Unable to write entry into object table - * @retval -4 FS not initialized - * @retval -5 - */ -int32_t PIOS_FLASHFS_GetNewAddress(uint32_t objId, uint16_t instId) -{ - struct objectHeader header; - - if(numObjects < 0) - return -4; - - // Don't worry about max size of flash chip here, other code will catch that - header.objMagic = cfg->obj_magic; - header.objId = objId; - header.instId = instId; - header.address = cfg->obj_table_end + cfg->sector_size * numObjects; - - int32_t addr = cfg->obj_table_start + sizeof(header) * numObjects; - - // No room for this header in object table - if((addr + sizeof(header)) > cfg->obj_table_end) - return -2; - - // Verify the address is within the chip - if((addr + cfg->sector_size) > cfg->chip_size) - return -5; - - if(PIOS_Flash_Jedec_WriteData(addr, (uint8_t *) &header, sizeof(header)) != 0) - return -3; - - // This numObejcts value must stay consistent or there will be a break in the table - // and later the table will have bad values in it - numObjects++; - return header.address; -} - - -/** - * @brief Saves one object instance per sector - * @param[in] obj UAVObjHandle the object to save - * @param[in] instId The instance of the object to save - * @return 0 if success or -1 if failure - * @note This uses one sector on the flash chip per object so that no buffering in ram - * must be done when erasing the sector before a save - */ -int32_t PIOS_FLASHFS_ObjSave(UAVObjHandle obj, uint16_t instId, uint8_t * data) -{ - uint32_t objId = UAVObjGetID(obj); - uint8_t crc = 0; - - if(PIOS_Flash_Jedec_StartTransaction() != 0) - return -1; - - int32_t addr = PIOS_FLASHFS_GetObjAddress(objId, instId); - - // Object currently not saved - if(addr < 0) - addr = PIOS_FLASHFS_GetNewAddress(objId, instId); - - // Could not allocate a sector - if(addr < 0) { - PIOS_Flash_Jedec_EndTransaction(); - return -1; - } - - struct fileHeader header = { - .id = objId, - .instId = instId, - .size = UAVObjGetNumBytes(obj) - }; - - // Update CRC - crc = PIOS_CRC_updateCRC(0, (uint8_t *) &header, sizeof(header)); - crc = PIOS_CRC_updateCRC(crc, (uint8_t *) data, UAVObjGetNumBytes(obj)); - - if(PIOS_Flash_Jedec_EraseSector(addr) != 0) { - PIOS_Flash_Jedec_EndTransaction(); - return -2; - } - - struct pios_flash_chunk chunks[3] = { - { - .addr = (uint8_t *) &header, - .len = sizeof(header), - }, - { - .addr = (uint8_t *) data, - .len = UAVObjGetNumBytes(obj) - }, - { - .addr = (uint8_t *) &crc, - .len = sizeof(crc) - } - }; - - if(PIOS_Flash_Jedec_WriteChunks(addr, chunks, NELEMENTS(chunks)) != 0) { - PIOS_Flash_Jedec_EndTransaction(); - return -1; - } - - if(PIOS_Flash_Jedec_EndTransaction() != 0) { - PIOS_Flash_Jedec_EndTransaction(); - return -1; - } - - return 0; -} - -/** - * @brief Load one object instance per sector - * @param[in] obj UAVObjHandle the object to save - * @param[in] instId The instance of the object to save - * @return 0 if success or error code - * @retval -1 if object not in file table - * @retval -2 if unable to retrieve object header - * @retval -3 if loaded data instId or objId don't match - * @retval -4 if unable to retrieve instance data - * @retval -5 if unable to read CRC - * @retval -6 if CRC doesn't match - * @note This uses one sector on the flash chip per object so that no buffering in ram - * must be done when erasing the sector before a save - */ -int32_t PIOS_FLASHFS_ObjLoad(UAVObjHandle obj, uint16_t instId, uint8_t * data) -{ - uint32_t objId = UAVObjGetID(obj); - uint16_t objSize = UAVObjGetNumBytes(obj); - uint8_t crc = 0; - uint8_t crcFlash = 0; - const uint8_t crc_read_step = 8; - uint8_t crc_read_buffer[crc_read_step]; - - if(PIOS_Flash_Jedec_StartTransaction() != 0) - return -1; - - int32_t addr = PIOS_FLASHFS_GetObjAddress(objId, instId); - - // Object currently not saved - if(addr < 0) { - PIOS_Flash_Jedec_EndTransaction(); - return -1; - } - - struct fileHeader header; - - // Load header - // This information IS redundant with the object table id. Oh well. Better safe than sorry. - if(PIOS_Flash_Jedec_ReadData(addr, (uint8_t *) &header, sizeof(header)) != 0) { - PIOS_Flash_Jedec_EndTransaction(); - return -2; - } - - // Update CRC - crc = PIOS_CRC_updateCRC(0, (uint8_t *) &header, sizeof(header)); - - if((header.id != objId) || (header.instId != instId)) { - PIOS_Flash_Jedec_EndTransaction(); - return -3; - } - - // To avoid having to allocate the RAM for a copy of the object, we read by chunks - // and compute the CRC - for(uint32_t i = 0; i < objSize; i += crc_read_step) { - PIOS_Flash_Jedec_ReadData(addr + sizeof(header) + i, crc_read_buffer, crc_read_step); - uint8_t valid_bytes = ((i + crc_read_step) >= objSize) ? objSize - i : crc_read_step; - crc = PIOS_CRC_updateCRC(crc, crc_read_buffer, valid_bytes); - } - - // Read CRC (written so will work when CRC changes to uint16) - if(PIOS_Flash_Jedec_ReadData(addr + sizeof(header) + objSize, (uint8_t *) &crcFlash, sizeof(crcFlash)) != 0) { - PIOS_Flash_Jedec_EndTransaction(); - return -5; - } - - if(crc != crcFlash) { - PIOS_Flash_Jedec_EndTransaction(); - return -6; - } - - // Read the instance data - if (PIOS_Flash_Jedec_ReadData(addr + sizeof(header), data, objSize) != 0) { - PIOS_Flash_Jedec_EndTransaction(); - return -4; - } - - if(PIOS_Flash_Jedec_EndTransaction() != 0) - return -1; - - return 0; -} - -/** - * @brief Delete object from flash - * @param[in] obj UAVObjHandle the object to save - * @param[in] instId The instance of the object to save - * @return 0 if success or error code - * @retval -1 if object not in file table - * @retval -2 Erase failed - * @note To avoid buffering the file table (1k ram!) the entry in the file table - * remains but destination sector is erased. This will make the load fail as the - * file header won't match the object. At next save it goes back there. - */ -int32_t PIOS_FLASHFS_ObjDelete(UAVObjHandle obj, uint16_t instId) -{ - uint32_t objId = UAVObjGetID(obj); - - int32_t addr = PIOS_FLASHFS_GetObjAddress(objId, instId); - - // Object currently not saved - if(addr < 0) - return -1; - - if(PIOS_Flash_Jedec_EraseSector(addr) != 0) - return -2; - - return 0; -} diff --git a/flight/PiOS/inc/pios_flashfs_objlist.h b/flight/PiOS/inc/pios_flashfs_objlist.h deleted file mode 100644 index a330da230..000000000 --- a/flight/PiOS/inc/pios_flashfs_objlist.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - ****************************************************************************** - * - * @addtogroup PIOS PIOS Core hardware abstraction layer - * @{ - * @addtogroup PIOS_FLASHFS_OBJLIST Object list based flash filesystem (low ram) - * @{ - * - * @file pios_flashfs_objlist.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief A file system for storing UAVObject in flash chip - * @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 - */ - -#include "openpilot.h" -#include "uavobjectmanager.h" - -struct flashfs_cfg { - uint32_t table_magic; - uint32_t obj_magic; - uint32_t obj_table_start; - uint32_t obj_table_end; - uint32_t sector_size; - uint32_t chip_size; -}; - -int32_t PIOS_FLASHFS_Init(const struct flashfs_cfg * cfg); -int32_t PIOS_FLASHFS_Format(); -int32_t PIOS_FLASHFS_ObjSave(UAVObjHandle obj, uint16_t instId, uint8_t * data); -int32_t PIOS_FLASHFS_ObjLoad(UAVObjHandle obj, uint16_t instId, uint8_t * data); -int32_t PIOS_FLASHFS_ObjDelete(UAVObjHandle obj, uint16_t instId); From d2a3f254bc5d7243914d209b9f13c72b3d68236b Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Wed, 12 Dec 2012 01:01:25 -0500 Subject: [PATCH 05/33] stmflash: add flash driver for internal flash in STM32 --- flight/PiOS/STM32F4xx/pios_flash_internal.c | 337 ++++++++++++++++++++ flight/PiOS/inc/pios_flash_internal_priv.h | 40 +++ 2 files changed, 377 insertions(+) create mode 100644 flight/PiOS/STM32F4xx/pios_flash_internal.c create mode 100644 flight/PiOS/inc/pios_flash_internal_priv.h diff --git a/flight/PiOS/STM32F4xx/pios_flash_internal.c b/flight/PiOS/STM32F4xx/pios_flash_internal.c new file mode 100644 index 000000000..c86cb7211 --- /dev/null +++ b/flight/PiOS/STM32F4xx/pios_flash_internal.c @@ -0,0 +1,337 @@ +/** + ****************************************************************************** + * @file pios_flash_internal.c + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 + * @addtogroup + * @{ + * @addtogroup + * @{ + * @brief Provides a flash driver for the STM32 internal flash sectors + *****************************************************************************/ +/* + * 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 + */ + +#include "pios.h" + +#if defined(PIOS_INCLUDE_FLASH_INTERNAL) + +#include "stm32f4xx_flash.h" +#include "pios_flash_internal_priv.h" +#include "pios_flash.h" +#include + +struct device_flash_sector { + uint32_t start; + uint32_t size; + uint16_t st_sector; +}; + +static struct device_flash_sector flash_sectors[] = { + [0] = { + .start = 0x08000000, + .size = 16 * 1024, + .st_sector = FLASH_Sector_0, + }, + [1] = { + .start = 0x08004000, + .size = 16 * 1024, + .st_sector = FLASH_Sector_1, + }, + [2] = { + .start = 0x08008000, + .size = 16 * 1024, + .st_sector = FLASH_Sector_2, + }, + [3] = { + .start = 0x0800C000, + .size = 16 * 1024, + .st_sector = FLASH_Sector_3, + }, + [4] = { + .start = 0x08010000, + .size = 64 * 1024, + .st_sector = FLASH_Sector_4, + }, + [5] = { + .start = 0x08020000, + .size = 128 * 1024, + .st_sector = FLASH_Sector_5, + }, + [6] = { + .start = 0x08040000, + .size = 128 * 1024, + .st_sector = FLASH_Sector_6, + }, + [7] = { + .start = 0x08060000, + .size = 128 * 1024, + .st_sector = FLASH_Sector_7, + }, + [8] = { + .start = 0x08080000, + .size = 128 * 1024, + .st_sector = FLASH_Sector_8, + }, + [9] = { + .start = 0x080A0000, + .size = 128 * 1024, + .st_sector = FLASH_Sector_9, + }, + [10] = { + .start = 0x080C0000, + .size = 128 * 1024, + .st_sector = FLASH_Sector_10, + }, + [11] = { + .start = 0x080E0000, + .size = 128 * 1024, + .st_sector = FLASH_Sector_11, + }, +}; + +static bool PIOS_Flash_Internal_GetSectorInfo(uint32_t address, uint8_t * sector_number, uint32_t *sector_start, uint32_t *sector_size) +{ + for (uint8_t i = 0; i < NELEMENTS(flash_sectors); i++) { + struct device_flash_sector * sector = &flash_sectors[i]; + if ((address >= sector->start) && + (address < (sector->start + sector->size))) { + /* address lies within this sector */ + *sector_number = sector->st_sector; + *sector_start = sector->start; + *sector_size = sector->size; + return (true); + } + } + + return (false); +} + +enum pios_internal_flash_dev_magic { + PIOS_INTERNAL_FLASH_DEV_MAGIC = 0x33445902, +}; + +struct pios_internal_flash_dev { + enum pios_internal_flash_dev_magic magic; + +#if defined(PIOS_INCLUDE_FREERTOS) + xSemaphoreHandle transaction_lock; +#endif /* defined(PIOS_INCLUDE_FREERTOS) */ +}; + +static bool PIOS_Flash_Internal_Validate(struct pios_internal_flash_dev * flash_dev) { + return (flash_dev && (flash_dev->magic == PIOS_INTERNAL_FLASH_DEV_MAGIC)); +} + +#if defined(PIOS_INCLUDE_FREERTOS) +static struct pios_internal_flash_dev * PIOS_Flash_Internal_alloc(void) +{ + struct pios_internal_flash_dev * flash_dev; + + flash_dev = (struct pios_internal_flash_dev *)pvPortMalloc(sizeof(* flash_dev)); + if (!flash_dev) return (NULL); + + flash_dev->magic = PIOS_INTERNAL_FLASH_DEV_MAGIC; + + return(flash_dev); +} +#else +static struct pios_internal_flash_dev pios_internal_flash_devs[PIOS_INTERNAL_FLASH_MAX_DEVS]; +static uint8_t pios_internal_flash_num_devs; +static struct pios_internal_flash_dev * PIOS_Flash_Internal_alloc(void) +{ + struct pios_internal_flash_dev * flash_dev; + + if (pios_internal_flash_num_devs >= PIOS_INTERNAL_FLASH_MAX_DEVS) { + return (NULL); + } + + flash_dev = &pios_internal_flash_devs[pios_internal_flash_num_devs++]; + flash_dev->magic = PIOS_INTERNAL_FLASH_DEV_MAGIC; + + return (flash_dev); +} + +#endif /* defined(PIOS_INCLUDE_FREERTOS) */ + +int32_t PIOS_Flash_Internal_Init(uint32_t * flash_id, const struct pios_flash_internal_cfg * cfg) +{ + struct pios_internal_flash_dev * flash_dev; + + flash_dev = PIOS_Flash_Internal_alloc(); + if (flash_dev == NULL) + return -1; + +#if defined(PIOS_INCLUDE_FREERTOS) + flash_dev->transaction_lock = xSemaphoreCreateMutex(); +#endif /* defined(PIOS_INCLUDE_FREERTOS) */ + + *flash_id = (uint32_t) flash_dev; + + return 0; +} + +/********************************** + * + * Provide a PIOS flash driver API + * + *********************************/ +#include "pios_flash.h" + +static int32_t PIOS_Flash_Internal_StartTransaction(uint32_t flash_id) +{ + struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id; + + if (!PIOS_Flash_Internal_Validate(flash_dev)) + return -1; + +#if defined(PIOS_INCLUDE_FREERTOS) + if (xSemaphoreTake(flash_dev->transaction_lock, portMAX_DELAY) != pdTRUE) + return -2; +#endif /* defined(PIOS_INCLUDE_FREERTOS) */ + + /* Unlock the internal flash so we can write to it */ + FLASH_Unlock(); + return 0; +} + +static int32_t PIOS_Flash_Internal_EndTransaction(uint32_t flash_id) +{ + struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id; + + if (!PIOS_Flash_Internal_Validate(flash_dev)) + return -1; + +#if defined(PIOS_INCLUDE_FREERTOS) + if (xSemaphoreGive(flash_dev->transaction_lock) != pdTRUE) + return -2; +#endif /* defined(PIOS_INCLUDE_FREERTOS) */ + + /* Lock the internal flash again so we can no longer write to it */ + FLASH_Lock(); + + return 0; +} + +static int32_t PIOS_Flash_Internal_EraseSector(uint32_t flash_id, uint32_t addr) +{ + struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id; + + if (!PIOS_Flash_Internal_Validate(flash_dev)) + return -1; + + uint8_t sector_number; + uint32_t sector_start; + uint32_t sector_size; + if (!PIOS_Flash_Internal_GetSectorInfo(addr, + §or_number, + §or_start, + §or_size)) { + /* We're asking for an invalid flash address */ + return -2; + } + + if (FLASH_EraseSector(sector_number, VoltageRange_3) != FLASH_COMPLETE) + return -3; + + return 0; +} + +static int32_t PIOS_Flash_Internal_WriteData(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) +{ + PIOS_Assert(data); + + struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id; + + if (!PIOS_Flash_Internal_Validate(flash_dev)) + return -1; + + uint8_t sector_number; + uint32_t sector_start; + uint32_t sector_size; + + /* Ensure that the base address is in a valid sector */ + if (!PIOS_Flash_Internal_GetSectorInfo(addr, + §or_number, + §or_start, + §or_size)) { + /* We're asking for an invalid flash address */ + return -2; + } + + /* Ensure that the entire write occurs within the same sector */ + if ((uintptr_t)addr + len > sector_start + sector_size) { + /* Write crosses the end of the sector */ + return -3; + } + + /* Write the data */ + for (uint16_t i = 0; i < len; i++) { + FLASH_Status status; + /* + * This is inefficient. Should try to do word writes. + * Not sure if word writes need to be aligned though. + */ + status = FLASH_ProgramByte(addr + i, data[i]); + PIOS_Assert(status == FLASH_COMPLETE); + } + + return 0; +} + +static int32_t PIOS_Flash_Internal_ReadData(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) +{ + PIOS_Assert(data); + + struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id; + + if (!PIOS_Flash_Internal_Validate(flash_dev)) + return -1; + + uint8_t sector_number; + uint32_t sector_start; + uint32_t sector_size; + + /* Ensure that the base address is in a valid sector */ + if (!PIOS_Flash_Internal_GetSectorInfo(addr, + §or_number, + §or_start, + §or_size)) { + /* We're asking for an invalid flash address */ + return -2; + } + + /* Ensure that the entire read occurs within the same sector */ + if ((uintptr_t)addr + len > sector_start + sector_size) { + /* Read crosses the end of the sector */ + return -3; + } + + /* Read the data into the buffer directly */ + memcpy(data, (void *)addr, len); + + return 0; +} + +/* Provide a flash driver to external drivers */ +const struct pios_flash_driver pios_internal_flash_driver = { + .start_transaction = PIOS_Flash_Internal_StartTransaction, + .end_transaction = PIOS_Flash_Internal_EndTransaction, + .erase_sector = PIOS_Flash_Internal_EraseSector, + .write_data = PIOS_Flash_Internal_WriteData, + .read_data = PIOS_Flash_Internal_ReadData, +}; + +#endif /* defined(PIOS_INCLUDE_FLASH_INTERNAL) */ diff --git a/flight/PiOS/inc/pios_flash_internal_priv.h b/flight/PiOS/inc/pios_flash_internal_priv.h new file mode 100644 index 000000000..b17682ae4 --- /dev/null +++ b/flight/PiOS/inc/pios_flash_internal_priv.h @@ -0,0 +1,40 @@ +/** + ****************************************************************************** + * @file pios_flash_internal_priv.h + * @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 + * @addtogroup + * @{ + * @addtogroup + * @{ + * @brief Provides a flash driver for the STM32 internal flash sectors + *****************************************************************************/ +/* + * 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_FLASH_INTERNAL_H_ +#define PIOS_FLASH_INTERNAL_H_ + +#include "pios_flash.h" /* API definition for flash drivers */ + +extern const struct pios_flash_driver pios_internal_flash_driver; + +struct pios_flash_internal_cfg { + ; +}; + +extern int32_t PIOS_Flash_Internal_Init(uint32_t * flash_id, const struct pios_flash_internal_cfg * cfg); + +#endif /* PIOS_FLASH_INTERNAL_H_ */ From 81059c41f70748cb95f6902bbb2093879affcf03 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Fri, 14 Dec 2012 00:14:17 -0500 Subject: [PATCH 06/33] flashfs: remove API dependency on uavobjmanager types The flashfs layer is now entirely decoupled from the UAVO data types. All UAVO related calls are now properly contained within uavobjectmanager.c. This will make the flashfs layer more portable as well as more testable in a standalone environment. Eventually, this layer could be used to store arbitrary files. Also fixed all of the doxygen headers for the flashfs API. --- flight/Modules/System/systemmod.c | 2 +- flight/PiOS/Common/pios_flashfs_logfs.c | 152 ++++++++++--------- flight/PiOS/inc/pios_flashfs.h | 9 +- flight/targets/UAVObjects/uavobjectmanager.c | 10 +- 4 files changed, 93 insertions(+), 80 deletions(-) diff --git a/flight/Modules/System/systemmod.c b/flight/Modules/System/systemmod.c index 2c8cc5586..5ac170608 100644 --- a/flight/Modules/System/systemmod.c +++ b/flight/Modules/System/systemmod.c @@ -305,7 +305,7 @@ static void objectUpdatedCb(UAVObjEvent * ev) } else if (objper.Operation == OBJECTPERSISTENCE_OPERATION_FULLERASE) { retval = -1; #if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS) - retval = PIOS_FLASHFS_Format(); + retval = PIOS_FLASHFS_Format(0); #endif } switch(retval) { diff --git a/flight/PiOS/Common/pios_flashfs_logfs.c b/flight/PiOS/Common/pios_flashfs_logfs.c index 2dbe8e8e1..ba9c42267 100644 --- a/flight/PiOS/Common/pios_flashfs_logfs.c +++ b/flight/PiOS/Common/pios_flashfs_logfs.c @@ -25,11 +25,11 @@ */ #include "openpilot.h" -#include "uavobjectmanager.h" /* UAVObjHandle, UAVObj* */ -#include "pios_flashfs.h" /* API for flash filesystem */ #include "pios_flashfs_logfs_priv.h" +#include + #define MIN(x,y) ((x) < (y) ? (x) : (y)) /* @@ -312,9 +312,9 @@ enum slot_state { struct slot_header { enum slot_state state; - uint32_t objid; - uint16_t instid; - uint16_t size; + uint32_t obj_id; + uint16_t obj_inst_id; + uint16_t obj_size; } __attribute__((packed)); /* NOTE: Must be called while holding the flash transaction lock */ @@ -553,7 +553,7 @@ static int32_t logfs_garbage_collect (void) { if (slot_hdr.state == SLOT_STATE_ACTIVE) { uintptr_t dst_addr = logfs_get_addr (dst_arena_id, dst_slot_id); if (logfs_raw_copy_bytes(src_addr, - sizeof(slot_hdr) + slot_hdr.size, + sizeof(slot_hdr) + slot_hdr.obj_size, dst_addr) != 0) { /* Failed to copy all bytes */ return -4; @@ -586,7 +586,7 @@ static int32_t logfs_garbage_collect (void) { } /* NOTE: Must be called while holding the flash transaction lock */ -static int16_t logfs_object_find_next (struct slot_header * slot_hdr, uint16_t * curr_slot, uint32_t objid, uint16_t instid) +static int16_t logfs_object_find_next (struct slot_header * slot_hdr, uint16_t * curr_slot, uint32_t obj_id, uint16_t obj_inst_id) { PIOS_Assert(slot_hdr); PIOS_Assert(curr_slot); @@ -610,8 +610,8 @@ static int16_t logfs_object_find_next (struct slot_header * slot_hdr, uint16_t * break; } if (slot_hdr->state == SLOT_STATE_ACTIVE && - slot_hdr->objid == objid && - slot_hdr->instid == instid) { + slot_hdr->obj_id == obj_id && + slot_hdr->obj_inst_id == obj_inst_id) { /* Found what we were looking for */ *curr_slot = slot_id; return 0; @@ -624,7 +624,7 @@ static int16_t logfs_object_find_next (struct slot_header * slot_hdr, uint16_t * /* NOTE: Must be called while holding the flash transaction lock */ /* OPTIMIZE: could trust that there is at most one active version of every object and terminate the search when we find one */ -static int8_t logfs_delete_object (uint32_t objid, uint16_t instid) +static int8_t logfs_delete_object (uint32_t obj_id, uint16_t obj_inst_id) { int8_t rc; @@ -632,7 +632,7 @@ static int8_t logfs_delete_object (uint32_t objid, uint16_t instid) uint16_t curr_slot_id = 0; do { struct slot_header slot_hdr; - switch (logfs_object_find_next (&slot_hdr, &curr_slot_id, objid, instid)) { + switch (logfs_object_find_next (&slot_hdr, &curr_slot_id, obj_id, obj_inst_id)) { case 0: /* Found a matching slot. Obsolete it. */ slot_hdr.state = SLOT_STATE_OBSOLETE; @@ -663,7 +663,7 @@ out_exit: } /* NOTE: Must be called while holding the flash transaction lock */ -static int8_t logfs_reserve_free_slot (uint16_t * slot_id, struct slot_header * slot_hdr, uint32_t objid, uint16_t instid, uint16_t objsize) +static int8_t logfs_reserve_free_slot (uint16_t * slot_id, struct slot_header * slot_hdr, uint32_t obj_id, uint16_t obj_inst_id, uint16_t obj_size) { PIOS_Assert(slot_id); PIOS_Assert(slot_hdr); @@ -673,7 +673,7 @@ static int8_t logfs_reserve_free_slot (uint16_t * slot_id, struct slot_header * return -1; } - if (objsize > (logfs.cfg->slot_size - sizeof (slot_hdr))) { + if (obj_size > (logfs.cfg->slot_size - sizeof (slot_hdr))) { /* This object is too big for the slot */ return -2; } @@ -698,10 +698,10 @@ static int8_t logfs_reserve_free_slot (uint16_t * slot_id, struct slot_header * } /* Mark this slot as RESERVED */ - slot_hdr->state = SLOT_STATE_RESERVED; - slot_hdr->objid = objid; - slot_hdr->instid = instid; - slot_hdr->size = objsize; + slot_hdr->state = SLOT_STATE_RESERVED; + slot_hdr->obj_id = obj_id; + slot_hdr->obj_inst_id = obj_inst_id; + slot_hdr->obj_size = obj_size; if (logfs.driver->write_data(logfs.flash_id, slot_addr, @@ -719,12 +719,12 @@ static int8_t logfs_reserve_free_slot (uint16_t * slot_id, struct slot_header * } /* NOTE: Must be called while holding the flash transaction lock */ -static int8_t logfs_append_to_log (uint32_t objid, uint16_t instid, uint8_t * data, uint16_t data_len) +static int8_t logfs_append_to_log (uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size) { /* Reserve a free slot for our new object */ uint16_t free_slot_id; struct slot_header slot_hdr; - if (logfs_reserve_free_slot (&free_slot_id, &slot_hdr, objid, instid, data_len) != 0) { + if (logfs_reserve_free_slot (&free_slot_id, &slot_hdr, obj_id, obj_inst_id, obj_size) != 0) { /* Failed to reserve a free slot */ return -1; } @@ -734,22 +734,22 @@ static int8_t logfs_append_to_log (uint32_t objid, uint16_t instid, uint8_t * da /* Write the data into the reserved slot, starting after the slot header */ uintptr_t slot_offset = sizeof(slot_hdr); - while (data_len > 0) { + while (obj_size > 0) { /* Individual writes must fit entirely within a single page buffer. */ uint16_t page_remaining = logfs.cfg->page_size - (slot_offset % logfs.cfg->page_size); - uint16_t write_size = MIN(data_len, page_remaining); + uint16_t write_size = MIN(obj_size, page_remaining); if (logfs.driver->write_data (logfs.flash_id, slot_addr + slot_offset, - data, + obj_data, write_size) != 0) { /* Failed to write the object data to the slot */ return -2; } /* Update our accounting */ - data += write_size; + obj_data += write_size; slot_offset += write_size; - data_len -= write_size; + obj_size -= write_size; } /* Mark this slot active in one atomic step */ @@ -767,27 +767,41 @@ static int8_t logfs_append_to_log (uint32_t objid, uint16_t instid, uint8_t * da return 0; } + +/********************************** + * + * Provide a PIOS_FLASHFS_* driver + * + *********************************/ +#include "pios_flashfs.h" /* API for flash filesystem */ + /** - * @brief Saves one object instance per sector - * @param[in] obj UAVObjHandle the object to save - * @param[in] instId The instance of the object to save - * @return 0 if success or -1 if failure + * @brief Saves one object instance to the filesystem + * @param[in] fs_id The filesystem to use for this action + * @param[in] obj UAVObject ID of the object to save + * @param[in] obj_inst_id The instance number of the object being saved + * @param[in] obj_data Contents of the object being saved + * @param[in] obj_size Size of the object being saved + * @return 0 if success or error code + * @retval -1 if failed to start transaction + * @retval -2 if failure to delete any previous versions of the object + * @retval -3 if filesystem is entirely full and garbage collection won't help + * @retval -4 if garbage collection failed + * @retval -5 if filesystem is full even after garbage collection should have freed space + * @retval -6 if writing the new object to the filesystem failed */ -int32_t PIOS_FLASHFS_ObjSave(UAVObjHandle obj, uint16_t instid, uint8_t * data) +int32_t PIOS_FLASHFS_ObjSave(uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size) { int8_t rc; - uint32_t objid = UAVObjGetID(obj); - uint16_t objsize = UAVObjGetNumBytes(obj); - - PIOS_Assert(objsize <= (logfs.cfg->slot_size - sizeof(struct slot_header))); + PIOS_Assert(obj_size <= (logfs.cfg->slot_size - sizeof(struct slot_header))); if (logfs.driver->start_transaction(logfs.flash_id) != 0) { rc = -1; goto out_exit; } - if (logfs_delete_object (objid, instid) != 0) { + if (logfs_delete_object (obj_id, obj_inst_id) != 0) { rc = -2; goto out_end_trans; } @@ -825,7 +839,7 @@ int32_t PIOS_FLASHFS_ObjSave(UAVObjHandle obj, uint16_t instid, uint8_t * data) } /* We have room for our new object. Append it to the log. */ - if (logfs_append_to_log(objid, instid, data, objsize) != 0) { + if (logfs_append_to_log(obj_id, obj_inst_id, obj_data, obj_size) != 0) { /* Error during append */ rc = -6; goto out_end_trans; @@ -842,25 +856,23 @@ out_exit: } /** - * @brief Load one object instance per sector - * @param[in] obj UAVObjHandle the object to save - * @param[in] instId The instance of the object to save + * @brief Load one object instance from the filesystem + * @param[in] fs_id The filesystem to use for this action + * @param[in] obj UAVObject ID of the object to load + * @param[in] obj_inst_id The instance of the object to load + * @param[in] obj_data Buffer to hold the contents of the loaded object + * @param[in] obj_size Size of the object to be loaded * @return 0 if success or error code - * @retval -1 if object not in file table - * @retval -2 if unable to retrieve object header - * @retval -3 if loaded data instId or objId don't match - * @retval -4 if unable to retrieve instance data - * @retval -5 if unable to read CRC - * @retval -6 if CRC doesn't match + * @retval -1 if failed to start transaction + * @retval -2 if object not found in filesystem + * @retval -3 if object size in filesystem does not exactly match buffer size + * @retval -4 if reading the object data from flash fails */ -int32_t PIOS_FLASHFS_ObjLoad(UAVObjHandle obj, uint16_t instid, uint8_t * data) +int32_t PIOS_FLASHFS_ObjLoad(uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size) { int8_t rc; - uint32_t objid = UAVObjGetID(obj); - uint16_t objsize = UAVObjGetNumBytes(obj); - - PIOS_Assert(objsize <= (logfs.cfg->slot_size - sizeof(struct slot_header))); + PIOS_Assert(obj_size <= (logfs.cfg->slot_size - sizeof(struct slot_header))); if (logfs.driver->start_transaction(logfs.flash_id) != 0) { rc = -1; @@ -870,14 +882,14 @@ int32_t PIOS_FLASHFS_ObjLoad(UAVObjHandle obj, uint16_t instid, uint8_t * data) /* Find the object in the log */ uint16_t slot_id = 0; struct slot_header slot_hdr; - if (logfs_object_find_next (&slot_hdr, &slot_id, objid, instid) != 0) { + if (logfs_object_find_next (&slot_hdr, &slot_id, obj_id, obj_inst_id) != 0) { /* Object does not exist in fs */ rc = -2; goto out_end_trans; } /* Sanity check what we've found */ - if (slot_hdr.size != objsize) { + if (slot_hdr.obj_size != obj_size) { /* Object sizes don't match. Not safe to copy contents. */ rc = -3; goto out_end_trans; @@ -887,8 +899,8 @@ int32_t PIOS_FLASHFS_ObjLoad(UAVObjHandle obj, uint16_t instid, uint8_t * data) uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, slot_id); if (logfs.driver->read_data(logfs.flash_id, slot_addr + sizeof(slot_hdr), - (uint8_t *)data, - objsize) != 0) { + (uint8_t *)obj_data, + obj_size) != 0) { /* Failed to read object data from the log */ rc = -4; goto out_end_trans; @@ -905,31 +917,24 @@ out_exit: } /** - * @brief Delete object from flash - * @param[in] obj UAVObjHandle the object to save - * @param[in] instId The instance of the object to save + * @brief Delete one instance of an object from the filesystem + * @param[in] fs_id The filesystem to use for this action + * @param[in] obj UAVObject ID of the object to delete + * @param[in] obj_inst_id The instance of the object to delete * @return 0 if success or error code - * @retval -1 if object not in file table - * @retval -2 Erase failed - * @note To avoid buffering the file table (1k ram!) the entry in the file table - * remains but destination sector is erased. This will make the load fail as the - * file header won't match the object. At next save it goes back there. + * @retval -1 if failed to start transaction + * @retval -2 if failed to delete the object from the filesystem */ -int32_t PIOS_FLASHFS_ObjDelete(UAVObjHandle obj, uint16_t instid) +int32_t PIOS_FLASHFS_ObjDelete(uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_id) { int8_t rc; - uint32_t objid = UAVObjGetID(obj); - uint16_t objsize = UAVObjGetNumBytes(obj); - - PIOS_Assert(objsize <= (logfs.cfg->slot_size - sizeof(struct slot_header))); - if (logfs.driver->start_transaction(logfs.flash_id) != 0) { rc = -1; goto out_exit; } - if (logfs_delete_object (objid, instid) != 0) { + if (logfs_delete_object (obj_id, obj_inst_id) != 0) { rc = -2; goto out_end_trans; } @@ -944,7 +949,16 @@ out_exit: return rc; } -int32_t PIOS_FLASHFS_Format() +/** + * @brief Erases all filesystem arenas and activate the first arena + * @param[in] fs_id The filesystem to use for this action + * @return 0 if success or error code + * @retval -1 if failed to start transaction + * @retval -2 if failed to erase all arenas + * @retval -3 if failed to activate arena 0 + * @retval -4 if failed to mount arena 0 + */ +int32_t PIOS_FLASHFS_Format(uint32_t fs_id) { int32_t rc; diff --git a/flight/PiOS/inc/pios_flashfs.h b/flight/PiOS/inc/pios_flashfs.h index 914ee6db2..b59cac48f 100644 --- a/flight/PiOS/inc/pios_flashfs.h +++ b/flight/PiOS/inc/pios_flashfs.h @@ -28,11 +28,10 @@ #define PIOS_FLASHFS_H_ #include -#include "uavobjectmanager.h" /* UAVObjHandle */ -int32_t PIOS_FLASHFS_Format(); -int32_t PIOS_FLASHFS_ObjSave(UAVObjHandle obj, uint16_t instId, uint8_t * data); -int32_t PIOS_FLASHFS_ObjLoad(UAVObjHandle obj, uint16_t instId, uint8_t * data); -int32_t PIOS_FLASHFS_ObjDelete(UAVObjHandle obj, uint16_t instId); +int32_t PIOS_FLASHFS_Format(uint32_t fs_id); +int32_t PIOS_FLASHFS_ObjSave(uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size); +int32_t PIOS_FLASHFS_ObjLoad(uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_id, uint8_t * obj_data, uint16_t obj_size); +int32_t PIOS_FLASHFS_ObjDelete(uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_id); #endif /* PIOS_FLASHFS_H_ */ diff --git a/flight/targets/UAVObjects/uavobjectmanager.c b/flight/targets/UAVObjects/uavobjectmanager.c index cb46c36c0..1f07e0c9c 100644 --- a/flight/targets/UAVObjects/uavobjectmanager.c +++ b/flight/targets/UAVObjects/uavobjectmanager.c @@ -772,7 +772,7 @@ int32_t UAVObjSave(UAVObjHandle obj_handle, uint16_t instId) if (instId != 0) return -1; - if (PIOS_FLASHFS_ObjSave(obj_handle, instId, (uint8_t*) MetaDataPtr((struct UAVOMeta *)obj_handle)) != 0) + if (PIOS_FLASHFS_ObjSave(0, UAVObjGetID(obj_handle), instId, (uint8_t*) MetaDataPtr((struct UAVOMeta *)obj_handle), UAVObjGetNumBytes(obj_handle)) != 0) return -1; } else { InstanceHandle instEntry = getInstance( (struct UAVOData *)obj_handle, instId); @@ -783,7 +783,7 @@ int32_t UAVObjSave(UAVObjHandle obj_handle, uint16_t instId) if (InstanceData(instEntry) == NULL) return -1; - if (PIOS_FLASHFS_ObjSave(obj_handle, instId, InstanceData(instEntry)) != 0) + if (PIOS_FLASHFS_ObjSave(0, UAVObjGetID(obj_handle), instId, InstanceData(instEntry), UAVObjGetNumBytes(obj_handle)) != 0) return -1; } #endif @@ -927,7 +927,7 @@ int32_t UAVObjLoad(UAVObjHandle obj_handle, uint16_t instId) return -1; // Fire event on success - if (PIOS_FLASHFS_ObjLoad(obj_handle, instId, (uint8_t*) MetaDataPtr((struct UAVOMeta *)obj_handle)) == 0) + if (PIOS_FLASHFS_ObjLoad(0, UAVObjGetID(obj_handle), instId, (uint8_t*) MetaDataPtr((struct UAVOMeta *)obj_handle), UAVObjGetNumBytes(obj_handle)) == 0) sendEvent((struct UAVOBase*)obj_handle, instId, EV_UNPACKED); else return -1; @@ -939,7 +939,7 @@ int32_t UAVObjLoad(UAVObjHandle obj_handle, uint16_t instId) return -1; // Fire event on success - if (PIOS_FLASHFS_ObjLoad(obj_handle, instId, InstanceData(instEntry)) == 0) + if (PIOS_FLASHFS_ObjLoad(0, UAVObjGetID(obj_handle), instId, InstanceData(instEntry), UAVObjGetNumBytes(obj_handle)) == 0) sendEvent((struct UAVOBase*)obj_handle, instId, EV_UNPACKED); else return -1; @@ -997,7 +997,7 @@ int32_t UAVObjDelete(UAVObjHandle obj_handle, uint16_t instId) { PIOS_Assert(obj_handle); #if defined(PIOS_INCLUDE_FLASH_SECTOR_SETTINGS) - PIOS_FLASHFS_ObjDelete(obj_handle, instId); + PIOS_FLASHFS_ObjDelete(0, UAVObjGetID(obj_handle), instId); #endif #if defined(PIOS_INCLUDE_SDCARD) uint8_t filename[14]; From b242f8b88c5e92e54ba6e07321507db45aca0554 Mon Sep 17 00:00:00 2001 From: lilvinz Date: Thu, 13 Dec 2012 11:56:21 +0100 Subject: [PATCH 07/33] pios_flashfs: adapted flashfs to work on f3 --- flight/PiOS/Common/pios_flashfs_logfs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/flight/PiOS/Common/pios_flashfs_logfs.c b/flight/PiOS/Common/pios_flashfs_logfs.c index ba9c42267..9cc5559c0 100644 --- a/flight/PiOS/Common/pios_flashfs_logfs.c +++ b/flight/PiOS/Common/pios_flashfs_logfs.c @@ -79,10 +79,10 @@ static uintptr_t logfs_get_addr(uint8_t arena_id, uint16_t slot_id) * of earlier ones in NOR flash without an erase cycle. */ enum arena_state { - ARENA_STATE_ERASED = 0xEEEEEEEE, - ARENA_STATE_RESERVED = 0xE6E6E6E6, - ARENA_STATE_ACTIVE = 0x66666666, - ARENA_STATE_OBSOLETE = 0x44444444, + ARENA_STATE_ERASED = 0xFFFFFFFF, + ARENA_STATE_RESERVED = 0x5555FFFF, + ARENA_STATE_ACTIVE = 0x0000FFFF, + ARENA_STATE_OBSOLETE = 0x00000000, }; struct arena_header { @@ -305,9 +305,9 @@ static int32_t logfs_find_active_arena() */ enum slot_state { SLOT_STATE_EMPTY = 0xFFFFFFFF, - SLOT_STATE_RESERVED = 0xFAFAFAFA, - SLOT_STATE_ACTIVE = 0xAAAAAAAA, - SLOT_STATE_OBSOLETE = 0x88888888, + SLOT_STATE_RESERVED = 0xAAAAFFFF, + SLOT_STATE_ACTIVE = 0x0000FFFF, + SLOT_STATE_OBSOLETE = 0x00000000, }; struct slot_header { From d611207789866cbb7e7a33c447b8e1d89f74efb4 Mon Sep 17 00:00:00 2001 From: lilvinz Date: Thu, 13 Dec 2012 13:54:08 +0100 Subject: [PATCH 08/33] pios_flashfs_logfs: moved modified ARENA and SLOT enums to an F3 branch also added a detailed comment --- flight/PiOS/Common/pios_flashfs_logfs.c | 40 ++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/flight/PiOS/Common/pios_flashfs_logfs.c b/flight/PiOS/Common/pios_flashfs_logfs.c index 9cc5559c0..67c23e0c4 100644 --- a/flight/PiOS/Common/pios_flashfs_logfs.c +++ b/flight/PiOS/Common/pios_flashfs_logfs.c @@ -79,10 +79,26 @@ static uintptr_t logfs_get_addr(uint8_t arena_id, uint16_t slot_id) * of earlier ones in NOR flash without an erase cycle. */ enum arena_state { +#ifdef STM32F30X + /* + * The STM32F30X flash subsystem is only capable of + * writing words or halfwords. In this case we use halfwords. + * In addition to that it is only capable to write to erased + * cells (0xffff) or write a cell from anything to (0x0000). + * To cope with this, the F3 gets different enum values. + * For this to work the underlying flash driver has to + * check each halfword if it has changed before writing. + */ ARENA_STATE_ERASED = 0xFFFFFFFF, - ARENA_STATE_RESERVED = 0x5555FFFF, - ARENA_STATE_ACTIVE = 0x0000FFFF, + ARENA_STATE_RESERVED = 0xE6E6FFFF, + ARENA_STATE_ACTIVE = 0xE6E66666, ARENA_STATE_OBSOLETE = 0x00000000, +#else + ARENA_STATE_ERASED = 0xEEEEEEEE, + ARENA_STATE_RESERVED = 0xE6E6E6E6, + ARENA_STATE_ACTIVE = 0x66666666, + ARENA_STATE_OBSOLETE = 0x44444444, +#endif }; struct arena_header { @@ -304,10 +320,26 @@ static int32_t logfs_find_active_arena() * of earlier ones in NOR flash without an erase cycle. */ enum slot_state { +#ifdef STM32F30X + /* + * The STM32F30X flash subsystem is only capable of + * writing words or halfwords. In this case we use halfwords. + * In addition to that it is only capable to write to erased + * cells (0xffff) or write a cell from anything to (0x0000). + * To cope with this, the F3 gets different enum values. + * For this to work the underlying flash driver has to + * check each halfword if it has changed before writing. + */ SLOT_STATE_EMPTY = 0xFFFFFFFF, - SLOT_STATE_RESERVED = 0xAAAAFFFF, - SLOT_STATE_ACTIVE = 0x0000FFFF, + SLOT_STATE_RESERVED = 0xFAFAFFFF, + SLOT_STATE_ACTIVE = 0xFAFAAAAA, SLOT_STATE_OBSOLETE = 0x00000000, +#else + SLOT_STATE_EMPTY = 0xFFFFFFFF, + SLOT_STATE_RESERVED = 0xFAFAFAFA, + SLOT_STATE_ACTIVE = 0xAAAAAAAA, + SLOT_STATE_OBSOLETE = 0x88888888, +#endif }; struct slot_header { From 7726b9e2a955c0be9274a6d9f07432dc49e1e3d3 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Fri, 14 Dec 2012 00:42:10 -0500 Subject: [PATCH 09/33] logfs: use f3-safe slot and arena states for all chips Filesystem magic value has been updated to deal with the format change. Conflicts: flight/targets/board_hw_defs/discoveryf4/board_hw_defs.c flight/targets/board_hw_defs/flyingf4/board_hw_defs.c flight/targets/board_hw_defs/freedom/board_hw_defs.c flight/targets/board_hw_defs/quanton/board_hw_defs.c --- flight/PiOS/Common/pios_flashfs_logfs.c | 18 ++---------------- .../coptercontrol/board_hw_defs.c | 4 ++-- .../board_hw_defs/revolution/board_hw_defs.c | 2 +- .../board_hw_defs/revomini/board_hw_defs.c | 2 +- 4 files changed, 6 insertions(+), 20 deletions(-) diff --git a/flight/PiOS/Common/pios_flashfs_logfs.c b/flight/PiOS/Common/pios_flashfs_logfs.c index 67c23e0c4..2e6638e40 100644 --- a/flight/PiOS/Common/pios_flashfs_logfs.c +++ b/flight/PiOS/Common/pios_flashfs_logfs.c @@ -79,13 +79,12 @@ static uintptr_t logfs_get_addr(uint8_t arena_id, uint16_t slot_id) * of earlier ones in NOR flash without an erase cycle. */ enum arena_state { -#ifdef STM32F30X /* * The STM32F30X flash subsystem is only capable of * writing words or halfwords. In this case we use halfwords. * In addition to that it is only capable to write to erased * cells (0xffff) or write a cell from anything to (0x0000). - * To cope with this, the F3 gets different enum values. + * To cope with this, the F3 needs carefully crafted enum values. * For this to work the underlying flash driver has to * check each halfword if it has changed before writing. */ @@ -93,12 +92,6 @@ enum arena_state { ARENA_STATE_RESERVED = 0xE6E6FFFF, ARENA_STATE_ACTIVE = 0xE6E66666, ARENA_STATE_OBSOLETE = 0x00000000, -#else - ARENA_STATE_ERASED = 0xEEEEEEEE, - ARENA_STATE_RESERVED = 0xE6E6E6E6, - ARENA_STATE_ACTIVE = 0x66666666, - ARENA_STATE_OBSOLETE = 0x44444444, -#endif }; struct arena_header { @@ -320,13 +313,12 @@ static int32_t logfs_find_active_arena() * of earlier ones in NOR flash without an erase cycle. */ enum slot_state { -#ifdef STM32F30X /* * The STM32F30X flash subsystem is only capable of * writing words or halfwords. In this case we use halfwords. * In addition to that it is only capable to write to erased * cells (0xffff) or write a cell from anything to (0x0000). - * To cope with this, the F3 gets different enum values. + * To cope with this, the F3 needs carfully crafted enum values. * For this to work the underlying flash driver has to * check each halfword if it has changed before writing. */ @@ -334,12 +326,6 @@ enum slot_state { SLOT_STATE_RESERVED = 0xFAFAFFFF, SLOT_STATE_ACTIVE = 0xFAFAAAAA, SLOT_STATE_OBSOLETE = 0x00000000, -#else - SLOT_STATE_EMPTY = 0xFFFFFFFF, - SLOT_STATE_RESERVED = 0xFAFAFAFA, - SLOT_STATE_ACTIVE = 0xAAAAAAAA, - SLOT_STATE_OBSOLETE = 0x88888888, -#endif }; struct slot_header { diff --git a/flight/targets/board_hw_defs/coptercontrol/board_hw_defs.c b/flight/targets/board_hw_defs/coptercontrol/board_hw_defs.c index fdd95a1e5..97d8743ce 100644 --- a/flight/targets/board_hw_defs/coptercontrol/board_hw_defs.c +++ b/flight/targets/board_hw_defs/coptercontrol/board_hw_defs.c @@ -404,7 +404,7 @@ void PIOS_SPI_flash_accel_irq_handler(void) #include "pios_flash_jedec_priv.h" static const struct flashfs_logfs_cfg flashfs_w25x_cfg = { - .fs_magic = 0x89abcdef, + .fs_magic = 0x99abcdef, .total_fs_size = 0x00080000, /* 512K bytes (128 sectors = entire chip) */ .arena_size = 0x00010000, /* 256 * slot size */ .slot_size = 0x00000100, /* 256 bytes */ @@ -420,7 +420,7 @@ static const struct pios_flash_jedec_cfg flash_w25x_cfg = { }; static const struct flashfs_logfs_cfg flashfs_m25p_cfg = { - .fs_magic = 0x89abceef, + .fs_magic = 0x99abceef, .total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */ .arena_size = 0x00010000, /* 256 * slot size */ .slot_size = 0x00000100, /* 256 bytes */ diff --git a/flight/targets/board_hw_defs/revolution/board_hw_defs.c b/flight/targets/board_hw_defs/revolution/board_hw_defs.c index f6d3560ca..513a318cb 100644 --- a/flight/targets/board_hw_defs/revolution/board_hw_defs.c +++ b/flight/targets/board_hw_defs/revolution/board_hw_defs.c @@ -452,7 +452,7 @@ void PIOS_SPI_flash_irq_handler(void) #include "pios_flash_jedec_priv.h" static const struct flashfs_logfs_cfg flashfs_m25p_cfg = { - .fs_magic = 0x89abceef, + .fs_magic = 0x99abceef, .total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */ .arena_size = 0x00010000, /* 256 * slot size */ .slot_size = 0x00000100, /* 256 bytes */ diff --git a/flight/targets/board_hw_defs/revomini/board_hw_defs.c b/flight/targets/board_hw_defs/revomini/board_hw_defs.c index 41a56894b..0ad69a044 100644 --- a/flight/targets/board_hw_defs/revomini/board_hw_defs.c +++ b/flight/targets/board_hw_defs/revomini/board_hw_defs.c @@ -567,7 +567,7 @@ const struct pios_rfm22b_cfg * PIOS_BOARD_HW_DEFS_GetRfm22Cfg (uint32_t board_re #include "pios_flash_jedec_priv.h" static const struct flashfs_logfs_cfg flashfs_m25p_cfg = { - .fs_magic = 0x89abceef, + .fs_magic = 0x99abceef, .total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */ .arena_size = 0x00010000, /* 256 * slot size */ .slot_size = 0x00000100, /* 256 bytes */ From 7f53aa422a183d150b3d4eb4670b01a26460d760 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Fri, 14 Dec 2012 00:25:02 -0500 Subject: [PATCH 10/33] ut: add basic unit test for logfs Build it with: make ut_logfs Create a raw flash file like this: dd if=/dev/zero bs=1 count=2MiB | tr '\000' '\377' > theflash.bin Run it with: ./build/unit_tests/logfs/logfs.elf && echo 'all good' Conflicts: Makefile --- Makefile | 40 ++++++ flight/tests/logfs/Makefile | 41 ++++++ flight/tests/logfs/main.c | 87 +++++++++++++ flight/tests/logfs/openpilot.h | 5 + flight/tests/logfs/pios.h | 4 + flight/tests/logfs/pios_config.h | 1 + flight/tests/logfs/pios_flash_ut.c | 159 ++++++++++++++++++++++++ flight/tests/logfs/pios_flash_ut_priv.h | 10 ++ 8 files changed, 347 insertions(+) create mode 100644 flight/tests/logfs/Makefile create mode 100644 flight/tests/logfs/main.c create mode 100644 flight/tests/logfs/openpilot.h create mode 100644 flight/tests/logfs/pios.h create mode 100644 flight/tests/logfs/pios_config.h create mode 100644 flight/tests/logfs/pios_flash_ut.c create mode 100644 flight/tests/logfs/pios_flash_ut_priv.h diff --git a/Makefile b/Makefile index 01e9ccd19..a57bf3f75 100644 --- a/Makefile +++ b/Makefile @@ -707,6 +707,46 @@ sim_osx_%: uavobjects_flight $(V1) mkdir -p $(BUILD_DIR)/sim_osx $(V1) $(MAKE) --no-print-directory \ -C $(ROOT_DIR)/flight/targets/Revolution --file=$(ROOT_DIR)/flight/targets/Revolution/Makefile.osx $* + + +############################## +# +# Unit Tests +# +############################## + +UT_TARGETS := logfs +.PHONY: ut_all +ut_all: $(addprefix ut_, $(UT_TARGETS)) + +UT_OUT_DIR := $(BUILD_DIR)/unit_tests + +$(UT_OUT_DIR): + $(V1) mkdir -p $@ + +ut_%: $(UT_OUT_DIR) + $(V1) cd $(ROOT_DIR)/flight/tests/$* && \ + $(MAKE) --no-print-directory \ + BUILD_TYPE=ut \ + BOARD_SHORT_NAME=$* \ + TCHAIN_PREFIX="" \ + REMOVE_CMD="$(RM)" \ + \ + TARGET=$* \ + OUTDIR="$(UT_OUT_DIR)/$*" \ + \ + PIOS=$(PIOS) \ + OPUAVOBJ=$(OPUAVOBJ) \ + OPUAVTALK=$(OPUAVTALK) \ + FLIGHTLIB=$(FLIGHTLIB) \ + \ + $* + +.PHONY: ut_clean +ut_clean: + $(V0) @echo " CLEAN $@" + $(V1) [ ! -d "$(UT_OUT_DIR)" ] || $(RM) -r "$(UT_OUT_DIR)" + ############################## # # Packaging components diff --git a/flight/tests/logfs/Makefile b/flight/tests/logfs/Makefile new file mode 100644 index 000000000..a1c302a1c --- /dev/null +++ b/flight/tests/logfs/Makefile @@ -0,0 +1,41 @@ +############################################################################### +# @file Makefile +# @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 +# @addtogroup +# @{ +# @addtogroup +# @{ +# @brief Makefile for unit test +############################################################################### +# +# 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 +# + +WHEREAMI := $(dir $(lastword $(MAKEFILE_LIST))) +TOP := $(realpath $(WHEREAMI)/../../../) +include $(TOP)/make/firmware-defs.mk + +EXTRAINCDIRS += $(PIOS)/inc + +CFLAGS += -O0 +CFLAGS += -Wall -Werror +CFLAGS += -g +CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I. + +CONLYFLAGS += -std=gnu99 + +SRC := $(PIOS)/Common/pios_flashfs_logfs.c + +include $(TOP)/make/unittest.mk diff --git a/flight/tests/logfs/main.c b/flight/tests/logfs/main.c new file mode 100644 index 000000000..87f7dd1a2 --- /dev/null +++ b/flight/tests/logfs/main.c @@ -0,0 +1,87 @@ +#include /* printf */ +#include /* abort */ +#include /* memset */ + +#include "pios_flash.h" /* PIOS_FLASH_* API */ +#include "pios_flash_ut_priv.h" + +const struct pios_flash_ut_cfg flash_config = { + .size_of_flash = 0x00200000, + .size_of_sector = 0x00010000, +}; + +#include "pios_flashfs_logfs_priv.h" + +const struct flashfs_logfs_cfg flashfs_config = { + .fs_magic = 0x89abceef, + .total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */ + .arena_size = 0x00010000, /* 256 * slot size */ + .slot_size = 0x00000100, /* 256 bytes */ + + .start_offset = 0, /* start at the beginning of the chip */ + .sector_size = 0x00010000, /* 64K bytes */ + .page_size = 0x00000100, /* 256 bytes */ +}; + +#include "pios_flashfs.h" /* PIOS_FLASHFS_* */ + +int main (int argc, char * argv[]) +{ + int32_t rc; + + /* dd if=/dev/zero bs=1 count=2MiB | tr '\000' '\377' > theflash.bin */ + + uint32_t flash_id; + rc = PIOS_Flash_UT_Init(&flash_id, &flash_config); + if (rc != 0) { + printf ("flash init failed (%d)\n", rc); + abort(); + } + + uint32_t fs_id; + rc = PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_config, &pios_ut_flash_driver, flash_id); + if (rc != 0) { + printf ("flash filesystem init failed (%d)\n", rc); + abort(); + } + +#define OBJ1_ID 0x12345678 +#define OBJ1_SIZE 76 + unsigned char obj1[OBJ1_SIZE]; + memset(obj1, 0xA5, sizeof(obj1)); + for (uint32_t i = 0; i < 10000; i++) { + rc = PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 0, obj1, sizeof(obj1)); + if (rc != 0) { + printf ("failed to save obj1 (%d)\n", rc); + abort(); + } + } + + unsigned char obj1_check[OBJ1_SIZE]; + memset(obj1_check, 0, sizeof(obj1_check)); + rc = PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check)); + if (rc != 0) { + printf ("failed to load obj1 (%d)\n", rc); + abort(); + } + + if (memcmp(obj1, obj1_check, sizeof(obj1)) != 0) { + printf ("read-back of obj1 failed\n"); + abort(); + } + + + rc = PIOS_FLASHFS_ObjDelete(fs_id, OBJ1_ID, 0); + if (rc != 0) { + printf ("failed to delete obj1 (%d)\n", rc); + abort(); + } + + rc = PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check)); + if (rc == 0) { + printf ("was able to load obj1 after delete!\n"); + abort(); + } + +} + diff --git a/flight/tests/logfs/openpilot.h b/flight/tests/logfs/openpilot.h new file mode 100644 index 000000000..473f27b93 --- /dev/null +++ b/flight/tests/logfs/openpilot.h @@ -0,0 +1,5 @@ +#include + +#define PIOS_Assert(x) if (!(x)) { while (1) ; } + +#define PIOS_DEBUG_Assert(x) PIOS_Assert(x) diff --git a/flight/tests/logfs/pios.h b/flight/tests/logfs/pios.h new file mode 100644 index 000000000..23ec3250e --- /dev/null +++ b/flight/tests/logfs/pios.h @@ -0,0 +1,4 @@ +#if defined(PIOS_INCLUDE_FLASH) +#include +#include +#endif diff --git a/flight/tests/logfs/pios_config.h b/flight/tests/logfs/pios_config.h new file mode 100644 index 000000000..98eeb42a3 --- /dev/null +++ b/flight/tests/logfs/pios_config.h @@ -0,0 +1 @@ +#define PIOS_INCLUDE_FLASH diff --git a/flight/tests/logfs/pios_flash_ut.c b/flight/tests/logfs/pios_flash_ut.c new file mode 100644 index 000000000..3ed3c6cce --- /dev/null +++ b/flight/tests/logfs/pios_flash_ut.c @@ -0,0 +1,159 @@ +#include /* abort */ +#include /* fopen/fread/fwrite/fseek */ +#include /* assert */ +#include /* memset */ + +#include +#include "pios_flash_ut_priv.h" + +enum flash_ut_magic { + FLASH_UT_MAGIC = 0x321dabc1, +}; + +struct flash_ut_dev { + enum flash_ut_magic magic; + const struct pios_flash_ut_cfg * cfg; + bool transaction_in_progress; + FILE * flash_file; +}; + +static struct flash_ut_dev * PIOS_Flash_UT_Alloc(void) +{ + struct flash_ut_dev * flash_dev = malloc(sizeof(struct flash_ut_dev)); + + flash_dev->magic = FLASH_UT_MAGIC; + + return flash_dev; +} + +int32_t PIOS_Flash_UT_Init(uint32_t * flash_id, const struct pios_flash_ut_cfg * cfg) +{ + /* Check inputs */ + assert(flash_id); + assert(cfg); + assert(cfg->size_of_flash); + assert(cfg->size_of_sector); + assert((cfg->size_of_flash % cfg->size_of_sector) == 0); + + struct flash_ut_dev * flash_dev = PIOS_Flash_UT_Alloc(); + assert(flash_dev); + + flash_dev->cfg = cfg; + flash_dev->transaction_in_progress = false; + + flash_dev->flash_file = fopen ("theflash.bin", "r+"); + if (flash_dev->flash_file == NULL) { + return -1; + } + + if (fseek (flash_dev->flash_file, flash_dev->cfg->size_of_flash, SEEK_SET) != 0) { + return -2; + } + + *flash_id = (uint32_t)flash_dev; + + return 0; +} + +/********************************** + * + * Provide a PIOS flash driver API + * + *********************************/ +#include "pios_flash.h" + +static int32_t PIOS_Flash_UT_StartTransaction(uint32_t flash_id) +{ + struct flash_ut_dev * flash_dev = (struct flash_ut_dev *)flash_id; + + assert(!flash_dev->transaction_in_progress); + + flash_dev->transaction_in_progress = true; + + return 0; +} + +static int32_t PIOS_Flash_UT_EndTransaction(uint32_t flash_id) +{ + struct flash_ut_dev * flash_dev = (struct flash_ut_dev *)flash_id; + + assert(flash_dev->transaction_in_progress); + + flash_dev->transaction_in_progress = false; + + return 0; +} + +static int32_t PIOS_Flash_UT_EraseSector(uint32_t flash_id, uint32_t addr) +{ + struct flash_ut_dev * flash_dev = (struct flash_ut_dev *)flash_id; + + assert(flash_dev->transaction_in_progress); + + if (fseek (flash_dev->flash_file, addr, SEEK_SET) != 0) { + assert(0); + } + + unsigned char * buf = malloc(flash_dev->cfg->size_of_sector); + assert (buf); + memset((void *)buf, 0xFF, flash_dev->cfg->size_of_sector); + + size_t s; + s = fwrite (buf, 1, flash_dev->cfg->size_of_sector, flash_dev->flash_file); + + assert (s == flash_dev->cfg->size_of_sector); + + return 0; +} + +static int32_t PIOS_Flash_UT_WriteData(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) +{ + /* Check inputs */ + assert(data); + + struct flash_ut_dev * flash_dev = (struct flash_ut_dev *)flash_id; + + assert(flash_dev->transaction_in_progress); + + if (fseek (flash_dev->flash_file, addr, SEEK_SET) != 0) { + assert(0); + } + + size_t s; + s = fwrite (data, 1, len, flash_dev->flash_file); + + assert (s == len); + + return 0; +} + +static int32_t PIOS_Flash_UT_ReadData(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) +{ + /* Check inputs */ + assert(data); + + struct flash_ut_dev * flash_dev = (struct flash_ut_dev *)flash_id; + + assert(flash_dev->transaction_in_progress); + + if (fseek (flash_dev->flash_file, addr, SEEK_SET) != 0) { + assert(0); + } + + size_t s; + s = fread (data, 1, len, flash_dev->flash_file); + + assert (s == len); + + return 0; +} + +/* Provide a flash driver to external drivers */ +const struct pios_flash_driver pios_ut_flash_driver = { + .start_transaction = PIOS_Flash_UT_StartTransaction, + .end_transaction = PIOS_Flash_UT_EndTransaction, + .erase_sector = PIOS_Flash_UT_EraseSector, + .write_data = PIOS_Flash_UT_WriteData, + .read_data = PIOS_Flash_UT_ReadData, +}; + diff --git a/flight/tests/logfs/pios_flash_ut_priv.h b/flight/tests/logfs/pios_flash_ut_priv.h new file mode 100644 index 000000000..7291fd1d5 --- /dev/null +++ b/flight/tests/logfs/pios_flash_ut_priv.h @@ -0,0 +1,10 @@ +#include + +struct pios_flash_ut_cfg { + uint32_t size_of_flash; + uint32_t size_of_sector; +}; + +int32_t PIOS_Flash_UT_Init(uint32_t * flash_id, const struct pios_flash_ut_cfg * cfg); + +extern const struct pios_flash_driver pios_ut_flash_driver; From cc2d5f8eae7e13f635c5b9a7f98e32ab148fd4a3 Mon Sep 17 00:00:00 2001 From: Alessio Morale Date: Fri, 15 Feb 2013 21:13:50 +0100 Subject: [PATCH 11/33] Fixes for missing openpilot.h include, previously coming from flashfs_objlist --- flight/Modules/Autotune/autotune.c | 3 ++- flight/Modules/Sensors/sensors.c | 3 ++- flight/PiOS/Common/pios_gcsrcvr.c | 2 ++ flight/targets/CopterControl/System/pios_board.c | 4 ++-- flight/targets/Revolution/System/pios_board.c | 4 ++-- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/flight/Modules/Autotune/autotune.c b/flight/Modules/Autotune/autotune.c index 96051b076..260f70750 100644 --- a/flight/Modules/Autotune/autotune.c +++ b/flight/Modules/Autotune/autotune.c @@ -48,7 +48,8 @@ * */ -#include "pios.h" +#include "openpilot.h" + #include "flightstatus.h" #include "hwsettings.h" #include "manualcontrolcommand.h" diff --git a/flight/Modules/Sensors/sensors.c b/flight/Modules/Sensors/sensors.c index b55d4ad2d..f6584c682 100644 --- a/flight/Modules/Sensors/sensors.c +++ b/flight/Modules/Sensors/sensors.c @@ -46,7 +46,8 @@ * */ -#include "pios.h" +#include "openpilot.h" + #include "homelocation.h" #include "magnetometer.h" #include "magbias.h" diff --git a/flight/PiOS/Common/pios_gcsrcvr.c b/flight/PiOS/Common/pios_gcsrcvr.c index 27e13c648..d5451157e 100644 --- a/flight/PiOS/Common/pios_gcsrcvr.c +++ b/flight/PiOS/Common/pios_gcsrcvr.c @@ -31,6 +31,8 @@ /* Project Includes */ #include "pios.h" +#include "uavobjectmanager.h" + #if defined(PIOS_INCLUDE_GCSRCVR) #include "pios_gcsrcvr_priv.h" diff --git a/flight/targets/CopterControl/System/pios_board.c b/flight/targets/CopterControl/System/pios_board.c index 9072f1e84..167ed8fe0 100644 --- a/flight/targets/CopterControl/System/pios_board.c +++ b/flight/targets/CopterControl/System/pios_board.c @@ -32,15 +32,15 @@ * * NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE */ -#include "board_hw_defs.c" -#include #include #include #include #include #include +#include "board_hw_defs.c" + /* One slot per selectable receiver group. * eg. PWM, PPM, GCS, DSMMAINPORT, DSMFLEXIPORT, SBUS diff --git a/flight/targets/Revolution/System/pios_board.c b/flight/targets/Revolution/System/pios_board.c index 18a49bdd7..369a2a132 100644 --- a/flight/targets/Revolution/System/pios_board.c +++ b/flight/targets/Revolution/System/pios_board.c @@ -32,14 +32,14 @@ * * NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE */ -#include "board_hw_defs.c" -#include #include #include #include "hwsettings.h" #include "manualcontrolsettings.h" +#include "board_hw_defs.c" + /** * Sensor configurations */ From 60c06b8c4b58b4fdd168c59ee0c52c828fb34fc4 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Fri, 14 Dec 2012 00:17:40 -0500 Subject: [PATCH 12/33] ut: add unit test build infrastructure New build targets: make ut_all make ut_clean to build (or clean) all unit tests. --- make/unittest.mk | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 make/unittest.mk diff --git a/make/unittest.mk b/make/unittest.mk new file mode 100644 index 000000000..0991a4827 --- /dev/null +++ b/make/unittest.mk @@ -0,0 +1,43 @@ +############################################################################### +# @file unittest.mk +# @author PhoenixPilot, http://github.com/PhoenixPilot, Copyright (C) 2012 +# @addtogroup +# @{ +# @addtogroup +# @{ +# @brief Makefile template for unit tests +############################################################################### +# +# 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 +# + +# Need to disable THUMB mode for unit tests +override THUMB := + +EXTRAINCDIRS += . +ALLSRC := $(SRC) $(wildcard ./*.c) +ALLSRCBASE := $(notdir $(basename $(ALLSRC))) +ALLOBJ := $(addprefix $(OUTDIR)/, $(addsuffix .o, $(ALLSRCBASE))) + +.PHONY: $(TARGET) +$(TARGET): | $(OUTDIR) +$(TARGET): $(OUTDIR)/$(TARGET).elf + +$(OUTDIR): + $(V1) mkdir -p $@ + +$(foreach src,$(ALLSRC),$(eval $(call COMPILE_C_TEMPLATE,$(src)))) +$(eval $(call LINK_TEMPLATE,$(OUTDIR)/$(TARGET).elf,$(ALLOBJ))) + From dd5f4b949cacaca5ca7eb6ca63a6569fd6d404a5 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Fri, 14 Dec 2012 21:53:26 -0500 Subject: [PATCH 13/33] logfs: use uintptr_t to hold opaque pointers When storing an opaque pointer value in a uint, the appropriate type is uintptr_t which is guaranteed to be wide enough to hold a pointer. This is particularly important when the code can be compiled in a sim or unit test environment which is intended to run on a 64-bit machine. Conflicts: flight/targets/DiscoveryF4/System/pios_board.c flight/targets/FlyingF4/System/pios_board.c flight/targets/Freedom/System/pios_board.c flight/targets/Quanton/System/pios_board.c --- flight/PiOS/Common/pios_flashfs_logfs.c | 4 ++-- flight/PiOS/inc/pios_flashfs_logfs_priv.h | 2 +- flight/targets/CopterControl/System/pios_board.c | 2 +- flight/targets/RevoMini/System/pios_board.c | 2 +- flight/targets/Revolution/System/pios_board.c | 2 +- flight/tests/logfs/main.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/flight/PiOS/Common/pios_flashfs_logfs.c b/flight/PiOS/Common/pios_flashfs_logfs.c index 2e6638e40..f44122da3 100644 --- a/flight/PiOS/Common/pios_flashfs_logfs.c +++ b/flight/PiOS/Common/pios_flashfs_logfs.c @@ -461,7 +461,7 @@ static int32_t logfs_mount_log(uint8_t arena_id) * @brief Initialize the flash object setting FS * @return 0 if success, -1 if failure */ -int32_t PIOS_FLASHFS_Logfs_Init(uint32_t * fs_id, const struct flashfs_logfs_cfg * cfg, const struct pios_flash_driver * driver, uint32_t flash_id) +int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t * fs_id, const struct flashfs_logfs_cfg * cfg, const struct pios_flash_driver * driver, uint32_t flash_id) { PIOS_Assert(cfg); PIOS_Assert(fs_id); @@ -524,7 +524,7 @@ int32_t PIOS_FLASHFS_Logfs_Init(uint32_t * fs_id, const struct flashfs_logfs_cfg /* Log has been mounted */ rc = 0; - *fs_id = (uint32_t) &logfs; + *fs_id = (uintptr_t) &logfs; out_end_trans: logfs.driver->end_transaction(logfs.flash_id); diff --git a/flight/PiOS/inc/pios_flashfs_logfs_priv.h b/flight/PiOS/inc/pios_flashfs_logfs_priv.h index ba1acdf1f..ead6177df 100644 --- a/flight/PiOS/inc/pios_flashfs_logfs_priv.h +++ b/flight/PiOS/inc/pios_flashfs_logfs_priv.h @@ -41,6 +41,6 @@ struct flashfs_logfs_cfg { uint32_t page_size; /* Maximum flash burst write size */ }; -int32_t PIOS_FLASHFS_Logfs_Init(uint32_t * fs_id, const struct flashfs_logfs_cfg * cfg, const struct pios_flash_driver * driver, uint32_t flash_id); +int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t * fs_id, const struct flashfs_logfs_cfg * cfg, const struct pios_flash_driver * driver, uint32_t flash_id); #endif /* PIOS_FLASHFS_LOGFS_PRIV_H_ */ diff --git a/flight/targets/CopterControl/System/pios_board.c b/flight/targets/CopterControl/System/pios_board.c index 167ed8fe0..726d82182 100644 --- a/flight/targets/CopterControl/System/pios_board.c +++ b/flight/targets/CopterControl/System/pios_board.c @@ -163,7 +163,7 @@ void PIOS_Board_Init(void) { #endif uint32_t flash_id; - uint32_t fs_id; + uintptr_t fs_id; switch(bdinfo->board_rev) { case BOARD_REVISION_CC: PIOS_Flash_Jedec_Init(&flash_id, pios_spi_flash_accel_id, 1, &flash_w25x_cfg); diff --git a/flight/targets/RevoMini/System/pios_board.c b/flight/targets/RevoMini/System/pios_board.c index 965b32b36..b226077c7 100644 --- a/flight/targets/RevoMini/System/pios_board.c +++ b/flight/targets/RevoMini/System/pios_board.c @@ -303,7 +303,7 @@ void PIOS_Board_Init(void) { /* Connect flash to the approrpiate interface and configure it */ uint32_t flash_id; PIOS_Flash_Jedec_Init(&flash_id, pios_spi_telem_flash_id, 1, &flash_m25p_cfg); - uint32_t fs_id; + uintptr_t fs_id; PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_m25p_cfg, &pios_jedec_flash_driver, flash_id); #endif diff --git a/flight/targets/Revolution/System/pios_board.c b/flight/targets/Revolution/System/pios_board.c index 369a2a132..2c766e148 100644 --- a/flight/targets/Revolution/System/pios_board.c +++ b/flight/targets/Revolution/System/pios_board.c @@ -389,7 +389,7 @@ void PIOS_Board_Init(void) { uint32_t flash_id; PIOS_Flash_Jedec_Init(&flash_id, pios_spi_accel_id, 1, &flash_m25p_cfg); #endif - uint32_t fs_id; + uintptr_t fs_id; PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_m25p_cfg, &pios_jedec_flash_driver, flash_id); /* Initialize UAVObject libraries */ diff --git a/flight/tests/logfs/main.c b/flight/tests/logfs/main.c index 87f7dd1a2..466417ee6 100644 --- a/flight/tests/logfs/main.c +++ b/flight/tests/logfs/main.c @@ -38,7 +38,7 @@ int main (int argc, char * argv[]) abort(); } - uint32_t fs_id; + uintptr_t fs_id; rc = PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_config, &pios_ut_flash_driver, flash_id); if (rc != 0) { printf ("flash filesystem init failed (%d)\n", rc); From 17b86962610a9c6bcb439209837d072141c225e8 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Fri, 14 Dec 2012 23:13:33 -0500 Subject: [PATCH 14/33] flash: use uintptr_t to hold opaque pointers When storing an opaque pointer value in a uint, the appropriate type is uintptr_t which is guaranteed to be wide enough to hold a pointer. This is particularly important when the code can be compiled in a sim or unit test environment which is intended to run on a 64-bit machine. Conflicts: flight/PiOS/Common/pios_flash_jedec.c flight/targets/DiscoveryF4/System/pios_board.c flight/targets/FlyingF4/System/pios_board.c flight/targets/Freedom/System/pios_board.c flight/targets/Quanton/System/pios_board.c --- flight/PiOS/Common/pios_flash_jedec.c | 140 +++++++++--------- flight/PiOS/Common/pios_flashfs_logfs.c | 4 +- flight/PiOS/STM32F4xx/pios_flash_internal.c | 14 +- flight/PiOS/inc/pios_flash.h | 14 +- flight/PiOS/inc/pios_flash_internal_priv.h | 2 +- flight/PiOS/inc/pios_flash_jedec_priv.h | 2 +- flight/PiOS/inc/pios_flashfs_logfs_priv.h | 2 +- .../targets/CopterControl/System/pios_board.c | 2 +- flight/targets/RevoMini/System/pios_board.c | 4 +- flight/targets/Revolution/System/pios_board.c | 8 +- flight/tests/logfs/main.c | 2 +- flight/tests/logfs/pios_flash_ut.c | 14 +- 12 files changed, 104 insertions(+), 104 deletions(-) diff --git a/flight/PiOS/Common/pios_flash_jedec.c b/flight/PiOS/Common/pios_flash_jedec.c index cf614259b..b1abd039e 100644 --- a/flight/PiOS/Common/pios_flash_jedec.c +++ b/flight/PiOS/Common/pios_flash_jedec.c @@ -13,19 +13,19 @@ * @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 +/* + * 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 + * + * 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., + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "pios.h" @@ -86,10 +86,10 @@ static int32_t PIOS_Flash_Jedec_Busy(struct jedec_flash_dev * flash_dev); static struct jedec_flash_dev * PIOS_Flash_Jedec_alloc(void) { struct jedec_flash_dev * flash_dev; - + flash_dev = (struct jedec_flash_dev *)pvPortMalloc(sizeof(*flash_dev)); if (!flash_dev) return (NULL); - + flash_dev->claimed = false; flash_dev->magic = PIOS_JEDEC_DEV_MAGIC; #if defined(FLASH_FREERTOS) @@ -114,7 +114,7 @@ static int32_t PIOS_Flash_Jedec_Validate(struct jedec_flash_dev * flash_dev) { /** * @brief Initialize the flash device and enable write access */ -int32_t PIOS_Flash_Jedec_Init(uint32_t * flash_id, uint32_t spi_id, uint32_t slave_num, const struct pios_flash_jedec_cfg * cfg) +int32_t PIOS_Flash_Jedec_Init(uintptr_t * flash_id, uint32_t spi_id, uint32_t slave_num, const struct pios_flash_jedec_cfg * cfg) { struct jedec_flash_dev * flash_dev = PIOS_Flash_Jedec_alloc(); if (flash_dev == NULL) @@ -129,7 +129,7 @@ int32_t PIOS_Flash_Jedec_Init(uint32_t * flash_id, uint32_t spi_id, uint32_t sla return -1; /* Give back a handle to this flash device */ - *flash_id = (uint32_t) flash_dev; + *flash_id = (uintptr_t) flash_dev; return 0; } @@ -141,12 +141,12 @@ int32_t PIOS_Flash_Jedec_Init(uint32_t * flash_id, uint32_t spi_id, uint32_t sla */ static int32_t PIOS_Flash_Jedec_ClaimBus(struct jedec_flash_dev * flash_dev) { - if(PIOS_SPI_ClaimBus(flash_dev->spi_id) < 0) + if (PIOS_SPI_ClaimBus(flash_dev->spi_id) < 0) return -1; - + PIOS_SPI_RC_PinSet(flash_dev->spi_id, flash_dev->slave_num, 0); flash_dev->claimed = true; - + return 0; } @@ -246,15 +246,15 @@ static int32_t PIOS_Flash_Jedec_ReadID(struct jedec_flash_dev * flash_dev) * @brief Grab the semaphore to perform a transaction * @return 0 for success, -1 for timeout */ -static int32_t PIOS_Flash_Jedec_StartTransaction(uint32_t flash_id) +static int32_t PIOS_Flash_Jedec_StartTransaction(uintptr_t flash_id) { struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; - if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) + if (PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; #if defined(PIOS_INCLUDE_FREERTOS) - if(xSemaphoreTake(flash_dev->transaction_lock, portMAX_DELAY) != pdTRUE) + if (xSemaphoreTake(flash_dev->transaction_lock, portMAX_DELAY) != pdTRUE) return -2; #endif @@ -265,15 +265,15 @@ static int32_t PIOS_Flash_Jedec_StartTransaction(uint32_t flash_id) * @brief Release the semaphore to perform a transaction * @return 0 for success, -1 for timeout */ -static int32_t PIOS_Flash_Jedec_EndTransaction(uint32_t flash_id) +static int32_t PIOS_Flash_Jedec_EndTransaction(uintptr_t flash_id) { struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; - if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) + if (PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; #if defined(PIOS_INCLUDE_FREERTOS) - if(xSemaphoreGive(flash_dev->transaction_lock) != pdTRUE) + if (xSemaphoreGive(flash_dev->transaction_lock) != pdTRUE) return -2; #endif @@ -282,16 +282,16 @@ static int32_t PIOS_Flash_Jedec_EndTransaction(uint32_t flash_id) #else /* FLASH_USE_FREERTOS_LOCKS */ -static int32_t PIOS_Flash_Jedec_StartTransaction(uint32_t flash_id) +static int32_t PIOS_Flash_Jedec_StartTransaction(uintptr_t flash_id) { return 0; - } - -static int32_t PIOS_Flash_Jedec_EndTransaction(uint32_t flash_id) +} + +static int32_t PIOS_Flash_Jedec_EndTransaction(uintptr_t flash_id) { return 0; - } - +} + #endif /* FLASH_USE_FREERTOS_LOCKS */ /** @@ -301,11 +301,11 @@ static int32_t PIOS_Flash_Jedec_EndTransaction(uint32_t flash_id) * @retval -1 if unable to claim bus * @retval */ -static int32_t PIOS_Flash_Jedec_EraseSector(uint32_t flash_id, uint32_t addr) +static int32_t PIOS_Flash_Jedec_EraseSector(uintptr_t flash_id, uint32_t addr) { struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; - if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) + if (PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; uint8_t ret; @@ -316,12 +316,12 @@ static int32_t PIOS_Flash_Jedec_EraseSector(uint32_t flash_id, uint32_t addr) if (PIOS_Flash_Jedec_ClaimBus(flash_dev) != 0) return -1; - - if(PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { + + if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -2; } - + PIOS_Flash_Jedec_ReleaseBus(flash_dev); // Keep polling when bus is busy too @@ -338,11 +338,11 @@ static int32_t PIOS_Flash_Jedec_EraseSector(uint32_t flash_id, uint32_t addr) * @brief Execute the whole chip * @returns 0 if successful, -1 if unable to claim bus */ -static int32_t PIOS_Flash_Jedec_EraseChip(uint32_t flash_id) +static int32_t PIOS_Flash_Jedec_EraseChip(uintptr_t flash_id) { struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; - if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) + if (PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; uint8_t ret; @@ -353,12 +353,12 @@ static int32_t PIOS_Flash_Jedec_EraseChip(uint32_t flash_id) if (PIOS_Flash_Jedec_ClaimBus(flash_dev) != 0) return -1; - - if(PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { + + if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -2; } - + PIOS_Flash_Jedec_ReleaseBus(flash_dev); // Keep polling when bus is busy too @@ -372,7 +372,7 @@ static int32_t PIOS_Flash_Jedec_EraseChip(uint32_t flash_id) #endif PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); - + } return 0; @@ -389,7 +389,7 @@ static int32_t PIOS_Flash_Jedec_EraseChip(uint32_t flash_id) * @retval -2 Size exceeds 256 bytes * @retval -3 Length to write would wrap around page boundary */ -static int32_t PIOS_Flash_Jedec_WriteData(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) +static int32_t PIOS_Flash_Jedec_WriteData(uintptr_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) { struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; @@ -400,11 +400,11 @@ static int32_t PIOS_Flash_Jedec_WriteData(uint32_t flash_id, uint32_t addr, uint uint8_t out[4] = {JEDEC_PAGE_WRITE, (addr >> 16) & 0xff, (addr >> 8) & 0xff , addr & 0xff}; /* Can only write one page at a time */ - if(len > 0x100) + if (len > 0x100) return -2; /* Ensure number of bytes fits after starting address before end of page */ - if(((addr & 0xff) + len) > 0x100) + if (((addr & 0xff) + len) > 0x100) return -3; if ((ret = PIOS_Flash_Jedec_WriteEnable(flash_dev)) != 0) @@ -413,14 +413,14 @@ static int32_t PIOS_Flash_Jedec_WriteData(uint32_t flash_id, uint32_t addr, uint /* Execute write page command and clock in address. Keep CS asserted */ if (PIOS_Flash_Jedec_ClaimBus(flash_dev) != 0) return -1; - - if(PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { + + if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -1; } /* Clock out data to flash */ - if(PIOS_SPI_TransferBlock(flash_dev->spi_id,data,NULL,len,NULL) < 0) { + if (PIOS_SPI_TransferBlock(flash_dev->spi_id,data,NULL,len,NULL) < 0) { PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -1; } @@ -439,8 +439,8 @@ static int32_t PIOS_Flash_Jedec_WriteData(uint32_t flash_id, uint32_t addr, uint return -1; PIOS_SPI_TransferByte(flash_dev->spi_id, JEDEC_READ_STATUS); - while(PIOS_SPI_TransferByte(flash_dev->spi_id, JEDEC_READ_STATUS) & JEDEC_STATUS_BUSY); - + while (PIOS_SPI_TransferByte(flash_dev->spi_id, JEDEC_READ_STATUS) & JEDEC_STATUS_BUSY); + PIOS_Flash_Jedec_ReleaseBus(flash_dev); #endif @@ -457,45 +457,45 @@ static int32_t PIOS_Flash_Jedec_WriteData(uint32_t flash_id, uint32_t addr, uint * @retval -2 Size exceeds 256 bytes * @retval -3 Length to write would wrap around page boundary */ -static int32_t PIOS_Flash_Jedec_WriteChunks(uint32_t flash_id, uint32_t addr, struct pios_flash_chunk chunks[], uint32_t num) +static int32_t PIOS_Flash_Jedec_WriteChunks(uintptr_t flash_id, uint32_t addr, struct pios_flash_chunk chunks[], uint32_t num) { struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; - if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) + if (PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; - + uint8_t ret; uint8_t out[4] = {JEDEC_PAGE_WRITE, (addr >> 16) & 0xff, (addr >> 8) & 0xff , addr & 0xff}; - + /* Can only write one page at a time */ uint32_t len = 0; - for(uint32_t i = 0; i < num; i++) + for (uint32_t i = 0; i < num; i++) len += chunks[i].len; - if(len > 0x100) + if (len > 0x100) return -2; - + /* Ensure number of bytes fits after starting address before end of page */ - if(((addr & 0xff) + len) > 0x100) + if (((addr & 0xff) + len) > 0x100) return -3; - + if ((ret = PIOS_Flash_Jedec_WriteEnable(flash_dev)) != 0) return ret; - + /* Execute write page command and clock in address. Keep CS asserted */ if (PIOS_Flash_Jedec_ClaimBus(flash_dev) != 0) return -1; - - if(PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { + + if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -1; } - - for(uint32_t i = 0; i < num; i++) { + + for (uint32_t i = 0; i < num; i++) { struct pios_flash_chunk * chunk = &chunks[i]; - + /* Clock out data to flash */ - if(PIOS_SPI_TransferBlock(flash_dev->spi_id,chunk->addr,NULL,chunk->len,NULL) < 0) { + if (PIOS_SPI_TransferBlock(flash_dev->spi_id,chunk->addr,NULL,chunk->len,NULL) < 0) { PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -1; } @@ -516,11 +516,11 @@ static int32_t PIOS_Flash_Jedec_WriteChunks(uint32_t flash_id, uint32_t addr, st * @return Zero if success or error code * @retval -1 Unable to claim SPI bus */ -static int32_t PIOS_Flash_Jedec_ReadData(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) +static int32_t PIOS_Flash_Jedec_ReadData(uintptr_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) { struct jedec_flash_dev * flash_dev = (struct jedec_flash_dev *)flash_id; - if(PIOS_Flash_Jedec_Validate(flash_dev) != 0) + if (PIOS_Flash_Jedec_Validate(flash_dev) != 0) return -1; if (PIOS_Flash_Jedec_ClaimBus(flash_dev) == -1) @@ -528,14 +528,14 @@ static int32_t PIOS_Flash_Jedec_ReadData(uint32_t flash_id, uint32_t addr, uint8 /* Execute read command and clock in address. Keep CS asserted */ uint8_t out[] = {JEDEC_READ_DATA, (addr >> 16) & 0xff, (addr >> 8) & 0xff , addr & 0xff}; - - if(PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { + + if (PIOS_SPI_TransferBlock(flash_dev->spi_id,out,NULL,sizeof(out),NULL) < 0) { PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -2; } /* Copy the transfer data to the buffer */ - if(PIOS_SPI_TransferBlock(flash_dev->spi_id,NULL,data,len,NULL) < 0) { + if (PIOS_SPI_TransferBlock(flash_dev->spi_id,NULL,data,len,NULL) < 0) { PIOS_Flash_Jedec_ReleaseBus(flash_dev); return -3; } diff --git a/flight/PiOS/Common/pios_flashfs_logfs.c b/flight/PiOS/Common/pios_flashfs_logfs.c index f44122da3..588a901de 100644 --- a/flight/PiOS/Common/pios_flashfs_logfs.c +++ b/flight/PiOS/Common/pios_flashfs_logfs.c @@ -50,7 +50,7 @@ struct logfs_state { /* Underlying flash driver glue */ const struct pios_flash_driver * driver; - uint32_t flash_id; + uintptr_t flash_id; }; static struct logfs_state logfs; @@ -461,7 +461,7 @@ static int32_t logfs_mount_log(uint8_t arena_id) * @brief Initialize the flash object setting FS * @return 0 if success, -1 if failure */ -int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t * fs_id, const struct flashfs_logfs_cfg * cfg, const struct pios_flash_driver * driver, uint32_t flash_id) +int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t * fs_id, const struct flashfs_logfs_cfg * cfg, const struct pios_flash_driver * driver, uintptr_t flash_id) { PIOS_Assert(cfg); PIOS_Assert(fs_id); diff --git a/flight/PiOS/STM32F4xx/pios_flash_internal.c b/flight/PiOS/STM32F4xx/pios_flash_internal.c index c86cb7211..534b911fd 100644 --- a/flight/PiOS/STM32F4xx/pios_flash_internal.c +++ b/flight/PiOS/STM32F4xx/pios_flash_internal.c @@ -166,7 +166,7 @@ static struct pios_internal_flash_dev * PIOS_Flash_Internal_alloc(void) #endif /* defined(PIOS_INCLUDE_FREERTOS) */ -int32_t PIOS_Flash_Internal_Init(uint32_t * flash_id, const struct pios_flash_internal_cfg * cfg) +int32_t PIOS_Flash_Internal_Init(uintptr_t * flash_id, const struct pios_flash_internal_cfg * cfg) { struct pios_internal_flash_dev * flash_dev; @@ -178,7 +178,7 @@ int32_t PIOS_Flash_Internal_Init(uint32_t * flash_id, const struct pios_flash_in flash_dev->transaction_lock = xSemaphoreCreateMutex(); #endif /* defined(PIOS_INCLUDE_FREERTOS) */ - *flash_id = (uint32_t) flash_dev; + *flash_id = (uintptr_t) flash_dev; return 0; } @@ -190,7 +190,7 @@ int32_t PIOS_Flash_Internal_Init(uint32_t * flash_id, const struct pios_flash_in *********************************/ #include "pios_flash.h" -static int32_t PIOS_Flash_Internal_StartTransaction(uint32_t flash_id) +static int32_t PIOS_Flash_Internal_StartTransaction(uintptr_t flash_id) { struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id; @@ -207,7 +207,7 @@ static int32_t PIOS_Flash_Internal_StartTransaction(uint32_t flash_id) return 0; } -static int32_t PIOS_Flash_Internal_EndTransaction(uint32_t flash_id) +static int32_t PIOS_Flash_Internal_EndTransaction(uintptr_t flash_id) { struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id; @@ -225,7 +225,7 @@ static int32_t PIOS_Flash_Internal_EndTransaction(uint32_t flash_id) return 0; } -static int32_t PIOS_Flash_Internal_EraseSector(uint32_t flash_id, uint32_t addr) +static int32_t PIOS_Flash_Internal_EraseSector(uintptr_t flash_id, uint32_t addr) { struct pios_internal_flash_dev * flash_dev = (struct pios_internal_flash_dev *)flash_id; @@ -249,7 +249,7 @@ static int32_t PIOS_Flash_Internal_EraseSector(uint32_t flash_id, uint32_t addr) return 0; } -static int32_t PIOS_Flash_Internal_WriteData(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) +static int32_t PIOS_Flash_Internal_WriteData(uintptr_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) { PIOS_Assert(data); @@ -291,7 +291,7 @@ static int32_t PIOS_Flash_Internal_WriteData(uint32_t flash_id, uint32_t addr, u return 0; } -static int32_t PIOS_Flash_Internal_ReadData(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) +static int32_t PIOS_Flash_Internal_ReadData(uintptr_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) { PIOS_Assert(data); diff --git a/flight/PiOS/inc/pios_flash.h b/flight/PiOS/inc/pios_flash.h index 7ea28398b..8ae69ab3f 100644 --- a/flight/PiOS/inc/pios_flash.h +++ b/flight/PiOS/inc/pios_flash.h @@ -35,13 +35,13 @@ struct pios_flash_chunk { }; struct pios_flash_driver { - int32_t (*start_transaction)(uint32_t flash_id); - int32_t (*end_transaction)(uint32_t flash_id); - int32_t (*erase_chip)(uint32_t flash_id); - int32_t (*erase_sector)(uint32_t flash_id, uint32_t addr); - int32_t (*write_data)(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len); - int32_t (*write_chunks)(uint32_t flash_id, uint32_t addr, struct pios_flash_chunk chunks[], uint32_t num_chunks); - int32_t (*read_data)(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len); + int32_t (*start_transaction)(uintptr_t flash_id); + int32_t (*end_transaction)(uintptr_t flash_id); + int32_t (*erase_chip)(uintptr_t flash_id); + int32_t (*erase_sector)(uintptr_t flash_id, uint32_t addr); + int32_t (*write_data)(uintptr_t flash_id, uint32_t addr, uint8_t * data, uint16_t len); + int32_t (*write_chunks)(uintptr_t flash_id, uint32_t addr, struct pios_flash_chunk chunks[], uint32_t num_chunks); + int32_t (*read_data)(uintptr_t flash_id, uint32_t addr, uint8_t * data, uint16_t len); }; #endif /* PIOS_FLASH_H_ */ diff --git a/flight/PiOS/inc/pios_flash_internal_priv.h b/flight/PiOS/inc/pios_flash_internal_priv.h index b17682ae4..4c690fefb 100644 --- a/flight/PiOS/inc/pios_flash_internal_priv.h +++ b/flight/PiOS/inc/pios_flash_internal_priv.h @@ -35,6 +35,6 @@ struct pios_flash_internal_cfg { ; }; -extern int32_t PIOS_Flash_Internal_Init(uint32_t * flash_id, const struct pios_flash_internal_cfg * cfg); +extern int32_t PIOS_Flash_Internal_Init(uintptr_t * flash_id, const struct pios_flash_internal_cfg * cfg); #endif /* PIOS_FLASH_INTERNAL_H_ */ diff --git a/flight/PiOS/inc/pios_flash_jedec_priv.h b/flight/PiOS/inc/pios_flash_jedec_priv.h index 180e929bc..80a82f97d 100644 --- a/flight/PiOS/inc/pios_flash_jedec_priv.h +++ b/flight/PiOS/inc/pios_flash_jedec_priv.h @@ -40,6 +40,6 @@ struct pios_flash_jedec_cfg { uint32_t chip_erase; }; -int32_t PIOS_Flash_Jedec_Init(uint32_t * flash_id, uint32_t spi_id, uint32_t slave_num, const struct pios_flash_jedec_cfg * cfg); +int32_t PIOS_Flash_Jedec_Init(uintptr_t * flash_id, uint32_t spi_id, uint32_t slave_num, const struct pios_flash_jedec_cfg * cfg); #endif /* PIOS_FLASH_JEDEC_H_ */ diff --git a/flight/PiOS/inc/pios_flashfs_logfs_priv.h b/flight/PiOS/inc/pios_flashfs_logfs_priv.h index ead6177df..d948f4f76 100644 --- a/flight/PiOS/inc/pios_flashfs_logfs_priv.h +++ b/flight/PiOS/inc/pios_flashfs_logfs_priv.h @@ -41,6 +41,6 @@ struct flashfs_logfs_cfg { uint32_t page_size; /* Maximum flash burst write size */ }; -int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t * fs_id, const struct flashfs_logfs_cfg * cfg, const struct pios_flash_driver * driver, uint32_t flash_id); +int32_t PIOS_FLASHFS_Logfs_Init(uintptr_t * fs_id, const struct flashfs_logfs_cfg * cfg, const struct pios_flash_driver * driver, uintptr_t flash_id); #endif /* PIOS_FLASHFS_LOGFS_PRIV_H_ */ diff --git a/flight/targets/CopterControl/System/pios_board.c b/flight/targets/CopterControl/System/pios_board.c index 726d82182..49928d786 100644 --- a/flight/targets/CopterControl/System/pios_board.c +++ b/flight/targets/CopterControl/System/pios_board.c @@ -162,7 +162,7 @@ void PIOS_Board_Init(void) { #endif - uint32_t flash_id; + uintptr_t flash_id; uintptr_t fs_id; switch(bdinfo->board_rev) { case BOARD_REVISION_CC: diff --git a/flight/targets/RevoMini/System/pios_board.c b/flight/targets/RevoMini/System/pios_board.c index b226077c7..a8ff61799 100644 --- a/flight/targets/RevoMini/System/pios_board.c +++ b/flight/targets/RevoMini/System/pios_board.c @@ -300,8 +300,8 @@ void PIOS_Board_Init(void) { } #if defined(PIOS_INCLUDE_FLASH) - /* Connect flash to the approrpiate interface and configure it */ - uint32_t flash_id; + /* Connect flash to the appropriate interface and configure it */ + uintptr_t flash_id; PIOS_Flash_Jedec_Init(&flash_id, pios_spi_telem_flash_id, 1, &flash_m25p_cfg); uintptr_t fs_id; PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_m25p_cfg, &pios_jedec_flash_driver, flash_id); diff --git a/flight/targets/Revolution/System/pios_board.c b/flight/targets/Revolution/System/pios_board.c index 2c766e148..7d105a964 100644 --- a/flight/targets/Revolution/System/pios_board.c +++ b/flight/targets/Revolution/System/pios_board.c @@ -381,12 +381,12 @@ void PIOS_Board_Init(void) { if (PIOS_SPI_Init(&pios_spi_flash_id, &pios_spi_flash_cfg)) { PIOS_DEBUG_Assert(0); } - /* Connect flash to the approrpiate interface and configure it */ - uint32_t flash_id; + /* Connect flash to the appropriate interface and configure it */ + uintptr_t flash_id; PIOS_Flash_Jedec_Init(&flash_id, pios_spi_flash_id, 0, &flash_m25p_cfg); #else - /* Connect flash to the approrpiate interface and configure it */ - uint32_t flash_id; + /* Connect flash to the appropriate interface and configure it */ + uintptr_t flash_id; PIOS_Flash_Jedec_Init(&flash_id, pios_spi_accel_id, 1, &flash_m25p_cfg); #endif uintptr_t fs_id; diff --git a/flight/tests/logfs/main.c b/flight/tests/logfs/main.c index 466417ee6..65d2f018a 100644 --- a/flight/tests/logfs/main.c +++ b/flight/tests/logfs/main.c @@ -31,7 +31,7 @@ int main (int argc, char * argv[]) /* dd if=/dev/zero bs=1 count=2MiB | tr '\000' '\377' > theflash.bin */ - uint32_t flash_id; + uintptr_t flash_id; rc = PIOS_Flash_UT_Init(&flash_id, &flash_config); if (rc != 0) { printf ("flash init failed (%d)\n", rc); diff --git a/flight/tests/logfs/pios_flash_ut.c b/flight/tests/logfs/pios_flash_ut.c index 3ed3c6cce..37fc4d980 100644 --- a/flight/tests/logfs/pios_flash_ut.c +++ b/flight/tests/logfs/pios_flash_ut.c @@ -26,7 +26,7 @@ static struct flash_ut_dev * PIOS_Flash_UT_Alloc(void) return flash_dev; } -int32_t PIOS_Flash_UT_Init(uint32_t * flash_id, const struct pios_flash_ut_cfg * cfg) +int32_t PIOS_Flash_UT_Init(uintptr_t * flash_id, const struct pios_flash_ut_cfg * cfg) { /* Check inputs */ assert(flash_id); @@ -50,7 +50,7 @@ int32_t PIOS_Flash_UT_Init(uint32_t * flash_id, const struct pios_flash_ut_cfg * return -2; } - *flash_id = (uint32_t)flash_dev; + *flash_id = (uintptr_t)flash_dev; return 0; } @@ -62,7 +62,7 @@ int32_t PIOS_Flash_UT_Init(uint32_t * flash_id, const struct pios_flash_ut_cfg * *********************************/ #include "pios_flash.h" -static int32_t PIOS_Flash_UT_StartTransaction(uint32_t flash_id) +static int32_t PIOS_Flash_UT_StartTransaction(uintptr_t flash_id) { struct flash_ut_dev * flash_dev = (struct flash_ut_dev *)flash_id; @@ -73,7 +73,7 @@ static int32_t PIOS_Flash_UT_StartTransaction(uint32_t flash_id) return 0; } -static int32_t PIOS_Flash_UT_EndTransaction(uint32_t flash_id) +static int32_t PIOS_Flash_UT_EndTransaction(uintptr_t flash_id) { struct flash_ut_dev * flash_dev = (struct flash_ut_dev *)flash_id; @@ -84,7 +84,7 @@ static int32_t PIOS_Flash_UT_EndTransaction(uint32_t flash_id) return 0; } -static int32_t PIOS_Flash_UT_EraseSector(uint32_t flash_id, uint32_t addr) +static int32_t PIOS_Flash_UT_EraseSector(uintptr_t flash_id, uint32_t addr) { struct flash_ut_dev * flash_dev = (struct flash_ut_dev *)flash_id; @@ -106,7 +106,7 @@ static int32_t PIOS_Flash_UT_EraseSector(uint32_t flash_id, uint32_t addr) return 0; } -static int32_t PIOS_Flash_UT_WriteData(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) +static int32_t PIOS_Flash_UT_WriteData(uintptr_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) { /* Check inputs */ assert(data); @@ -127,7 +127,7 @@ static int32_t PIOS_Flash_UT_WriteData(uint32_t flash_id, uint32_t addr, uint8_t return 0; } -static int32_t PIOS_Flash_UT_ReadData(uint32_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) +static int32_t PIOS_Flash_UT_ReadData(uintptr_t flash_id, uint32_t addr, uint8_t * data, uint16_t len) { /* Check inputs */ assert(data); From b6eeb59b2674c0a1bab1d03b1323674435f67e77 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Fri, 14 Dec 2012 23:16:31 -0500 Subject: [PATCH 15/33] flash: verify JEDEC ID during flash init Verify that the flash component on the board matches exactly what we're expecting. This is a simple way to verify that we are communicating properly with the JEDEC flash chip. Conflicts: flight/targets/board_hw_defs/freedom/board_hw_defs.c flight/targets/board_hw_defs/quanton/board_hw_defs.c --- flight/PiOS/Common/pios_flash_jedec.c | 24 ++++++++++++------- flight/PiOS/inc/pios_flash_jedec_priv.h | 7 ++++++ .../coptercontrol/board_hw_defs.c | 14 +++++++---- .../board_hw_defs/revolution/board_hw_defs.c | 7 ++++-- .../board_hw_defs/revomini/board_hw_defs.c | 7 ++++-- 5 files changed, 42 insertions(+), 17 deletions(-) diff --git a/flight/PiOS/Common/pios_flash_jedec.c b/flight/PiOS/Common/pios_flash_jedec.c index b1abd039e..6d382a1c1 100644 --- a/flight/PiOS/Common/pios_flash_jedec.c +++ b/flight/PiOS/Common/pios_flash_jedec.c @@ -49,8 +49,6 @@ #define JEDEC_STATUS_SEC 0x40 #define JEDEC_STATUS_SRP0 0x80 -static uint8_t device_type; - enum pios_jedec_dev_magic { PIOS_JEDEC_DEV_MAGIC = 0xcb55aa55, }; @@ -60,8 +58,11 @@ struct jedec_flash_dev { uint32_t spi_id; uint32_t slave_num; bool claimed; - uint32_t device_type; - uint32_t capacity; + + uint8_t manufacturer; + uint8_t memorytype; + uint8_t capacity; + const struct pios_flash_jedec_cfg * cfg; #if defined(FLASH_FREERTOS) xSemaphoreHandle transaction_lock; @@ -124,9 +125,13 @@ int32_t PIOS_Flash_Jedec_Init(uintptr_t * flash_id, uint32_t spi_id, uint32_t sl flash_dev->slave_num = slave_num; flash_dev->cfg = cfg; - device_type = PIOS_Flash_Jedec_ReadID(flash_dev); - if (device_type == 0) + (void) PIOS_Flash_Jedec_ReadID(flash_dev); + if ((flash_dev->manufacturer != flash_dev->cfg->expect_manufacturer) || + (flash_dev->memorytype != flash_dev->cfg->expect_memorytype) || + (flash_dev->capacity != flash_dev->cfg->expect_capacity)) { + /* Mismatched device has been discovered */ return -1; + } /* Give back a handle to this flash device */ *flash_id = (uintptr_t) flash_dev; @@ -227,10 +232,11 @@ static int32_t PIOS_Flash_Jedec_ReadID(struct jedec_flash_dev * flash_dev) PIOS_Flash_Jedec_ReleaseBus(flash_dev); - flash_dev->device_type = in[1]; - flash_dev->capacity = in[3]; + flash_dev->manufacturer = in[1]; + flash_dev->memorytype = in[2]; + flash_dev->capacity = in[3]; - return in[1]; + return flash_dev->manufacturer; } /********************************** diff --git a/flight/PiOS/inc/pios_flash_jedec_priv.h b/flight/PiOS/inc/pios_flash_jedec_priv.h index 80a82f97d..8b772c0b9 100644 --- a/flight/PiOS/inc/pios_flash_jedec_priv.h +++ b/flight/PiOS/inc/pios_flash_jedec_priv.h @@ -35,7 +35,14 @@ extern const struct pios_flash_driver pios_jedec_flash_driver; +#define JEDEC_MANUFACTURER_ST 0x20 +#define JEDEC_MANUFACTURER_MACRONIX 0xC2 +#define JEDEC_MANUFACTURER_WINBOND 0xEF + struct pios_flash_jedec_cfg { + uint8_t expect_manufacturer; + uint8_t expect_memorytype; + uint8_t expect_capacity; uint32_t sector_erase; uint32_t chip_erase; }; diff --git a/flight/targets/board_hw_defs/coptercontrol/board_hw_defs.c b/flight/targets/board_hw_defs/coptercontrol/board_hw_defs.c index 97d8743ce..4c425d529 100644 --- a/flight/targets/board_hw_defs/coptercontrol/board_hw_defs.c +++ b/flight/targets/board_hw_defs/coptercontrol/board_hw_defs.c @@ -415,8 +415,11 @@ static const struct flashfs_logfs_cfg flashfs_w25x_cfg = { }; static const struct pios_flash_jedec_cfg flash_w25x_cfg = { - .sector_erase = 0x20, - .chip_erase = 0x60 + .expect_manufacturer = JEDEC_MANUFACTURER_WINBOND, + .expect_memorytype = 0x30, + .expect_capacity = 0x13, + .sector_erase = 0x20, + .chip_erase = 0x60 }; static const struct flashfs_logfs_cfg flashfs_m25p_cfg = { @@ -431,8 +434,11 @@ static const struct flashfs_logfs_cfg flashfs_m25p_cfg = { }; static const struct pios_flash_jedec_cfg flash_m25p_cfg = { - .sector_erase = 0xD8, - .chip_erase = 0xC7 + .expect_manufacturer = JEDEC_MANUFACTURER_ST, + .expect_memorytype = 0x20, + .expect_capacity = 0x15, + .sector_erase = 0xD8, + .chip_erase = 0xC7, }; #include "pios_flash.h" diff --git a/flight/targets/board_hw_defs/revolution/board_hw_defs.c b/flight/targets/board_hw_defs/revolution/board_hw_defs.c index 513a318cb..75128549f 100644 --- a/flight/targets/board_hw_defs/revolution/board_hw_defs.c +++ b/flight/targets/board_hw_defs/revolution/board_hw_defs.c @@ -463,8 +463,11 @@ static const struct flashfs_logfs_cfg flashfs_m25p_cfg = { }; static const struct pios_flash_jedec_cfg flash_m25p_cfg = { - .sector_erase = 0xD8, - .chip_erase = 0xC7 + .expect_manufacturer = JEDEC_MANUFACTURER_ST, + .expect_memorytype = 0x20, + .expect_capacity = 0x15, + .sector_erase = 0xD8, + .chip_erase = 0xC7, }; #endif /* PIOS_INCLUDE_FLASH */ diff --git a/flight/targets/board_hw_defs/revomini/board_hw_defs.c b/flight/targets/board_hw_defs/revomini/board_hw_defs.c index 0ad69a044..30844dd0a 100644 --- a/flight/targets/board_hw_defs/revomini/board_hw_defs.c +++ b/flight/targets/board_hw_defs/revomini/board_hw_defs.c @@ -578,8 +578,11 @@ static const struct flashfs_logfs_cfg flashfs_m25p_cfg = { }; static const struct pios_flash_jedec_cfg flash_m25p_cfg = { - .sector_erase = 0xD8, - .chip_erase = 0xC7 + .expect_manufacturer = JEDEC_MANUFACTURER_ST, + .expect_memorytype = 0x20, + .expect_capacity = 0x15, + .sector_erase = 0xD8, + .chip_erase = 0xC7, }; #endif /* PIOS_INCLUDE_FLASH */ From b211840104dfca29b82958a2daa246e8491a4ec5 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Tue, 18 Dec 2012 00:58:33 -0500 Subject: [PATCH 16/33] logfs: allow loading zero length files This was found by the logfs unit tests. This may be useful if we want to use empty files as existence flags in the future. Doesn't make any sense for UAVOs but is valid in the general sense of a filesystem. --- flight/PiOS/Common/pios_flashfs_logfs.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/flight/PiOS/Common/pios_flashfs_logfs.c b/flight/PiOS/Common/pios_flashfs_logfs.c index 588a901de..5861a1b24 100644 --- a/flight/PiOS/Common/pios_flashfs_logfs.c +++ b/flight/PiOS/Common/pios_flashfs_logfs.c @@ -914,14 +914,16 @@ int32_t PIOS_FLASHFS_ObjLoad(uint32_t fs_id, uint32_t obj_id, uint16_t obj_inst_ } /* Read the contents of the object from the log */ - uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, slot_id); - if (logfs.driver->read_data(logfs.flash_id, - slot_addr + sizeof(slot_hdr), - (uint8_t *)obj_data, - obj_size) != 0) { - /* Failed to read object data from the log */ - rc = -4; - goto out_end_trans; + if (obj_size > 0) { + uintptr_t slot_addr = logfs_get_addr (logfs.active_arena_id, slot_id); + if (logfs.driver->read_data(logfs.flash_id, + slot_addr + sizeof(slot_hdr), + (uint8_t *)obj_data, + obj_size) != 0) { + /* Failed to read object data from the log */ + rc = -4; + goto out_end_trans; + } } /* Object successfully loaded */ From 842b275e139eabb498e28de8647258d988b7cef6 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Tue, 18 Dec 2012 01:03:31 -0500 Subject: [PATCH 17/33] logfs: fix bugs in handling full filesystem conditions This was caught by the logfs unit tests. --- flight/PiOS/Common/pios_flashfs_logfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/flight/PiOS/Common/pios_flashfs_logfs.c b/flight/PiOS/Common/pios_flashfs_logfs.c index 5861a1b24..5bad06383 100644 --- a/flight/PiOS/Common/pios_flashfs_logfs.c +++ b/flight/PiOS/Common/pios_flashfs_logfs.c @@ -385,7 +385,7 @@ static int32_t logfs_raw_copy_bytes (uintptr_t src_addr, uint16_t src_size, uint */ static bool logfs_fs_is_full(void) { - return (logfs.num_active_slots == (logfs.cfg->arena_size / logfs.cfg->slot_size)); + return (logfs.num_active_slots == (logfs.cfg->arena_size / logfs.cfg->slot_size) - 1); } /* @@ -663,6 +663,8 @@ static int8_t logfs_delete_object (uint32_t obj_id, uint16_t obj_inst_id) rc = -2; goto out_exit; } + /* Object has been successfully obsoleted and is no longer active */ + logfs.num_active_slots--; break; case -1: /* Search completed, object not found */ From e05ec8ed2733aed37a251d81cb69670664040a29 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Tue, 18 Dec 2012 01:51:07 -0500 Subject: [PATCH 18/33] ut: drop dependency on C++0x Conflicts: make/unittest.mk --- make/unittest.mk | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/make/unittest.mk b/make/unittest.mk index 0991a4827..18559bfb4 100644 --- a/make/unittest.mk +++ b/make/unittest.mk @@ -23,12 +23,35 @@ # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# Flags passed to the preprocessor. +CPPFLAGS += -I$(GTEST_DIR)/include + +# Flags passed to the C++ compiler. +CXXFLAGS += -g -Wall -Wextra + +# All Google Test headers. +GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ + $(GTEST_DIR)/include/gtest/internal/*.h + +# Google Test libraries +GTEST_LIBS = $(GTEST_DIR)/lib/.libs/libgtest_main.a $(GTEST_DIR)/lib/.libs/libgtest.a + +# Google Test needs the pthread library +LDFLAGS += -lpthread + +################################# +# +# Template to build the user test +# +################################# + # Need to disable THUMB mode for unit tests override THUMB := EXTRAINCDIRS += . ALLSRC := $(SRC) $(wildcard ./*.c) -ALLSRCBASE := $(notdir $(basename $(ALLSRC))) +ALLCPPSRC := $(wildcard ./*.cpp) +ALLSRCBASE := $(notdir $(basename $(ALLSRC) $(ALLCPPSRC))) ALLOBJ := $(addprefix $(OUTDIR)/, $(addsuffix .o, $(ALLSRCBASE))) .PHONY: $(TARGET) @@ -39,5 +62,7 @@ $(OUTDIR): $(V1) mkdir -p $@ $(foreach src,$(ALLSRC),$(eval $(call COMPILE_C_TEMPLATE,$(src)))) -$(eval $(call LINK_TEMPLATE,$(OUTDIR)/$(TARGET).elf,$(ALLOBJ))) +$(foreach src,$(ALLCPPSRC),$(eval $(call COMPILE_CXX_TEMPLATE,$(src)))) + +$(eval $(call LINK_CXX_TEMPLATE,$(OUTDIR)/$(TARGET).elf,$(ALLOBJ) $(GTEST_LIBS))) From f934ebfd4c8fd2609f14d051318f063c394f4ec4 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sat, 15 Dec 2012 19:32:38 -0500 Subject: [PATCH 19/33] makefile: ensure that the builds are not run as root When running the build as root, any bugs in the Makefiles can have disasterous results. This will be even more important once we start automatically running unit tests as part of our build. This change ensures that the builds cannot be run as root. --- Makefile | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Makefile b/Makefile index a57bf3f75..f4616023d 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,21 @@ $(foreach var, $(SANITIZE_GCC_VARS), $(eval $(call SANITIZE_VAR,$(var),disallowe SANITIZE_DEPRECATED_VARS := USE_BOOTLOADER $(foreach var, $(SANITIZE_DEPRECATED_VARS), $(eval $(call SANITIZE_VAR,$(var),deprecated))) +# Deal with unreasonable requests +# See: http://xkcd.com/149/ +ifeq ($(MAKECMDGOALS),me a sandwich) + ifeq ($(shell whoami),root) + $(error Okay) + else + $(error What? Make it yourself) + endif +endif + +# Make sure this isn't being run as root +ifeq ($(shell whoami),root) +$(error You should not be running this as root) +endif + # Decide on a verbosity level based on the V= parameter export AT := @ From e00372a54026315e22ab7412b25148d2af226336 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 16 Dec 2012 00:18:07 -0500 Subject: [PATCH 20/33] makefile: define ARCH before including make/tools.mk ARCH is required in order to pick up the right versions of the tools for each architecture. --- Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f4616023d..713c105c9 100644 --- a/Makefile +++ b/Makefile @@ -58,14 +58,17 @@ export V1 := $(AT) else ifeq ($(V), 1) endif +# Make sure we know a few things about the architecture before including +# the tools.mk to ensure that we download/install the right tools. +UNAME := $(shell uname) +ARCH := $(shell uname -m) + include $(ROOT_DIR)/make/tools.mk # We almost need to consider autoconf/automake instead of this # I don't know if windows supports uname :-( QT_SPEC=win32-g++ UAVOBJGENERATOR="$(BUILD_DIR)/ground/uavobjgenerator/debug/uavobjgenerator.exe" -UNAME := $(shell uname) -ARCH := $(shell uname -m) ifeq ($(UNAME), Linux) QT_SPEC=linux-g++ UAVOBJGENERATOR="$(BUILD_DIR)/ground/uavobjgenerator/uavobjgenerator" From 264d76382bca306eca4e13fdf4a6ec87df9578cc Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 16 Dec 2012 02:14:34 -0500 Subject: [PATCH 21/33] makefile: allow arch-specific path to qmake This will be required once we move to Qt5. --- Makefile | 4 ++-- make/tools.mk | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 713c105c9..bed8b91a6 100644 --- a/Makefile +++ b/Makefile @@ -185,10 +185,10 @@ $(BUILD_DIR): ############################## ifeq ($(shell [ -d "$(QT_SDK_DIR)" ] && echo "exists"), exists) - QMAKE=$(QT_SDK_DIR)/Desktop/Qt/4.8.1/gcc/bin/qmake + QMAKE = $(QT_SDK_QMAKE_PATH) else # not installed, hope it's in the path... - QMAKE=qmake + QMAKE = qmake endif ifeq ($(shell [ -d "$(ARM_SDK_DIR)" ] && echo "exists"), exists) diff --git a/make/tools.mk b/make/tools.mk index 49e58066f..25ad92e4f 100644 --- a/make/tools.mk +++ b/make/tools.mk @@ -14,10 +14,12 @@ QT_SDK_DIR := $(TOOLS_DIR)/qtsdk-v1.2.1 # Choose the appropriate installer based on host architecture ifneq (,$(filter $(ARCH), x86_64 amd64)) # 64-bit +QT_SDK_QMAKE_PATH := $(QT_SDK_DIR)/Desktop/Qt/4.8.1/gcc/bin/qmake qt_sdk_install: QT_SDK_FILE := QtSdk-offline-linux-x86_64-v1.2.1.run qt_sdk_install: QT_SDK_URL := http://www.developer.nokia.com/dp?uri=http://sw.nokia.com/id/14b2039c-0e1f-4774-a4f2-9aa60b6d5313/Qt_SDK_Lin64_offline else # 32-bit +QT_SDK_QMAKE_PATH := $(QT_SDK_DIR)/Desktop/Qt/4.8.1/gcc/bin/qmake qt_sdk_install: QT_SDK_URL := http://www.developer.nokia.com/dp?uri=http://sw.nokia.com/id/8ea74da4-fec1-4277-8b26-c58cc82e204b/Qt_SDK_Lin32_offline qt_sdk_install: QT_SDK_FILE := QtSdk-offline-linux-x86-v1.2.1.run endif From 06f805b00e9ae456dd1dedcb91861b4e363b9f7f Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Tue, 18 Dec 2012 00:55:05 -0500 Subject: [PATCH 22/33] ut: add googletest (gtest) install rules See: http://code.google.com/p/googletest/ --- make/tools.mk | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/make/tools.mk b/make/tools.mk index 25ad92e4f..753a2cb62 100644 --- a/make/tools.mk +++ b/make/tools.mk @@ -318,3 +318,42 @@ android_sdk_update: $(V0) @echo " UPDATE $(ANDROID_SDK_DIR)" $(ANDROID_SDK_DIR)/tools/android update sdk --no-ui -t platform-tools,android-16,addon-google_apis-google-16 +# Set up Google Test (gtest) tools +ifeq ($(V), 1) +GTEST_SILENT := +else +GTEST_SILENT := --silent +endif + +GTEST_DIR := $(TOOLS_DIR)/gtest-1.6.0 +GTEST_BUILD_DIR := $(DL_DIR)/gtest-build + +.PHONY: gtest_install +gtest_install: | $(DL_DIR) $(TOOLS_DIR) +gtest_install: GTEST_URL := http://googletest.googlecode.com/files/gtest-1.6.0.zip +gtest_install: GTEST_FILE := $(notdir $(GTEST_URL)) +gtest_install: gtest_clean + # download the file unconditionally since google code gives back 404 + # for HTTP HEAD requests which are used when using the wget -N option + $(V1) [ ! -f "$(DL_DIR)/$(GTEST_FILE)" ] || $(RM) -f "$(DL_DIR)/$(GTEST_FILE)" + $(V1) wget -P "$(DL_DIR)" --trust-server-name "$(GTEST_URL)" + + # extract the source + $(V1) [ ! -d "$(GTEST_DIR)" ] || $(RM) -rf "$(GTEST_DIR)" + $(V1) mkdir -p "$(GTEST_DIR)" + $(V1) unzip -q -d "$(TOOLS_DIR)" "$(DL_DIR)/$(GTEST_FILE)" + + # build + $(V1) ( \ + cd $(GTEST_DIR) ; \ + ./configure $(GTEST_SILENT) ; \ + $(MAKE) $(GTEST_SILENT) ; \ + ) + + # delete the extracted source when we're done + #$(V1) [ ! -d "$(GTEST_BUILD_DIR)" ] || $(RM) -rf "$(GTEST_BUILD_DIR)" + +.PHONY: gtest_clean +gtest_clean: + $(V0) @echo " CLEAN $(GTEST_DIR)" + $(V1) [ ! -d "$(GTEST_DIR)" ] || $(RM) -rf "$(GTEST_DIR)" From 14c5af61487dbf60ac778531687d89e627d9683c Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Thu, 20 Dec 2012 02:02:35 -0500 Subject: [PATCH 23/33] ut: convert make rules to template and add TAP file generation Make targets changed to: make ut_ make ut__tap make ut__run make ut__clean make all_ut make all_ut_tap make all_ut_run make all_ut_clean Conflicts: Makefile --- Makefile | 68 ++++++++++++++++++++++++++++++++++++++---------- make/tools.mk | 3 --- make/unittest.mk | 19 +++++++++----- 3 files changed, 67 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index bed8b91a6..fe92b2942 100644 --- a/Makefile +++ b/Makefile @@ -116,6 +116,10 @@ help: @echo " all_ - Build all available images for " @echo " all__clean - Remove all available images for " @echo + @echo " all_ut - Build all unit tests" + @echo " all_ut_tap - Run all unit tests and capture all TAP output to files" + @echo " all_ut_run - Run all unit tests and dump TAP output to console" + @echo @echo " [Firmware]" @echo " - Build firmware for " @echo " supported boards are ($(ALL_BOARDS))" @@ -138,6 +142,10 @@ help: @echo " [Unbrick a board]" @echo " unbrick_ - Use the STM32's built in boot ROM to write a bootloader to " @echo " supported boards are ($(BL_BOARDS))" + @echo " [Unittests]" + @echo " ut_ - Build unit test " + @echo " ut__tap - Run test and capture TAP output into a file" + @echo " ut__run - Run test and dump TAP output to console" @echo @echo " [Simulation]" @echo " sim_osx - Build OpenPilot simulation firmware for OSX" @@ -733,37 +741,69 @@ sim_osx_%: uavobjects_flight # ############################## -UT_TARGETS := logfs -.PHONY: ut_all -ut_all: $(addprefix ut_, $(UT_TARGETS)) +ALL_UNITTESTS := logfs UT_OUT_DIR := $(BUILD_DIR)/unit_tests $(UT_OUT_DIR): $(V1) mkdir -p $@ -ut_%: $(UT_OUT_DIR) - $(V1) cd $(ROOT_DIR)/flight/tests/$* && \ - $(MAKE) --no-print-directory \ +.PHONY: all_ut +all_ut: $(addsuffix _elf, $(addprefix ut_, $(ALL_UNITTESTS))) + +.PHONY: all_ut_tap +all_ut_tap: $(addsuffix _tap, $(addprefix ut_, $(ALL_UNITTESTS))) + +.PHONY: all_ut_run +all_ut_run: $(addsuffix _run, $(addprefix ut_, $(ALL_UNITTESTS))) + +.PHONY: ut_all_clean +all_ut_clean: + $(V0) @echo " CLEAN $@" + $(V1) [ ! -d "$(UT_OUT_DIR)" ] || $(RM) -r "$(UT_OUT_DIR)" + +# $(1) = Unit test name +define UT_TEMPLATE +.PHONY: ut_$(1) +ut_$(1): ut_$(1)_run + +ut_$(1)_%: $$(UT_OUT_DIR) + $(V1) mkdir -p $(UT_OUT_DIR)/$(1) + $(V1) cd $(ROOT_DIR)/flight/tests/$(1) && \ + $$(MAKE) -r --no-print-directory \ BUILD_TYPE=ut \ - BOARD_SHORT_NAME=$* \ + BOARD_SHORT_NAME=$(1) \ TCHAIN_PREFIX="" \ REMOVE_CMD="$(RM)" \ \ - TARGET=$* \ - OUTDIR="$(UT_OUT_DIR)/$*" \ + TARGET=$(1) \ + OUTDIR="$(UT_OUT_DIR)/$(1)" \ \ PIOS=$(PIOS) \ OPUAVOBJ=$(OPUAVOBJ) \ OPUAVTALK=$(OPUAVTALK) \ FLIGHTLIB=$(FLIGHTLIB) \ \ - $* + GTEST_DIR=$(GTEST_DIR) \ + \ + $$* -.PHONY: ut_clean -ut_clean: - $(V0) @echo " CLEAN $@" - $(V1) [ ! -d "$(UT_OUT_DIR)" ] || $(RM) -r "$(UT_OUT_DIR)" +.PHONY: ut_$(1)_clean +ut_$(1)_clean: + $(V0) @echo " CLEAN $(1)" + $(V1) [ ! -d "$(UT_OUT_DIR)/$(1)" ] || $(RM) -r "$(UT_OUT_DIR)/$(1)" + +endef + +# Expand the unittest rules +$(foreach ut, $(ALL_UNITTESTS), $(eval $(call UT_TEMPLATE,$(ut)))) + +# Disable parallel make when the all_ut_run target is requested otherwise the TAP +# output is interleaved with the rest of the make output. +ifneq ($(strip $(filter all_ut_run,$(MAKECMDGOALS))),) +.NOTPARALLEL: +$(info *NOTE* Parallel make disabled by all_ut_run target so we have sane console output) +endif ############################## # diff --git a/make/tools.mk b/make/tools.mk index 753a2cb62..8e5d675e6 100644 --- a/make/tools.mk +++ b/make/tools.mk @@ -350,9 +350,6 @@ gtest_install: gtest_clean $(MAKE) $(GTEST_SILENT) ; \ ) - # delete the extracted source when we're done - #$(V1) [ ! -d "$(GTEST_BUILD_DIR)" ] || $(RM) -rf "$(GTEST_BUILD_DIR)" - .PHONY: gtest_clean gtest_clean: $(V0) @echo " CLEAN $(GTEST_DIR)" diff --git a/make/unittest.mk b/make/unittest.mk index 18559bfb4..5aeefb0f9 100644 --- a/make/unittest.mk +++ b/make/unittest.mk @@ -54,15 +54,22 @@ ALLCPPSRC := $(wildcard ./*.cpp) ALLSRCBASE := $(notdir $(basename $(ALLSRC) $(ALLCPPSRC))) ALLOBJ := $(addprefix $(OUTDIR)/, $(addsuffix .o, $(ALLSRCBASE))) -.PHONY: $(TARGET) -$(TARGET): | $(OUTDIR) -$(TARGET): $(OUTDIR)/$(TARGET).elf - -$(OUTDIR): - $(V1) mkdir -p $@ +.PHONY: elf +elf: $(OUTDIR)/$(TARGET).elf $(foreach src,$(ALLSRC),$(eval $(call COMPILE_C_TEMPLATE,$(src)))) $(foreach src,$(ALLCPPSRC),$(eval $(call COMPILE_CXX_TEMPLATE,$(src)))) $(eval $(call LINK_CXX_TEMPLATE,$(OUTDIR)/$(TARGET).elf,$(ALLOBJ) $(GTEST_LIBS))) +.PHONY: tap +tap: $(OUTDIR)/$(TARGET).tap + +$(OUTDIR)/$(TARGET).tap: $(OUTDIR)/$(TARGET).elf + $(V0) @echo " TAP $(MSG_EXTRA) $(call toprel, $@)" + $(V1) $< > $@ + +.PHONY: run +run: $(OUTDIR)/$(TARGET).elf + $(V0) @echo " TAP RUN $(MSG_EXTRA) $(call toprel, $<)" + $(V1) $< From fb4a1d7b1b839909533065a0bb90f10097cbcb82 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Wed, 9 Jan 2013 01:01:32 -0500 Subject: [PATCH 24/33] gtest: stop compiling gtest libraries on installation --- make/tools.mk | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/make/tools.mk b/make/tools.mk index 8e5d675e6..5dec32f58 100644 --- a/make/tools.mk +++ b/make/tools.mk @@ -319,14 +319,7 @@ android_sdk_update: $(ANDROID_SDK_DIR)/tools/android update sdk --no-ui -t platform-tools,android-16,addon-google_apis-google-16 # Set up Google Test (gtest) tools -ifeq ($(V), 1) -GTEST_SILENT := -else -GTEST_SILENT := --silent -endif - GTEST_DIR := $(TOOLS_DIR)/gtest-1.6.0 -GTEST_BUILD_DIR := $(DL_DIR)/gtest-build .PHONY: gtest_install gtest_install: | $(DL_DIR) $(TOOLS_DIR) @@ -343,14 +336,8 @@ gtest_install: gtest_clean $(V1) mkdir -p "$(GTEST_DIR)" $(V1) unzip -q -d "$(TOOLS_DIR)" "$(DL_DIR)/$(GTEST_FILE)" - # build - $(V1) ( \ - cd $(GTEST_DIR) ; \ - ./configure $(GTEST_SILENT) ; \ - $(MAKE) $(GTEST_SILENT) ; \ - ) - .PHONY: gtest_clean gtest_clean: $(V0) @echo " CLEAN $(GTEST_DIR)" $(V1) [ ! -d "$(GTEST_DIR)" ] || $(RM) -rf "$(GTEST_DIR)" + From 9b94eeb7454d59e64d7f5e7fadfc3578dfe9c5bd Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Tue, 18 Dec 2012 00:56:40 -0500 Subject: [PATCH 25/33] ut: convert logfs unit test to gtest Conflicts: Makefile make/unittest.mk --- Makefile | 2 +- flight/tests/logfs/main.c | 87 ---------- flight/tests/logfs/unittest.cpp | 259 +++++++++++++++++++++++++++++ flight/tests/logfs/unittest_init.c | 26 +++ make/firmware-defs.mk | 29 +++- make/unittest.mk | 9 +- 6 files changed, 307 insertions(+), 105 deletions(-) delete mode 100644 flight/tests/logfs/main.c create mode 100644 flight/tests/logfs/unittest.cpp create mode 100644 flight/tests/logfs/unittest_init.c diff --git a/Makefile b/Makefile index fe92b2942..94b9d84e0 100644 --- a/Makefile +++ b/Makefile @@ -786,7 +786,7 @@ ut_$(1)_%: $$(UT_OUT_DIR) \ GTEST_DIR=$(GTEST_DIR) \ \ - $$* + $* .PHONY: ut_$(1)_clean ut_$(1)_clean: diff --git a/flight/tests/logfs/main.c b/flight/tests/logfs/main.c deleted file mode 100644 index 65d2f018a..000000000 --- a/flight/tests/logfs/main.c +++ /dev/null @@ -1,87 +0,0 @@ -#include /* printf */ -#include /* abort */ -#include /* memset */ - -#include "pios_flash.h" /* PIOS_FLASH_* API */ -#include "pios_flash_ut_priv.h" - -const struct pios_flash_ut_cfg flash_config = { - .size_of_flash = 0x00200000, - .size_of_sector = 0x00010000, -}; - -#include "pios_flashfs_logfs_priv.h" - -const struct flashfs_logfs_cfg flashfs_config = { - .fs_magic = 0x89abceef, - .total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */ - .arena_size = 0x00010000, /* 256 * slot size */ - .slot_size = 0x00000100, /* 256 bytes */ - - .start_offset = 0, /* start at the beginning of the chip */ - .sector_size = 0x00010000, /* 64K bytes */ - .page_size = 0x00000100, /* 256 bytes */ -}; - -#include "pios_flashfs.h" /* PIOS_FLASHFS_* */ - -int main (int argc, char * argv[]) -{ - int32_t rc; - - /* dd if=/dev/zero bs=1 count=2MiB | tr '\000' '\377' > theflash.bin */ - - uintptr_t flash_id; - rc = PIOS_Flash_UT_Init(&flash_id, &flash_config); - if (rc != 0) { - printf ("flash init failed (%d)\n", rc); - abort(); - } - - uintptr_t fs_id; - rc = PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_config, &pios_ut_flash_driver, flash_id); - if (rc != 0) { - printf ("flash filesystem init failed (%d)\n", rc); - abort(); - } - -#define OBJ1_ID 0x12345678 -#define OBJ1_SIZE 76 - unsigned char obj1[OBJ1_SIZE]; - memset(obj1, 0xA5, sizeof(obj1)); - for (uint32_t i = 0; i < 10000; i++) { - rc = PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 0, obj1, sizeof(obj1)); - if (rc != 0) { - printf ("failed to save obj1 (%d)\n", rc); - abort(); - } - } - - unsigned char obj1_check[OBJ1_SIZE]; - memset(obj1_check, 0, sizeof(obj1_check)); - rc = PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check)); - if (rc != 0) { - printf ("failed to load obj1 (%d)\n", rc); - abort(); - } - - if (memcmp(obj1, obj1_check, sizeof(obj1)) != 0) { - printf ("read-back of obj1 failed\n"); - abort(); - } - - - rc = PIOS_FLASHFS_ObjDelete(fs_id, OBJ1_ID, 0); - if (rc != 0) { - printf ("failed to delete obj1 (%d)\n", rc); - abort(); - } - - rc = PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check)); - if (rc == 0) { - printf ("was able to load obj1 after delete!\n"); - abort(); - } - -} - diff --git a/flight/tests/logfs/unittest.cpp b/flight/tests/logfs/unittest.cpp new file mode 100644 index 000000000..664f4e841 --- /dev/null +++ b/flight/tests/logfs/unittest.cpp @@ -0,0 +1,259 @@ +#include "gtest/gtest.h" + +#include /* printf */ +#include /* abort */ +#include /* memset */ + +extern "C" { + +#include "pios_flash.h" /* PIOS_FLASH_* API */ +#include "pios_flash_ut_priv.h" + +extern struct pios_flash_ut_cfg flash_config; + +#include "pios_flashfs_logfs_priv.h" + +extern struct flashfs_logfs_cfg flashfs_config; + +#include "pios_flashfs.h" /* PIOS_FLASHFS_* */ + +} + +#define OBJ0_ID 0xAA55AA55 + +#define OBJ1_ID 0x12345678 +#define OBJ1_SIZE 76 + +#define OBJ2_ID 0xABCDEFAB +#define OBJ2_SIZE 123 + +#define OBJ3_ID 0x99999999 +#define OBJ3_SIZE (256 - 12) // leave room for the slot header + +// To use a test fixture, derive a class from testing::Test. +class LogfsTestRaw : public testing::Test { +protected: + virtual void SetUp() { + /* create an empty, appropriately sized flash filesystem */ + FILE * theflash = fopen("theflash.bin", "w"); + uint8_t sector[flash_config.size_of_sector]; + memset(sector, 0xFF, sizeof(sector)); + for (uint32_t i = 0; i < flash_config.size_of_flash / flash_config.size_of_sector; i++) { + fwrite(sector, sizeof(sector), 1, theflash); + } + fclose(theflash); + + /* Set up obj1 */ + for (uint32_t i = 0; i < sizeof(obj1); i++) { + obj1[i] = 0x10 + (i % 10); + } + + /* Set up a second version of obj1 with different data */ + for (uint32_t i = 0; i < sizeof(obj1_alt); i++) { + obj1_alt[i] = 0xA0 + (i % 10); + } + + /* Set up obj2 */ + for (uint32_t i = 0; i < sizeof(obj2); i++) { + obj2[i] = 0x20 + (i % 10); + } + + /* Set up obj3 */ + for (uint32_t i = 0; i < sizeof(obj3); i++) { + obj3[i] = 0x30 + (i % 10); + } + } + + virtual void TearDown() { + unlink("theflash.bin"); + } + + unsigned char obj1[OBJ1_SIZE]; + unsigned char obj1_alt[OBJ1_SIZE]; + unsigned char obj2[OBJ2_SIZE]; + unsigned char obj3[OBJ3_SIZE]; +}; + +TEST_F(LogfsTestRaw, FlashInit) { + uintptr_t flash_id; + EXPECT_EQ(0, PIOS_Flash_UT_Init(&flash_id, &flash_config)); +} + +TEST_F(LogfsTestRaw, LogfsInit) { + uintptr_t flash_id; + EXPECT_EQ(0, PIOS_Flash_UT_Init(&flash_id, &flash_config)); + + uintptr_t fs_id; + EXPECT_EQ(0, PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_config, &pios_ut_flash_driver, flash_id)); +} + +class LogfsTestCooked : public LogfsTestRaw { +protected: + virtual void SetUp() { + /* First, we need to set up the super fixture (LogfsTestRaw) */ + LogfsTestRaw::SetUp(); + + /* Init the flash and the flashfs so we don't need to repeat this in every test */ + uintptr_t flash_id; + EXPECT_EQ(0, PIOS_Flash_UT_Init(&flash_id, &flash_config)); + EXPECT_EQ(0, PIOS_FLASHFS_Logfs_Init(&fs_id, &flashfs_config, &pios_ut_flash_driver, flash_id)); + } + + uintptr_t fs_id; +}; + +TEST_F(LogfsTestCooked, LogfsFormat) { + EXPECT_EQ(0, PIOS_FLASHFS_Format(fs_id)); +} + +TEST_F(LogfsTestCooked, WriteOne) { + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 0, obj1, sizeof(obj1))); +} + +TEST_F(LogfsTestCooked, WriteVerifyOne) { + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 0, obj1, sizeof(obj1))); + + unsigned char obj1_check[OBJ1_SIZE]; + memset(obj1_check, 0, sizeof(obj1_check)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check))); + EXPECT_EQ(0, memcmp(obj1, obj1_check, sizeof(obj1))); +} + +TEST_F(LogfsTestCooked, WriteVerifyDeleteVerifyOne) { + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 0, obj1, sizeof(obj1))); + + unsigned char obj1_check[OBJ1_SIZE]; + memset(obj1_check, 0, sizeof(obj1_check)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check))); + EXPECT_EQ(0, memcmp(obj1, obj1_check, sizeof(obj1))); + + EXPECT_EQ(0, PIOS_FLASHFS_ObjDelete(fs_id, OBJ1_ID, 0)); + + EXPECT_EQ(-2, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check))); +} + +TEST_F(LogfsTestCooked, WriteTwoVerifyOneA) { + /* Write obj1 then obj2 */ + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 0, obj1, sizeof(obj1))); + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ2_ID, 0, obj2, sizeof(obj2))); + + /* Read back obj1 */ + unsigned char obj1_check[OBJ1_SIZE]; + memset(obj1_check, 0, sizeof(obj1_check)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check))); + EXPECT_EQ(0, memcmp(obj1, obj1_check, sizeof(obj1))); +} + +TEST_F(LogfsTestCooked, WriteTwoVerifyOneB) { + /* Write obj2 then obj1 */ + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ2_ID, 0, obj2, sizeof(obj2))); + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 0, obj1, sizeof(obj1))); + + /* Read back obj1 */ + unsigned char obj1_check[OBJ1_SIZE]; + memset(obj1_check, 0, sizeof(obj1_check)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check))); + EXPECT_EQ(0, memcmp(obj1, obj1_check, sizeof(obj1))); +} + +TEST_F(LogfsTestCooked, WriteZeroSize) { + /* Write a zero length object */ + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ0_ID, 0, NULL, 0)); +} + +TEST_F(LogfsTestCooked, WriteVerifyZeroLength) { + /* Write a zero length object */ + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ0_ID, 0, NULL, 0)); + + /* Read back a zero length object -- effectively an existence check */ + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ0_ID, 0, NULL, 0)); +} + +TEST_F(LogfsTestCooked, WriteMaxSize) { + /* Write a zero length object */ + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ3_ID, 0, obj3, sizeof(obj3))); +} + +TEST_F(LogfsTestCooked, ReadNonexistent) { + /* Read back a zero length object -- basically an existence check */ + unsigned char obj1_check[OBJ1_SIZE]; + memset(obj1_check, 0, sizeof(obj1_check)); + EXPECT_EQ(-2, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check))); +} + +TEST_F(LogfsTestCooked, WriteVerifyMultiInstance) { + /* Write instance zero */ + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 0, obj1, sizeof(obj1))); + + /* Write a non-zero instance ID */ + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 123, obj1_alt, sizeof(obj1_alt))); + + unsigned char obj1_check[OBJ1_SIZE]; + + /* Read back instance 123 */ + memset(obj1_check, 0, sizeof(obj1_check)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 123, obj1_check, sizeof(obj1_check))); + EXPECT_EQ(0, memcmp(obj1_alt, obj1_check, sizeof(obj1_alt))); + + /* Read back instance 0 */ + memset(obj1_check, 0, sizeof(obj1_check)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check))); + EXPECT_EQ(0, memcmp(obj1, obj1_check, sizeof(obj1))); +} + +TEST_F(LogfsTestCooked, FillFilesystemAndGarbageCollect) { + /* Fill up the entire filesystem with multiple instances of obj1 */ + for (uint32_t i = 0; i < (flashfs_config.arena_size / flashfs_config.slot_size) - 1; i++) { + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, i, obj1, sizeof(obj1))); + } + + /* Should fail to add a new object since the filesystem is full */ + EXPECT_EQ(-3, PIOS_FLASHFS_ObjSave(fs_id, OBJ2_ID, 0, obj2, sizeof(obj2))); + + /* Now save a new version of an existing object which should trigger gc and succeed */ + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 0, obj1_alt, sizeof(obj1_alt))); + + /* Read back one of the original obj1 instances */ + unsigned char obj1_check[OBJ1_SIZE]; + memset(obj1_check, 0, sizeof(obj1_check)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 1, obj1_check, sizeof(obj1_check))); + EXPECT_EQ(0, memcmp(obj1, obj1_check, sizeof(obj1))); + + /* Read back the new version of obj1 written after gc */ + memset(obj1_check, 0, sizeof(obj1_check)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check))); + EXPECT_EQ(0, memcmp(obj1_alt, obj1_check, sizeof(obj1_alt))); +} + +TEST_F(LogfsTestCooked, WriteManyVerify) { + for (uint32_t i = 0; i < 10000; i++) { + /* Write a collection of objects */ + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ0_ID, 0, NULL, 0)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 0, obj1, sizeof(obj1))); + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ1_ID, 123, obj1_alt, sizeof(obj1_alt))); + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ2_ID, 0, obj2, sizeof(obj2))); + EXPECT_EQ(0, PIOS_FLASHFS_ObjSave(fs_id, OBJ3_ID, 0, obj3, sizeof(obj3))); + } + + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ0_ID, 0, NULL, 0)); + + unsigned char obj1_check[OBJ1_SIZE]; + memset(obj1_check, 0, sizeof(obj1_check)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 0, obj1_check, sizeof(obj1_check))); + EXPECT_EQ(0, memcmp(obj1, obj1_check, sizeof(obj1))); + + unsigned char obj1_alt_check[OBJ1_SIZE]; + memset(obj1_alt_check, 0, sizeof(obj1_alt_check)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ1_ID, 123, obj1_alt_check, sizeof(obj1_alt_check))); + EXPECT_EQ(0, memcmp(obj1_alt, obj1_alt_check, sizeof(obj1_alt))); + + unsigned char obj2_check[OBJ2_SIZE]; + memset(obj2_check, 0, sizeof(obj2_check)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ2_ID, 0, obj2_check, sizeof(obj2_check))); + EXPECT_EQ(0, memcmp(obj2, obj2_check, sizeof(obj2))); + + unsigned char obj3_check[OBJ3_SIZE]; + memset(obj3_check, 0, sizeof(obj3_check)); + EXPECT_EQ(0, PIOS_FLASHFS_ObjLoad(fs_id, OBJ3_ID, 0, obj3_check, sizeof(obj3_check))); + EXPECT_EQ(0, memcmp(obj3, obj3_check, sizeof(obj3))); +} diff --git a/flight/tests/logfs/unittest_init.c b/flight/tests/logfs/unittest_init.c new file mode 100644 index 000000000..b60570c38 --- /dev/null +++ b/flight/tests/logfs/unittest_init.c @@ -0,0 +1,26 @@ +/* + * These need to be defined in a .c file so that we can use + * designated initializer syntax which c++ doesn't support (yet). + */ + +#include "pios_flash_ut_priv.h" + + +const struct pios_flash_ut_cfg flash_config = { + .size_of_flash = 0x00200000, + .size_of_sector = 0x00010000, +}; + +#include "pios_flashfs_logfs_priv.h" + +const struct flashfs_logfs_cfg flashfs_config = { + .fs_magic = 0x89abceef, + .total_fs_size = 0x00200000, /* 2M bytes (32 sectors = entire chip) */ + .arena_size = 0x00010000, /* 256 * slot size */ + .slot_size = 0x00000100, /* 256 bytes */ + + .start_offset = 0, /* start at the beginning of the chip */ + .sector_size = 0x00010000, /* 64K bytes */ + .page_size = 0x00000100, /* 256 bytes */ +}; + diff --git a/make/firmware-defs.mk b/make/firmware-defs.mk index e77e71d2a..afcc26f52 100644 --- a/make/firmware-defs.mk +++ b/make/firmware-defs.mk @@ -3,7 +3,7 @@ TCHAIN_PREFIX ?= arm-none-eabi- # Define toolchain component names. CC = $(TCHAIN_PREFIX)gcc -CPP = $(TCHAIN_PREFIX)g++ +CXX = $(TCHAIN_PREFIX)g++ AR = $(TCHAIN_PREFIX)ar OBJCOPY = $(TCHAIN_PREFIX)objcopy OBJDUMP = $(TCHAIN_PREFIX)objdump @@ -43,8 +43,8 @@ MSG_SYMBOL_TABLE = ${quote} NM $(MSG_EXTRA) ${quote} MSG_LINKING = ${quote} LD $(MSG_EXTRA) ${quote} MSG_COMPILING = ${quote} CC ${MSG_EXTRA} ${quote} MSG_COMPILING_ARM = ${quote} CC-ARM $(MSG_EXTRA) ${quote} -MSG_COMPILINGCPP = ${quote} CXX $(MSG_EXTRA) ${quote} -MSG_COMPILINGCPP_ARM = ${quote} CXX-ARM $(MSG_EXTRA) ${quote} +MSG_COMPILINGCXX = ${quote} CXX $(MSG_EXTRA) ${quote} +MSG_COMPILINGCXX_ARM = ${quote} CXX-ARM $(MSG_EXTRA) ${quote} MSG_ASSEMBLING = ${quote} AS $(MSG_EXTRA) ${quote} MSG_ASSEMBLING_ARM = ${quote} AS-ARM $(MSG_EXTRA) ${quote} MSG_CLEANING = ${quote} CLEAN $(MSG_EXTRA) ${quote} @@ -170,17 +170,17 @@ $(OUTDIR)/$(notdir $(basename $(1))).o : $(1) endef # Compile: create object files from C++ source files. -define COMPILE_CPP_TEMPLATE +define COMPILE_CXX_TEMPLATE $(OUTDIR)/$(notdir $(basename $(1))).o : $(1) - @echo $(MSG_COMPILINGCPP) $$(call toprel, $$<) - $(V1) $(CC) -c $(THUMB) $$(CFLAGS) $$(CPPFLAGS) $$< -o $$@ + @echo $(MSG_COMPILINGCXX) $$(call toprel, $$<) + $(V1) $(CXX) -c $(THUMB) $$(CFLAGS) $$(CPPFLAGS) $$(CXXFLAGS) $$< -o $$@ endef # Compile: create object files from C++ source files. ARM-only -define COMPILE_CPP_ARM_TEMPLATE +define COMPILE_CXX_ARM_TEMPLATE $(OUTDIR)/$(notdir $(basename $(1))).o : $(1) - @echo $(MSG_COMPILINGCPP_ARM) $$(call toprel, $$<) - $(V1) $(CC) -c $$(CFLAGS) $$(CPPFLAGS) $$< -o $$@ + @echo $(MSG_COMPILINGCXX_ARM) $$(call toprel, $$<) + $(V1) $(CPP) -c $$(CFLAGS) $$(CPPFLAGS) $$(CXXFLAGS) $$< -o $$@ endef # Link: create ELF output file from object files. @@ -194,6 +194,17 @@ $(1): $(2) $(V1) $(CC) $(THUMB) $$(CFLAGS) $(2) --output $$@ $$(LDFLAGS) endef +# Link: create ELF output file from object files. +# $1 = elf file to produce +# $2 = list of object files that make up the elf file +define LINK_CXX_TEMPLATE +.SECONDARY : $(1) +.PRECIOUS : $(2) +$(1): $(2) + @echo $(MSG_LINKING) $$(call toprel, $$@) + $(V1) $(CXX) $(THUMB) $$(CFLAGS) $(2) --output $$@ $$(LDFLAGS) +endef + # Compile: create assembler files from C source files. ARM/Thumb define PARTIAL_COMPILE_TEMPLATE $($(1):.c=.s) : %.s : %.c diff --git a/make/unittest.mk b/make/unittest.mk index 5aeefb0f9..9654af174 100644 --- a/make/unittest.mk +++ b/make/unittest.mk @@ -27,7 +27,7 @@ CPPFLAGS += -I$(GTEST_DIR)/include # Flags passed to the C++ compiler. -CXXFLAGS += -g -Wall -Wextra +CXXFLAGS += -g -Wall -Wextra -std=gnu++0x # All Google Test headers. GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ @@ -62,13 +62,6 @@ $(foreach src,$(ALLCPPSRC),$(eval $(call COMPILE_CXX_TEMPLATE,$(src)))) $(eval $(call LINK_CXX_TEMPLATE,$(OUTDIR)/$(TARGET).elf,$(ALLOBJ) $(GTEST_LIBS))) -.PHONY: tap -tap: $(OUTDIR)/$(TARGET).tap - -$(OUTDIR)/$(TARGET).tap: $(OUTDIR)/$(TARGET).elf - $(V0) @echo " TAP $(MSG_EXTRA) $(call toprel, $@)" - $(V1) $< > $@ - .PHONY: run run: $(OUTDIR)/$(TARGET).elf $(V0) @echo " TAP RUN $(MSG_EXTRA) $(call toprel, $<)" From ea09a53adc61cf282c6dfa65663db4a63842f511 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Wed, 9 Jan 2013 01:09:55 -0500 Subject: [PATCH 26/33] unittest: build gtest-all and gtest_main directly Conflicts: make/unittest.mk --- Makefile | 8 +++++++- make/unittest.mk | 31 ++++++++++++++++++------------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 94b9d84e0..5f960cadc 100644 --- a/Makefile +++ b/Makefile @@ -751,8 +751,14 @@ $(UT_OUT_DIR): .PHONY: all_ut all_ut: $(addsuffix _elf, $(addprefix ut_, $(ALL_UNITTESTS))) +# The all_ut_tap goal is a legacy alias for the all_ut_xml target so that Jenkins +# can still build old branches. This can be deleted in a few months when all +# branches are using the newer targets. .PHONY: all_ut_tap -all_ut_tap: $(addsuffix _tap, $(addprefix ut_, $(ALL_UNITTESTS))) +all_ut_tap: all_ut_xml + +.PHONY: all_ut_xml +all_ut_xml: $(addsuffix _xml, $(addprefix ut_, $(ALL_UNITTESTS))) .PHONY: all_ut_run all_ut_run: $(addsuffix _run, $(addprefix ut_, $(ALL_UNITTESTS))) diff --git a/make/unittest.mk b/make/unittest.mk index 9654af174..c932d9132 100644 --- a/make/unittest.mk +++ b/make/unittest.mk @@ -29,13 +29,6 @@ CPPFLAGS += -I$(GTEST_DIR)/include # Flags passed to the C++ compiler. CXXFLAGS += -g -Wall -Wextra -std=gnu++0x -# All Google Test headers. -GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ - $(GTEST_DIR)/include/gtest/internal/*.h - -# Google Test libraries -GTEST_LIBS = $(GTEST_DIR)/lib/.libs/libgtest_main.a $(GTEST_DIR)/lib/.libs/libgtest.a - # Google Test needs the pthread library LDFLAGS += -lpthread @@ -50,19 +43,31 @@ override THUMB := EXTRAINCDIRS += . ALLSRC := $(SRC) $(wildcard ./*.c) -ALLCPPSRC := $(wildcard ./*.cpp) +ALLCPPSRC := $(wildcard ./*.cpp) $(GTEST_DIR)/src/gtest_main.cc ALLSRCBASE := $(notdir $(basename $(ALLSRC) $(ALLCPPSRC))) ALLOBJ := $(addprefix $(OUTDIR)/, $(addsuffix .o, $(ALLSRCBASE))) -.PHONY: elf -elf: $(OUTDIR)/$(TARGET).elf - $(foreach src,$(ALLSRC),$(eval $(call COMPILE_C_TEMPLATE,$(src)))) $(foreach src,$(ALLCPPSRC),$(eval $(call COMPILE_CXX_TEMPLATE,$(src)))) -$(eval $(call LINK_CXX_TEMPLATE,$(OUTDIR)/$(TARGET).elf,$(ALLOBJ) $(GTEST_LIBS))) + +# Specific extensions to CPPFLAGS only for the google test library +$(OUTDIR)/gtest-all.o : CPPFLAGS += -I$(GTEST_DIR) +$(eval $(call COMPILE_CXX_TEMPLATE, $(GTEST_DIR)/src/gtest-all.cc)) + +$(eval $(call LINK_CXX_TEMPLATE,$(OUTDIR)/$(TARGET).elf,$(ALLOBJ) $(OUTDIR)/gtest-all.o)) + +.PHONY: elf +elf: $(OUTDIR)/$(TARGET).elf + +.PHONY: xml +xml: $(OUTDIR)/$(TARGET).xml + +$(OUTDIR)/$(TARGET).xml: $(OUTDIR)/$(TARGET).elf + $(V0) @echo " TEST XML $(MSG_EXTRA) $(call toprel, $@)" + $(V1) $< --gtest_output=xml:$(OUTDIR)/$(TARGET).xml > /dev/null .PHONY: run run: $(OUTDIR)/$(TARGET).elf - $(V0) @echo " TAP RUN $(MSG_EXTRA) $(call toprel, $<)" + $(V0) @echo " TEST RUN $(MSG_EXTRA) $(call toprel, $<)" $(V1) $< From b3178c3966f9a9e535309cf6091505f3beea92f3 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Tue, 18 Dec 2012 01:44:01 -0500 Subject: [PATCH 27/33] flash_ut: fix forward declaration of init function --- flight/tests/logfs/pios_flash_ut_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flight/tests/logfs/pios_flash_ut_priv.h b/flight/tests/logfs/pios_flash_ut_priv.h index 7291fd1d5..a38bf21e2 100644 --- a/flight/tests/logfs/pios_flash_ut_priv.h +++ b/flight/tests/logfs/pios_flash_ut_priv.h @@ -5,6 +5,6 @@ struct pios_flash_ut_cfg { uint32_t size_of_sector; }; -int32_t PIOS_Flash_UT_Init(uint32_t * flash_id, const struct pios_flash_ut_cfg * cfg); +int32_t PIOS_Flash_UT_Init(uintptr_t * flash_id, const struct pios_flash_ut_cfg * cfg); extern const struct pios_flash_driver pios_ut_flash_driver; From 67de4f0e0c23998c1b509313dec923ce68ff5cb3 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Tue, 18 Dec 2012 01:51:07 -0500 Subject: [PATCH 28/33] ut: drop dependency on C++0x --- make/unittest.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/unittest.mk b/make/unittest.mk index c932d9132..3ddc57533 100644 --- a/make/unittest.mk +++ b/make/unittest.mk @@ -27,7 +27,7 @@ CPPFLAGS += -I$(GTEST_DIR)/include # Flags passed to the C++ compiler. -CXXFLAGS += -g -Wall -Wextra -std=gnu++0x +CXXFLAGS += -g -Wall -Wextra # Google Test needs the pthread library LDFLAGS += -lpthread From 8901cde35bfb7d106bab6240ebecfe74c0c6bf15 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 23 Feb 2013 18:04:20 +0200 Subject: [PATCH 29/33] ut: remove unused targets --- Makefile | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 5f960cadc..36adf6b61 100644 --- a/Makefile +++ b/Makefile @@ -751,12 +751,6 @@ $(UT_OUT_DIR): .PHONY: all_ut all_ut: $(addsuffix _elf, $(addprefix ut_, $(ALL_UNITTESTS))) -# The all_ut_tap goal is a legacy alias for the all_ut_xml target so that Jenkins -# can still build old branches. This can be deleted in a few months when all -# branches are using the newer targets. -.PHONY: all_ut_tap -all_ut_tap: all_ut_xml - .PHONY: all_ut_xml all_ut_xml: $(addsuffix _xml, $(addprefix ut_, $(ALL_UNITTESTS))) @@ -792,7 +786,7 @@ ut_$(1)_%: $$(UT_OUT_DIR) \ GTEST_DIR=$(GTEST_DIR) \ \ - $* + $$* .PHONY: ut_$(1)_clean ut_$(1)_clean: From 14db5c80f1570954c2de65a4e16e22098ab285cf Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sun, 24 Feb 2013 04:03:17 +0200 Subject: [PATCH 30/33] ut: change xml output directory to make Bamboo a bit happier --- make/unittest.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/make/unittest.mk b/make/unittest.mk index 3ddc57533..624864cab 100644 --- a/make/unittest.mk +++ b/make/unittest.mk @@ -61,11 +61,11 @@ $(eval $(call LINK_CXX_TEMPLATE,$(OUTDIR)/$(TARGET).elf,$(ALLOBJ) $(OUTDIR)/gtes elf: $(OUTDIR)/$(TARGET).elf .PHONY: xml -xml: $(OUTDIR)/$(TARGET).xml +xml: $(OUTDIR)/test-reports/$(TARGET).xml -$(OUTDIR)/$(TARGET).xml: $(OUTDIR)/$(TARGET).elf +$(OUTDIR)/test-reports/$(TARGET).xml: $(OUTDIR)/$(TARGET).elf $(V0) @echo " TEST XML $(MSG_EXTRA) $(call toprel, $@)" - $(V1) $< --gtest_output=xml:$(OUTDIR)/$(TARGET).xml > /dev/null + $(V1) $< --gtest_output=xml:$@ > /dev/null .PHONY: run run: $(OUTDIR)/$(TARGET).elf From c038f6b9871115bfafd765b1b4eb3f81b9927dbd Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sun, 24 Feb 2013 03:21:12 +0200 Subject: [PATCH 31/33] ut_logfs: fix fseek()/fread() problem on Windows --- flight/tests/logfs/pios_flash_ut.c | 2 +- flight/tests/logfs/unittest.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/flight/tests/logfs/pios_flash_ut.c b/flight/tests/logfs/pios_flash_ut.c index 37fc4d980..aa7728352 100644 --- a/flight/tests/logfs/pios_flash_ut.c +++ b/flight/tests/logfs/pios_flash_ut.c @@ -41,7 +41,7 @@ int32_t PIOS_Flash_UT_Init(uintptr_t * flash_id, const struct pios_flash_ut_cfg flash_dev->cfg = cfg; flash_dev->transaction_in_progress = false; - flash_dev->flash_file = fopen ("theflash.bin", "r+"); + flash_dev->flash_file = fopen ("theflash.bin", "rb+"); if (flash_dev->flash_file == NULL) { return -1; } diff --git a/flight/tests/logfs/unittest.cpp b/flight/tests/logfs/unittest.cpp index 664f4e841..c7e04f555 100644 --- a/flight/tests/logfs/unittest.cpp +++ b/flight/tests/logfs/unittest.cpp @@ -35,7 +35,7 @@ class LogfsTestRaw : public testing::Test { protected: virtual void SetUp() { /* create an empty, appropriately sized flash filesystem */ - FILE * theflash = fopen("theflash.bin", "w"); + FILE * theflash = fopen("theflash.bin", "wb"); uint8_t sector[flash_config.size_of_sector]; memset(sector, 0xFF, sizeof(sector)); for (uint32_t i = 0; i < flash_config.size_of_flash / flash_config.size_of_sector; i++) { From 776ec4f3ea20263a046192f1628b7845fccaca96 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sun, 24 Feb 2013 04:24:25 +0200 Subject: [PATCH 32/33] ut_logfs: do not pollute the source tree with temp files --- flight/tests/logfs/Makefile | 2 ++ flight/tests/logfs/pios_flash_ut.c | 2 +- flight/tests/logfs/pios_flash_ut_priv.h | 4 ++++ flight/tests/logfs/unittest.cpp | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/flight/tests/logfs/Makefile b/flight/tests/logfs/Makefile index a1c302a1c..dc939c067 100644 --- a/flight/tests/logfs/Makefile +++ b/flight/tests/logfs/Makefile @@ -34,6 +34,8 @@ CFLAGS += -Wall -Werror CFLAGS += -g CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I. +CFLAGS += "-DFLASH_IMAGE_FILE=\"$(OUTDIR)/theflash.bin\"" + CONLYFLAGS += -std=gnu99 SRC := $(PIOS)/Common/pios_flashfs_logfs.c diff --git a/flight/tests/logfs/pios_flash_ut.c b/flight/tests/logfs/pios_flash_ut.c index aa7728352..32a749783 100644 --- a/flight/tests/logfs/pios_flash_ut.c +++ b/flight/tests/logfs/pios_flash_ut.c @@ -41,7 +41,7 @@ int32_t PIOS_Flash_UT_Init(uintptr_t * flash_id, const struct pios_flash_ut_cfg flash_dev->cfg = cfg; flash_dev->transaction_in_progress = false; - flash_dev->flash_file = fopen ("theflash.bin", "rb+"); + flash_dev->flash_file = fopen (FLASH_IMAGE_FILE, "rb+"); if (flash_dev->flash_file == NULL) { return -1; } diff --git a/flight/tests/logfs/pios_flash_ut_priv.h b/flight/tests/logfs/pios_flash_ut_priv.h index a38bf21e2..90a4aeba9 100644 --- a/flight/tests/logfs/pios_flash_ut_priv.h +++ b/flight/tests/logfs/pios_flash_ut_priv.h @@ -8,3 +8,7 @@ struct pios_flash_ut_cfg { int32_t PIOS_Flash_UT_Init(uintptr_t * flash_id, const struct pios_flash_ut_cfg * cfg); extern const struct pios_flash_driver pios_ut_flash_driver; + +#if !defined(FLASH_IMAGE_FILE) +#define FLASH_IMAGE_FILE "theflash.bin" +#endif diff --git a/flight/tests/logfs/unittest.cpp b/flight/tests/logfs/unittest.cpp index c7e04f555..c0c383e76 100644 --- a/flight/tests/logfs/unittest.cpp +++ b/flight/tests/logfs/unittest.cpp @@ -35,7 +35,7 @@ class LogfsTestRaw : public testing::Test { protected: virtual void SetUp() { /* create an empty, appropriately sized flash filesystem */ - FILE * theflash = fopen("theflash.bin", "wb"); + FILE * theflash = fopen(FLASH_IMAGE_FILE, "wb"); uint8_t sector[flash_config.size_of_sector]; memset(sector, 0xFF, sizeof(sector)); for (uint32_t i = 0; i < flash_config.size_of_flash / flash_config.size_of_sector; i++) { From 990048cf29894f4ee1d8e2e2a12cb307de130cd9 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Thu, 3 Jan 2013 19:58:29 -0500 Subject: [PATCH 33/33] ut: fix up unit test clean target name --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 36adf6b61..d1df984b9 100644 --- a/Makefile +++ b/Makefile @@ -757,7 +757,7 @@ all_ut_xml: $(addsuffix _xml, $(addprefix ut_, $(ALL_UNITTESTS))) .PHONY: all_ut_run all_ut_run: $(addsuffix _run, $(addprefix ut_, $(ALL_UNITTESTS))) -.PHONY: ut_all_clean +.PHONY: all_ut_clean all_ut_clean: $(V0) @echo " CLEAN $@" $(V1) [ ! -d "$(UT_OUT_DIR)" ] || $(RM) -r "$(UT_OUT_DIR)"