From c3beca20c637f2b05755cedc2890697cd8ae7893 Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Thu, 6 Sep 2018 16:03:00 +0100 Subject: [PATCH 1/5] First compiling build of overriding heap allocator --- inc/core/MicroBitConfig.h | 16 +-- inc/core/MicroBitHeapAllocator.h | 96 ++------------- source/core/MicroBitHeapAllocator.cpp | 169 ++++++++++++-------------- 3 files changed, 89 insertions(+), 192 deletions(-) diff --git a/inc/core/MicroBitConfig.h b/inc/core/MicroBitConfig.h index a2f48f3..ccb8ed6 100644 --- a/inc/core/MicroBitConfig.h +++ b/inc/core/MicroBitConfig.h @@ -110,24 +110,12 @@ extern uint32_t __etext; #endif -// Enables or disables the MicroBitHeapllocator. Note that if disabled, no reuse of the SRAM normally -// reserved for SoftDevice is possible, and out of memory condition will no longer be trapped... -// i.e. panic() will no longer be triggered on memory full conditions. -#ifndef MICROBIT_HEAP_ALLOCATOR -#define MICROBIT_HEAP_ALLOCATOR 1 -#endif - // Block size used by the allocator in bytes. // n.b. Currently only 32 bits (4 bytes) is supported. #ifndef MICROBIT_HEAP_BLOCK_SIZE #define MICROBIT_HEAP_BLOCK_SIZE 4 #endif -// The proportion of SRAM available on the mbed heap to reserve for the micro:bit heap. -#ifndef MICROBIT_NESTED_HEAP_SIZE -#define MICROBIT_NESTED_HEAP_SIZE 0.75 -#endif - // If defined, reuse any unused SRAM normally reserved for SoftDevice (Nordic's memory resident BLE stack) as heap memory. // The amount of memory reused depends upon whether or not BLE is enabled using MICROBIT_BLE_ENABLED. // Set '1' to enable. @@ -437,14 +425,14 @@ extern uint32_t __etext; // n.b. This also disables the user serial port 'uBit.serial'. // Set '1' to enable. #ifndef MICROBIT_DBG -#define MICROBIT_DBG 0 +#define MICROBIT_DBG 1 #endif // Enable this to receive diagnostic messages from the heap allocator via the USB serial interface. // n.b. This requires MICROBIT_DBG to be defined. // Set '1' to enable. #ifndef MICROBIT_HEAP_DBG -#define MICROBIT_HEAP_DBG 0 +#define MICROBIT_HEAP_DBG 1 #endif // Versioning options. diff --git a/inc/core/MicroBitHeapAllocator.h b/inc/core/MicroBitHeapAllocator.h index 0f0dfb5..63c9cc9 100644 --- a/inc/core/MicroBitHeapAllocator.h +++ b/inc/core/MicroBitHeapAllocator.h @@ -51,15 +51,20 @@ DEALINGS IN THE SOFTWARE. #ifndef MICROBIT_HEAP_ALLOCTOR_H #define MICROBIT_HEAP_ALLOCTOR_H -#include "mbed.h" #include "MicroBitConfig.h" -#include // The maximum number of heap segments that can be created. #define MICROBIT_MAXIMUM_HEAPS 2 -// Flag to indicate that a given block is FREE/USED +// Flag to indicate that a given block is FREE/USED (top bit of a CPU word) #define MICROBIT_HEAP_BLOCK_FREE 0x80000000 +#define MICROBIT_HEAP_BLOCK_SIZE 4 + +struct HeapDefinition +{ + uint32_t *heap_start; // Physical address of the start of this heap. + uint32_t *heap_end; // Physical address of the end of this heap. +}; /** * Create and initialise a given memory region as for heap storage. @@ -79,89 +84,4 @@ DEALINGS IN THE SOFTWARE. */ int microbit_create_heap(uint32_t start, uint32_t end); -/** - * Create and initialise a heap region within the current the heap region specified - * by the linker script. - * - * If the requested amount is not available, then the amount requested will be reduced - * automatically to fit the space available. - * - * @param ratio The proportion of the underlying heap to allocate. - * - * @return MICROBIT_OK on success, or MICROBIT_NO_RESOURCES if the heap could not be allocated. - */ -int microbit_create_nested_heap(float ratio); - -/** - * Attempt to allocate a given amount of memory from any of our configured heap areas. - * - * @param size The amount of memory, in bytes, to allocate. - * - * @return A pointer to the allocated memory, or NULL if insufficient memory is available. - */ -void *microbit_malloc(size_t size); - - -/** - * Release a given area of memory from the heap. - * - * @param mem The memory area to release. - */ -void microbit_free(void *mem); - -/* - * Wrapper function to ensure we have an explicit handle on the heap allocator provided - * by our underlying platform. - * - * @param size The amount of memory, in bytes, to allocate. - * - * @return A pointer to the memory allocated. NULL if no memory is available. - */ -inline void *native_malloc(size_t size) -{ - return malloc(size); -} - -/* - * Wrapper function to ensure we have an explicit handle on the heap allocator provided - * by our underlying platform. - * - * @param p Pointer to the memory to be freed. - */ -inline void native_free(void *p) -{ - free(p); -} - -/** - * Overrides the 'new' operator globally, and redirects calls to the micro:bit heap allocator. - */ -inline void* operator new(size_t size) -{ - return microbit_malloc(size); -} - -/** - * Overrides the 'new' operator globally, and redirects calls to the micro:bit theap allocator. - */ -inline void* operator new[](size_t size) -{ - return microbit_malloc(size); -} - -/** - * Overrides the 'delete' operator globally, and redirects calls to the micro:bit theap allocator. - */ -inline void operator delete(void *ptr) -{ - microbit_free(ptr); -} - - -// Macros to override overrides the 'malloc' and 'delete' functions globally, and redirects calls -// to the micro:bit theap allocator. - -#define malloc(X) microbit_malloc( X ) -#define free(X) microbit_free( X ) - #endif diff --git a/source/core/MicroBitHeapAllocator.cpp b/source/core/MicroBitHeapAllocator.cpp index 10c7f69..57512fd 100644 --- a/source/core/MicroBitHeapAllocator.cpp +++ b/source/core/MicroBitHeapAllocator.cpp @@ -51,17 +51,13 @@ DEALINGS IN THE SOFTWARE. #include "MicroBitConfig.h" #include "MicroBitHeapAllocator.h" #include "MicroBitDevice.h" +#include "MicroBitCompat.h" #include "ErrorNo.h" -struct HeapDefinition -{ - uint32_t *heap_start; // Physical address of the start of this heap. - uint32_t *heap_end; // Physical address of the end of this heap. -}; - // A list of all active heap regions, and their dimensions in memory. HeapDefinition heap[MICROBIT_MAXIMUM_HEAPS] = { }; uint8_t heap_count = 0; +extern "C" int __end__; #if CONFIG_ENABLED(MICROBIT_DBG) && CONFIG_ENABLED(MICROBIT_HEAP_DBG) // Diplays a usage summary about a given heap... @@ -90,7 +86,7 @@ void microbit_heap_print(HeapDefinition &heap) while (block < heap.heap_end) { blockSize = *block & ~MICROBIT_HEAP_BLOCK_FREE; - if(SERIAL_DEBUG) SERIAL_DEBUG->printf("[%c:%d] ", *block & MICROBIT_HEAP_BLOCK_FREE ? 'F' : 'U', blockSize*4); + if(SERIAL_DEBUG) SERIAL_DEBUG->printf("[%c:%d] ", *block & MICROBIT_HEAP_BLOCK_FREE ? 'F' : 'U', blockSize*MICROBIT_HEAP_BLOCK_SIZE); if (cols++ == 20) { if(SERIAL_DEBUG) SERIAL_DEBUG->printf("\n"); @@ -110,8 +106,8 @@ void microbit_heap_print(HeapDefinition &heap) if(SERIAL_DEBUG) SERIAL_DEBUG->printf("\n"); - if(SERIAL_DEBUG) SERIAL_DEBUG->printf("mb_total_free : %d\n", totalFreeBlock*4); - if(SERIAL_DEBUG) SERIAL_DEBUG->printf("mb_total_used : %d\n", totalUsedBlock*4); + if(SERIAL_DEBUG) SERIAL_DEBUG->printf("mb_total_free : %d\n", totalFreeBlock*MICROBIT_HEAP_BLOCK_SIZE); + if(SERIAL_DEBUG) SERIAL_DEBUG->printf("mb_total_used : %d\n", totalUsedBlock*MICROBIT_HEAP_BLOCK_SIZE); } @@ -126,13 +122,6 @@ void microbit_heap_print() } #endif -void microbit_initialise_heap(HeapDefinition &heap) -{ - // Simply mark the entire heap as free. - *heap.heap_start = ((uint32_t) heap.heap_end - (uint32_t) heap.heap_start) / MICROBIT_HEAP_BLOCK_SIZE; - *heap.heap_start |= MICROBIT_HEAP_BLOCK_FREE; -} - /** * Create and initialise a given memory region as for heap storage. * After this is called, any future calls to malloc, new, free or delete may use the new heap. @@ -151,23 +140,25 @@ void microbit_initialise_heap(HeapDefinition &heap) */ int microbit_create_heap(uint32_t start, uint32_t end) { + HeapDefinition *h = &heap[heap_count]; + // Ensure we don't exceed the maximum number of heap segments. if (heap_count == MICROBIT_MAXIMUM_HEAPS) return MICROBIT_NO_RESOURCES; // Sanity check. Ensure range is valid, large enough and word aligned. - if (end <= start || end - start < MICROBIT_HEAP_BLOCK_SIZE*2 || end % 4 != 0 || start % 4 != 0) + if (end <= start || end - start < MICROBIT_HEAP_BLOCK_SIZE*2 || end % MICROBIT_HEAP_BLOCK_SIZE != 0 || start % MICROBIT_HEAP_BLOCK_SIZE != 0) return MICROBIT_INVALID_PARAMETER; // Disable IRQ temporarily to ensure no race conditions! __disable_irq(); // Record the dimensions of this new heap - heap[heap_count].heap_start = (uint32_t *)start; - heap[heap_count].heap_end = (uint32_t *)end; + h->heap_start = (uint32_t *)start; + h->heap_end = (uint32_t *)end; // Initialise the heap as being completely empty and available for use. - microbit_initialise_heap(heap[heap_count]); + *h->heap_start = MICROBIT_HEAP_BLOCK_FREE | (((uint32_t) h->heap_end - (uint32_t) h->heap_start) / MICROBIT_HEAP_BLOCK_SIZE); heap_count++; // Enable Interrupts @@ -180,55 +171,6 @@ int microbit_create_heap(uint32_t start, uint32_t end) return MICROBIT_OK; } -/** - * Create and initialise a heap region within the current the heap region specified - * by the linker script. - * - * If the requested amount is not available, then the amount requested will be reduced - * automatically to fit the space available. - * - * @param ratio The proportion of the underlying heap to allocate. - * - * @return MICROBIT_OK on success, or MICROBIT_NO_RESOURCES if the heap could not be allocated. - */ -int microbit_create_nested_heap(float ratio) -{ - uint32_t length; - void *p; - - if (ratio <= 0.0 || ratio > 1.0) - return MICROBIT_INVALID_PARAMETER; - - // Snapshot something at the top of the main heap. - p = native_malloc(sizeof(uint32_t)); - - // Estimate the size left in our heap, taking care to ensure it lands on a word boundary. - length = (uint32_t) (((float)(MICROBIT_HEAP_END - (uint32_t)p)) * ratio); - length &= 0xFFFFFFFC; - - // Release our reference pointer. - native_free(p); - p = NULL; - - // Allocate memory for our heap. - // We iteratively reduce the size of memory are allocate until it fits within available space. - while (p == NULL) - { - p = native_malloc(length); - if (p == NULL) - { - length -= 32; - if (length <= 0) - return MICROBIT_NO_RESOURCES; - } - } - - uint32_t start = (uint32_t) p; - microbit_create_heap(start, start + length); - - return MICROBIT_OK; -} - /** * Attempt to allocate a given amount of memory from a given heap area. * @@ -327,42 +269,40 @@ void *microbit_malloc(size_t size, HeapDefinition &heap) * * @return A pointer to the allocated memory, or NULL if insufficient memory is available. */ -void *microbit_malloc(size_t size) +void *malloc(size_t size) { + static uint8_t initialised = 0; void *p; + if (!initialised) + { + heap_count = 0; + + if(microbit_create_heap((uint32_t)(&__end__), (uint32_t)(MICROBIT_HEAP_END)) == MICROBIT_INVALID_PARAMETER) + microbit_panic(MICROBIT_HEAP_ERROR); + + initialised = 1; + } + // Assign the memory from the first heap created that has space. for (int i=0; i < heap_count; i++) { p = microbit_malloc(size, heap[i]); if (p != NULL) - { -#if CONFIG_ENABLED(MICROBIT_DBG) && CONFIG_ENABLED(MICROBIT_HEAP_DBG) - if(SERIAL_DEBUG) SERIAL_DEBUG->printf("microbit_malloc: ALLOCATED: %d [%p]\n", size, p); -#endif - return p; - } + break; } - // If we reach here, then either we have no memory available, or our heap spaces - // haven't been initialised. Either way, we try the native allocator. - - p = native_malloc(size); if (p != NULL) { #if CONFIG_ENABLED(MICROBIT_DBG) && CONFIG_ENABLED(MICROBIT_HEAP_DBG) - // Keep everything trasparent if we've not been initialised yet - if (heap_count > 0) - if(SERIAL_DEBUG) SERIAL_DEBUG->printf("microbit_malloc: NATIVE ALLOCATED: %d [%p]\n", size, p); + if(SERIAL_DEBUG) SERIAL_DEBUG->printf("malloc: ALLOCATED: %d [%p]\n", size, p); #endif return p; } // We're totally out of options (and memory!). #if CONFIG_ENABLED(MICROBIT_DBG) && CONFIG_ENABLED(MICROBIT_HEAP_DBG) - // Keep everything transparent if we've not been initialised yet - if (heap_count > 0) - if(SERIAL_DEBUG) SERIAL_DEBUG->printf("microbit_malloc: OUT OF MEMORY [%d]\n", size); + if(SERIAL_DEBUG) SERIAL_DEBUG->printf("malloc: OUT OF MEMORY [%d]\n", size); #endif #if CONFIG_ENABLED(MICROBIT_PANIC_HEAP_FULL) @@ -377,14 +317,14 @@ void *microbit_malloc(size_t size) * * @param mem The memory area to release. */ -void microbit_free(void *mem) +void free(void *mem) { uint32_t *memory = (uint32_t *)mem; uint32_t *cb = memory-1; #if CONFIG_ENABLED(MICROBIT_DBG) && CONFIG_ENABLED(MICROBIT_HEAP_DBG) if (heap_count > 0) - if(SERIAL_DEBUG) SERIAL_DEBUG->printf("microbit_free: %p\n", mem); + if(SERIAL_DEBUG) SERIAL_DEBUG->printf("free: %p\n", mem); #endif // Sanity check. if (memory == NULL) @@ -397,12 +337,61 @@ void microbit_free(void *mem) { // The memory block given is part of this heap, so we can simply // flag that this memory area is now free, and we're done. + if (*cb == 0 || *cb & MICROBIT_HEAP_BLOCK_FREE) + microbit_panic(MICROBIT_HEAP_ERROR); + *cb |= MICROBIT_HEAP_BLOCK_FREE; return; } } // If we reach here, then the memory is not part of any registered heap. - // Forward it to the native heap allocator, and let nature take its course... - native_free(mem); + microbit_panic(MICROBIT_HEAP_ERROR); +} + +void* calloc (size_t num, size_t size) +{ + void *mem = malloc(num*size); + + if (mem) + memclr(mem, num*size); + + return mem; +} + +void* realloc (void* ptr, size_t size) +{ + void *mem = malloc(size); + + // handle the simplest case - no previous memory allocted. + if (ptr != NULL && mem != NULL) + { + + // Otherwise we need to copy and free up the old data. + uint32_t *cb = ((uint32_t *)ptr) - 1; + uint32_t blockSize = *cb & ~MICROBIT_HEAP_BLOCK_FREE; + + memcpy(mem, ptr, min(blockSize * sizeof(uint32_t), size)); + free(ptr); + } + + return mem; +} + +// make sure the libc allocator is not pulled in +void *_malloc_r(struct _reent *, size_t len) +{ + return malloc(len); +} + +void _free_r(struct _reent *, void *addr) +{ + free(addr); +} + +void * +_realloc_r (struct _reent *ptr, void *old, size_t newlen) +{ + (void) ptr; + return realloc (old, newlen); } From aba1a2c2ab8f66d5ae6e0a3730cad43b84090d22 Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Thu, 6 Sep 2018 20:54:58 +0100 Subject: [PATCH 2/5] Add diagnostic information --- source/bluetooth/MicroBitBLEManager.cpp | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/source/bluetooth/MicroBitBLEManager.cpp b/source/bluetooth/MicroBitBLEManager.cpp index 8b3a2ba..affb7f5 100644 --- a/source/bluetooth/MicroBitBLEManager.cpp +++ b/source/bluetooth/MicroBitBLEManager.cpp @@ -310,15 +310,26 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb btle_set_gatt_table_size(MICROBIT_SD_GATT_TABLE_SIZE); #endif + SERIAL_DEBUG->printf("******\r\n"); + SERIAL_DEBUG->printf(" sizeof(BLEDevice): %d\r\n", sizeof(BLEDevice)); ble = new BLEDevice(); + SERIAL_DEBUG->printf("******\r\n"); ble->init(); + SERIAL_DEBUG->printf("******\r\n"); + SERIAL_DEBUG->printf("******\r\n"); // automatically restart advertising after a device disconnects. + SERIAL_DEBUG->printf("******\r\n"); ble->gap().onDisconnection(bleDisconnectionCallback); + SERIAL_DEBUG->printf("******\r\n"); + SERIAL_DEBUG->printf("******\r\n"); ble->gattServer().onSysAttrMissing(bleSysAttrMissingCallback); + SERIAL_DEBUG->printf("******\r\n"); // generate an event when a Bluetooth connection is established + SERIAL_DEBUG->printf("******\r\n"); ble->gap().onConnection(bleConnectionCallback); + SERIAL_DEBUG->printf("******\r\n"); // Configure the stack to hold onto the CPU during critical timing events. // mbed-classic performs __disable_irq() calls in its timers that can cause @@ -338,6 +349,7 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb // @bluetooth_mdw: select either passkey pairing (more secure), "just works" pairing (less secure but nice and simple for the user) // or no security // Default to passkey pairing with MITM protection + SERIAL_DEBUG->printf("******\r\n"); #if (SECURITY_MODE_IS(SECURITY_MODE_ENCRYPTION_NO_MITM)) // Just Works ble->securityManager().init(enableBonding, false, SecurityManager::IO_CAPS_NONE); @@ -348,7 +360,9 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb // passkey ble->securityManager().init(enableBonding, true, SecurityManager::IO_CAPS_DISPLAY_ONLY); #endif + SERIAL_DEBUG->printf("******\r\n"); + SERIAL_DEBUG->printf("******\r\n"); if (enableBonding) { // If we're in pairing mode, review the size of the bond table. @@ -361,7 +375,9 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb if (bonds >= MICROBIT_BLE_MAXIMUM_BONDS) ble->securityManager().purgeAllBondingState(); } + SERIAL_DEBUG->printf("******\r\n"); + SERIAL_DEBUG->printf("******\r\n"); #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) // Configure a whitelist to filter all connection requetss from unbonded devices. // Most BLE stacks only permit one connection at a time, so this prevents denial of service attacks. @@ -376,27 +392,34 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb ble->gap().setScanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST); ble->gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_FILTER_CONN_REQS); #endif + SERIAL_DEBUG->printf("******\r\n"); // Configure the radio at our default power level setTransmitPower(MICROBIT_BLE_DEFAULT_TX_POWER); // Bring up core BLE services. + SERIAL_DEBUG->printf("******\r\n"); #if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE) new MicroBitDFUService(*ble); new MicroBitPartialFlashingService(*ble, messageBus); #endif + SERIAL_DEBUG->printf("******\r\n"); + SERIAL_DEBUG->printf("******\r\n"); #if CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE) DeviceInformationService ble_device_information_service(*ble, MICROBIT_BLE_MANUFACTURER, MICROBIT_BLE_MODEL, serialNumber.toCharArray(), MICROBIT_BLE_HARDWARE_VERSION, MICROBIT_BLE_FIRMWARE_VERSION, MICROBIT_BLE_SOFTWARE_VERSION); #else (void)serialNumber; #endif + SERIAL_DEBUG->printf("******\r\n"); + SERIAL_DEBUG->printf("******\r\n"); #if CONFIG_ENABLED(MICROBIT_BLE_EVENT_SERVICE) new MicroBitEventService(*ble, messageBus); #else (void)messageBus; #endif + SERIAL_DEBUG->printf("******\r\n"); // Configure for high speed mode where possible. Gap::ConnectionParams_t fast; @@ -423,10 +446,13 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb // If we have whitelisting enabled, then prevent only enable advertising of we have any binded devices... // This is to further protect kids' privacy. If no-one initiates BLE, then the device is unreachable. // If whiltelisting is disabled, then we always advertise. + SERIAL_DEBUG->printf("******\r\n"); #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) if (whitelist.size > 0) #endif ble->startAdvertising(); + + SERIAL_DEBUG->printf("******\r\n"); } /** From 6c9b3e7d1c2cc01edcf28cc03a511e85f15081fe Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Fri, 7 Sep 2018 14:48:41 +0100 Subject: [PATCH 3/5] Remove diagnostic information --- source/bluetooth/MicroBitBLEManager.cpp | 26 ------------------------- 1 file changed, 26 deletions(-) diff --git a/source/bluetooth/MicroBitBLEManager.cpp b/source/bluetooth/MicroBitBLEManager.cpp index affb7f5..8b3a2ba 100644 --- a/source/bluetooth/MicroBitBLEManager.cpp +++ b/source/bluetooth/MicroBitBLEManager.cpp @@ -310,26 +310,15 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb btle_set_gatt_table_size(MICROBIT_SD_GATT_TABLE_SIZE); #endif - SERIAL_DEBUG->printf("******\r\n"); - SERIAL_DEBUG->printf(" sizeof(BLEDevice): %d\r\n", sizeof(BLEDevice)); ble = new BLEDevice(); - SERIAL_DEBUG->printf("******\r\n"); ble->init(); - SERIAL_DEBUG->printf("******\r\n"); - SERIAL_DEBUG->printf("******\r\n"); // automatically restart advertising after a device disconnects. - SERIAL_DEBUG->printf("******\r\n"); ble->gap().onDisconnection(bleDisconnectionCallback); - SERIAL_DEBUG->printf("******\r\n"); - SERIAL_DEBUG->printf("******\r\n"); ble->gattServer().onSysAttrMissing(bleSysAttrMissingCallback); - SERIAL_DEBUG->printf("******\r\n"); // generate an event when a Bluetooth connection is established - SERIAL_DEBUG->printf("******\r\n"); ble->gap().onConnection(bleConnectionCallback); - SERIAL_DEBUG->printf("******\r\n"); // Configure the stack to hold onto the CPU during critical timing events. // mbed-classic performs __disable_irq() calls in its timers that can cause @@ -349,7 +338,6 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb // @bluetooth_mdw: select either passkey pairing (more secure), "just works" pairing (less secure but nice and simple for the user) // or no security // Default to passkey pairing with MITM protection - SERIAL_DEBUG->printf("******\r\n"); #if (SECURITY_MODE_IS(SECURITY_MODE_ENCRYPTION_NO_MITM)) // Just Works ble->securityManager().init(enableBonding, false, SecurityManager::IO_CAPS_NONE); @@ -360,9 +348,7 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb // passkey ble->securityManager().init(enableBonding, true, SecurityManager::IO_CAPS_DISPLAY_ONLY); #endif - SERIAL_DEBUG->printf("******\r\n"); - SERIAL_DEBUG->printf("******\r\n"); if (enableBonding) { // If we're in pairing mode, review the size of the bond table. @@ -375,9 +361,7 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb if (bonds >= MICROBIT_BLE_MAXIMUM_BONDS) ble->securityManager().purgeAllBondingState(); } - SERIAL_DEBUG->printf("******\r\n"); - SERIAL_DEBUG->printf("******\r\n"); #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) // Configure a whitelist to filter all connection requetss from unbonded devices. // Most BLE stacks only permit one connection at a time, so this prevents denial of service attacks. @@ -392,34 +376,27 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb ble->gap().setScanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST); ble->gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_FILTER_CONN_REQS); #endif - SERIAL_DEBUG->printf("******\r\n"); // Configure the radio at our default power level setTransmitPower(MICROBIT_BLE_DEFAULT_TX_POWER); // Bring up core BLE services. - SERIAL_DEBUG->printf("******\r\n"); #if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE) new MicroBitDFUService(*ble); new MicroBitPartialFlashingService(*ble, messageBus); #endif - SERIAL_DEBUG->printf("******\r\n"); - SERIAL_DEBUG->printf("******\r\n"); #if CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE) DeviceInformationService ble_device_information_service(*ble, MICROBIT_BLE_MANUFACTURER, MICROBIT_BLE_MODEL, serialNumber.toCharArray(), MICROBIT_BLE_HARDWARE_VERSION, MICROBIT_BLE_FIRMWARE_VERSION, MICROBIT_BLE_SOFTWARE_VERSION); #else (void)serialNumber; #endif - SERIAL_DEBUG->printf("******\r\n"); - SERIAL_DEBUG->printf("******\r\n"); #if CONFIG_ENABLED(MICROBIT_BLE_EVENT_SERVICE) new MicroBitEventService(*ble, messageBus); #else (void)messageBus; #endif - SERIAL_DEBUG->printf("******\r\n"); // Configure for high speed mode where possible. Gap::ConnectionParams_t fast; @@ -446,13 +423,10 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb // If we have whitelisting enabled, then prevent only enable advertising of we have any binded devices... // This is to further protect kids' privacy. If no-one initiates BLE, then the device is unreachable. // If whiltelisting is disabled, then we always advertise. - SERIAL_DEBUG->printf("******\r\n"); #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) if (whitelist.size > 0) #endif ble->startAdvertising(); - - SERIAL_DEBUG->printf("******\r\n"); } /** From 4dda6ef29834a9cd27eba2507f5ca587fbb6b9b4 Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Fri, 7 Sep 2018 14:51:26 +0100 Subject: [PATCH 4/5] Disable DEBUG information --- inc/core/MicroBitConfig.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/core/MicroBitConfig.h b/inc/core/MicroBitConfig.h index ccb8ed6..fe086ee 100644 --- a/inc/core/MicroBitConfig.h +++ b/inc/core/MicroBitConfig.h @@ -425,14 +425,14 @@ extern uint32_t __etext; // n.b. This also disables the user serial port 'uBit.serial'. // Set '1' to enable. #ifndef MICROBIT_DBG -#define MICROBIT_DBG 1 +#define MICROBIT_DBG 0 #endif // Enable this to receive diagnostic messages from the heap allocator via the USB serial interface. // n.b. This requires MICROBIT_DBG to be defined. // Set '1' to enable. #ifndef MICROBIT_HEAP_DBG -#define MICROBIT_HEAP_DBG 1 +#define MICROBIT_HEAP_DBG 0 #endif // Versioning options. From 1a4d5abd7b3d1ad50a5dfd2eb20df4be0d40b1dd Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Fri, 7 Sep 2018 17:41:49 +0100 Subject: [PATCH 5/5] Introduce CONFIG option to enable/disable microbit heap allocator - Add CONFIG option to MicroBitConfig.h - Add YOTTA glue for config.json mapping - Introduce conditional compilation into MicroBitHeapAllocator.cpp --- inc/core/MicroBitConfig.h | 9 +++++++++ inc/platform/yotta_cfg_mappings.h | 4 ++++ source/core/MicroBitHeapAllocator.cpp | 14 ++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/inc/core/MicroBitConfig.h b/inc/core/MicroBitConfig.h index fe086ee..37742db 100644 --- a/inc/core/MicroBitConfig.h +++ b/inc/core/MicroBitConfig.h @@ -109,6 +109,15 @@ extern uint32_t __etext; #define FLASH_PROGRAM_END (uint32_t) (&__etext) #endif +// +// If set to '1', this option enables the microbit heap allocator. This supports multiple heaps and interrupt safe operation. +// If set to '0', the standard GCC libc heap allocator is used, which restricts available memory in BLE scenarios, and MessageBus operations +// in ISR contexts will no longer be safe. +// +#ifndef MICROBIT_HEAP_ENABLED +#define MICROBIT_HEAP_ENABLED 1 +#endif + // Block size used by the allocator in bytes. // n.b. Currently only 32 bits (4 bytes) is supported. diff --git a/inc/platform/yotta_cfg_mappings.h b/inc/platform/yotta_cfg_mappings.h index f017796..b2c2e15 100644 --- a/inc/platform/yotta_cfg_mappings.h +++ b/inc/platform/yotta_cfg_mappings.h @@ -71,6 +71,10 @@ #define MICROBIT_DEFAULT_PULLMODE YOTTA_CFG_MICROBIT_DAL_DEFAULT_PULLMODE #endif +#ifdef YOTTA_CFG_MICROBIT_DAL_HEAP_ENABLED + #define MICROBIT_HEAP_ENABLED YOTTA_CFG_MICROBIT_DAL_HEAP_ENABLED +#endif + #ifdef YOTTA_CFG_MICROBIT_DAL_PANIC_ON_HEAP_FULL #define MICROBIT_PANIC_HEAP_FULL YOTTA_CFG_MICROBIT_DAL_PANIC_ON_HEAP_FULL #endif diff --git a/source/core/MicroBitHeapAllocator.cpp b/source/core/MicroBitHeapAllocator.cpp index 57512fd..c42b3da 100644 --- a/source/core/MicroBitHeapAllocator.cpp +++ b/source/core/MicroBitHeapAllocator.cpp @@ -54,6 +54,8 @@ DEALINGS IN THE SOFTWARE. #include "MicroBitCompat.h" #include "ErrorNo.h" +#if CONFIG_ENABLED(MICROBIT_HEAP_ENABLED) + // A list of all active heap regions, and their dimensions in memory. HeapDefinition heap[MICROBIT_MAXIMUM_HEAPS] = { }; uint8_t heap_count = 0; @@ -395,3 +397,15 @@ _realloc_r (struct _reent *ptr, void *old, size_t newlen) (void) ptr; return realloc (old, newlen); } + +#else + +int microbit_create_heap(uint32_t start, uint32_t end) +{ + (void) start; + (void) end; + + return MICROBIT_OK; +} + +#endif