Added Partial Flashing Service (#9)
* Memory Map + Partial Flash Service * Moved Partial Flash Service to Management Mode * PF Service appears in YT Build not PXT * PF in PXT * Swapped DFU and PF Services * Fixing Flash Writew * write flash via bluetooth * Partial Flash - Fixed Address * Update module.json * Adjust flash pointer * Adjust flash start * Adjust Flash Pointer * Added offset to xfer * Writing to FLASH_END * Writing to FLASH_END * Modified PFS read callback * Reenable BLE Security * removed pf * Check diff * Check diff * Replaced ContextSwitch * PF * Test. Writing Hex File to 0x30000 * Writing to PXT empty space * Reversed byte order * Flash 16 bytes at once * Copy data from static var to local var * blocks -> bytes * Fixed offset * Fixed Offset * Flash to 0x30000 + offset * Bypass scratch page * Changed byte order * Write Without Response * Without Fast BLE * Added fast BLE * Updated Connection Parameters * Iterate through BLE data bytes * Get Hashes From PXT Build * Copy Hash from Flash * Testing FLASH_END * Read Hash From Flash * Read Hash from Flash * Reading correct hash from mem * Endianess * Modified MAGIC * Fix Start Address * Sequence # * Write 0xdeadbeef to 0x36000 on PF Seq # error * Group 4 packet blocks for writing * Added error case * Increased flash write size * Blocks * Fire event to write * Decreased flash time * Reformat * Reduced hash size in MemoryMap * Partial Flashing w/ Notifications * One Characteristic - WRITE/WRITE_WOUT_RESP/NOTIFY * Modified WRITE Notification * Tidied - Moved end of transfer logic * Removed VI Swap files * Added Pairing Mode Event ID * Modified Retransmit behaviour * updateFlash caused stack overflow * Removed flash write from memory map * Instantiate Memory Map where used * Word aligned. Added Status and Reset commands * Fixed: storage. becomes storage-> * Fixed warnings: switch case fall through * Fix Hash * Rebuild Map everytime * Hash Error * Edited animation. Hash testing * persistent memory map issues * Moved EOT * Modified BLE animation. Removed globals from PFS * Updated MM * Added incomplete flash flag * Re added CCS.s
This commit is contained in:
parent
2cff906f01
commit
3413d5487d
|
@ -57,6 +57,7 @@ DEALINGS IN THE SOFTWARE.
|
|||
#include "MicroBitButtonService.h"
|
||||
#include "MicroBitIOPinService.h"
|
||||
#include "MicroBitTemperatureService.h"
|
||||
#include "MicroBitPartialFlashingService.h"
|
||||
#include "ExternalEvents.h"
|
||||
#include "MicroBitButton.h"
|
||||
#include "MicroBitStorage.h"
|
||||
|
@ -78,6 +79,9 @@ DEALINGS IN THE SOFTWARE.
|
|||
#define MICROBIT_BLE_STATUS_STORE_SYSATTR 0x02
|
||||
#define MICROBIT_BLE_STATUS_DISCONNECT 0x04
|
||||
|
||||
#define MICROBIT_BLE_MODE_PAIRING 0x00
|
||||
#define MICROBIT_BLE_MODE_APPLICATION 0x01
|
||||
|
||||
extern const int8_t MICROBIT_BLE_POWER_LEVEL[];
|
||||
|
||||
struct BLESysAttribute
|
||||
|
@ -146,7 +150,7 @@ class MicroBitBLEManager : MicroBitComponent
|
|||
* @param enableBonding If true, the security manager enabled bonding.
|
||||
*
|
||||
* @code
|
||||
* bleManager.init(uBit.getName(), uBit.getSerial(), uBit.messageBus, true);
|
||||
* bleManager.init(uBit.getName(), uBit.getSerial(), uBit.messageBus);
|
||||
* @endcode
|
||||
*/
|
||||
void init(ManagedString deviceName, ManagedString serialNumber, EventModel &messageBus, bool enableBonding);
|
||||
|
@ -281,6 +285,19 @@ class MicroBitBLEManager : MicroBitComponent
|
|||
int advertiseEddystoneUid(const char* uid_namespace, const char* uid_instance, int8_t calibratedPower = MICROBIT_BLE_EDDYSTONE_DEFAULT_POWER, bool connectable = true, uint16_t interval = MICROBIT_BLE_EDDYSTONE_ADV_INTERVAL);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Restarts in BLE Mode
|
||||
*
|
||||
*/
|
||||
void restartInBLEMode();
|
||||
|
||||
/**
|
||||
* Get current BLE mode; application, pairing
|
||||
* #define MICROBIT_BLE_MODE_PAIRING 0x00
|
||||
* #define MICROBIT_BLE_MODE_APPLICATION 0x01
|
||||
*/
|
||||
uint8_t getBLEMode();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Displays the device's ID code as a histogram on the provided MicroBitDisplay instance.
|
||||
|
@ -289,12 +306,21 @@ class MicroBitBLEManager : MicroBitComponent
|
|||
*/
|
||||
void showNameHistogram(MicroBitDisplay &display);
|
||||
|
||||
|
||||
/**
|
||||
* Displays pairing mode animation
|
||||
*
|
||||
* @param display The display instance used for displaying the histogram.
|
||||
*/
|
||||
void showManagementModeAnimation(MicroBitDisplay &display);
|
||||
|
||||
#define MICROBIT_BLE_DISCONNECT_AFTER_PAIRING_DELAY 500
|
||||
unsigned long pairing_completed_at_time;
|
||||
|
||||
int pairingStatus;
|
||||
ManagedString passKey;
|
||||
ManagedString deviceName;
|
||||
uint8_t bleMode = MICROBIT_BLE_MODE_APPLICATION;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 British Broadcasting Corporation.
|
||||
This software is provided by Lancaster University by arrangement with the BBC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROBIT_PARTIAL_FLASH_SERVICE_H
|
||||
#define MICROBIT_PARTIAL_FLASH_SERVICE_H
|
||||
|
||||
#include "MicroBitConfig.h"
|
||||
#include "MicroBitBLEManager.h"
|
||||
#include "ble/BLE.h"
|
||||
#include "MicroBitMemoryMap.h"
|
||||
|
||||
#include "MicroBitFlash.h"
|
||||
#include "MicroBitStorage.h"
|
||||
|
||||
#include "MicroBitComponent.h"
|
||||
#include "MicroBitEvent.h"
|
||||
#include "MicroBitListener.h"
|
||||
#include "EventModel.h"
|
||||
|
||||
#define PARTIAL_FLASHING_VERSION 0x01
|
||||
|
||||
// UUIDs for our service and characteristics
|
||||
extern const uint8_t MicroBitPartialFlashingServiceUUID[];
|
||||
extern const uint8_t MicroBitPartialFlashingServiceCharacteristicUUID[];
|
||||
|
||||
/**
|
||||
* Class definition for the custom MicroBit Partial Flash Service.
|
||||
* Provides a BLE service to remotely read the memory map and flash the PXT program.
|
||||
*/
|
||||
class MicroBitPartialFlashingService
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a representation of the Partial Flash Service
|
||||
* @param _ble The instance of a BLE device that we're running on.
|
||||
* @param _memoryMap An instance of MicroBiteMemoryMap to interface with.
|
||||
*/
|
||||
MicroBitPartialFlashingService(BLEDevice &_ble, EventModel &_messageBus);
|
||||
|
||||
/**
|
||||
* Callback. Invoked when any of our attributes are written via BLE.
|
||||
*/
|
||||
void onDataWritten(const GattWriteCallbackParams *params);
|
||||
|
||||
/**
|
||||
* Callback. Invoked when any of our attributes are read via BLE.
|
||||
*/
|
||||
void onDataRead(GattReadAuthCallbackParams *params);
|
||||
|
||||
private:
|
||||
// M:B Bluetooth stack and MessageBus
|
||||
BLEDevice &ble;
|
||||
EventModel &messageBus;
|
||||
|
||||
/**
|
||||
* Writing to flash inside MicroBitEvent rather than in the ISR
|
||||
*/
|
||||
void partialFlashingEvent(MicroBitEvent e);
|
||||
|
||||
// The base address to write to. Bit masked: (0xFFFF0000 & region.endAddress) >> 16
|
||||
uint8_t baseAddress = 0x3;
|
||||
|
||||
// Handles to access each characteristic when they are held by Soft Device.
|
||||
GattAttribute::Handle_t partialFlashCharacteristicHandle;
|
||||
|
||||
/**
|
||||
* Process a Partial Flashing data packet
|
||||
*/
|
||||
void flashData(uint8_t *data);
|
||||
|
||||
// Ensure packets are in order
|
||||
uint8_t packetCount = 0;
|
||||
uint8_t blockPacketCount = 0;
|
||||
|
||||
// Keep track of blocks of data
|
||||
uint32_t block[16];
|
||||
uint8_t blockNum = 0;
|
||||
uint16_t offset = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -68,6 +68,9 @@ DEALINGS IN THE SOFTWARE.
|
|||
#define MICROBIT_ID_MULTIBUTTON_ATTACH 31
|
||||
#define MICROBIT_ID_SERIAL 32
|
||||
|
||||
#define MICROBIT_ID_PFLASH_NOTIFICATION 33
|
||||
#define MICROBIT_ID_PAIRING_MODE 34
|
||||
|
||||
#define MICROBIT_ID_MESSAGE_BUS_LISTENER 1021 // Message bus indication that a handler for a given ID has been registered.
|
||||
#define MICROBIT_ID_NOTIFY_ONE 1022 // Notfication channel, for general purpose synchronisation
|
||||
#define MICROBIT_ID_NOTIFY 1023 // Notfication channel, for general purpose synchronisation
|
||||
|
|
|
@ -86,8 +86,14 @@ DEALINGS IN THE SOFTWARE.
|
|||
#define BLE_BOND_DATA_PAGE (PAGE_SIZE * (NRF_FICR->CODESIZE - 18))
|
||||
#endif
|
||||
|
||||
#ifndef MEMORY_MAP_PAGE
|
||||
#define MEMORY_MAP_PAGE (PAGE_SIZE * (NRF_FICR->CODESIZE - 19))
|
||||
#endif
|
||||
|
||||
// Scratch moved from page 19 to page 20
|
||||
// MicroBitFileSystem uses DEFAULT_SCRATCH_PAGE to mark end of FileSystem
|
||||
#ifndef DEFAULT_SCRATCH_PAGE
|
||||
#define DEFAULT_SCRATCH_PAGE (PAGE_SIZE * (NRF_FICR->CODESIZE - 19))
|
||||
#define DEFAULT_SCRATCH_PAGE (PAGE_SIZE * (NRF_FICR->CODESIZE - 20))
|
||||
#endif
|
||||
|
||||
// Address of the end of the current program in FLASH memory.
|
||||
|
@ -130,7 +136,7 @@ extern uint32_t __etext;
|
|||
// For standard S110 builds, this should be word aligned and in the range 0x300 - 0x700.
|
||||
// Any unused memory will be automatically reclaimed as HEAP memory if both MICROBIT_HEAP_REUSE_SD and MICROBIT_HEAP_ALLOCATOR are enabled.
|
||||
#ifndef MICROBIT_SD_GATT_TABLE_SIZE
|
||||
#define MICROBIT_SD_GATT_TABLE_SIZE 0x300
|
||||
#define MICROBIT_SD_GATT_TABLE_SIZE 0x400
|
||||
#endif
|
||||
|
||||
//
|
||||
|
|
|
@ -73,7 +73,7 @@ class MicroBitFlash
|
|||
* Erase an entire page.
|
||||
* @param page_address address of first word of page.
|
||||
*/
|
||||
void erase_page(uint32_t* page_address);
|
||||
uint8_t erase_page(uint32_t* page_address);
|
||||
|
||||
/**
|
||||
* Write to flash memory, assuming that a write is valid
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 British Broadcasting Corporation.
|
||||
This software is provided by Lancaster University by arrangement with the BBC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROBIT_MEMORY_MAP_H
|
||||
#define MICROBIT_MEMORY_MAP_H
|
||||
|
||||
#include "mbed.h"
|
||||
#include "MicroBitConfig.h"
|
||||
#include "ManagedString.h"
|
||||
#include "ErrorNo.h"
|
||||
|
||||
#define MICROBIT_MEMORY_MAP_MAGIC 0xCA8E
|
||||
|
||||
#define NUMBER_OF_REGIONS 3
|
||||
|
||||
/**
|
||||
* Class definition for the MicroBitMemoryMap class.
|
||||
* This allows reading and writing of regions within the memory map.
|
||||
*
|
||||
* This class maps the different regions used on the flash memory to allow
|
||||
* a region to updated independently of the others AKA Partial Flashing.
|
||||
*/
|
||||
class MicroBitMemoryMap
|
||||
{
|
||||
struct Region
|
||||
{
|
||||
uint8_t regionId;
|
||||
uint32_t startAddress;
|
||||
uint32_t endAddress;
|
||||
uint8_t hash[8];
|
||||
|
||||
Region(uint8_t regionId, uint32_t startAddress, uint32_t endAddress, uint8_t hash[8])
|
||||
{
|
||||
this->regionId = regionId;
|
||||
this->startAddress = startAddress;
|
||||
this->endAddress = endAddress;
|
||||
memmove( this->hash, &hash, 8 );
|
||||
}
|
||||
|
||||
Region(){
|
||||
this->regionId = 0x0;
|
||||
this->startAddress = 0x0;
|
||||
this->endAddress = 0x0;
|
||||
memset( this->hash, 0xDD, 8 );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct MemoryMapStore
|
||||
{
|
||||
Region memoryMap[3];
|
||||
};
|
||||
|
||||
uint8_t regionCount = 0;
|
||||
|
||||
/**
|
||||
* Function to update the flash with the current MemoryMapStore
|
||||
*
|
||||
* @param memoryMapStore The memory map to write to flash
|
||||
*/
|
||||
void updateFlash(MemoryMapStore *store);
|
||||
|
||||
public:
|
||||
|
||||
MemoryMapStore memoryMapStore;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* Creates an instance of MicroBitMemoryMap
|
||||
*/
|
||||
MicroBitMemoryMap();
|
||||
|
||||
/**
|
||||
* Function for adding a Region to the end of the MemoryMap
|
||||
*
|
||||
* @param region The Region to add to the MemoryMap
|
||||
*
|
||||
* @return MICROBIT_OK on success
|
||||
*
|
||||
*/
|
||||
int pushRegion(Region region);
|
||||
|
||||
/**
|
||||
* Function for updating a Region of the MemoryMap
|
||||
*
|
||||
* @param region The Region to update in the MemoryMap. The name is used as the selector.
|
||||
*
|
||||
* @return MICROBIT_OK success, MICROBIT_NO_DATA if the region is not found
|
||||
*/
|
||||
int updateRegion(Region region);
|
||||
|
||||
/**
|
||||
* Function to fetch hashes from PXT build
|
||||
*
|
||||
* @return int Boolean result of the search. 1 = Hashes Found; 0 = No Hash Found
|
||||
*/
|
||||
void findHashes();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "microbit-dal",
|
||||
"version": "2.0.0-rc9",
|
||||
"version": "2.0.0-pf",
|
||||
"license": "MIT",
|
||||
"description": "The runtime library for the BBC micro:bit, developed by Lancaster University",
|
||||
"keywords": [
|
||||
|
|
|
@ -45,6 +45,7 @@ set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES
|
|||
"drivers/MicroBitFlash.cpp"
|
||||
"drivers/MicroBitFile.cpp"
|
||||
"drivers/MicroBitFileSystem.cpp"
|
||||
"drivers/MicroBitMemoryMap.cpp"
|
||||
|
||||
"bluetooth/MicroBitAccelerometerService.cpp"
|
||||
"bluetooth/MicroBitBLEManager.cpp"
|
||||
|
@ -57,6 +58,8 @@ set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES
|
|||
"bluetooth/MicroBitMagnetometerService.cpp"
|
||||
"bluetooth/MicroBitTemperatureService.cpp"
|
||||
"bluetooth/MicroBitUARTService.cpp"
|
||||
"bluetooth/MicroBitPartialFlashingService.cpp"
|
||||
|
||||
)
|
||||
|
||||
execute_process(WORKING_DIRECTORY "../../yotta_modules/${PROJECT_NAME}" COMMAND "git" "log" "--pretty=format:%h" "-n" "1" OUTPUT_VARIABLE git_hash)
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 British Broadcasting Corporation.
|
||||
This software is provided by Lancaster University by arrangement with the BBC.
|
||||
|
||||
|
@ -380,11 +378,14 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb
|
|||
// Configure the radio at our default power level
|
||||
setTransmitPower(MICROBIT_BLE_DEFAULT_TX_POWER);
|
||||
|
||||
|
||||
// Bring up core BLE services.
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE)
|
||||
new MicroBitDFUService(*ble);
|
||||
new MicroBitPartialFlashingService(*ble, messageBus);
|
||||
#endif
|
||||
|
||||
|
||||
#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
|
||||
|
@ -641,12 +642,14 @@ void MicroBitBLEManager::pairingMode(MicroBitDisplay &display, MicroBitButton &a
|
|||
ManagedString namePostfix("]");
|
||||
ManagedString BLEName = namePrefix + deviceName + namePostfix;
|
||||
|
||||
ManagedString msg("PAIRING MODE!");
|
||||
ManagedString msg("M M!");
|
||||
|
||||
int timeInPairingMode = 0;
|
||||
int brightness = 255;
|
||||
int fadeDirection = 0;
|
||||
|
||||
bleMode = MICROBIT_BLE_MODE_PAIRING;
|
||||
|
||||
ble->gap().stopAdvertising();
|
||||
|
||||
// Clear the whitelist (if we have one), so that we're discoverable by all BLE devices.
|
||||
|
@ -673,13 +676,17 @@ void MicroBitBLEManager::pairingMode(MicroBitDisplay &display, MicroBitButton &a
|
|||
|
||||
// Stop any running animations on the display
|
||||
display.stopAnimation();
|
||||
display.scroll(msg);
|
||||
|
||||
// Replaced by animation TODO remove
|
||||
//display.scroll(msg);
|
||||
|
||||
fiber_add_idle_component(this);
|
||||
|
||||
showManagementModeAnimation(display);
|
||||
|
||||
// Display our name, visualised as a histogram in the display to aid identification.
|
||||
showNameHistogram(display);
|
||||
|
||||
fiber_add_idle_component(this);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (pairingStatus & MICROBIT_BLE_PAIR_REQUEST)
|
||||
|
@ -765,6 +772,50 @@ void MicroBitBLEManager::pairingMode(MicroBitDisplay &display, MicroBitButton &a
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the management mode animation on the provided MicroBitDisplay instance.
|
||||
*
|
||||
* @param display The Display instance used for displaying the animation.
|
||||
*/
|
||||
void MicroBitBLEManager::showManagementModeAnimation(MicroBitDisplay &display)
|
||||
{
|
||||
// Animation for display object
|
||||
// https://makecode.microbit.org/93264-81126-90471-58367
|
||||
|
||||
const int mgmt_animation_w = 20;
|
||||
const int mgmt_animation_h = 5;
|
||||
const uint8_t mgmt_animation[] =
|
||||
{
|
||||
1,1,1,1,1, 1,1,1,1,1, 1,1,0,1,1, 1,0,0,0,1,
|
||||
1,1,1,1,1, 1,1,0,1,1, 1,0,0,0,1, 0,0,0,0,0,
|
||||
1,1,0,1,1, 1,0,0,0,1, 0,0,0,0,0, 0,0,0,0,0,
|
||||
1,1,1,1,1, 1,1,0,1,1, 1,0,0,0,1, 0,0,0,0,0,
|
||||
1,1,1,1,1, 1,1,1,1,1, 1,1,0,1,1, 1,0,0,0,1
|
||||
};
|
||||
|
||||
MicroBitImage mgmt(mgmt_animation_w,mgmt_animation_h,mgmt_animation);
|
||||
display.animate(mgmt,100,5);
|
||||
|
||||
const uint8_t bt_icon_raw[] =
|
||||
{
|
||||
255,255,255,0 ,255,
|
||||
255,0 ,255,255,0 ,
|
||||
255,255,255,0 ,0 ,
|
||||
255,0 ,255,255,0 ,
|
||||
255,255,255,0 ,255
|
||||
};
|
||||
|
||||
MicroBitImage bt_icon(5,5,bt_icon_raw);
|
||||
display.print(bt_icon,0,0,0,0);
|
||||
|
||||
for(int i=0; i < 255; i = i + 5){
|
||||
display.setBrightness(i);
|
||||
fiber_sleep(5);
|
||||
}
|
||||
fiber_sleep(1000);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the device's ID code as a histogram on the provided MicroBitDisplay instance.
|
||||
*
|
||||
|
@ -790,3 +841,24 @@ void MicroBitBLEManager::showNameHistogram(MicroBitDisplay &display)
|
|||
display.image.setPixelValue(MICROBIT_DFU_HISTOGRAM_WIDTH - i - 1, MICROBIT_DFU_HISTOGRAM_HEIGHT - j - 1, 255);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts in BLE Mode
|
||||
*
|
||||
*/
|
||||
void MicroBitBLEManager::restartInBLEMode(){
|
||||
KeyValuePair* BLEMode = storage->get("BLEMode");
|
||||
if(BLEMode == NULL){
|
||||
uint8_t BLEMode = 0x01;
|
||||
storage->put("BLEMode", &BLEMode, sizeof(BLEMode));
|
||||
delete &BLEMode;
|
||||
}
|
||||
microbit_reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get BLE mode. Returns the current mode: application, pairing mode
|
||||
*/
|
||||
uint8_t MicroBitBLEManager::getBLEMode(){
|
||||
return bleMode;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,322 @@
|
|||
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 British Broadcasting Corporation.
|
||||
This software is provided by Lancaster University by arrangement with the BBC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class definition for the custom MicroBit Partial Flashing service.
|
||||
* Provides a BLE service to remotely write the user program to the device.
|
||||
*/
|
||||
#include "MicroBitConfig.h"
|
||||
#include "ble/UUID.h"
|
||||
#include "MicroBitPartialFlashingService.h"
|
||||
|
||||
// BLE PF Control Codes
|
||||
#define REGION_INFO 0x00
|
||||
#define FLASH_DATA 0x01
|
||||
#define END_OF_TRANSMISSION 0x02
|
||||
|
||||
// BLE Utilities
|
||||
#define MICROBIT_STATUS 0xEE
|
||||
#define MICROBIT_RESET 0xFF
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a representation of the PartialFlashService
|
||||
* @param _ble The instance of a BLE device that we're running on.
|
||||
* @param _messageBus The instance of a EventModel that we're running on.
|
||||
*/
|
||||
MicroBitPartialFlashingService::MicroBitPartialFlashingService(BLEDevice &_ble, EventModel &_messageBus) :
|
||||
ble(_ble), messageBus(_messageBus)
|
||||
{
|
||||
// Set up partial flashing characteristic
|
||||
uint8_t initCharacteristicValue = 0x00;
|
||||
GattCharacteristic partialFlashCharacteristic(MicroBitPartialFlashingServiceCharacteristicUUID, &initCharacteristicValue, sizeof(initCharacteristicValue),
|
||||
20, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
|
||||
|
||||
// Set default security requirements
|
||||
partialFlashCharacteristic.requireSecurity(SecurityManager::MICROBIT_BLE_SECURITY_LEVEL);
|
||||
|
||||
// Create Partial Flashing Service
|
||||
GattCharacteristic *characteristics[] = {&partialFlashCharacteristic};
|
||||
GattService service(MicroBitPartialFlashingServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic*) );
|
||||
ble.addService(service);
|
||||
|
||||
// Get characteristic handle for future use
|
||||
partialFlashCharacteristicHandle = partialFlashCharacteristic.getValueHandle();
|
||||
ble.gattServer().onDataWritten(this, &MicroBitPartialFlashingService::onDataWritten);
|
||||
|
||||
// Set up listener for SD writing
|
||||
messageBus.listen(MICROBIT_ID_PFLASH_NOTIFICATION, MICROBIT_EVT_ANY, this, &MicroBitPartialFlashingService::partialFlashingEvent);
|
||||
|
||||
// Set up Memory map
|
||||
// This will create the Memory Map and store it in flash
|
||||
MicroBitMemoryMap memoryMap;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback. Invoked when any of our attributes are written via BLE.
|
||||
*/
|
||||
void MicroBitPartialFlashingService::onDataWritten(const GattWriteCallbackParams *params)
|
||||
{
|
||||
// Get data from BLE callback params
|
||||
uint8_t *data = (uint8_t *)params->data;
|
||||
|
||||
if(params->handle == partialFlashCharacteristicHandle && params->len > 0)
|
||||
{
|
||||
// Switch CONTROL byte
|
||||
switch(data[0]){
|
||||
case REGION_INFO:
|
||||
{
|
||||
// Create instance of Memory Map to return info
|
||||
MicroBitMemoryMap memoryMap;
|
||||
|
||||
uint8_t buffer[18];
|
||||
// Response:
|
||||
// Region and Region #
|
||||
buffer[0] = 0x00;
|
||||
buffer[1] = data[1];
|
||||
|
||||
// Start Address
|
||||
buffer[2] = (memoryMap.memoryMapStore.memoryMap[data[1]].startAddress & 0xFF000000) >> 24;
|
||||
buffer[3] = (memoryMap.memoryMapStore.memoryMap[data[1]].startAddress & 0x00FF0000) >> 16;
|
||||
buffer[4] = (memoryMap.memoryMapStore.memoryMap[data[1]].startAddress & 0x0000FF00) >> 8;
|
||||
buffer[5] = (memoryMap.memoryMapStore.memoryMap[data[1]].startAddress & 0x000000FF);
|
||||
|
||||
// End Address
|
||||
buffer[6] = (memoryMap.memoryMapStore.memoryMap[data[1]].endAddress & 0xFF000000) >> 24;
|
||||
buffer[7] = (memoryMap.memoryMapStore.memoryMap[data[1]].endAddress & 0x00FF0000) >> 16;
|
||||
buffer[8] = (memoryMap.memoryMapStore.memoryMap[data[1]].endAddress & 0x0000FF00) >> 8;
|
||||
buffer[9] = (memoryMap.memoryMapStore.memoryMap[data[1]].endAddress & 0x000000FF);
|
||||
|
||||
// Region Hash
|
||||
for(int i = 0; i < 8; ++i)
|
||||
buffer[10+i] = memoryMap.memoryMapStore.memoryMap[data[1]].hash[i];
|
||||
|
||||
// Send BLE Notification
|
||||
ble.gattServer().notify(partialFlashCharacteristicHandle, (const uint8_t *)buffer, 18);
|
||||
|
||||
// Set offset for writing
|
||||
baseAddress = (memoryMap.memoryMapStore.memoryMap[data[1]].startAddress & 0xFFFF0000) >> 16; // Offsets are 16 bit
|
||||
|
||||
// Reset packet count
|
||||
packetCount = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
case FLASH_DATA:
|
||||
{
|
||||
// Process FLASH data packet
|
||||
flashData(data);
|
||||
break;
|
||||
}
|
||||
case END_OF_TRANSMISSION:
|
||||
{
|
||||
/* Start of embedded source isn't always on a page border so client must
|
||||
* inform the micro:bit that it's the last packet.
|
||||
* - Write final packet
|
||||
* The END_OF_TRANSMISSION packet contains no data. Write any data left in the buffer.
|
||||
*/
|
||||
MicroBitEvent evt(MICROBIT_ID_PFLASH_NOTIFICATION, END_OF_TRANSMISSION ,CREATE_AND_FIRE); break;
|
||||
}
|
||||
case MICROBIT_STATUS:
|
||||
{
|
||||
/*
|
||||
* Return the version of the Partial Flashing Service and the current BLE mode (application / pairing)
|
||||
*/
|
||||
uint8_t flashNotificationBuffer[] = {MICROBIT_STATUS, PARTIAL_FLASHING_VERSION, MicroBitBLEManager::manager->getBLEMode()};
|
||||
ble.gattServer().notify(partialFlashCharacteristicHandle, (const uint8_t *)flashNotificationBuffer, sizeof(flashNotificationBuffer));
|
||||
break;
|
||||
}
|
||||
case MICROBIT_RESET:
|
||||
{
|
||||
/*
|
||||
* data[1] determines which mode to reset into: MICROBIT_BLE_MODE_PAIRING or MICROBIT_BLE_MODE_APPLICATION
|
||||
*/
|
||||
switch(data[1]) {
|
||||
case MICROBIT_BLE_MODE_PAIRING:
|
||||
{
|
||||
MicroBitEvent evt(MICROBIT_ID_PFLASH_NOTIFICATION, MICROBIT_RESET ,CREATE_AND_FIRE);
|
||||
break;
|
||||
}
|
||||
case MICROBIT_BLE_MODE_APPLICATION:
|
||||
{
|
||||
microbit_reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param data - A pointer to the data to process
|
||||
*
|
||||
*/
|
||||
void MicroBitPartialFlashingService::flashData(uint8_t *data)
|
||||
{
|
||||
// Receive 16 bytes per packet
|
||||
// Buffer 8 packets - 32 uint32_t // 128 bytes per block
|
||||
// When buffer is full trigger partialFlashingEvent
|
||||
// When write is complete notify app and repeat
|
||||
// +-----------+---------+---------+----------+
|
||||
// | 1 Byte | 2 Bytes | 1 Byte | 16 Bytes |
|
||||
// +-----------+---------+---------+----------+
|
||||
// | COMMAND | OFFSET | PACKET# | DATA |
|
||||
// +-----------+---------+---------+----------+
|
||||
uint8_t packetNum = data[3];
|
||||
/**
|
||||
* Packets with packet num < packet count
|
||||
* Ignore as part of retransmitted block
|
||||
*/
|
||||
if(packetNum < packetCount)
|
||||
return;
|
||||
|
||||
/**
|
||||
* Check packet count
|
||||
* If the packet count doesn't match send a notification to the client
|
||||
* and set the packet count to the next block number
|
||||
*/
|
||||
if(packetNum != ++packetCount)
|
||||
{
|
||||
uint8_t flashNotificationBuffer[] = {FLASH_DATA, 0xAA};
|
||||
ble.gattServer().notify(partialFlashCharacteristicHandle, (const uint8_t *)flashNotificationBuffer, sizeof(flashNotificationBuffer));
|
||||
packetCount = blockPacketCount + 3;
|
||||
blockNum = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Add to block
|
||||
for(int x = 0; x < 4; x++)
|
||||
block[(4*blockNum) + x] = data[(4*x) + 4] | data[(4*x) + 5] << 8 | data[(4*x) + 6] << 16 | data[(4*x) + 7] << 24;
|
||||
|
||||
// Actions
|
||||
switch(blockNum) {
|
||||
// blockNum is 0, set up offset
|
||||
case 0:
|
||||
{
|
||||
offset = ((data[1] << 8) | data[2]);
|
||||
blockPacketCount = packetNum;
|
||||
blockNum++;
|
||||
break;
|
||||
}
|
||||
// blockNum is 7, block is full
|
||||
case 3:
|
||||
{
|
||||
// Fire write event
|
||||
MicroBitEvent evt(MICROBIT_ID_PFLASH_NOTIFICATION, FLASH_DATA ,CREATE_AND_FIRE);
|
||||
// Reset blockNum
|
||||
blockNum = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
blockNum++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write Event
|
||||
* Used the write data to the flash outside of the BLE ISR
|
||||
*/
|
||||
void MicroBitPartialFlashingService::partialFlashingEvent(MicroBitEvent e)
|
||||
{
|
||||
MicroBitFlash flash;
|
||||
|
||||
switch(e.value){
|
||||
case FLASH_DATA:
|
||||
{
|
||||
/*
|
||||
* Set BLE Mode flag if not already set to boot into BLE mode
|
||||
* upon a failed flash.
|
||||
*/
|
||||
MicroBitStorage storage;
|
||||
KeyValuePair* flashIncomplete = storage.get("flashIncomplete");
|
||||
if(flashIncomplete == NULL){
|
||||
uint8_t flashIncomplete = 0x01;
|
||||
storage.put("flashIncomplete", &flashIncomplete, sizeof(flashIncomplete));
|
||||
}
|
||||
|
||||
|
||||
// Flash Pointer
|
||||
uint32_t *flashPointer = (uint32_t *) ((baseAddress << 16) + offset);
|
||||
|
||||
// If the pointer is on a page boundary erase the page
|
||||
if(!((uint32_t)flashPointer % 0x400))
|
||||
flash.erase_page(flashPointer);
|
||||
|
||||
// Create a pointer to the data block
|
||||
uint32_t *blockPointer;
|
||||
blockPointer = block;
|
||||
|
||||
// Write to flash
|
||||
flash.flash_burn(flashPointer, blockPointer, 16);
|
||||
|
||||
// Update flash control buffer to send next packet
|
||||
uint8_t flashNotificationBuffer[] = {FLASH_DATA, 0xFF};
|
||||
ble.gattServer().notify(partialFlashCharacteristicHandle, (const uint8_t *)flashNotificationBuffer, sizeof(flashNotificationBuffer));
|
||||
break;
|
||||
}
|
||||
case END_OF_TRANSMISSION:
|
||||
{
|
||||
// Write one more packet over the next block: if source embed magic was not previously erased, it will be now!
|
||||
uint32_t *blockPointer;
|
||||
uint32_t *flashPointer = (uint32_t *) ((baseAddress << 16) + offset + 0x40);
|
||||
|
||||
blockPointer = block;
|
||||
flash.flash_burn(flashPointer, blockPointer, 16);
|
||||
|
||||
// Once the final packet has been written remove the BLE mode flag and reset
|
||||
// the micro:bit
|
||||
MicroBitStorage storage;
|
||||
storage.remove("flashIncomplete");
|
||||
delete &storage;
|
||||
microbit_reset();
|
||||
break;
|
||||
}
|
||||
case MICROBIT_RESET:
|
||||
{
|
||||
MicroBitBLEManager::manager->restartInBLEMode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const uint8_t MicroBitPartialFlashingServiceUUID[] = {
|
||||
0xe9,0x7d,0xd9,0x1d,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
|
||||
};
|
||||
|
||||
const uint8_t MicroBitPartialFlashingServiceCharacteristicUUID[] = {
|
||||
0xe9,0x7d,0x3b,0x10,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
|
||||
};
|
|
@ -55,6 +55,13 @@ extern "C" void btle_set_user_evt_handler(void (*func)(uint32_t));
|
|||
static bool evt_handler_registered = false;
|
||||
static volatile bool flash_op_complete = false;
|
||||
|
||||
/*
|
||||
* static void SWI1_IRQHandler(uint32_t evt)
|
||||
{
|
||||
flash_op_complete = true;
|
||||
}
|
||||
*/
|
||||
|
||||
static void nvmc_event_handler(uint32_t evt)
|
||||
{
|
||||
if(evt == NRF_EVT_FLASH_OPERATION_SUCCESS)
|
||||
|
@ -101,15 +108,19 @@ int MicroBitFlash::need_erase(uint8_t* source, uint8_t* flash_addr, int len)
|
|||
* Erase an entire page
|
||||
* @param page_address address of first word of page
|
||||
*/
|
||||
void MicroBitFlash::erase_page(uint32_t* pg_addr)
|
||||
uint8_t MicroBitFlash::erase_page(uint32_t* pg_addr)
|
||||
{
|
||||
if (ble_running())
|
||||
{
|
||||
flash_op_complete = false;
|
||||
while(1)
|
||||
{
|
||||
if (sd_flash_page_erase(((uint32_t)pg_addr)/PAGE_SIZE) == NRF_SUCCESS)
|
||||
uint8_t ret = sd_flash_page_erase(((uint32_t)pg_addr)/PAGE_SIZE);
|
||||
if (ret == NRF_SUCCESS) {
|
||||
break;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
|
||||
wait_ms(10);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 British Broadcasting Corporation.
|
||||
This software is provided by Lancaster University by arrangement with the BBC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class definition for the MicroBitMemoryMap class.
|
||||
* This allows reading and writing of regions within the memory map.
|
||||
*
|
||||
* This class maps the different regions used on the flash memory to allow
|
||||
* a region to updated independently of the others AKA Partial Flashing.
|
||||
*/
|
||||
|
||||
#include "MicroBitConfig.h"
|
||||
#include "MicroBitMemoryMap.h"
|
||||
#include "MicroBitFlash.h"
|
||||
#include "MicroBitSerial.h"
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*
|
||||
* Creates an instance of MicroBitMemoryMap
|
||||
*/
|
||||
MicroBitMemoryMap::MicroBitMemoryMap()
|
||||
{
|
||||
// Assumes PXT Built program
|
||||
// SD
|
||||
pushRegion(Region(0x00, 0x00, 0x18000, 0x00)); // Soft Device
|
||||
|
||||
// DAL
|
||||
pushRegion(Region(0x01, 0x18000, FLASH_PROGRAM_END, 0x00)); // micro:bit Device Abstractation Layer
|
||||
|
||||
// PXT
|
||||
// PXT will be on the start of the next page
|
||||
// padding to next page = 0x400 - (FLASH_PROGRAM_END % 0x400);
|
||||
pushRegion(Region(0x02, FLASH_PROGRAM_END + (0x400 - (FLASH_PROGRAM_END % 0x400)), 0x3BBFF, 0x00)); // micro:bit PXT
|
||||
|
||||
// Find Hashes if PXT Built Program
|
||||
findHashes();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for adding a Region to the end of the MemoryMap
|
||||
*
|
||||
* @param region The Region to add to the MemoryMap
|
||||
*
|
||||
* @return MICROBIT_OK on success
|
||||
*
|
||||
*/
|
||||
int MicroBitMemoryMap::pushRegion(Region region)
|
||||
{
|
||||
|
||||
// Find next blank Region in map
|
||||
if(regionCount == NUMBER_OF_REGIONS){
|
||||
return MICROBIT_NO_DATA;
|
||||
} else {
|
||||
// Add data
|
||||
memoryMapStore.memoryMap[regionCount].startAddress = region.startAddress;
|
||||
memoryMapStore.memoryMap[regionCount].endAddress = region.endAddress;
|
||||
memcpy(&memoryMapStore.memoryMap[regionCount].hash, ®ion.hash, 8);
|
||||
memoryMapStore.memoryMap[regionCount].regionId = region.regionId;
|
||||
regionCount++;
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for updating a Region of the MemoryMap
|
||||
*
|
||||
* @param region The Region to update in the MemoryMap. The name is used as the selector.
|
||||
*
|
||||
* @return MICROBIT_OK success, MICROBIT_NO_DATA if the region is not found
|
||||
*/
|
||||
int MicroBitMemoryMap::updateRegion(Region region)
|
||||
{
|
||||
// Find Region name in map
|
||||
int i = 0;
|
||||
while(memoryMapStore.memoryMap[i].regionId != region.regionId && i < NUMBER_OF_REGIONS) i++;
|
||||
|
||||
if(i == NUMBER_OF_REGIONS){
|
||||
return MICROBIT_NO_DATA;
|
||||
} else {
|
||||
// Add data
|
||||
memoryMapStore.memoryMap[i] = region;
|
||||
updateFlash(&memoryMapStore);
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to update the flash with the current MemoryMapStore
|
||||
*
|
||||
* @param memoryMapStore The memory map to write to flash
|
||||
*/
|
||||
void MicroBitMemoryMap::updateFlash(MemoryMapStore *store)
|
||||
{
|
||||
MicroBitFlash flash;
|
||||
flash.flash_write((uint32_t *)MEMORY_MAP_PAGE, store, (sizeof(MemoryMapStore) / 4));
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to fetch the hashes from a PXT generated build
|
||||
*/
|
||||
void MicroBitMemoryMap::findHashes()
|
||||
{
|
||||
// Iterate through pages to find magic
|
||||
for(int x = 0; x < NRF_FICR->CODESIZE - 1; x++)
|
||||
{
|
||||
|
||||
uint32_t volatile *magicAddress = (uint32_t *)(0x400 * x);
|
||||
|
||||
// Check for first 32 bits of Magic
|
||||
if(*magicAddress == 0x923b8e70)
|
||||
{
|
||||
// Check remaining magic
|
||||
if(
|
||||
*(uint32_t *)(magicAddress + 0x1) == 0x41A815C6 &&
|
||||
*(uint32_t *)(magicAddress + 0x2) == 0xC96698C4 &&
|
||||
*(uint32_t *)(magicAddress + 0x3) == 0x9751EE75
|
||||
)
|
||||
{
|
||||
// If the magic has been found use the hashes follow
|
||||
magicAddress = (uint32_t *)(magicAddress + 0x4);
|
||||
|
||||
memoryMapStore.memoryMap[1].hash[0] = (*magicAddress & 0xFF);
|
||||
memoryMapStore.memoryMap[1].hash[1] = (*magicAddress & 0xFF00) >> 8;
|
||||
memoryMapStore.memoryMap[1].hash[2] = (*magicAddress & 0xFF0000) >> 16;
|
||||
memoryMapStore.memoryMap[1].hash[3] = (*magicAddress & 0xFF000000) >> 24;
|
||||
|
||||
magicAddress = (uint32_t *)(magicAddress + 0x1);
|
||||
|
||||
memoryMapStore.memoryMap[1].hash[4] = (*magicAddress & 0xFF);
|
||||
memoryMapStore.memoryMap[1].hash[5] = (*magicAddress & 0xFF00) >> 8;
|
||||
memoryMapStore.memoryMap[1].hash[6] = (*magicAddress & 0xFF0000) >> 16;
|
||||
memoryMapStore.memoryMap[1].hash[7] = (*magicAddress & 0xFF000000) >> 24;
|
||||
|
||||
magicAddress = (uint32_t *)(magicAddress + 0x1);
|
||||
|
||||
memoryMapStore.memoryMap[2].hash[0] = (*magicAddress & 0xFF);
|
||||
memoryMapStore.memoryMap[2].hash[1] = (*magicAddress & 0xFF00) >> 8;
|
||||
memoryMapStore.memoryMap[2].hash[2] = (*magicAddress & 0xFF0000) >> 16;
|
||||
memoryMapStore.memoryMap[2].hash[3] = (*magicAddress & 0xFF000000) >> 24;
|
||||
|
||||
magicAddress = (uint32_t *)(magicAddress + 0x1);
|
||||
|
||||
memoryMapStore.memoryMap[2].hash[4] = (*magicAddress & 0xFF);
|
||||
memoryMapStore.memoryMap[2].hash[5] = (*magicAddress & 0xFF00) >> 8;
|
||||
memoryMapStore.memoryMap[2].hash[6] = (*magicAddress & 0xFF0000) >> 16;
|
||||
memoryMapStore.memoryMap[2].hash[7] = (*magicAddress & 0xFF000000) >> 24;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue