Simple Mbed Cloud Client application using features of K64 & K66
Connect to Mbed Cloud!
This example was customized a bit for FRDM-K66 and FRDM-K64F.
It depends on having an SD Card plugged in for storage of credentials. It could be changed later to use a SPI flash or other storage on a shield or wired in.
The app keeps track of how many times switch 2 (SW2) is pressed. The value can be retrieved via a GET request to Mbed Cloud.
Also, it will blink a pattern based on milisecond (ms) timing values that can be sent from Mbed Cloud. The pattern can be sent with a PUT request and the blinking sequence can be triggered by a POST request.
Diff: combine_bootloader_with_app.py
- Revision:
- 1:1ccf36276cd3
- Parent:
- 0:e13a8a944e25
- Child:
- 2:6ed27f413b30
--- a/combine_bootloader_with_app.py Tue Feb 13 10:07:23 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,253 +0,0 @@
-#!/usr/bin/env python
-
-## ----------------------------------------------------------------------------
-## Copyright 2016-2017 ARM Ltd.
-##
-## SPDX-License-Identifier: Apache-2.0
-##
-## Licensed 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.
-## ----------------------------------------------------------------------------
-
-from os import path
-import json
-import hashlib, zlib, struct
-import time
-import sys
-
-'''
-define FIRMWARE_HEADER_MAGIC 0x5a51b3d4UL
-define FIRMWARE_HEADER_VERSION 2
-define ARM_UC_SHA512_SIZE (512/8)
-define ARM_UC_GUID_SIZE (128/8)
-typedef struct _arm_uc_internal_header_t
-{
- /* Metadata-header specific magic code */
- uint32_t headerMagic;
-
- /* Revision number for metadata header. */
- uint32_t headerVersion;
-
- /* Version number accompanying the firmware. Larger numbers imply more
- recent and preferred versions. This is used for determining the
- selection order when multiple versions are available. For downloaded
- firmware the manifest timestamp is used as the firmware version.
- */
- uint64_t firmwareVersion;
-
- /* Total space (in bytes) occupied by the firmware BLOB. */
- uint64_t firmwareSize;
-
- /* Firmware hash calculated over the firmware size. Should match the hash
- generated by standard command line tools, e.g., shasum on Linux/Mac.
- */
- uint8_t firmwareHash[ARM_UC_SHA512_SIZE];
-
- /* The ID for the update campaign that resulted in the firmware update.
- */
- uint8_t campaign[ARM_UC_GUID_SIZE];
-
- /* Size of the firmware signature. Must be 0 if no signature is supplied. */
- uint32_t firmwareSignatureSize;
-
- /* Header 32 bit CRC. Calculated over the entire header, including the CRC
- field, but with the CRC set to zero.
- */
- uint32_t headerCRC;
-
- /* Optional firmware signature. Hashing algorithm should be the same as the
- one used for the firmware hash. The firmwareSignatureSize must be set.
- */
- uint8_t firmwareSignature[0];
-} arm_uc_internal_header_t;
-'''
-
-# define defaults to go into the metadata header
-SIZEOF_SHA512 = int(512/8)
-SIZEOF_GUID = int(128/8)
-FIRMWARE_HEADER_MAGIC = 0x5a51b3d4
-FIRMWARE_HEADER_VERSION = 2
-header_format = ">2I2Q{}s{}s2I".format(SIZEOF_SHA512, SIZEOF_GUID)
-
-if sys.version_info < (3,):
- def b(x):
- return bytearray(x)
-else:
- def b(x):
- return x
-
-def create_header(app_blob, firmwareVersion):
- # calculate the hash of the application
- firmwareHash = hashlib.sha256(app_blob).digest()
-
- # calculate the total size which is defined as the application size + metadata header
- firmwareSize = len(app_blob)
-
- # set campaign GUID to 0
- campaign = b'\00'
-
- # signature not supported, set size to 0
- signatureSize = 0
-
- print ('imageSize: {}'.format(firmwareSize))
- print ('imageHash: {}'.format(''.join(['{:0>2x}'.format(c) for c in b(firmwareHash)])))
- print ('imageversion: {}'.format(firmwareVersion))
-
- # construct struct for CRC calculation
- headerCRC = 0
- FirmwareHeader = struct.pack(header_format,
- FIRMWARE_HEADER_MAGIC,
- FIRMWARE_HEADER_VERSION,
- firmwareVersion,
- firmwareSize,
- firmwareHash,
- campaign,
- signatureSize,
- headerCRC)
-
- # calculate checksum over header, including signatureSize but without headerCRC
- headerCRC = zlib.crc32(FirmwareHeader[:-4]) & 0xffffffff
-
- # Pack the data into a binary blob
- FirmwareHeader = struct.pack(header_format,
- FIRMWARE_HEADER_MAGIC,
- FIRMWARE_HEADER_VERSION,
- firmwareVersion,
- firmwareSize,
- firmwareHash,
- campaign,
- signatureSize,
- headerCRC)
-
- return FirmwareHeader
-
-
-def combine(bootloader_blob, app_blob, app_offset, hdr_offset, output, version):
-
- # create header to go with the application binary
- FirmwareHeader = create_header(app_blob, version)
-
- # write the bootloader first
- offset = 0
- output.write(bootloader_blob)
- offset += len(bootloader_blob)
-
- # write the padding between bootloader and firmware header
- output.write(b'\00' * (hdr_offset - offset))
- offset += (hdr_offset - offset)
-
- # write firmware header
- output.write(FirmwareHeader)
- offset += len(FirmwareHeader)
-
- # write padding between header and application
- output.write(b'\00' * (app_offset - offset))
-
- # write the application
- output.write(app_blob)
-
-
-if __name__ == '__main__':
- import argparse
-
- parser = argparse.ArgumentParser(
- description='Combine bootloader with application adding metadata header.')
-
- def offset_arg(s):
- if s.startswith('0x'):
- return int(s, 16)
- else:
- return int(s)
-
- bin_map = {
- 'k64f': {
- 'mem_start': '0x0'
- },
- 'ublox_evk_odin_w2': {
- 'mem_start': '0x08000000'
- },
- 'nucleo_f429zi': {
- 'mem_start': '0x08000000'
- }
- }
-
- curdir = path.dirname(path.abspath(__file__))
-
- def parse_mbed_app_offset(mcu, key):
- mem_start = bin_map[mcu]["mem_start"]
- with open(path.join(curdir, "..", "mbed_app.json")) as fd:
- mbed_json = json.load(fd)
- offset = mbed_json["target_overrides"][mcu.upper()][key]
- return offset_arg(offset) - offset_arg(mem_start)
-
- # specify arguments
- parser.add_argument('-m', '--mcu', type=lambda s : s.lower().replace("-","_"), required=False,
- help='mcu', choices=bin_map.keys())
- parser.add_argument('-b', '--bootloader', type=argparse.FileType('rb'), required=False,
- help='path to the bootloader binary')
- parser.add_argument('-a', '--app', type=argparse.FileType('rb'), required=True,
- help='path to application binary')
- parser.add_argument('-c', '--app-offset', type=offset_arg, required=False,
- help='offset of the application')
- parser.add_argument('-d', '--header-offset', type=offset_arg, required=False,
- help='offset of the firmware metadata header')
- parser.add_argument('-o', '--output', type=argparse.FileType('wb'), required=True,
- help='output combined file path')
- parser.add_argument('-s', '--set-version', type=int, required=False,
- help='set version number', default=int(time.time()))
-
- # workaround for http://bugs.python.org/issue9694
- parser._optionals.title = "arguments"
-
- # get and validate arguments
- args = parser.parse_args()
-
- if(not (args.mcu or args.bootloader)):
- print("Please specify bootloader location or MCU")
- exit(-1)
-
- fname = ''
- if args.mcu:
- fname = path.join(curdir, 'mbed-bootloader-' + args.mcu.replace('_', '-')+'.bin')
- if not path.exists(fname):
- print("Specified MCU does not have a binary in this location")
- exit(-1)
-
- # Use specified bootloader or default if none is provided
- bootloader = args.bootloader or open(fname, 'rb')
-
- # read the contents of bootloader and application binaries into buffers
- bootloader_blob = bootloader.read()
- bootloader.close()
- app_blob = args.app.read()
- args.app.close()
-
- # Use specified offsets or default if none are provided
- if(not (args.mcu or args.app_offset)):
- print("Please specify app offset or MCU")
- exit(-1)
- app_offset = args.app_offset or parse_mbed_app_offset(args.mcu, "target.mbed_app_start")
-
- if(not (args.mcu or args.header_offset)):
- print("Please specify header offset or MCU")
- exit(-1)
- header_offset = args.header_offset or parse_mbed_app_offset(args.mcu, "update-client.application-details")
-
- # combine application and bootloader adding metadata info
- combine(bootloader_blob, app_blob, app_offset, header_offset, args.output, args.set_version)
-
- # close output file
- output_fn = path.abspath(args.output.name)
- args.output.close()
-
- # print the output file path
- print('Combined binary:' + output_fn)