diff --git a/overo/lib/UAVTalk/inc/uavtalk.h b/overo/lib/UAVTalk/inc/uavtalk.h new file mode 100644 index 000000000..3b7f2a2f9 --- /dev/null +++ b/overo/lib/UAVTalk/inc/uavtalk.h @@ -0,0 +1,62 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotLibraries OpenPilot System Libraries + * @{ + * @file uavtalk.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Include file of the UAVTalk library + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef UAVTALK_H +#define UAVTALK_H + +// Public types +typedef int32_t (*UAVTalkOutputStream)(uint8_t* data, int32_t length); + +typedef struct { + uint32_t txBytes; + uint32_t rxBytes; + uint32_t txObjectBytes; + uint32_t rxObjectBytes; + uint32_t rxObjects; + uint32_t txObjects; + uint32_t txErrors; + uint32_t rxErrors; +} UAVTalkStats; + +typedef void* UAVTalkConnection; + +// Public functions +UAVTalkConnection UAVTalkInitialize(UAVTalkOutputStream outputStream); +int32_t UAVTalkSetOutputStream(UAVTalkConnection connection, UAVTalkOutputStream outputStream); +UAVTalkOutputStream UAVTalkGetOutputStream(UAVTalkConnection connection); +int32_t UAVTalkSendObject(UAVTalkConnection connection, UAVObjHandle obj, uint16_t instId, uint8_t acked, int32_t timeoutMs); +int32_t UAVTalkSendObjectRequest(UAVTalkConnection connection, UAVObjHandle obj, uint16_t instId, int32_t timeoutMs); +int32_t UAVTalkProcessInputStream(UAVTalkConnection connection, uint8_t rxbyte); +void UAVTalkGetStats(UAVTalkConnection connection, UAVTalkStats *stats); +void UAVTalkResetStats(UAVTalkConnection connection); + +#endif // UAVTALK_H +/** + * @} + * @} + */ diff --git a/overo/lib/UAVTalk/inc/uavtalk_priv.h b/overo/lib/UAVTalk/inc/uavtalk_priv.h new file mode 100644 index 000000000..77863a6a8 --- /dev/null +++ b/overo/lib/UAVTalk/inc/uavtalk_priv.h @@ -0,0 +1,112 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotLibraries OpenPilot System Libraries + * @{ + * @file uavtalk.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Private include file of the UAVTalk library + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef UAVTALK_PRIV_H +#define UAVTALK_PRIV_H + +#include "uavobjectsinit.h" + +// Private types and constants +typedef struct { + uint8_t sync; + uint8_t type; + uint16_t size; + uint32_t objId; +} uavtalk_min_header; +#define UAVTALK_MIN_HEADER_LENGTH sizeof(uavtalk_min_header) + +typedef struct { + uint8_t sync; + uint8_t type; + uint16_t size; + uint32_t objId; + uint16_t instId; +} uavtalk_max_header; +#define UAVTALK_MAX_HEADER_LENGTH sizeof(uavtalk_max_header) + +typedef uint8_t uavtalk_checksum; +#define UAVTALK_CHECKSUM_LENGTH sizeof(uavtalk_checksum) +#define UAVTALK_MAX_PAYLOAD_LENGTH (UAVOBJECTS_LARGEST + 1) +#define UAVTALK_MIN_PACKET_LENGTH UAVTALK_MAX_HEADER_LENGTH + UAVTALK_CHECKSUM_LENGTH +#define UAVTALK_MAX_PACKET_LENGTH UAVTALK_MIN_PACKET_LENGTH + UAVTALK_MAX_PAYLOAD_LENGTH + +typedef enum {UAVTALK_STATE_SYNC, UAVTALK_STATE_TYPE, UAVTALK_STATE_SIZE, UAVTALK_STATE_OBJID, UAVTALK_STATE_INSTID, UAVTALK_STATE_DATA, UAVTALK_STATE_CS} UAVTalkRxState; + +typedef struct { + UAVObjHandle obj; + uint8_t type; + uint16_t packet_size; + uint32_t objId; + uint16_t instId; + uint32_t length; + uint8_t instanceLength; + uint8_t cs; + int32_t rxCount; + UAVTalkRxState state; + uint16_t rxPacketLength; +} UAVTalkInputProcessor; + +typedef struct { + uint8_t canari; + UAVTalkOutputStream outStream; + xSemaphoreHandle lock; + xSemaphoreHandle transLock; + xSemaphoreHandle respSema; + UAVObjHandle respObj; + uint16_t respInstId; + UAVTalkStats stats; + UAVTalkInputProcessor iproc; + uint8_t *rxBuffer; + uint32_t txSize; + uint8_t *txBuffer; +} UAVTalkConnectionData; + +#define UAVTALK_CANARI 0xCA +#define UAVTALK_WAITFOREVER -1 +#define UAVTALK_NOWAIT 0 +#define UAVTALK_SYNC_VAL 0x3C +#define UAVTALK_TYPE_MASK 0xF8 +#define UAVTALK_TYPE_VER 0x20 +#define UAVTALK_TYPE_OBJ (UAVTALK_TYPE_VER | 0x00) +#define UAVTALK_TYPE_OBJ_REQ (UAVTALK_TYPE_VER | 0x01) +#define UAVTALK_TYPE_OBJ_ACK (UAVTALK_TYPE_VER | 0x02) +#define UAVTALK_TYPE_ACK (UAVTALK_TYPE_VER | 0x03) +#define UAVTALK_TYPE_NACK (UAVTALK_TYPE_VER | 0x04) + +//macros +#define CHECKCONHANDLE(handle,variable,failcommand) \ + variable = (UAVTalkConnectionData*) handle; \ + if (variable == NULL || variable->canari != UAVTALK_CANARI) { \ + failcommand; \ + } + +#endif // UAVTALK__PRIV_H +/** + * @} + * @} + */ diff --git a/overo/lib/UAVTalk/uavtalk.c b/overo/lib/UAVTalk/uavtalk.c new file mode 100644 index 000000000..844ed5e38 --- /dev/null +++ b/overo/lib/UAVTalk/uavtalk.c @@ -0,0 +1,763 @@ +/** + ****************************************************************************** + * @addtogroup OpenPilotSystem OpenPilot System + * @{ + * @addtogroup OpenPilotLibraries OpenPilot System Libraries + * @{ + * + * @file uavtalk.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief UAVTalk library, implements to telemetry protocol. See the wiki for more details. + * This library should not be called directly by the application, it is only used by the + * Telemetry module. + * @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 "uavtalk_priv.h" + + +// Private functions +static int32_t objectTransaction(UAVTalkConnectionData *connection, UAVObjHandle objectId, uint16_t instId, uint8_t type, int32_t timeout); +static int32_t sendObject(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId, uint8_t type); +static int32_t sendSingleObject(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId, uint8_t type); +static int32_t sendNack(UAVTalkConnectionData *connection, uint32_t objId); +static int32_t receiveObject(UAVTalkConnectionData *connection, uint8_t type, uint32_t objId, uint16_t instId, uint8_t* data, int32_t length); +static void updateAck(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId); + +/** + * Initialize the UAVTalk library + * \param[in] connection UAVTalkConnection to be used + * \param[in] outputStream Function pointer that is called to send a data buffer + * \return 0 Success + * \return -1 Failure + */ +UAVTalkConnection UAVTalkInitialize(UAVTalkOutputStream outputStream) +{ + // allocate object + UAVTalkConnectionData * connection = pvPortMalloc(sizeof(UAVTalkConnectionData)); + if (!connection) return 0; + connection->canari = UAVTALK_CANARI; + connection->iproc.rxPacketLength = 0; + connection->iproc.state = UAVTALK_STATE_SYNC; + connection->outStream = outputStream; + connection->lock = xSemaphoreCreateRecursiveMutex(); + connection->transLock = xSemaphoreCreateRecursiveMutex(); + // allocate buffers + connection->rxBuffer = pvPortMalloc(UAVTALK_MAX_PACKET_LENGTH); + if (!connection->rxBuffer) return 0; + connection->txBuffer = pvPortMalloc(UAVTALK_MAX_PACKET_LENGTH); + if (!connection->txBuffer) return 0; + vSemaphoreCreateBinary(connection->respSema); + xSemaphoreTake(connection->respSema, 0); // reset to zero + UAVTalkResetStats( (UAVTalkConnection) connection ); + return (UAVTalkConnection) connection; +} + +/** + * Set the communication output stream + * \param[in] connection UAVTalkConnection to be used + * \param[in] outputStream Function pointer that is called to send a data buffer + * \return 0 Success + * \return -1 Failure + */ +int32_t UAVTalkSetOutputStream(UAVTalkConnection connectionHandle, UAVTalkOutputStream outputStream) +{ + + UAVTalkConnectionData *connection; + CHECKCONHANDLE(connectionHandle,connection,return -1); + + // Lock + xSemaphoreTakeRecursive(connection->lock, portMAX_DELAY); + + // set output stream + connection->outStream = outputStream; + + // Release lock + xSemaphoreGiveRecursive(connection->lock); + + return 0; + +} + +/** + * Get current output stream + * \param[in] connection UAVTalkConnection to be used + * @return UAVTarlkOutputStream the output stream used + */ +UAVTalkOutputStream UAVTalkGetOutputStream(UAVTalkConnection connectionHandle) +{ + UAVTalkConnectionData *connection; + CHECKCONHANDLE(connectionHandle,connection,return NULL); + return connection->outStream; +} + +/** + * Get communication statistics counters + * \param[in] connection UAVTalkConnection to be used + * @param[out] statsOut Statistics counters + */ +void UAVTalkGetStats(UAVTalkConnection connectionHandle, UAVTalkStats* statsOut) +{ + UAVTalkConnectionData *connection; + CHECKCONHANDLE(connectionHandle,connection,return ); + + // Lock + xSemaphoreTakeRecursive(connection->lock, portMAX_DELAY); + + // Copy stats + memcpy(statsOut, &connection->stats, sizeof(UAVTalkStats)); + + // Release lock + xSemaphoreGiveRecursive(connection->lock); +} + +/** + * Reset the statistics counters. + * \param[in] connection UAVTalkConnection to be used + */ +void UAVTalkResetStats(UAVTalkConnection connectionHandle) +{ + UAVTalkConnectionData *connection; + CHECKCONHANDLE(connectionHandle,connection,return); + + // Lock + xSemaphoreTakeRecursive(connection->lock, portMAX_DELAY); + + // Clear stats + memset(&connection->stats, 0, sizeof(UAVTalkStats)); + + // Release lock + xSemaphoreGiveRecursive(connection->lock); +} + +/** + * Request an update for the specified object, on success the object data would have been + * updated by the GCS. + * \param[in] connection UAVTalkConnection to be used + * \param[in] obj Object to update + * \param[in] instId The instance ID or UAVOBJ_ALL_INSTANCES for all instances. + * \param[in] timeout Time to wait for the response, when zero it will return immediately + * \return 0 Success + * \return -1 Failure + */ +int32_t UAVTalkSendObjectRequest(UAVTalkConnection connectionHandle, UAVObjHandle obj, uint16_t instId, int32_t timeout) +{ + UAVTalkConnectionData *connection; + CHECKCONHANDLE(connectionHandle,connection,return -1); + return objectTransaction(connection, obj, instId, UAVTALK_TYPE_OBJ_REQ, timeout); +} + +/** + * Send the specified object through the telemetry link. + * \param[in] connection UAVTalkConnection to be used + * \param[in] obj Object to send + * \param[in] instId The instance ID or UAVOBJ_ALL_INSTANCES for all instances. + * \param[in] acked Selects if an ack is required (1:ack required, 0: ack not required) + * \param[in] timeoutMs Time to wait for the ack, when zero it will return immediately + * \return 0 Success + * \return -1 Failure + */ +int32_t UAVTalkSendObject(UAVTalkConnection connectionHandle, UAVObjHandle obj, uint16_t instId, uint8_t acked, int32_t timeoutMs) +{ + UAVTalkConnectionData *connection; + CHECKCONHANDLE(connectionHandle,connection,return -1); + // Send object + if (acked == 1) + { + return objectTransaction(connection, obj, instId, UAVTALK_TYPE_OBJ_ACK, timeoutMs); + } + else + { + return objectTransaction(connection, obj, instId, UAVTALK_TYPE_OBJ, timeoutMs); + } +} + +/** + * Execute the requested transaction on an object. + * \param[in] connection UAVTalkConnection to be used + * \param[in] obj Object + * \param[in] instId The instance ID of UAVOBJ_ALL_INSTANCES for all instances. + * \param[in] type Transaction type + * UAVTALK_TYPE_OBJ: send object, + * UAVTALK_TYPE_OBJ_REQ: request object update + * UAVTALK_TYPE_OBJ_ACK: send object with an ack + * \return 0 Success + * \return -1 Failure + */ +static int32_t objectTransaction(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId, uint8_t type, int32_t timeoutMs) +{ + int32_t respReceived; + + // Send object depending on if a response is needed + if (type == UAVTALK_TYPE_OBJ_ACK || type == UAVTALK_TYPE_OBJ_REQ) + { + // Get transaction lock (will block if a transaction is pending) + xSemaphoreTakeRecursive(connection->transLock, portMAX_DELAY); + // Send object + xSemaphoreTakeRecursive(connection->lock, portMAX_DELAY); + connection->respObj = obj; + connection->respInstId = instId; + sendObject(connection, obj, instId, type); + xSemaphoreGiveRecursive(connection->lock); + // Wait for response (or timeout) + respReceived = xSemaphoreTake(connection->respSema, timeoutMs/portTICK_RATE_MS); + // Check if a response was received + if (respReceived == pdFALSE) + { + // Cancel transaction + xSemaphoreTakeRecursive(connection->lock, portMAX_DELAY); + xSemaphoreTake(connection->respSema, 0); // non blocking call to make sure the value is reset to zero (binary sema) + connection->respObj = 0; + xSemaphoreGiveRecursive(connection->lock); + xSemaphoreGiveRecursive(connection->transLock); + return -1; + } + else + { + xSemaphoreGiveRecursive(connection->transLock); + return 0; + } + } + else if (type == UAVTALK_TYPE_OBJ) + { + xSemaphoreTakeRecursive(connection->lock, portMAX_DELAY); + sendObject(connection, obj, instId, UAVTALK_TYPE_OBJ); + xSemaphoreGiveRecursive(connection->lock); + return 0; + } + else + { + return -1; + } +} + +/** + * Process an byte from the telemetry stream. + * \param[in] connection UAVTalkConnection to be used + * \param[in] rxbyte Received byte + * \return 0 Success + * \return -1 Failure + */ +int32_t UAVTalkProcessInputStream(UAVTalkConnection connectionHandle, uint8_t rxbyte) +{ + UAVTalkConnectionData *connection; + CHECKCONHANDLE(connectionHandle,connection,return -1); + + UAVTalkInputProcessor *iproc = &connection->iproc; + ++connection->stats.rxBytes; + + if (iproc->rxPacketLength < 0xffff) + iproc->rxPacketLength++; // update packet byte count + + // Receive state machine + switch (iproc->state) + { + case UAVTALK_STATE_SYNC: + if (rxbyte != UAVTALK_SYNC_VAL) + break; + + // Initialize and update the CRC + iproc->cs = PIOS_CRC_updateByte(0, rxbyte); + + iproc->rxPacketLength = 1; + + iproc->state = UAVTALK_STATE_TYPE; + break; + + case UAVTALK_STATE_TYPE: + + // update the CRC + iproc->cs = PIOS_CRC_updateByte(iproc->cs, rxbyte); + + if ((rxbyte & UAVTALK_TYPE_MASK) != UAVTALK_TYPE_VER) + { + iproc->state = UAVTALK_STATE_SYNC; + break; + } + + iproc->type = rxbyte; + + iproc->packet_size = 0; + + iproc->state = UAVTALK_STATE_SIZE; + iproc->rxCount = 0; + break; + + case UAVTALK_STATE_SIZE: + + // update the CRC + iproc->cs = PIOS_CRC_updateByte(iproc->cs, rxbyte); + + if (iproc->rxCount == 0) + { + iproc->packet_size += rxbyte; + iproc->rxCount++; + break; + } + + iproc->packet_size += rxbyte << 8; + + if (iproc->packet_size < UAVTALK_MIN_HEADER_LENGTH || iproc->packet_size > UAVTALK_MAX_HEADER_LENGTH + UAVTALK_MAX_PAYLOAD_LENGTH) + { // incorrect packet size + iproc->state = UAVTALK_STATE_SYNC; + break; + } + + iproc->rxCount = 0; + iproc->objId = 0; + iproc->state = UAVTALK_STATE_OBJID; + break; + + case UAVTALK_STATE_OBJID: + + // update the CRC + iproc->cs = PIOS_CRC_updateByte(iproc->cs, rxbyte); + + iproc->objId += rxbyte << (8*(iproc->rxCount++)); + + if (iproc->rxCount < 4) + break; + + // Search for object, if not found reset state machine + // except if we got a OBJ_REQ for an object which does not + // exist, in which case we'll send a NACK + + iproc->obj = UAVObjGetByID(iproc->objId); + if (iproc->obj == 0 && iproc->type != UAVTALK_TYPE_OBJ_REQ) + { + connection->stats.rxErrors++; + iproc->state = UAVTALK_STATE_SYNC; + break; + } + + // Determine data length + if (iproc->type == UAVTALK_TYPE_OBJ_REQ || iproc->type == UAVTALK_TYPE_ACK || iproc->type == UAVTALK_TYPE_NACK) + { + iproc->length = 0; + iproc->instanceLength = 0; + } + else + { + iproc->length = UAVObjGetNumBytes(iproc->obj); + iproc->instanceLength = (UAVObjIsSingleInstance(iproc->obj) ? 0 : 2); + } + + // Check length and determine next state + if (iproc->length >= UAVTALK_MAX_PAYLOAD_LENGTH) + { + connection->stats.rxErrors++; + iproc->state = UAVTALK_STATE_SYNC; + break; + } + + // Check the lengths match + if ((iproc->rxPacketLength + iproc->instanceLength + iproc->length) != iproc->packet_size) + { // packet error - mismatched packet size + connection->stats.rxErrors++; + iproc->state = UAVTALK_STATE_SYNC; + break; + } + + iproc->instId = 0; + if (iproc->obj == 0) + { + // If this is a NACK, we skip to Checksum + iproc->state = UAVTALK_STATE_CS; + iproc->rxCount = 0; + + } + // Check if this is a single instance object (i.e. if the instance ID field is coming next) + else if (UAVObjIsSingleInstance(iproc->obj)) + { + // If there is a payload get it, otherwise receive checksum + if (iproc->length > 0) + iproc->state = UAVTALK_STATE_DATA; + else + iproc->state = UAVTALK_STATE_CS; + + iproc->rxCount = 0; + } + else + { + iproc->state = UAVTALK_STATE_INSTID; + iproc->rxCount = 0; + } + + break; + + case UAVTALK_STATE_INSTID: + + // update the CRC + iproc->cs = PIOS_CRC_updateByte(iproc->cs, rxbyte); + + iproc->instId += rxbyte << (8*(iproc->rxCount++)); + + if (iproc->rxCount < 2) + break; + + iproc->rxCount = 0; + + // If there is a payload get it, otherwise receive checksum + if (iproc->length > 0) + iproc->state = UAVTALK_STATE_DATA; + else + iproc->state = UAVTALK_STATE_CS; + + break; + + case UAVTALK_STATE_DATA: + + // update the CRC + iproc->cs = PIOS_CRC_updateByte(iproc->cs, rxbyte); + + connection->rxBuffer[iproc->rxCount++] = rxbyte; + if (iproc->rxCount < iproc->length) + break; + + iproc->state = UAVTALK_STATE_CS; + iproc->rxCount = 0; + break; + + case UAVTALK_STATE_CS: + + // the CRC byte + if (rxbyte != iproc->cs) + { // packet error - faulty CRC + connection->stats.rxErrors++; + iproc->state = UAVTALK_STATE_SYNC; + break; + } + + if (iproc->rxPacketLength != (iproc->packet_size + 1)) + { // packet error - mismatched packet size + connection->stats.rxErrors++; + iproc->state = UAVTALK_STATE_SYNC; + break; + } + + xSemaphoreTakeRecursive(connection->lock, portMAX_DELAY); + receiveObject(connection, iproc->type, iproc->objId, iproc->instId, connection->rxBuffer, iproc->length); + connection->stats.rxObjectBytes += iproc->length; + connection->stats.rxObjects++; + xSemaphoreGiveRecursive(connection->lock); + + iproc->state = UAVTALK_STATE_SYNC; + break; + + default: + connection->stats.rxErrors++; + iproc->state = UAVTALK_STATE_SYNC; + } + + // Done + return 0; +} + +/** + * Receive an object. This function process objects received through the telemetry stream. + * \param[in] connection UAVTalkConnection to be used + * \param[in] type Type of received message (UAVTALK_TYPE_OBJ, UAVTALK_TYPE_OBJ_REQ, UAVTALK_TYPE_OBJ_ACK, UAVTALK_TYPE_ACK, UAVTALK_TYPE_NACK) + * \param[in] objId ID of the object to work on + * \param[in] instId The instance ID of UAVOBJ_ALL_INSTANCES for all instances. + * \param[in] data Data buffer + * \param[in] length Buffer length + * \return 0 Success + * \return -1 Failure + */ +static int32_t receiveObject(UAVTalkConnectionData *connection, uint8_t type, uint32_t objId, uint16_t instId, uint8_t* data, int32_t length) +{ + UAVObjHandle obj; + int32_t ret = 0; + + // Get the handle to the Object. Will be zero + // if object does not exist. + obj = UAVObjGetByID(objId); + + // Process message type + switch (type) { + case UAVTALK_TYPE_OBJ: + // All instances, not allowed for OBJ messages + if (instId != UAVOBJ_ALL_INSTANCES) + { + // Unpack object, if the instance does not exist it will be created! + UAVObjUnpack(obj, instId, data); + // Check if an ack is pending + updateAck(connection, obj, instId); + } + else + { + ret = -1; + } + break; + case UAVTALK_TYPE_OBJ_ACK: + // All instances, not allowed for OBJ_ACK messages + if (instId != UAVOBJ_ALL_INSTANCES) + { + // Unpack object, if the instance does not exist it will be created! + if ( UAVObjUnpack(obj, instId, data) == 0 ) + { + // Transmit ACK + sendObject(connection, obj, instId, UAVTALK_TYPE_ACK); + } + else + { + ret = -1; + } + } + else + { + ret = -1; + } + break; + case UAVTALK_TYPE_OBJ_REQ: + // Send requested object if message is of type OBJ_REQ + if (obj == 0) + sendNack(connection, objId); + else + sendObject(connection, obj, instId, UAVTALK_TYPE_OBJ); + break; + case UAVTALK_TYPE_NACK: + // Do nothing on flight side, let it time out. + break; + case UAVTALK_TYPE_ACK: + // All instances, not allowed for ACK messages + if (instId != UAVOBJ_ALL_INSTANCES) + { + // Check if an ack is pending + updateAck(connection, obj, instId); + } + else + { + ret = -1; + } + break; + default: + ret = -1; + } + // Done + return ret; +} + +/** + * Check if an ack is pending on an object and give response semaphore + * \param[in] connection UAVTalkConnection to be used + * \param[in] obj Object + * \param[in] instId The instance ID of UAVOBJ_ALL_INSTANCES for all instances. + */ +static void updateAck(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId) +{ + if (connection->respObj == obj && (connection->respInstId == instId || connection->respInstId == UAVOBJ_ALL_INSTANCES)) + { + xSemaphoreGive(connection->respSema); + connection->respObj = 0; + } +} + +/** + * Send an object through the telemetry link. + * \param[in] connection UAVTalkConnection to be used + * \param[in] obj Object handle to send + * \param[in] instId The instance ID or UAVOBJ_ALL_INSTANCES for all instances + * \param[in] type Transaction type + * \return 0 Success + * \return -1 Failure + */ +static int32_t sendObject(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId, uint8_t type) +{ + uint32_t numInst; + uint32_t n; + + // If all instances are requested and this is a single instance object, force instance ID to zero + if ( instId == UAVOBJ_ALL_INSTANCES && UAVObjIsSingleInstance(obj) ) + { + instId = 0; + } + + // Process message type + if ( type == UAVTALK_TYPE_OBJ || type == UAVTALK_TYPE_OBJ_ACK ) + { + if (instId == UAVOBJ_ALL_INSTANCES) + { + // Get number of instances + numInst = UAVObjGetNumInstances(obj); + // Send all instances + for (n = 0; n < numInst; ++n) + { + sendSingleObject(connection, obj, n, type); + } + return 0; + } + else + { + return sendSingleObject(connection, obj, instId, type); + } + } + else if (type == UAVTALK_TYPE_OBJ_REQ) + { + return sendSingleObject(connection, obj, instId, UAVTALK_TYPE_OBJ_REQ); + } + else if (type == UAVTALK_TYPE_ACK) + { + if ( instId != UAVOBJ_ALL_INSTANCES ) + { + return sendSingleObject(connection, obj, instId, UAVTALK_TYPE_ACK); + } + else + { + return -1; + } + } + else + { + return -1; + } +} + +/** + * Send an object through the telemetry link. + * \param[in] connection UAVTalkConnection to be used + * \param[in] obj Object handle to send + * \param[in] instId The instance ID (can NOT be UAVOBJ_ALL_INSTANCES, use sendObject() instead) + * \param[in] type Transaction type + * \return 0 Success + * \return -1 Failure + */ +static int32_t sendSingleObject(UAVTalkConnectionData *connection, UAVObjHandle obj, uint16_t instId, uint8_t type) +{ + int32_t length; + int32_t dataOffset; + uint32_t objId; + + if (!connection->outStream) return -1; + + // Setup type and object id fields + objId = UAVObjGetID(obj); + connection->txBuffer[0] = UAVTALK_SYNC_VAL; // sync byte + connection->txBuffer[1] = type; + // data length inserted here below + connection->txBuffer[4] = (uint8_t)(objId & 0xFF); + connection->txBuffer[5] = (uint8_t)((objId >> 8) & 0xFF); + connection->txBuffer[6] = (uint8_t)((objId >> 16) & 0xFF); + connection->txBuffer[7] = (uint8_t)((objId >> 24) & 0xFF); + + // Setup instance ID if one is required + if (UAVObjIsSingleInstance(obj)) + { + dataOffset = 8; + } + else + { + connection->txBuffer[8] = (uint8_t)(instId & 0xFF); + connection->txBuffer[9] = (uint8_t)((instId >> 8) & 0xFF); + dataOffset = 10; + } + + // Determine data length + if (type == UAVTALK_TYPE_OBJ_REQ || type == UAVTALK_TYPE_ACK) + { + length = 0; + } + else + { + length = UAVObjGetNumBytes(obj); + } + + // Check length + if (length >= UAVTALK_MAX_PAYLOAD_LENGTH) + { + return -1; + } + + // Copy data (if any) + if (length > 0) + { + if ( UAVObjPack(obj, instId, &connection->txBuffer[dataOffset]) < 0 ) + { + return -1; + } + } + + // Store the packet length + connection->txBuffer[2] = (uint8_t)((dataOffset+length) & 0xFF); + connection->txBuffer[3] = (uint8_t)(((dataOffset+length) >> 8) & 0xFF); + + // Calculate checksum + connection->txBuffer[dataOffset+length] = PIOS_CRC_updateCRC(0, connection->txBuffer, dataOffset+length); + + uint16_t tx_msg_len = dataOffset+length+UAVTALK_CHECKSUM_LENGTH; + int32_t rc = (*connection->outStream)(connection->txBuffer, tx_msg_len); + + if (rc == tx_msg_len) { + // Update stats + ++connection->stats.txObjects; + connection->stats.txBytes += tx_msg_len; + connection->stats.txObjectBytes += length; + } + + // Done + return 0; +} + +/** + * Send a NACK through the telemetry link. + * \param[in] connection UAVTalkConnection to be used + * \param[in] objId Object ID to send a NACK for + * \return 0 Success + * \return -1 Failure + */ +static int32_t sendNack(UAVTalkConnectionData *connection, uint32_t objId) +{ + int32_t dataOffset; + + if (!connection->outStream) return -1; + + connection->txBuffer[0] = UAVTALK_SYNC_VAL; // sync byte + connection->txBuffer[1] = UAVTALK_TYPE_NACK; + // data length inserted here below + connection->txBuffer[4] = (uint8_t)(objId & 0xFF); + connection->txBuffer[5] = (uint8_t)((objId >> 8) & 0xFF); + connection->txBuffer[6] = (uint8_t)((objId >> 16) & 0xFF); + connection->txBuffer[7] = (uint8_t)((objId >> 24) & 0xFF); + + dataOffset = 8; + + // Store the packet length + connection->txBuffer[2] = (uint8_t)((dataOffset) & 0xFF); + connection->txBuffer[3] = (uint8_t)(((dataOffset) >> 8) & 0xFF); + + // Calculate checksum + connection->txBuffer[dataOffset] = PIOS_CRC_updateCRC(0, connection->txBuffer, dataOffset); + + uint16_t tx_msg_len = dataOffset+UAVTALK_CHECKSUM_LENGTH; + int32_t rc = (*connection->outStream)(connection->txBuffer, tx_msg_len); + + if (rc == tx_msg_len) { + // Update stats + connection->stats.txBytes += tx_msg_len; + } + + // Done + return 0; +} + +/** + * @} + * @} + */ diff --git a/overo/server/Makefile b/overo/server/Makefile new file mode 100644 index 000000000..e759fecf7 --- /dev/null +++ b/overo/server/Makefile @@ -0,0 +1,478 @@ +##### +# Project: Overo Server +# +# The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2012. +# +# +# 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 +include $(TOP)/make/boards/$(BOARD_NAME)/board-info.mk + +# Target file name (without extension). +TARGET := fw_$(BOARD_NAME) + +# Directory for output files (lst, obj, dep, elf, sym, map, hex, bin etc.) +OUTDIR := $(TOP)/build/$(TARGET) + +# Set developer code and compile options +# Set to YES for debugging +DEBUG ?= NO + +# Set to YES when using Code Sourcery toolchain +CODE_SOURCERY ?= NO + +ifeq ($(CODE_SOURCERY), YES) +REMOVE_CMD = cs-rm +else +REMOVE_CMD = rm +endif + +FLASH_TOOL = OPENOCD + +# List of modules to include +MODULES = Sensors Attitude/revolution ManualControl Stabilization Altitude/revolution Actuator GPS Telemetry FirmwareIAP +PYMODULES = +#FlightPlan + +# Paths +OPSYSTEM = ./System +OPSYSTEMINC = $(OPSYSTEM)/inc +OPUAVTALK = ../UAVTalk +OPUAVTALKINC = $(OPUAVTALK)/inc +OPUAVOBJ = ../UAVObjects +OPUAVOBJINC = $(OPUAVOBJ)/inc +PIOS = ../PiOS +PIOSINC = $(PIOS)/inc +OPMODULEDIR = ../Modules +FLIGHTLIB = ../Libraries +FLIGHTLIBINC = ../Libraries/inc +PIOSSTM32F4XX = $(PIOS)/STM32F4xx +PIOSCOMMON = $(PIOS)/Common +PIOSBOARDS = $(PIOS)/Boards +PIOSCOMMONLIB = $(PIOSCOMMON)/Libraries +APPLIBDIR = $(PIOSSTM32F4XX)/Libraries +STMLIBDIR = $(APPLIBDIR) +STMSPDDIR = $(STMLIBDIR)/STM32F4xx_StdPeriph_Driver +STMSPDSRCDIR = $(STMSPDDIR)/src +STMSPDINCDIR = $(STMSPDDIR)/inc +OPUAVOBJ = ../UAVObjects +OPUAVOBJINC = $(OPUAVOBJ)/inc +BOOT = ../Bootloaders/INS +BOOTINC = $(BOOT)/inc +PYMITE = $(FLIGHTLIB)/PyMite +PYMITELIB = $(PYMITE)/lib +PYMITEPLAT = $(PYMITE)/platform/openpilot +PYMITETOOLS = $(PYMITE)/tools +PYMITEVM = $(PYMITE)/vm +PYMITEINC = $(PYMITEVM) +PYMITEINC += $(PYMITEPLAT) +PYMITEINC += $(OUTDIR) +FLIGHTPLANLIB = $(OPMODULEDIR)/FlightPlan/lib +FLIGHTPLANS = $(OPMODULEDIR)/FlightPlan/flightplans +HWDEFSINC = ../board_hw_defs/$(BOARD_NAME) +UAVOBJSYNTHDIR = $(OUTDIR)/../uavobject-synthetics/flight + +SRC = +# optional component libraries +include $(PIOSCOMMONLIB)/FreeRTOS/library.mk +#include $(PIOSCOMMONLIB)/dosfs/library.mk +include $(PIOSCOMMONLIB)/msheap/library.mk + + +# List C source files here. (C dependencies are automatically generated.) +# use file-extension c for "c-only"-files + +## PyMite files and modules +SRC += $(OUTDIR)/pmlib_img.c +SRC += $(OUTDIR)/pmlib_nat.c +SRC += $(OUTDIR)/pmlibusr_img.c +SRC += $(OUTDIR)/pmlibusr_nat.c +PYSRC += $(wildcard ${PYMITEVM}/*.c) +PYSRC += $(wildcard ${PYMITEPLAT}/*.c) +PYSRC += ${foreach MOD, ${PYMODULES}, ${wildcard ${OPMODULEDIR}/${MOD}/*.c}} +SRC += $(PYSRC) + +## MODULES +SRC += ${foreach MOD, ${MODULES}, ${wildcard ${OPMODULEDIR}/${MOD}/*.c}} +## OPENPILOT CORE: +SRC += ${OPMODULEDIR}/System/systemmod.c +SRC += $(OPSYSTEM)/revolution.c +SRC += $(OPSYSTEM)/pios_board.c +SRC += $(OPSYSTEM)/alarms.c +SRC += $(OPUAVTALK)/uavtalk.c +SRC += $(OPUAVOBJ)/uavobjectmanager.c +SRC += $(OPUAVOBJ)/eventdispatcher.c + +#ifeq ($(DEBUG),YES) +SRC += $(OPSYSTEM)/dcc_stdio.c +SRC += $(OPSYSTEM)/cm3_fault_handlers.c +#endif + +SRC += $(FLIGHTLIB)/CoordinateConversions.c +SRC += $(FLIGHTLIB)/fifo_buffer.c +SRC += $(FLIGHTLIB)/WorldMagModel.c +SRC += $(FLIGHTLIB)/insgps13state.c +SRC += $(FLIGHTLIB)/taskmonitor.c + +## PIOS Hardware (STM32F4xx) +include $(PIOS)/STM32F4xx/library.mk + +## PIOS Hardware (Common) +SRC += $(PIOSCOMMON)/pios_mpu6000.c +SRC += $(PIOSCOMMON)/pios_bma180.c +SRC += $(PIOSCOMMON)/pios_l3gd20.c +SRC += $(PIOSCOMMON)/pios_hmc5883.c +SRC += $(PIOSCOMMON)/pios_ms5611.c +SRC += $(PIOSCOMMON)/pios_crc.c +SRC += $(PIOSCOMMON)/pios_com.c +SRC += $(PIOSCOMMON)/pios_rcvr.c +SRC += $(PIOSCOMMON)/pios_flash_jedec.c +SRC += $(PIOSCOMMON)/pios_flashfs_objlist.c +SRC += $(PIOSCOMMON)/printf-stdarg.c + +include ./UAVObjects.inc +SRC += $(UAVOBJSRC) + +# List C source files here which must be compiled in ARM-Mode (no -mthumb). +# use file-extension c for "c-only"-files +## just for testing, timer.c could be compiled in thumb-mode too +SRCARM = + +# List C++ source files here. +# use file-extension .cpp for C++-files (not .C) +CPPSRC = + +# List C++ source files here which must be compiled in ARM-Mode. +# use file-extension .cpp for C++-files (not .C) +#CPPSRCARM = $(TARGET).cpp +CPPSRCARM = + +# List Assembler source files here. +# Make them always end in a capital .S. Files ending in a lowercase .s +# will not be considered source files but generated files (assembler +# output from the compiler), and will be deleted upon "make clean"! +# Even though the DOS/Win* filesystem matches both .s and .S the same, +# it will preserve the spelling of the filenames, and gcc itself does +# care about how the name is spelled on its command-line. + + +# List Assembler source files here which must be assembled in ARM-Mode.. +ASRCARM = + +# List any extra directories to look for include files here. +# Each directory must be seperated by a space. +EXTRAINCDIRS += $(PIOS) +EXTRAINCDIRS += $(PIOSINC) +EXTRAINCDIRS += $(OPSYSTEMINC) +EXTRAINCDIRS += $(OPUAVTALK) +EXTRAINCDIRS += $(OPUAVTALKINC) +EXTRAINCDIRS += $(OPUAVOBJ) +EXTRAINCDIRS += $(OPUAVOBJINC) +EXTRAINCDIRS += $(UAVOBJSYNTHDIR) +EXTRAINCDIRS += $(FLIGHTLIBINC) +EXTRAINCDIRS += $(PIOSSTM32F4XX) +EXTRAINCDIRS += $(PIOSCOMMON) +EXTRAINCDIRS += $(PIOSBOARDS) +EXTRAINCDIRS += $(STMSPDINCDIR) +EXTRAINCDIRS += $(CMSISDIR) +EXTRAINCDIRS += $(OPUAVSYNTHDIR) +EXTRAINCDIRS += $(BOOTINC) +EXTRAINCDIRS += $(PYMITEINC) +EXTRAINCDIRS += $(HWDEFSINC) + +# Generate intermediate code +gencode: ${OUTDIR}/pmlib_img.c ${OUTDIR}/pmlib_nat.c ${OUTDIR}/pmlibusr_img.c ${OUTDIR}/pmlibusr_nat.c ${OUTDIR}/pmfeatures.h + +$(PYSRC): gencode + +PYTHON = python + +# Generate code for PyMite +${OUTDIR}/pmlib_img.c ${OUTDIR}/pmlib_nat.c ${OUTDIR}/pmlibusr_img.c ${OUTDIR}/pmlibusr_nat.c ${OUTDIR}/pmfeatures.h: $(wildcard ${PYMITELIB}/*.py) $(wildcard ${PYMITEPLAT}/*.py) $(wildcard ${FLIGHTPLANLIB}/*.py) $(wildcard ${FLIGHTPLANS}/*.py) + @echo $(MSG_PYMITEINIT) $(call toprel, $@) + @$(PYTHON) $(PYMITETOOLS)/pmImgCreator.py -f $(PYMITEPLAT)/pmfeatures.py -c -s --memspace=flash -o $(OUTDIR)/pmlib_img.c --native-file=$(OUTDIR)/pmlib_nat.c $(PYMITELIB)/list.py $(PYMITELIB)/dict.py $(PYMITELIB)/__bi.py $(PYMITELIB)/sys.py $(PYMITELIB)/string.py $(wildcard $(FLIGHTPLANLIB)/*.py) + @$(PYTHON) $(PYMITETOOLS)/pmGenPmFeatures.py $(PYMITEPLAT)/pmfeatures.py > $(OUTDIR)/pmfeatures.h + @$(PYTHON) $(PYMITETOOLS)/pmImgCreator.py -f $(PYMITEPLAT)/pmfeatures.py -c -u -o $(OUTDIR)/pmlibusr_img.c --native-file=$(OUTDIR)/pmlibusr_nat.c $(FLIGHTPLANS)/test.py +EXTRAINCDIRS += ${foreach MOD, ${MODULES} ${PYMODULES}, $(OPMODULEDIR)/${MOD}/inc} ${OPMODULEDIR}/System/inc + +# List any extra directories to look for library files here. +# Also add directories where the linker should search for +# includes from linker-script to the list +# Each directory must be seperated by a space. +EXTRA_LIBDIRS = + +# Extra Libraries +# Each library-name must be seperated by a space. +# i.e. to link with libxyz.a, libabc.a and libefsl.a: +# EXTRA_LIBS = xyz abc efsl +# for newlib-lpc (file: libnewlibc-lpc.a): +# EXTRA_LIBS = newlib-lpc +EXTRA_LIBS = + +# Path to Linker-Scripts +LINKERSCRIPTPATH = $(PIOSSTM32F4XX) + +# Optimization level, can be [0, 1, 2, 3, s]. +# 0 = turn off optimization. s = optimize for size. +# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) + +ifeq ($(DEBUG),YES) +CFLAGS += -O0 +CFLAGS += -DGENERAL_COV +CFLAGS += -finstrument-functions -ffixed-r10 +else +CFLAGS += -Os +endif + + + +# common architecture-specific flags from the device-specific library makefile +CFLAGS += $(ARCHFLAGS) + + +CFLAGS += -DDIAGNOSTICS + +# This is not the best place for these. Really should abstract out +# to the board file or something +CFLAGS += -DSTM32F4XX +CFLAGS += -DMEM_SIZE=1024000000 + +# Output format. (can be ihex or binary or both) +# binary to create a load-image in raw-binary format i.e. for SAM-BA, +# ihex to create a load-image in Intel hex format +#LOADFORMAT = ihex +#LOADFORMAT = binary +LOADFORMAT = both + +# Debugging format. +DEBUGF = dwarf-2 + +# Place project-specific -D (define) and/or +# -U options for C here. +CDEFS += -DSTM32F10X_$(MODEL) +CDEFS += -DSYSCLK_FREQ=$(SYSCLK_FREQ) +CDEFS += -DUSE_STDPERIPH_DRIVER +CDEFS += -DUSE_$(BOARD) + +# Place project-specific -D and/or -U options for +# Assembler with preprocessor here. +#ADEFS = -DUSE_IRQ_ASM_WRAPPER +ADEFS = -D__ASSEMBLY__ + +# Compiler flag to set the C Standard level. +# c89 - "ANSI" C +# gnu89 - c89 plus GCC extensions +# c99 - ISO C99 standard (not yet fully implemented) +# gnu99 - c99 plus GCC extensions +CSTANDARD = -std=gnu99 + +#----- + +# Compiler flags. + +# -g*: generate debugging information +# -O*: optimization level +# -f...: tuning, see GCC manual and avr-libc documentation +# -Wall...: warning level +# -Wa,...: tell GCC to pass this to the assembler. +# -adhlns...: create assembler listing +# +# Flags for C and C++ (arm-elf-gcc/arm-elf-g++) + +CFLAGS += -g$(DEBUGF) + +CFLAGS += -ffast-math + +CFLAGS += -mcpu=$(MCU) +CFLAGS += $(CDEFS) +CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I. + +CFLAGS += -mapcs-frame +CFLAGS += -fomit-frame-pointer +ifeq ($(CODE_SOURCERY), YES) +CFLAGS += -fpromote-loop-indices +endif + +#CFLAGS += -Wall +#CFLAGS += -Werror +CFLAGS += -Wa,-adhlns=$(addprefix $(OUTDIR)/, $(notdir $(addsuffix .lst, $(basename $<)))) +# Compiler flags to generate dependency files: +CFLAGS += -MD -MP -MF $(OUTDIR)/dep/$(@F).d + +# flags only for C +#CONLYFLAGS += -Wnested-externs +CONLYFLAGS += $(CSTANDARD) + +# Assembler flags. +# -Wa,...: tell GCC to pass this to the assembler. +# -ahlns: create listing +ASFLAGS = $(ARCHFLAGS) -mthumb -I. -x assembler-with-cpp +ASFLAGS += $(ADEFS) +ASFLAGS += -Wa,-adhlns=$(addprefix $(OUTDIR)/, $(notdir $(addsuffix .lst, $(basename $<)))) +ASFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) + +MATH_LIB = -lm + +# Linker flags. +# -Wl,...: tell GCC to pass this to linker. +# -Map: create map file +# --cref: add cross reference to map file +LDFLAGS = -nostartfiles -Wl,-Map=$(OUTDIR)/$(TARGET).map,--cref,--gc-sections +LDFLAGS += $(patsubst %,-L%,$(EXTRA_LIBDIRS)) +LDFLAGS += -lc +LDFLAGS += $(patsubst %,-l%,$(EXTRA_LIBS)) +LDFLAGS += $(MATH_LIB) +LDFLAGS += -lc -lgcc + +#Linker scripts +LDFLAGS += $(addprefix -T,$(LINKER_SCRIPTS_APP)) + + +# Define programs and commands. +REMOVE = $(REMOVE_CMD) -f +PYHON = python + +# List of all source files. +ALLSRC = $(ASRCARM) $(ASRC) $(SRCARM) $(SRC) $(CPPSRCARM) $(CPPSRC) +# List of all source files without directory and file-extension. +ALLSRCBASE = $(notdir $(basename $(ALLSRC))) + +# Define all object files. +ALLOBJ = $(addprefix $(OUTDIR)/, $(addsuffix .o, $(ALLSRCBASE))) + +# Define all listing files (used for make clean). +LSTFILES = $(addprefix $(OUTDIR)/, $(addsuffix .lst, $(ALLSRCBASE))) +# Define all depedency-files (used for make clean). +DEPFILES = $(addprefix $(OUTDIR)/dep/, $(addsuffix .o.d, $(ALLSRCBASE))) + +# Default target. +all: gccversion build + +ifeq ($(LOADFORMAT),ihex) +build: elf hex lss sym +else +ifeq ($(LOADFORMAT),binary) +build: elf bin lss sym +else +ifeq ($(LOADFORMAT),both) +build: elf hex bin lss sym +else +$(error "$(MSG_FORMATERROR) $(FORMAT)") +endif +endif +endif + + +# Link: create ELF output file from object files. +$(eval $(call LINK_TEMPLATE, $(OUTDIR)/$(TARGET).elf, $(ALLOBJ))) + +# Assemble: create object files from assembler source files. +$(foreach src, $(ASRC), $(eval $(call ASSEMBLE_TEMPLATE, $(src)))) + +# Assemble: create object files from assembler source files. ARM-only +$(foreach src, $(ASRCARM), $(eval $(call ASSEMBLE_ARM_TEMPLATE, $(src)))) + +# Compile: create object files from C source files. +$(foreach src, $(SRC), $(eval $(call COMPILE_C_TEMPLATE, $(src)))) + +# Compile: create object files from C source files. ARM-only +$(foreach src, $(SRCARM), $(eval $(call COMPILE_C_ARM_TEMPLATE, $(src)))) + +# Compile: create object files from C++ source files. +$(foreach src, $(CPPSRC), $(eval $(call COMPILE_CPP_TEMPLATE, $(src)))) + +# Compile: create object files from C++ source files. ARM-only +$(foreach src, $(CPPSRCARM), $(eval $(call COMPILE_CPP_ARM_TEMPLATE, $(src)))) + +# Compile: create assembler files from C source files. ARM/Thumb +$(eval $(call PARTIAL_COMPILE_TEMPLATE, SRC)) + +# Compile: create assembler files from C source files. ARM only +$(eval $(call PARTIAL_COMPILE_ARM_TEMPLATE, SRCARM)) + +$(OUTDIR)/$(TARGET).bin.o: $(OUTDIR)/$(TARGET).bin + +$(eval $(call OPFW_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BOARD_TYPE),$(BOARD_REVISION))) + +# Add jtag targets (program and wipe) +$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE),$(OPENOCD_CONFIG))) + +.PHONY: elf lss sym hex bin bino opfw +elf: $(OUTDIR)/$(TARGET).elf +lss: $(OUTDIR)/$(TARGET).lss +sym: $(OUTDIR)/$(TARGET).sym +hex: $(OUTDIR)/$(TARGET).hex +bin: $(OUTDIR)/$(TARGET).bin +bino: $(OUTDIR)/$(TARGET).bin.o +opfw: $(OUTDIR)/$(TARGET).opfw + +# Display sizes of sections. +$(eval $(call SIZE_TEMPLATE, $(OUTDIR)/$(TARGET).elf)) + +# Generate Doxygen documents +docs: + doxygen $(DOXYGENDIR)/doxygen.cfg + +# Install: install binary file with prefix/suffix into install directory +install: $(OUTDIR)/$(TARGET).opfw +ifneq ($(INSTALL_DIR),) + @echo $(MSG_INSTALLING) $(call toprel, $<) + $(V1) mkdir -p $(INSTALL_DIR) + $(V1) $(INSTALL) $< $(INSTALL_DIR)/$(INSTALL_PFX)$(TARGET)$(INSTALL_SFX).opfw +else + $(error INSTALL_DIR must be specified for $@) +endif + +# Target: clean project. +clean: clean_list + +clean_list : + @echo $(MSG_CLEANING) + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).map + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).elf + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).hex + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).bin + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).sym + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).lss + $(V1) $(REMOVE) $(OUTDIR)/$(TARGET).bin.o + $(V1) $(REMOVE) $(ALLOBJ) + $(V1) $(REMOVE) $(LSTFILES) + $(V1) $(REMOVE) $(DEPFILES) + $(V1) $(REMOVE) $(SRC:.c=.s) + $(V1) $(REMOVE) $(SRCARM:.c=.s) + $(V1) $(REMOVE) $(CPPSRC:.cpp=.s) + $(V1) $(REMOVE) $(CPPSRCARM:.cpp=.s) + +# Create output files directory +# all known MS Windows OS define the ComSpec environment variable +ifdef ComSpec +$(shell md $(subst /,\\,$(OUTDIR)) 2>NUL) +else +$(shell mkdir -p $(OUTDIR) 2>/dev/null) +endif + +# Include the dependency files. +ifdef ComSpec +-include $(shell md $(subst /,\\,$(OUTDIR))\dep 2>NUL) $(wildcard $(OUTDIR)/dep/*) +else +-include $(shell mkdir $(OUTDIR) 2>/dev/null) $(shell mkdir $(OUTDIR)/dep 2>/dev/null) $(wildcard $(OUTDIR)/dep/*) +endif + +# Listing of phony targets. +.PHONY : all build clean clean_list install