diff --git a/controller/inc/FreeRTOSConfig.h b/controller/inc/FreeRTOSConfig.h index dfab423d..2ec69b4e 100644 --- a/controller/inc/FreeRTOSConfig.h +++ b/controller/inc/FreeRTOSConfig.h @@ -91,7 +91,7 @@ #define configTICK_RATE_HZ ( ( portTickType ) 1000 ) #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 ) -#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 75 * 1024 ) ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 48 * 1024 ) ) #define configMAX_TASK_NAME_LEN ( 10 ) #define configUSE_TRACE_FACILITY 1 #define configUSE_16_BIT_TICKS 0 diff --git a/controller/inc/lowlevel_misc.h b/controller/inc/lowlevel_misc.h new file mode 100644 index 00000000..1a6ec7d8 --- /dev/null +++ b/controller/inc/lowlevel_misc.h @@ -0,0 +1,24 @@ +// Licensed to Pioneers in Engineering under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. Pioneers in Engineering licenses +// this file to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License + +#ifndef INC_LOWLEVEL_MISC_H_ +#define INC_LOWLEVEL_MISC_H_ + +#define CCM_DATA __attribute__((section(".ccmram"))) +#define CCM_BSS __attribute__((section(".ccmbss"))) + +#endif // INC_LOWLEVEL_MISC_H_ diff --git a/controller/inc/uart_serial_driver.h b/controller/inc/uart_serial_driver.h index b65d78b7..cee52eec 100755 --- a/controller/inc/uart_serial_driver.h +++ b/controller/inc/uart_serial_driver.h @@ -43,8 +43,10 @@ extern int uart_serial_packets_waiting(uart_serial_module *module); // Returns 1 if the queue is full extern int uart_serial_is_full(uart_serial_module *module); -extern void *uart_serial_send_data(uart_serial_module *module, uint8_t *data, - size_t len); +// This function makes a copy of the data. It is not necessary to retain it +// past the call. +extern void *uart_serial_send_data(uart_serial_module *module, + const uint8_t *data, size_t len); extern int uart_serial_send_status(uart_serial_module *module, void *transaction); extern int uart_serial_send_finish(uart_serial_module *module, @@ -52,10 +54,14 @@ extern int uart_serial_send_finish(uart_serial_module *module, extern int uart_serial_send_and_finish_data(uart_serial_module *module, uint8_t *data, size_t len); -extern uint8_t *uart_serial_receive_packet(uart_serial_module *module, - size_t *len_out, int shouldBlock); -extern uint8_t *uart_serial_receive_packet_timeout(uart_serial_module *module, - size_t *len_out, TickType_t timeout); + +// The packet will be written into buf. len should contain the max size of the +// buffer on input and will be replaced with the actual number of bytes written +// on output. This function returns 0 on success. +extern int uart_serial_receive_packet(uart_serial_module *module, + uint8_t *buf, size_t *len, int shouldBlock); +extern int uart_serial_receive_packet_timeout(uart_serial_module *module, + uint8_t *buf, size_t *len, TickType_t timeout); extern int uart_bus_logic_level(uart_serial_module *module); diff --git a/controller/src/FreeRTOS/heap_3.c b/controller/src/FreeRTOS/heap_1.c similarity index 64% rename from controller/src/FreeRTOS/heap_3.c rename to controller/src/FreeRTOS/heap_1.c index e6c5960e..c144810e 100644 --- a/controller/src/FreeRTOS/heap_3.c +++ b/controller/src/FreeRTOS/heap_1.c @@ -65,16 +65,12 @@ /* - * Implementation of pvPortMalloc() and vPortFree() that relies on the - * compilers own malloc() and free() implementations. + * The simplest possible implementation of pvPortMalloc(). Note that this + * implementation does NOT allow allocated memory to be freed again. * - * This file can only be used if the linker is configured to to generate - * a heap memory area. - * - * See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the + * See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the * memory management pages of http://www.FreeRTOS.org for more information. */ - #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining @@ -87,15 +83,52 @@ task.h is included from an application file. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE +#include "inc/lowlevel_misc.h" + +/* A few bytes might be lost to byte aligning the heap start address. */ +#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) + +/* Allocate the memory for the heap. */ +static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] CCM_BSS; +static size_t xNextFreeByte = ( size_t ) 0; + /*-----------------------------------------------------------*/ void *pvPortMalloc( size_t xWantedSize ) { -void *pvReturn; +void *pvReturn = NULL; +static uint8_t *pucAlignedHeap = NULL; + + /* Ensure that blocks are always aligned to the required number of bytes. */ + #if portBYTE_ALIGNMENT != 1 + if( xWantedSize & portBYTE_ALIGNMENT_MASK ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + } + #endif + + vTaskSuspendAll(); + { + if( pucAlignedHeap == NULL ) + { + /* Ensure the heap starts on a correctly aligned boundary. */ + pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); + } + + /* Check there is enough room left for the allocation. */ + if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) && + ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) )/* Check for overflow. */ + { + /* Return the next free byte then increment the index past this + block. */ + pvReturn = pucAlignedHeap + xNextFreeByte; + xNextFreeByte += xWantedSize; + } - // Our malloc already calls FreeRTOS to synchronize properly - pvReturn = malloc( xWantedSize ); - traceMALLOC( pvReturn, xWantedSize ); + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); #if( configUSE_MALLOC_FAILED_HOOK == 1 ) { @@ -113,11 +146,26 @@ void *pvReturn; void vPortFree( void *pv ) { - if( pv ) - { - free( pv ); - traceFREE( pv, 0 ); - } + /* Memory cannot be freed using this scheme. See heap_2.c, heap_3.c and + heap_4.c for alternative implementations, and the memory management pages of + http://www.FreeRTOS.org for more information. */ + ( void ) pv; + + /* Force an assert as it is invalid to call this function. */ + configASSERT( pv == NULL ); +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* Only required when static memory is not cleared. */ + xNextFreeByte = ( size_t ) 0; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return ( configADJUSTED_HEAP_SIZE - xNextFreeByte ); } diff --git a/controller/src/i2c_master.c b/controller/src/i2c_master.c index 55ba3a5d..d25299e2 100644 --- a/controller/src/i2c_master.c +++ b/controller/src/i2c_master.c @@ -59,7 +59,7 @@ static portTASK_FUNCTION_PROTO(i2c_master_task, pvParameters) { i2c_master_module *i2c_master_init_module(void *periph_base) { i2c_master_module_private *module_obj = - pvPortMalloc(sizeof(i2c_master_module_private)); + malloc(sizeof(i2c_master_module_private)); I2C_TypeDef *i2c = (I2C_TypeDef *)periph_base; // TODO(rqou): Figure out magic to make pin init and clock init work @@ -93,14 +93,14 @@ i2c_master_module *i2c_master_init_module(void *periph_base) { module_obj->currentTxn = NULL; // Start the task - xTaskCreate(i2c_master_task, "I2C", 256, module_obj, tskIDLE_PRIORITY, NULL); + xTaskCreate(i2c_master_task, "I2C", 128, module_obj, tskIDLE_PRIORITY, NULL); return (i2c_master_module *)module_obj; } void *i2c_issue_transaction(i2c_master_module *module, uint8_t addr, uint8_t *data_out, size_t len_out, uint8_t *data_in, size_t len_in) { - i2c_transaction_obj *obj = pvPortMalloc(sizeof(i2c_transaction_obj)); + i2c_transaction_obj *obj = malloc(sizeof(i2c_transaction_obj)); obj->data_out = data_out; obj->data_in = data_in; @@ -239,7 +239,7 @@ int i2c_transaction_finish(i2c_master_module *module, return 0; } - vPortFree(transaction); + free(transaction); return 1; } diff --git a/controller/src/led_driver.c b/controller/src/led_driver.c index f08c6330..ff0ebeb6 100755 --- a/controller/src/led_driver.c +++ b/controller/src/led_driver.c @@ -320,7 +320,7 @@ static portTASK_FUNCTION_PROTO(led_driver_task, pvParameters) { void led_driver_init(void) { led_driver_init_hw(); - xTaskCreate(led_driver_task, "LEDs", 256, NULL, tskIDLE_PRIORITY, NULL); + xTaskCreate(led_driver_task, "LEDs", 128, NULL, tskIDLE_PRIORITY, NULL); } void led_driver_set_mode(uint8_t mode) { diff --git a/controller/src/main.c b/controller/src/main.c index 8de228bc..2e69fa30 100644 --- a/controller/src/main.c +++ b/controller/src/main.c @@ -144,7 +144,9 @@ static portTASK_FUNCTION_PROTO(radioTask, pvParameters) { int started_angelic = 0; while (1) { - uint8_t *buf; + // TODO(rqou): Size is hardcoded. Yuck. + uint8_t buf[256]; + int ret; size_t len; if (!got_a_packet && should_harass) { @@ -181,21 +183,20 @@ static portTASK_FUNCTION_PROTO(radioTask, pvParameters) { } got_a_packet = 0; - buf = uart_serial_receive_packet(radio_driver, &len, 0); - if (!buf) { + len = sizeof(buf); + ret = uart_serial_receive_packet(radio_driver, buf, &len, 0); + if (ret) { // TODO(rqou): Proper timer, why the f*ck do I need to copy this here? vTaskDelay(20 / portTICK_RATE_MS); continue; } xbee_api_packet *packetIn = (xbee_api_packet *)buf; if (!xbee_verify_checksum(packetIn)) { - vPortFree(buf); // TODO(rqou): Proper timer, why the f*ck do I need to copy this here? vTaskDelay(20 / portTICK_RATE_MS); continue; } if (packetIn->payload.xbee_api_type != XBEE_API_TYPE_RX64) { - vPortFree(buf); // TODO(rqou): Proper timer, why the f*ck do I need to copy this here? vTaskDelay(20 / portTICK_RATE_MS); continue; @@ -224,7 +225,7 @@ static portTASK_FUNCTION_PROTO(radioTask, pvParameters) { (tenshi_bulk_start *)(packetIn->payload.rx64.data); // TODO(rqou): What happens if I already have one? // TODO(rqou): Stream ID? - code_buffer = pvPortMalloc(bulk_start->length); + code_buffer = malloc(bulk_start->length); code_received_to = 0; code_buffer_len = code_received_len = bulk_start->length; got_a_packet = 1; @@ -287,8 +288,6 @@ static portTASK_FUNCTION_PROTO(radioTask, pvParameters) { break; } - vPortFree(buf); - // TODO(rqou): Proper timer vTaskDelay(20 / portTICK_RATE_MS); } diff --git a/controller/src/radio.c b/controller/src/radio.c index 48d20e08..f63d9475 100644 --- a/controller/src/radio.c +++ b/controller/src/radio.c @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License +#include #include #include @@ -102,7 +103,7 @@ BaseType_t radioInit() { radioQueue = xQueueCreate(100, sizeof(RadioMessage)); - return xTaskCreate(radioNewTask, "Radio", 1024, NULL, tskIDLE_PRIORITY, + return xTaskCreate(radioNewTask, "Radio", 512, NULL, tskIDLE_PRIORITY, NULL); } void radioPushUbjson(const char *ubjson, size_t len) { @@ -166,13 +167,13 @@ void radio_send_xbee(uint8_t *data, size_t len) { } void *ndAlloc(NDL3_size size, void * userdata) { (void) userdata; - void *ret = pvPortMalloc(size); + void *ret = malloc(size); while (!ret) {} return ret; } void ndFree(void * to_free, void * userdata) { (void) userdata; - vPortFree(to_free); + free(to_free); } @@ -189,7 +190,9 @@ static portTASK_FUNCTION_PROTO(radioNewTask, pvParameters) { char * recvMsg = NULL; const uint8_t prefixLen = 1; - xbee_api_packet *recXbeePacket; + // TODO(rqou): Ugly + uint8_t recXbeePacket_buf[256]; + xbee_api_packet *recXbeePacket = (xbee_api_packet *)(recXbeePacket_buf); xbee_rx64_header *recXbeeHeader; uint8_t buffer[NDL3_PACKET_SIZE]; NDL3_size popSize = 0; @@ -208,7 +211,7 @@ static portTASK_FUNCTION_PROTO(radioNewTask, pvParameters) { // Trust this to free recvMsg runtimeRecieveUbjson(recvMsg, recvSize); } else { - vPortFree(recvMsg); + free(recvMsg); } recvMsg = NULL; @@ -219,7 +222,7 @@ static portTASK_FUNCTION_PROTO(radioNewTask, pvParameters) { // Trust this to free recvMsg runtimeRecieveUbjson(recvMsg, recvSize); } else { - vPortFree(recvMsg); + free(recvMsg); } recvMsg = NULL; @@ -227,7 +230,7 @@ static portTASK_FUNCTION_PROTO(radioNewTask, pvParameters) { NDL3_recv(target, NDL3_STRING_PORT, (void **) &recvMsg, &recvSize); // Do stuff with recieved message - vPortFree(recvMsg); + free(recvMsg); recvMsg = NULL; recvSize = 0; @@ -237,7 +240,7 @@ static portTASK_FUNCTION_PROTO(radioNewTask, pvParameters) { // Trust this to free recvMsg runtimeRecieveCode(recvMsg, recvSize); } else { - vPortFree(recvMsg); + free(recvMsg); } recvMsg = NULL; @@ -248,9 +251,9 @@ static portTASK_FUNCTION_PROTO(radioNewTask, pvParameters) { // Trust this to free recvMsg // TODO(cduck): Do something printf("Got config data\n"); - vPortFree(recvMsg); + free(recvMsg); } else { - vPortFree(recvMsg); + free(recvMsg); } @@ -272,9 +275,10 @@ static portTASK_FUNCTION_PROTO(radioNewTask, pvParameters) { printf("Radio error b%d\n", err); } - recXbeePacket = (xbee_api_packet*)uart_serial_receive_packet(radio_driver, + uartRecvSize = sizeof(recXbeePacket_buf); + int ret = uart_serial_receive_packet(radio_driver, recXbeePacket, &uartRecvSize, 0); - if (recXbeePacket) { + if (!ret) { recXbeePacket->length = __REV16(recXbeePacket->length); recXbeeHeader = (xbee_rx64_header*)&(recXbeePacket->payload); if (recXbeeHeader->xbee_api_type == XBEE_API_TYPE_RX64) { @@ -284,7 +288,6 @@ static portTASK_FUNCTION_PROTO(radioNewTask, pvParameters) { recXbeePacket->length-sizeof(xbee_rx64_header)-prefixLen); } } - vPortFree(recXbeePacket); } err = NDL3_pop_error(target); diff --git a/controller/src/runtime.c b/controller/src/runtime.c index 068e2493..195f30a6 100644 --- a/controller/src/runtime.c +++ b/controller/src/runtime.c @@ -74,7 +74,7 @@ BaseType_t runtimeInit() { // Get updates from smart sensor protocol registerSensorUpdateCallback(&sensorUpdateCallback); - return xTaskCreate(runtimeTask, "Runtime", 2048, NULL, tskIDLE_PRIORITY, + return xTaskCreate(runtimeTask, "Runtime", 512, NULL, tskIDLE_PRIORITY, NULL); } @@ -203,7 +203,7 @@ static portTASK_FUNCTION_PROTO(runtimeTask, pvParameters) { int ret = RUNTIME_OK, firstErr = RUNTIME_OK; TenshiRuntimeState s = NULL; TenshiActorState a = NULL; - char *studentCode = pvPortMalloc(sizeof(studentCodeTemplate)); + char *studentCode = malloc(sizeof(studentCodeTemplate)); memcpy(studentCode, studentCodeTemplate, sizeof(studentCodeTemplate)); size_t studentCodeLen = sizeof(studentCodeTemplate)-1; @@ -234,12 +234,12 @@ static portTASK_FUNCTION_PROTO(runtimeTask, pvParameters) { } else { switch (msg.type) { case RuntimeMessageUbjson: - vPortFree(lastUbjson); + free(lastUbjson); lastUbjson = msg.info; lastUbjsonLen = msg.infoLen; break; case RuntimeMessageNewCode: - vPortFree(studentCode); + free(studentCode); studentCode = msg.info; studentCodeLen = msg.infoLen; @@ -264,7 +264,7 @@ static portTASK_FUNCTION_PROTO(runtimeTask, pvParameters) { setGameMode(RuntimeModeDisabled); break; default: - vPortFree(msg.info); + free(msg.info); break; } } diff --git a/controller/src/runtime_interface.c b/controller/src/runtime_interface.c index 1df45eab..5f3d89b0 100644 --- a/controller/src/runtime_interface.c +++ b/controller/src/runtime_interface.c @@ -171,7 +171,7 @@ int lua_set_radio_val(lua_State *L) { size_t ubjsonLen = 0; char *ubjson = lua_tolstring(L, 2, &ubjsonLen); - char *ubjsonMalloc = pvPortMalloc(ubjsonLen); + char *ubjsonMalloc = malloc(ubjsonLen); memcpy(ubjsonMalloc, ubjson, ubjsonLen); radioPushUbjson(ubjsonMalloc, ubjsonLen); @@ -187,7 +187,7 @@ int lua_get_radio_val(lua_State *L) { if (ubjson) { lua_pushlstring(L, ubjson, ubjsonLen); - vPortFree(ubjson); + free(ubjson); ubjson = NULL; ubjsonLen = 0; } else { diff --git a/controller/src/smartsensor/smartsensor.c b/controller/src/smartsensor/smartsensor.c index abf9c7bd..01d00486 100755 --- a/controller/src/smartsensor/smartsensor.c +++ b/controller/src/smartsensor/smartsensor.c @@ -110,7 +110,7 @@ void smartsensor_init() { sensorArrLock = xSemaphoreCreateBinary(); numSensorsAlloc = numSensors = 0; - sensorArr = pvPortMalloc(numSensorsAlloc*sizeof(SSState*)); + sensorArr = malloc(numSensorsAlloc*sizeof(SSState*)); xSemaphoreGive(sensorArrLock); @@ -119,7 +119,7 @@ void smartsensor_init() { tskIDLE_PRIORITY, NULL); for (int i = 0; i < SS_BUS_COUNT; i++) { busState[i] = SS_BUS_ENUMERATION; - xTaskCreate(smartSensorTX, (const char *)"SensorTX", 1024, (void*)i, + xTaskCreate(smartSensorTX, (const char *)"SensorTX", 512, (void*)i, tskIDLE_PRIORITY, NULL); } for (int i = 0; i < SS_BUS_COUNT; i++) { @@ -139,7 +139,7 @@ void ssBlockUntilActive() { void registerSensorUpdateCallback(void(*func)(uint16_t i, SSState *sensor)) { if (xSemaphoreTake(sensorCallbackLock, SEMAPHORE_WAIT_TIME) == pdTRUE) { struct SensorCallback *callback = - pvPortMalloc(sizeof(struct SensorCallback)); + malloc(sizeof(struct SensorCallback)); callback->func = func, callback->next = NULL; @@ -172,7 +172,7 @@ portTASK_FUNCTION_PROTO(smartSensorTX, pvParameters) { led_driver_set_mode(PATTERN_ENUMERATING); KnownIDs enumIDs = { - .arr = pvPortMalloc(SS_MAX_SENSORS_PER_BUS * sizeof(SSState*)), + .arr = malloc(SS_MAX_SENSORS_PER_BUS * sizeof(SSState*)), .len = 0, .maxLen = SS_MAX_SENSORS_PER_BUS, }; @@ -207,7 +207,7 @@ portTASK_FUNCTION_PROTO(smartSensorTX, pvParameters) { ss_select_delay(); } - vPortFree(enumIDs.arr); + free(enumIDs.arr); busState[busNum] = SS_BUS_ACTIVE; } @@ -349,11 +349,14 @@ portTASK_FUNCTION_PROTO(smartSensorRX, pvParameters) { while (busState[busNum] == SS_BUS_ACTIVE) { // Recieve the response to the packet // 1 means wait for packet - uint8_t *data = uart_serial_receive_packet(bus, &recLen, 0); + // TODO(rqou): Ugly hardcoded size + uint8_t data[256]; + recLen = sizeof(data); + int ret = uart_serial_receive_packet(bus, data, &recLen, 0); if (busState[busNum] != SS_BUS_ACTIVE) break; - if (data) { + if (!ret) { uint8_t prefixLen = 3; if (recLen > prefixLen) { uint8_t sampleNumber = (data[1] >> 3) & 0b111; @@ -361,7 +364,7 @@ portTASK_FUNCTION_PROTO(smartSensorRX, pvParameters) { uint8_t frameNumber = (data[1] & 0b111) - SS_FIRST_FRAME; uint8_t inband = data[1] >> 7; uint8_t decodeLen = recLen-prefixLen-1; - uint8_t *data_decode = pvPortMalloc(decodeLen); + uint8_t *data_decode = malloc(decodeLen); cobs_decode(data_decode, data+prefixLen, decodeLen+1); // led_driver_set_mode(PATTERN_JUST_RED); @@ -379,9 +382,8 @@ portTASK_FUNCTION_PROTO(smartSensorRX, pvParameters) { } } - if (data_decode) vPortFree(data_decode); + if (data_decode) free(data_decode); } - vPortFree(data); } } } diff --git a/controller/src/smartsensor/ssutil.c b/controller/src/smartsensor/ssutil.c index 7357f673..880a0fd1 100644 --- a/controller/src/smartsensor/ssutil.c +++ b/controller/src/smartsensor/ssutil.c @@ -72,7 +72,9 @@ uint8_t *ss_read_descriptor(SSState *sensor, uint32_t *readLen) { const uint8_t requestLen = 3; uint8_t request[3] = {0, 0, 2}; // Request two length bytes size_t recLen = 0; - uint8_t *recData; + // TODO(rqou): Ugly hardcoded size + uint8_t recData[256]; + int ret; const uint8_t prefixLen = 3; uint8_t temp[4]; @@ -80,24 +82,26 @@ uint8_t *ss_read_descriptor(SSState *sensor, uint32_t *readLen) { uint8_t *allData = NULL; // Clear missed packets - while (uart_serial_receive_packet(bus, &recLen, 0)) {} + do { + recLen = sizeof(recData); + } while (uart_serial_receive_packet(bus, recData, &recLen, 0) == 0); int success = ss_send_maintenance_to_sensor(sensor, SS_PACKET_DESCRIPTOR, request, requestLen); // Request two length bytes if (!success) return NULL; - recData = uart_serial_receive_packet_timeout(bus, &recLen, + recLen = sizeof(recData); + ret = uart_serial_receive_packet_timeout(bus, recData, &recLen, SENSOR_REPLY_TIMEOUT); - if (!recData) return NULL; + if (ret) return NULL; if (recLen < prefixLen+3 || recData[1] != SS_PACKET_DESCRIPTOR) { - vPortFree(recData); + free(recData); return NULL; } // At least two bytes decoded, at most 3 if extra data was recieved. cobs_decode(temp, recData+prefixLen, 4); - vPortFree(recData); allLen = temp[0] + temp[1]*0x100; // Little endian - allData = pvPortMalloc(allLen); + allData = malloc(allLen); while (partLen < allLen) { request[0] = partLen & 0xFF; @@ -107,21 +111,20 @@ uint8_t *ss_read_descriptor(SSState *sensor, uint32_t *readLen) { int success = ss_send_maintenance_to_sensor(sensor, SS_PACKET_DESCRIPTOR, request, requestLen); // Request descriptor bytes if (!success) { - vPortFree(allData); + free(allData); return NULL; } - recData = uart_serial_receive_packet_timeout(bus, &recLen, + recLen = sizeof(recData); + ret = uart_serial_receive_packet_timeout(bus, recData, &recLen, SENSOR_REPLY_TIMEOUT); - if (!recData || recLen < prefixLen+2 // Minimum 1 byte of descriptor data + if (ret || recLen < prefixLen+2 // Minimum 1 byte of descriptor data || recData[1] != SS_PACKET_DESCRIPTOR) { - vPortFree(allData); - vPortFree(recData); + free(allData); return NULL; } if (partLen + (recLen-prefixLen-1) > allLen) // If too much data recieved recLen = allLen-partLen + prefixLen+1; cobs_decode(allData + partLen, recData+prefixLen, recLen-prefixLen); - vPortFree(recData); partLen += recLen-prefixLen-1; } @@ -146,8 +149,8 @@ int ss_interpret_descriptor(SSState *sensor, uint8_t *data, uint32_t len) { sensor->descriptionLen = data[0]; ++data; if (data + sensor->descriptionLen > end) return 0; - vPortFree(sensor->description); - sensor->description = pvPortMalloc(sensor->descriptionLen); + free(sensor->description); + sensor->description = malloc(sensor->descriptionLen); if (!sensor->description) return 0; memcpy(sensor->description, data, sensor->descriptionLen); data += sensor->descriptionLen; @@ -162,14 +165,14 @@ int ss_interpret_descriptor(SSState *sensor, uint8_t *data, uint32_t len) { if (data + 1 > end) return 0; uint8_t channelsNum = data[0]; ++data; - vPortFree(sensor->channels); - sensor->channels = pvPortMalloc(sensor->channelsNum * sizeof(SSChannel*)); + free(sensor->channels); + sensor->channels = malloc(sensor->channelsNum * sizeof(SSChannel*)); if (!sensor->channels) return 0; sensor->outgoingLen = 0; sensor->incomingLen = 0; - vPortFree(sensor->outgoingBytes); - vPortFree(sensor->incomingBytes); + free(sensor->outgoingBytes); + free(sensor->incomingBytes); sensor->outgoingBytes = NULL; sensor->incomingBytes = NULL; @@ -178,15 +181,15 @@ int ss_interpret_descriptor(SSState *sensor, uint8_t *data, uint32_t len) { if (data + 3 > end) return 0; if (data[1] + 3 > data[0]) return 0; if (data + data[0] > end) return 0; - SSChannel *channel = pvPortMalloc(sizeof(SSChannel)); + SSChannel *channel = malloc(sizeof(SSChannel)); if (!channel) return 0; channel->descriptionLen = data[1]; uint8_t descriptorLen = data[0]; data += 2; - channel->description = pvPortMalloc(channel->descriptionLen); + channel->description = malloc(channel->descriptionLen); if (!channel->description) { - vPortFree(channel); + free(channel); return 0; } memcpy(channel->description, data, channel->descriptionLen); @@ -196,10 +199,10 @@ int ss_interpret_descriptor(SSState *sensor, uint8_t *data, uint32_t len) { ++data; channel->additionalLen = descriptorLen - 3 - channel->descriptionLen; - channel->additional = pvPortMalloc(channel->additionalLen); + channel->additional = malloc(channel->additionalLen); if (!channel->additional) { - vPortFree(channel->description); - vPortFree(channel); + free(channel->description); + free(channel); return 0; } memcpy(channel->additional, data, channel->additionalLen); @@ -228,10 +231,10 @@ int ss_interpret_descriptor(SSState *sensor, uint8_t *data, uint32_t len) { } if (sensor->outgoingLen) { - sensor->outgoingBytes = pvPortMalloc(sensor->outgoingLen); + sensor->outgoingBytes = malloc(sensor->outgoingLen); } if (sensor->incomingLen) { - sensor->incomingBytes = pvPortMalloc(sensor->incomingLen); + sensor->incomingBytes = malloc(sensor->incomingLen); } if (sensor->outgoingBytes) { memset(sensor->outgoingBytes, 0, sensor->outgoingLen); @@ -264,7 +267,7 @@ int ss_update_descriptor(SSState *sensor) { if (data && len > 0) { ret = ss_interpret_descriptor(sensor, data, len); } - vPortFree(data); + free(data); return ret; } @@ -273,7 +276,7 @@ int ss_update_descriptor(SSState *sensor) { // Helper functions for smartsensor.c SSState *ss_init_sensor(uint8_t id[SMART_ID_LEN], uint8_t busNum) { - SSState *s = pvPortMalloc(sizeof(SSState)); + SSState *s = malloc(sizeof(SSState)); s->busNum = busNum; s->outLock = xSemaphoreCreateBinary(); @@ -306,10 +309,10 @@ size_t ss_add_sensor(SSState *sensor) { const int numAllocAtOnce = 10; if (numSensorsAlloc <= numSensors) { - SSState **newPtr = pvPortMalloc((numSensorsAlloc+numAllocAtOnce) * + SSState **newPtr = malloc((numSensorsAlloc+numAllocAtOnce) * sizeof(SSState*)); memcpy(newPtr, sensorArr, numSensorsAlloc*sizeof(SSState*)); - vPortFree(sensorArr); + free(sensorArr); sensorArr = newPtr; numSensorsAlloc += numAllocAtOnce; } @@ -325,10 +328,10 @@ size_t ss_add_sensors(KnownIDs *sensors) { if (xSemaphoreTake(sensorArrLock, SENSOR_WAIT_TIME) != pdTRUE) return -1; if (numSensorsAlloc < numSensors+sensors->len) { - SSState **newPtr = pvPortMalloc((numSensors+sensors->len) * + SSState **newPtr = malloc((numSensors+sensors->len) * sizeof(SSState*)); memcpy(newPtr, sensorArr, numSensors*sizeof(SSState*)); - vPortFree(sensorArr); + free(sensorArr); sensorArr = newPtr; numSensorsAlloc = numSensors+sensors->len; } @@ -428,7 +431,7 @@ int ss_send_maintenance(uart_serial_module *module, uint8_t type, const uint8_t *data, uint8_t len) { if (len > 255-4)return 0; - uint8_t *data_cobs = (uint8_t*)pvPortMalloc(4+len); + uint8_t *data_cobs = (uint8_t*)malloc(4+len); // Four extra for 0x00, type, len, and extra COBS byte. data_cobs[0] = 0x00; @@ -437,23 +440,23 @@ int ss_send_maintenance(uart_serial_module *module, uint8_t type, cobs_encode(data_cobs+3, data, len); int r = ss_uart_serial_send_and_finish_data(module, data_cobs, len+4); - vPortFree(data_cobs); + free(data_cobs); return r; } int ss_send_maintenance_to_sensor(SSState *sensor, uint8_t type, const uint8_t *data, uint8_t len) { - uint8_t *buffer = pvPortMalloc(SMART_ID_LEN+len); + uint8_t *buffer = malloc(SMART_ID_LEN+len); memcpy(buffer, sensor->id, SMART_ID_LEN); memcpy(buffer+SMART_ID_LEN, data, len); int ret = ss_send_maintenance(ssBusses[sensor->busNum], type, buffer, SMART_ID_LEN+len); - vPortFree(buffer); + free(buffer); return ret; } int ss_all_send_maintenance(uint8_t type, const uint8_t *data, uint8_t len) { if (len > 255-4)return 0; - uint8_t *data_cobs = (uint8_t*)pvPortMalloc(4+len); + uint8_t *data_cobs = (uint8_t*)malloc(4+len); // Four extra for 0x00, type, len, and extra COBS byte. data_cobs[0] = 0x00; @@ -462,13 +465,13 @@ int ss_all_send_maintenance(uint8_t type, const uint8_t *data, uint8_t len) { cobs_encode(data_cobs+3, data, len); int r = ss_all_uart_serial_send_and_finish_data(data_cobs, len+4); - vPortFree(data_cobs); + free(data_cobs); return r; } int ss_send_ping_pong(SSState *sensor, const uint8_t *data, uint8_t len) { if (len > 255-4-SMART_ID_LEN)return 0; - uint8_t *temp = (uint8_t*)pvPortMalloc(len+SMART_ID_LEN); + uint8_t *temp = (uint8_t*)malloc(len+SMART_ID_LEN); for (uint8_t i = 0; i < SMART_ID_LEN; i++) { temp[i] = sensor->id[i]; } @@ -478,7 +481,7 @@ int ss_send_ping_pong(SSState *sensor, const uint8_t *data, uint8_t len) { int r = ss_send_maintenance(ssBusses[sensor->busNum], 0xFE, temp, len+SMART_ID_LEN); - vPortFree(temp); + free(temp); return r; } @@ -549,7 +552,7 @@ transmit_allocations ss_send_active(uart_serial_module *module, uint8_t inband, if (len > 12)return allocs; // Too long for active packet if ((frame & 7) == 0)return allocs; // Frame can never be zero - uint8_t *data_cobs = (uint8_t*)pvPortMalloc(4+len); + uint8_t *data_cobs = (uint8_t*)malloc(4+len); // Four extra for 0x00, sample/frame, len, and extra COBS byte. data_cobs[0] = 0x00; @@ -569,7 +572,7 @@ void ss_wait_until_done(uart_serial_module *module, UART_SERIAL_SEND_ERROR)) {} } void ss_send_finish(uart_serial_module *module, transmit_allocations allocs) { - if (allocs.data) vPortFree(allocs.data); + if (allocs.data) free(allocs.data); if (allocs.txn) uart_serial_send_finish(module, allocs.txn); } diff --git a/controller/src/uart_serial_driver.c b/controller/src/uart_serial_driver.c index 2174ddf9..fe03d265 100755 --- a/controller/src/uart_serial_driver.c +++ b/controller/src/uart_serial_driver.c @@ -17,8 +17,11 @@ #include "inc/uart_serial_driver.h" +#include + #include "inc/FreeRTOS.h" #include "inc/pindef.h" +#include "inc/pool_alloc.h" #include "inc/portable.h" #include "inc/queue.h" #include "inc/semphr.h" @@ -28,10 +31,10 @@ #define UART_QUEUE_SIZE 8 typedef struct tag_uart_txn { - uint8_t *data; size_t len; // Used only for TX int status; + uint8_t data[UART_RX_BUFFER_SIZE]; } uart_txn; typedef struct tag_uart_serial_module_private { @@ -45,6 +48,8 @@ typedef struct tag_uart_serial_module_private { xSemaphoreHandle rxSignal; uart_txn *currentTxTxn; uart_txn *currentRxTxn; + pool_alloc_t txPacketPool; + pool_alloc_t rxPacketPool; } uart_serial_module_private; typedef struct tag_uart_periph_info { @@ -176,14 +181,8 @@ static portTASK_FUNCTION_PROTO(uart_rx_task, pvParameters) { // A packet just came in. We now need to allocate a new buffer. // We will block in this task if we can't. - uart_txn *txn = pvPortMalloc(sizeof(uart_txn)); + uart_txn *txn = pool_alloc_block(module->rxPacketPool); txn->len = 0; - txn->data = pvPortMalloc(UART_RX_BUFFER_SIZE); - - if (!txn->data) { - continue; - } - module->currentRxTxn = txn; } } @@ -192,7 +191,7 @@ uart_serial_module *uart_serial_init_module(int uart_num, ssize_t (*length_finder_fn)(uart_serial_module *, uint8_t), void (*txen_fn)(int), int baud) { uart_serial_module_private *module = - pvPortMalloc(sizeof(uart_serial_module_private)); + malloc(sizeof(uart_serial_module_private)); USART_TypeDef *periph_base = periph_info[uart_num - 1].periph; DMA_TypeDef *dma_base = periph_info[uart_num - 1].dma; @@ -269,10 +268,15 @@ uart_serial_module *uart_serial_init_module(int uart_num, xSemaphoreGive(module->txInUse); vSemaphoreCreateBinary(module->rxSignal); - // Allocate a buffer for RX - uart_txn *rxTxn = pvPortMalloc(sizeof(uart_txn)); + // Allocate a packet pool for RX and TX + module->txPacketPool = pool_alloc_create(sizeof(uart_txn), UART_QUEUE_SIZE, + malloc); + module->rxPacketPool = pool_alloc_create(sizeof(uart_txn), UART_QUEUE_SIZE, + malloc); + + // Preallocate an RX transaction object + uart_txn *rxTxn = pool_alloc_block(module->rxPacketPool); rxTxn->len = 0; - rxTxn->data = pvPortMalloc(UART_RX_BUFFER_SIZE); module->currentRxTxn = rxTxn; module->currentTxTxn = NULL; @@ -298,11 +302,12 @@ int uart_serial_is_full(uart_serial_module *module) { uxQueueSpacesAvailable(((uart_serial_module_private *)module)->txQueue); } -void *uart_serial_send_data(uart_serial_module *module, uint8_t *data, +void *uart_serial_send_data(uart_serial_module *module, const uint8_t *data, size_t len) { - uart_txn *txn = pvPortMalloc(sizeof(uart_txn)); + uart_txn *txn = pool_alloc_block( + ((uart_serial_module_private *)module)->txPacketPool); - txn->data = data; + memcpy(txn->data, data, len); txn->len = len; txn->status = UART_SERIAL_SEND_QUEUED; @@ -328,7 +333,7 @@ int uart_serial_send_finish(uart_serial_module *module, void *_transaction) { return 0; } - vPortFree(transaction); + pool_alloc_free(transaction); return 1; } @@ -347,31 +352,32 @@ int uart_serial_send_and_finish_data(uart_serial_module *module, uint8_t *data, return uart_serial_send_finish(module, txn); } -uint8_t *uart_serial_receive_packet(uart_serial_module *module, - size_t *len_out, int shouldBlock) { - return uart_serial_receive_packet_timeout(module, len_out, +int uart_serial_receive_packet(uart_serial_module *module, + uint8_t *buf, size_t *len, int shouldBlock) { + return uart_serial_receive_packet_timeout(module, buf, len, shouldBlock ? portMAX_DELAY : 0); } -uint8_t *uart_serial_receive_packet_timeout(uart_serial_module *module, - size_t *len_out, TickType_t timeout) { +int uart_serial_receive_packet_timeout(uart_serial_module *module, + uint8_t *buf, size_t *len, TickType_t timeout) { uart_txn *txn; int ret = xQueueReceive( ((uart_serial_module_private *)module)->rxQueue, &txn, timeout); if (!ret) { - return NULL; + return 1; } - if (len_out) { - *len_out = txn->len; + if (*len < txn->len) { + return 2; } - uint8_t *outBuf = txn->data; + memcpy(buf, txn->data, txn->len); + *len = txn->len; - vPortFree(txn); + pool_alloc_free(txn); - return outBuf; + return 0; } extern int uart_bus_logic_level(uart_serial_module *_module) {