/*==================[internal functions definition]==========================*/ static void UPDT_configParse(const uint8_t *payload, size_t size, UPDT_configType *info) { uint32_t word; const uint32_t *ptr; ciaaPOSIX_assert(NULL != payload); ciaaPOSIX_assert (NULL != info); ptr = (const uint32_t *) payload; word = ciaaLibs_utilsNtohl(*ptr); info->reserved1 = 0xFFu & (word >> 24); info->firmware_version = 0xFFFFFFu & (word); word = ciaaLibs_utilsNtohl(*(ptr + 1)); info->bootloader_flags = 0xFFu & (word >> 24); info->bootloader_version = 0xFFFFFFu & (word); word = ciaaLibs_utilsNtohl(*(ptr + 2)); info->reserved2 = 0xFFu & (word >> 24); info->application_version = 0xFFFFFFu & (word); word = ciaaLibs_utilsNtohl(*(ptr + 3)); info->vendor_id = 0xFFu & (word >> 24); info->model_id = 0xFFFFFFu & (word); info->unique_id_high = ciaaLibs_setHigh (ptr+4); info->unique_id_low = ciaaLibs_setLow(ptr+4); info->data_size = ciaaLibs_utilsNtohl(*(ptr + 6)); }
/*==================[external functions definition]==========================*/ int32_t UPDT_slaveInit(UPDT_slaveType *slave, UPDT_ITransportType *transport) { ciaaPOSIX_assert(NULL != slave); ciaaPOSIX_assert(NULL != transport); slave->transport = transport; slave->protocol_version = 0; slave->sequence_number = 0; slave->payload_size = 0; slave->done = 0; return 0; }
/** \brief UPDT_configFormat stores in a buffer, in compacted format, the parameters of to data structure ** \param config_buffer is the buffer wherein the content of the structure is stored ** \param data_size is the number of elements that will have the buffer ** \param info is a variable of the type structure used to assemble the buffer **/ static void UPDT_configFormat (uint8_t *config_buffer,size_t data_size, UPDT_configType *type) { ciaaPOSIX_assert(data_size == 32); /*Set of the field "reserved1" in the buffer*/ ciaaLibs_SetByte (config_buffer,0,(type->reserved1)); /*Set of the field "firmware_version" in the buffer*/ ciaaLibs_SetUint24 (config_buffer,1,(type->firmware_version)); /*Set of the field "bootloader_flags" in the buffer*/ ciaaLibs_SetByte (config_buffer,4,(type->bootloader_flags)); /*Set of the field "bootloader_version" in the buffer*/ ciaaLibs_SetUint24 (config_buffer,5,(type->bootloader_version)); /*Set of the field "reserved2" in the buffer*/ ciaaLibs_SetByte (config_buffer,8,(type->reserved2)); /*Set of the field "application_version" in the buffer*/ ciaaLibs_SetUint24 (config_buffer,9,(type->application_version)); /*Set of the field "vendor_id" in the buffer*/ ciaaLibs_SetByte (config_buffer,12,(type->vendor_id)); /*Set of the field "model_id" in the buffer*/ ciaaLibs_SetUint24 (config_buffer,13,(type->model_id)); /*Set of the field "unique_id" in the buffer*/ #if CIAAPLATFORM_BIGENDIAN == 0 ciaaLibs_SetUint32 (config_buffer,16,(type->unique_id_low)); ciaaLibs_SetUint32 (config_buffer,20,(type->unique_id_high)); #else ciaaLibs_SetUint32 (config_buffer,16,(type->unique_id_high)); ciaaLibs_SetUint32 (config_buffer,20,(type->unique_id_low)); #endif // CIAAPLATFORM_BIGENDIAN /*Set of the field "data_size" in the buffer*/ ciaaLibs_SetUint32 (config_buffer,24,(type->data_size)); }
extern void ciaaBlockDevices_readIndication(ciaaDevices_deviceType const * const device, uint32_t const nbyte) { /* get block device */ ciaaBlockDevices_deviceType * blockDevice = (ciaaBlockDevices_deviceType*) device->layer; TaskType taskID = blockDevice->blocked.taskID; if ( (255 != taskID) && ( (void*)ciaaBlockDevices_read == blockDevice->blocked.fct) ) { /* invalidate task id */ blockDevice->blocked.taskID = 255; /* TODO add macro */ /* reset blocked function */ blockDevice->blocked.fct = NULL; #ifdef POSIXE /* set task event */ SetEvent(taskID, POSIXE); #else #endif } else { /* this shall not happens */ ciaaPOSIX_assert(0); } }
static int32_t ciaaDriverFlash_blockWrite(uint32_t address, uint8_t const * const data, uint32_t size) { /* holds return values */ int32_t ret; /* index used to iterate through the data */ uint32_t data_index = -1; /* index used to iterate through the memory buffer */ uint32_t buffer_index; /* size of data to be written */ uint32_t write_size; ciaaDriverFlash_flashType * flash = &ciaaDriverFlash_flash; uint8_t buffer[CIAADRVFLASH_BLOCK_SIZE]; if (address <= CIAADRVFLASH_SIZE) { data_index = 0; while(data_index < size) { /* calculate how much is to be written in this iteration */ write_size = (data_index + CIAADRVFLASH_BLOCK_SIZE <= size) ? CIAADRVFLASH_BLOCK_SIZE : size - data_index; /* rewind to change i/o mode */ rewind(flash->storage); /* seek the position to write in and bring its contents */ ret = fseek(flash->storage, address + data_index, SEEK_SET); ciaaPOSIX_assert(0 == ret); ret = fread(buffer, 1, write_size, flash->storage); ciaaPOSIX_assert(ret == write_size); /* rewind to change i/o mode */ rewind(flash->storage); /* seek the position to write in */ ret = fseek(flash->storage, address + data_index, SEEK_SET); ciaaPOSIX_assert(0 == ret); /* perform the and operation between the block brought and the new data */ for(buffer_index = 0; buffer_index < write_size; buffer_index++, data_index++) buffer[buffer_index] &= data[data_index]; /* write in to the previously sought position */ ret = fwrite(buffer, 1, write_size, flash->storage); ciaaPOSIX_assert(ret == write_size); } } return data_index; }
/*==================[internal functions definition]==========================*/ static int32_t UPDT_slaveSendResponse( UPDT_slaveType *slave, const uint8_t* payload, size_t payload_size, uint8_t response_type) { uint8_t *buffer; ciaaPOSIX_assert(NULL != slave); ciaaPOSIX_assert(NULL != payload); buffer = slave->send_buffer; UPDT_protocolSetHeader(buffer, response_type, slave->sequence_number, payload_size); ciaaPOSIX_memcpy(buffer + UPDT_PROTOCOL_HEADER_SIZE, payload, payload_size); return UPDT_protocolSend(slave->transport, buffer, UPDT_PROTOCOL_HEADER_SIZE + payload_size); }
void UPDT_slaveClear(UPDT_slaveType *slave) { ciaaPOSIX_assert(NULL != slave); slave->sequence_number = 0; slave->protocol_version = 0; slave->transport = NULL; slave->payload_size = 0; slave->done = 0; }
extern ciaaDevices_deviceType * ciaaBlockDevices_open(char const * path, ciaaDevices_deviceType * device, uint8_t const oflag) { ciaaBlockDevices_deviceType * blockDevice = (ciaaBlockDevices_deviceType*) device->layer; /* block devices does not support that the drivers update the device */ /* the returned device shall be the same as passed */ ciaaPOSIX_assert(blockDevice->device->open(path, (ciaaDevices_deviceType *)device->loLayer, oflag) == device->loLayer); return device; }
extern ciaaDevices_deviceType * ciaaDioDevices_open(char const * path, ciaaDevices_deviceType * device, uint8_t const oflag) { ciaaDevices_deviceType * drv = (ciaaDevices_deviceType*) device->loLayer; /* serial devices does not support that the drivers update the device */ /* the returned device shall be the same as passed */ ciaaPOSIX_assert(drv->open(path, drv, oflag) == drv); return device; }
ssize_t UPDT_slaveRecvInfo( UPDT_slaveType *slave, uint8_t *payload_buffer, size_t buffer_size) { /* holds return values */ int32_t ret; /* received payload size */ ssize_t payload_size = 0; /* received packet header */ uint8_t header[UPDT_PROTOCOL_HEADER_SIZE]; /* received sequence number */ uint8_t sequence_number; ciaaPOSIX_assert(buffer_size >= UPDT_PROTOCOL_PAYLOAD_MAX_SIZE); do { /* receive header */ /** \todo review the timeouts. In this state a timeout does not matter */ ret = UPDT_protocolRecv(slave->transport, header, UPDT_PROTOCOL_HEADER_SIZE); if(UPDT_PROTOCOL_ERROR_NONE != ret) { /* transport layer error or timeout */ return -1; } payload_size = UPDT_protocolGetPayloadSize(header); sequence_number = UPDT_protocolGetSequenceNumber(header); /* get the data packet and remove it from the buffer */ ret = UPDT_protocolRecv(slave->transport, payload_buffer, payload_size); if(UPDT_PROTOCOL_ERROR_NONE != ret) { /* transport layer error or timeout */ return -1; } } /* receive again if the packet is corrupted */ while(UPDT_protocolGetPacketType(header) != UPDT_PROTOCOL_PACKET_INF); /* set the expected sequence number */ slave->sequence_number = sequence_number + 1; return payload_size; }
extern ciaaDevices_deviceType * ciaaSerialDevices_open(char const * path, ciaaDevices_deviceType * device, uint8_t const oflag) { ciaaSerialDevices_deviceType * serialDevice = (ciaaSerialDevices_deviceType*) device->layer; /* serial devices does not support that the drivers update the device */ /* the returned device shall be the same as passed */ ciaaPOSIX_assert(serialDevice->device->open(path, (ciaaDevices_deviceType *)device->loLayer, oflag) == device->loLayer); if(oflag & O_NONBLOCK) { serialDevice->flags |= ciaaSerialDevices_NONBLOCK_MODE; } return device; }
int32_t UPDT_configWrite(void) { int32_t ret = -1; ciaaPOSIX_assert(UPDT_config_fd >= 0); /*To the previous configuration is assigned the new version of protocol and firmware, because it's the only change (the other parameters are kept)*/ UPDT_config_old.firmware_version = (UPDT_config_new.firmware_version); UPDT_config_old.application_version = UPDT_config_new.application_version; /*Becomes the structure in an bytes sequence*/ UPDT_configFormat(UPDT_config_buffer,28,&UPDT_config_old); /*function call to move the point to the memory address where it will be written*/ if (ciaaPOSIX_lseek (UPDT_config_fd,UPDT_CONFIG_ADDRESS,SEEK_SET) == UPDT_CONFIG_ADDRESS); { ret = ciaaPOSIX_write (UPDT_config_fd,UPDT_config_buffer,28); } return ret; }
/** \todo Go back to the initial state if an info packet is received */ ssize_t UPDT_slaveRecvData( UPDT_slaveType *slave, uint8_t *payload_buffer, size_t buffer_size) { /* holds return values */ int32_t ret; /* received payload size */ ssize_t payload_size = 0; /* received packet header */ uint8_t header[UPDT_PROTOCOL_HEADER_SIZE]; /* received sequence number */ uint8_t sequence_number; ciaaPOSIX_assert(buffer_size >= UPDT_PROTOCOL_PAYLOAD_MAX_SIZE); if(0 == slave->done) { do { /* receive header */ ret = UPDT_protocolRecv(slave->transport, header, UPDT_PROTOCOL_HEADER_SIZE); if(UPDT_PROTOCOL_ERROR_NONE != ret) { /* transport layer error or timeout */ return -1; } payload_size = UPDT_protocolGetPayloadSize(header); sequence_number = UPDT_protocolGetSequenceNumber(header); /* if the expected payload size does not match with the received */ if(slave->payload_size != payload_size) { /* if this is the first packet */ if(0 == slave->payload_size) { /* then set the expected payload size */ slave->payload_size = payload_size; } else { /* this is the last packet */ slave->done = 1; } } /* if we receive the same sequence number again */ if(slave->sequence_number - 1 == sequence_number) { /* then ACK sent may be lost. does not matter the packet type */ /* resend ACK */ UPDT_slaveSendResponse(slave, slave->send_buffer, 0, UPDT_PROTOCOL_PACKET_ACK); } /* get the data packet and remove it from the buffer */ ret = UPDT_protocolRecv(slave->transport, payload_buffer, payload_size); if(UPDT_PROTOCOL_ERROR_NONE != ret) { /* transport layer error or timeout */ return -1; } } /* receive again if the packet is corrupted */ while(UPDT_protocolGetPacketType(header) != UPDT_PROTOCOL_PACKET_DAT || slave->sequence_number != sequence_number); /* increment expected sequence number */ ++slave->sequence_number; /* send acknowledge */ UPDT_slaveSendResponse(slave, slave->send_buffer, 0, UPDT_PROTOCOL_PACKET_ACK); } return payload_size; }
static uint32_t testDataOk(uint8_t *vector) { ciaaPOSIX_assert (UPDT_PROTOCOL_PACKET_ACK == UPDT_protocolGetPacketType(vector)); ciaaPOSIX_assert (SequenceNumber==UPDT_protocolGetSequenceNumber(vector)); return 0; }
static uint32_t testHandshakeOkNextSequenceNumber(test_updt_configType *type, uint8_t *vector) { ciaaPOSIX_assert (UPDT_PROTOCOL_PACKET_ACK == UPDT_protocolGetPacketType(vector)); ciaaPOSIX_assert (SequenceNumber == UPDT_protocolGetSequenceNumber(vector)); return 0; }