/** * @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]; int32_t addr = PIOS_FLASHFS_GetObjAddress(objId, instId); // Object currently not saved if(addr < 0) 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_W25X_ReadData(addr, (uint8_t *) &header, sizeof(header)) != 0) return -2; // Update CRC crc = PIOS_CRC_updateCRC(0, (uint8_t *) &header, sizeof(header)); if((header.id != objId) || (header.instId != instId)) 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_W25X_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_W25X_ReadData(addr + sizeof(header) + objSize, (uint8_t *) &crcFlash, sizeof(crcFlash)) != 0) return -5; if(crc != crcFlash) return -6; // Read the instance data if (PIOS_Flash_W25X_ReadData(addr + sizeof(header), data, objSize) != 0) return -4; 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 * @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; 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) return -1; struct fileHeader header = { .id = objId, .instId = instId, .size = UAVObjGetNumBytes(obj) }; if(PIOS_Flash_W25X_EraseSector(addr) != 0) return -2; // Save header // This information IS redundant with the object table id. Oh well. Better safe than sorry. if(PIOS_Flash_W25X_WriteData(addr, (uint8_t *) &header, sizeof(header)) != 0) return -3; // Update CRC crc = PIOS_CRC_updateCRC(0, (uint8_t *) &header, sizeof(header)); // Save data if(PIOS_Flash_W25X_WriteData(addr + sizeof(header), data, UAVObjGetNumBytes(obj)) != 0) return -4; // Update CRC crc = PIOS_CRC_updateCRC(crc, (uint8_t *) data, UAVObjGetNumBytes(obj)); // Save CRC (written so will work when CRC changes to uint16) if(PIOS_Flash_W25X_WriteData(addr + sizeof(header) + UAVObjGetNumBytes(obj), (uint8_t *) &crc, sizeof(crc)) != 0) return -4; return 0; }
/** * Sends a message. */ void UAVTalk::sendTestMessage(){ struct UAVTalkVelocityMessage vMessage; vMessage.header.startByte = 0x3C; // Not sure if the type is right, see: http://wiki.openpilot.org/display/Doc/UAVTalk vMessage.header.messageType = 0x10; // length = number of bytes in header and payload without checksum (Header: 10b, payload: 3x4b). vMessage.header.length = 22; vMessage.header.objectID = 0x43007EB0; // openpilot wiki says; Unique object instance ID. Only present in UAVObjects that are NOT of type 'single instance' // Could either mean that these bytes are not part of the message at all // or that these bytes are 0x0. vMessage.header.instanceID = 0; vMessage.down = 1; vMessage.east = 2; vMessage.north = 3; //this->setChecksum(&(vMessage.header.startByte)); vMessage.end.checksum = PIOS_CRC_updateCRC(0, &(vMessage.header.startByte), 22); xbee->sendData( (uint8_t*)(&vMessage), vMessage.header.length + 1); return; }//eof