From d75787a4d20d98b8b0307aff5058737a54c8961c Mon Sep 17 00:00:00 2001 From: 0xc0170 Date: Wed, 25 Jan 2017 14:41:04 +0200 Subject: [PATCH 01/10] hal: add flash hal api 4 functions that are covered - init, free, program_page and erase_sector. --- hal/flash_api.h | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 hal/flash_api.h diff --git a/hal/flash_api.h b/hal/flash_api.h new file mode 100644 index 00000000000..84af6424642 --- /dev/null +++ b/hal/flash_api.h @@ -0,0 +1,53 @@ +/** \addtogroup hal */ +/** @{*/ + +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * 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. + */ +#ifndef MBED_FLASH_API_H +#define MBED_FLASH_API_H + +#include "device.h" +#include "stdint.h" + +#if DEVICE_FLASH + +typedef struct flash_s flash_t; + +#ifdef __cplusplus +extern "C" { +#endif + +// maps to FlashAlgo Init +int32_t flash_init(flash_t *obj); + +// maps to FlashAlgo UnInit +int32_t flash_free(flash_t *obj); + +// maps to FlashAlgo EraseSector +int32_t flash_erase_sector(flash_t *obj, uint32_t address); + +// maps FlashAlgo to ProgramPage +int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +/** @}*/ From fb37a763b45416d41b80b90cc512522d67a9fe99 Mon Sep 17 00:00:00 2001 From: 0xc0170 Date: Wed, 25 Jan 2017 14:42:58 +0200 Subject: [PATCH 02/10] test: add flash functional tests for flash HAL --- .../mbed_hal/flash/functional_tests/main.cpp | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 TESTS/mbed_hal/flash/functional_tests/main.cpp diff --git a/TESTS/mbed_hal/flash/functional_tests/main.cpp b/TESTS/mbed_hal/flash/functional_tests/main.cpp new file mode 100644 index 00000000000..4e835a12f3d --- /dev/null +++ b/TESTS/mbed_hal/flash/functional_tests/main.cpp @@ -0,0 +1,190 @@ +/* mbed Microcontroller Library + * Copyright (c) 2016 ARM Limited + * + * 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. + */ + +#if !DEVICE_FLASH + #error [NOT_SUPPORTED] Flash API not supported for this target +#endif + +#include "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" + +#include "mbed.h" +#include "flash_api.h" +#include "flash_data.h" + +using namespace utest::v1; + +/* + return values to be checked are documented at: + http://arm-software.github.io/CMSIS_5/Pack/html/algorithmFunc.html#Verify +*/ + +#ifndef ALIGN_DOWN +#define ALIGN_DOWN(x, a) ((x)& ~((a) - 1)) +#endif + +void flash_init_test() +{ + flash_t test_flash; + int32_t ret = flash_init(&test_flash); + TEST_ASSERT_EQUAL_INT32(ret, 0); + ret = flash_free(&test_flash); + TEST_ASSERT_EQUAL_INT32(ret, 0); +} + +// Erase sector, write one page, erase sector and write new data +void flash_program_page_test() +{ + flash_t test_flash; + int32_t ret = flash_init(&test_flash); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + uint32_t test_size = flash_get_page_size(&test_flash); + uint8_t *data = new uint8_t[test_size]; + for (uint32_t i = 0; i < test_size; i++) { + data[i] = 0xCE; + } + + // the one before the last page in the system + uint32_t address = (test_flash.target_config->flash_start + test_flash.target_config->flash_size) - (2*test_size); + + // sector size might not be same as page size + uint32_t erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address)); + ret = flash_erase_sector(&test_flash, erase_sector_boundary); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + ret = flash_program_page(&test_flash, address, data, test_size); + TEST_ASSERT_EQUAL_INT32(ret, 0); + uint8_t *data_flashed = (uint8_t *)address; + TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, test_size); + + // sector size might not be same as page size + erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address)); + ret = flash_erase_sector(&test_flash, erase_sector_boundary); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + // write another data to be certain we are re-flashing + for (uint32_t i = 0; i < test_size; i++) { + data[i] = 0xAC; + } + ret = flash_program_page(&test_flash, address, data, test_size); + TEST_ASSERT_EQUAL_INT32(ret, 0); + TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, test_size); + + ret = flash_free(&test_flash); + TEST_ASSERT_EQUAL_INT32(ret, 0); + delete[] data; +} + +void flash_erase_sector_test() +{ + flash_t test_flash; + int32_t ret = flash_init(&test_flash); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + uint32_t sector_size = 0x1000; + uint32_t address = (test_flash.target_config->flash_start + test_flash.target_config->flash_size) - (4*sector_size); + // sector size might not be same as page size + uint32_t erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address)); + ret = flash_erase_sector(&test_flash, erase_sector_boundary); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + ret = flash_free(&test_flash); + TEST_ASSERT_EQUAL_INT32(ret, 0); +} + +void flash_erase_sector_error_test() +{ + flash_t test_flash; + int32_t ret = flash_init(&test_flash); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + // most common sector size to get an sector address + uint32_t sector_size = 0x1000; + uint32_t address = (test_flash.target_config->flash_start + test_flash.target_config->flash_size) - (4*sector_size); + uint32_t erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address)); + + // unaligned address + erase_sector_boundary += 1; + ret = flash_erase_sector(&test_flash, erase_sector_boundary); + TEST_ASSERT_EQUAL_INT32(ret, -1); + + ret = flash_free(&test_flash); + TEST_ASSERT_EQUAL_INT32(ret, 0); +} + +void flash_program_page_error_test() +{ + flash_t test_flash; + int32_t ret = flash_init(&test_flash); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + + uint32_t test_size = flash_get_page_size(&test_flash); + // the one before the last page in the system + uint32_t address = (test_flash.target_config->flash_start + test_flash.target_config->flash_size) - (2*test_size); + + // sector size might not be same as page size + uint32_t erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address)); + ret = flash_erase_sector(&test_flash, erase_sector_boundary); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + // we store the current data, and verify later they have not changed + uint8_t *data = new uint8_t[test_size]; + uint8_t *previous_data = new uint8_t[test_size]; + uint8_t *current_data = (uint8_t *)address; + for (uint32_t i = 0; i < test_size; i++) { + previous_data[i] = *current_data; + data[i] = 0xCE; + current_data++; + } + + address += 1UL; + ret = flash_program_page(&test_flash, address, data, test_size); + TEST_ASSERT_EQUAL_INT32(ret, -1); + TEST_ASSERT_EQUAL_UINT8_ARRAY(previous_data, current_data, test_size); + + ret = flash_free(&test_flash); + TEST_ASSERT_EQUAL_INT32(ret, 0); + delete[] data; + delete[] previous_data; +} + +utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) { + greentea_case_failure_abort_handler(source, reason); + return STATUS_CONTINUE; +} + +Case cases[] = { + Case("Flash - init", flash_init_test, greentea_failure_handler), + Case("Flash - erase sector", flash_erase_sector_test, greentea_failure_handler), + Case("Flash - program page", flash_program_page_test, greentea_failure_handler), + Case("Flash - erase sector errors", flash_erase_sector_error_test, greentea_failure_handler), + Case("Flash - program page errors", flash_program_page_error_test, greentea_failure_handler), + +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(20, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() { + Harness::run(specification); +} From 648dbf4b9f8be3a0a3250e51e52082ea48ac763b Mon Sep 17 00:00:00 2001 From: 0xc0170 Date: Wed, 25 Jan 2017 14:45:57 +0200 Subject: [PATCH 03/10] flash: add flash algo common layer K64F and KL46Z addition to use this common layer. This implementation uses flash algo blob that are generated via scripts. If target supports flash algo, it can get common HAL implementation, providing feature "HAL_FLASH_CMSIS_ALGO". This simplifies target code, and having one implementation that can be shared by many targets. Be careful with flash cmsis algo, in some cases they execute code that can affect the system. For instance, it can disable cache, or affect some system clocks. Therefore this feature should be well tested. --- .../flash_common_algo.c | 172 ++++++++++++++++++ hal/TARGET_FLASH_CMSIS_ALGO/flash_data.h | 84 +++++++++ hal/flash_api.h | 2 +- .../TARGET_KLXX/TARGET_KL46Z/flash_api.c | 100 ++++++++++ .../TARGET_MCU_K64F/flash_api.c | 86 +++++++++ targets/targets.json | 16 +- 6 files changed, 451 insertions(+), 9 deletions(-) create mode 100644 hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c create mode 100644 hal/TARGET_FLASH_CMSIS_ALGO/flash_data.h create mode 100644 targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/flash_api.c create mode 100644 targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/flash_api.c diff --git a/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c b/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c new file mode 100644 index 00000000000..c8ee7fe57fc --- /dev/null +++ b/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c @@ -0,0 +1,172 @@ +/* mbed Microcontroller Library + * Copyright (c) 2016 ARM Limited + * + * 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. + */ + +#include "flash_api.h" +#include "flash_data.h" +#include "critical.h" + +#define MBED_FLASH_ALGO_ERASE 1UL +#define MBED_FLASH_ALGO_PROGRAM 2UL + +extern uint32_t SystemCoreClock; + +/* + This binary blob (thumb code) sets r9 (static base) as the code we are jumping to + is PIC (position independent code). + + These are the instructions (r0 is a pointer to arg_t): + push {r5, lr, r4} + mov r5, r9 + push {r5} + ldr r5, [r0, #20] + ldr r3, [r0, #16] + mov r9, r3 + ldr r3, [r0, #12] + ldr r2, [r0, #8] + ldr r1, [r0, #4] + ldr r0, [r0, #0] + blx r5 + pop {r5} + mov r9, r5 + pop {r4-r5, pc} + bx r14 +*/ +static uint32_t jump_to_flash_algo[] = { + 0x464DB530, + 0x6945B420, + 0x46996903, + 0x688268C3, + 0x68006841, + 0xBC2047A8, + 0xBD3046A9 +}; + +static uint32_t get_sector_index(flash_t *obj, uint32_t address) +{ + // check where address belongs to + size_t sector_index = 0; + size_t sectors_count = sizeof(obj->target_config->sectors) / sizeof(sector_info_t); + for (; sector_index < sectors_count; sector_index++) { + if ((address > obj->target_config->sectors[sector_index].start) && + (address < (obj->target_config->sectors[sector_index].start +obj->target_config->sectors[sector_index].size))) { + break; + } + } + return sector_index; +} + +// should be called within critical section +static int32_t flash_algo_init(flash_t *obj, uint32_t address, uint32_t function) +{ + args_t arguments = { + .r0 = address, + .r1 = SystemCoreClock, + .r2 = function, + .r3 = 0, + .r9 = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->static_base, + .pc = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->init + }; + return ((flash_algo_jump_t)(((uint32_t)&jump_to_flash_algo) | 1))(&arguments); +} + +// should be called within critical section +static int32_t flash_algo_uninit(flash_t *obj, uint32_t address, uint32_t function) +{ + args_t arguments = { + .r0 = address, + .r1 = SystemCoreClock, + .r2 = function, + .r3 = 0, + .r9 = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->static_base, + .pc = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->uninit + }; + return ((flash_algo_jump_t)(((uint32_t)&jump_to_flash_algo) | 1))(&arguments); +} + + +int32_t flash_init(flash_t *obj) +{ + flash_set_target_config(obj); + return 0; +} + +int32_t flash_free(flash_t *obj) +{ + return 0; +} + +int32_t flash_erase_sector(flash_t *obj, uint32_t address) +{ + size_t sector_index = get_sector_index(obj, address); + + // erase sector boundary + if ((address % obj->target_config->sectors[sector_index].size) != 0) { + return -1; + } + + core_util_critical_section_enter(); + flash_algo_init(obj, address, MBED_FLASH_ALGO_ERASE); + + args_t arguments = { + .r0 = address, + .r1 = 0, + .r2 = 0, + .r3 = 0, + .r9 = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->static_base, + .pc = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->erase_sector + }; + int32_t ret = ((flash_algo_jump_t)(((uint32_t)&jump_to_flash_algo) | 1))(&arguments); + + flash_algo_uninit(obj, address, MBED_FLASH_ALGO_ERASE); + core_util_critical_section_exit(); + return ret ? -1 : 0; +} + + +int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size) +{ + // write size boundary + if ((address % obj->target_config->page_size) != 0) { + return -1; // TODO return types + } + // size multiple of sectors + if ((size < obj->target_config->page_size) || (size % obj->target_config->page_size != 0)) { + return -1; + } + + uint32_t sector_index = get_sector_index(obj, address); + // should not cross sector boundary + if (((address % obj->target_config->sectors[sector_index].size) + size) > obj->target_config->sectors[sector_index].size) { + return -1; + } + + core_util_critical_section_enter(); + flash_algo_init(obj, address, MBED_FLASH_ALGO_PROGRAM); + + args_t arguments = { + .r0 = address, + .r1 = size, + .r2 = (uint32_t)data, + .r3 = 0, + .r9 = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->static_base, + .pc = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->program_page + }; + int32_t ret = ((flash_algo_jump_t)(((uint32_t)&jump_to_flash_algo) | 1))(&arguments); + + flash_algo_uninit(obj, address, MBED_FLASH_ALGO_PROGRAM); + core_util_critical_section_exit(); + return ret ? -1 : 0; +} diff --git a/hal/TARGET_FLASH_CMSIS_ALGO/flash_data.h b/hal/TARGET_FLASH_CMSIS_ALGO/flash_data.h new file mode 100644 index 00000000000..e00e06d757e --- /dev/null +++ b/hal/TARGET_FLASH_CMSIS_ALGO/flash_data.h @@ -0,0 +1,84 @@ +/* mbed Microcontroller Library + * Copyright (c) 2016 ARM Limited + * + * 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. + */ +#ifndef MBED_FLASH_DATA_H +#define MBED_FLASH_DATA_H + +// This file is automagically generated from flash-algo repository + +#include + +// Target flash algorithm structure +typedef struct { + const uint32_t init; + const uint32_t uninit; + const uint32_t erase_sector; + const uint32_t program_page; + const uint32_t static_base; + uint32_t *algo_blob; +} flash_algo_t; + +typedef struct { + const uint32_t start; + const uint32_t size; +} sector_info_t; + +typedef struct { + const uint32_t page_size; + const uint32_t flash_start; + const uint32_t flash_size; + const sector_info_t *sectors; +} flash_target_config_t; + +// Target flash configuration +struct flash_s { + const flash_target_config_t *target_config; + const flash_algo_t *flash_algo; +}; + +typedef struct { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r9; + uint32_t pc; +} args_t; + +typedef int32_t (*flash_algo_jump_t)(args_t*); + +// prototypes for flash algo CMSIS API + +typedef int (*CMSIS_Algo_Function_Init)(unsigned long adr, unsigned long clk, unsigned long fnc); +typedef int (*CMSIS_Algo_Function_UnInit)(unsigned long fnc); +typedef int (*CMSIS_Algo_Function_EraseSector)(unsigned long adr); +typedef int (*CMSIS_Algo_Function_EraseChip)(void); +typedef int (*CMSIS_Algo_Function_ProgramPage)(unsigned long adr, unsigned long sz, unsigned char *buf); +typedef unsigned long (*CMSIS_Algo_Function_Verify)(unsigned long adr, unsigned long sz, unsigned char *buf); + +#ifdef __cplusplus +extern "C" { +#endif + +/* Set target configuration + */ +void flash_set_target_config(flash_t *obj); + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/hal/flash_api.h b/hal/flash_api.h index 84af6424642..684af2a54ee 100644 --- a/hal/flash_api.h +++ b/hal/flash_api.h @@ -20,7 +20,7 @@ #define MBED_FLASH_API_H #include "device.h" -#include "stdint.h" +#include #if DEVICE_FLASH diff --git a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/flash_api.c b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/flash_api.c new file mode 100644 index 00000000000..cf442a1f0ec --- /dev/null +++ b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/flash_api.c @@ -0,0 +1,100 @@ +/* mbed Microcontroller Library + * Copyright (c) 2016 ARM Limited + * + * 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. + */ + +#include "flash_api.h" +#include "flash_data.h" +#include "critical.h" + +// This file is automagically generated + +// This is a flash algo binary blob. It is PIC (position independent code) that should be stored in RAM +static uint32_t FLASH_ALGO[] = { + 0xb5104935, 0x60084449, 0x21004834, 0x48356001, 0x44484a33, 0x22016002, 0x04926041, 0x02926082, + 0x220560c2, 0x61420692, 0x03122201, 0x46026182, 0x70113220, 0x62411e49, 0xf939f000, 0xd0002800, + 0xbd102001, 0x47702000, 0xb5084a27, 0x0349447a, 0x0c0a9200, 0x48234601, 0x44482300, 0xf9c4f000, + 0xd0002800, 0xbd082001, 0x491fb508, 0x481d4479, 0x44483920, 0xf8a1f000, 0xd10e2800, 0x4478481a, + 0x38324b1a, 0x9000447b, 0x22044816, 0x44484918, 0xf967f000, 0xd0002800, 0xbd082001, 0x4b12b510, + 0x4601447b, 0x2201480f, 0x02923b54, 0xf0004448, 0xbd10f8b6, 0x460cb538, 0x4479490b, 0x9100396e, + 0x48084601, 0x46224613, 0xf0004448, 0x2800f94a, 0x2001d000, 0x0000bd38, 0x00000004, 0x40048100, + 0x40020000, 0x00000008, 0x000000a5, 0x0000055c, 0x0000040c, 0x4604b570, 0x25006800, 0x061b7803, + 0x2370d5fc, 0x20007003, 0x0003e03a, 0xfa5df000, 0x0f0b070c, 0x1f1b1713, 0x2f2b2723, 0x68263633, + 0x71f37813, 0x6826e02a, 0x71b37853, 0x6826e026, 0x71737893, 0x6826e022, 0x713378d3, 0x6826e01e, + 0x72f37913, 0x6826e01a, 0x72b37953, 0x6826e016, 0x72737993, 0x6826e012, 0x723379d3, 0x6826e00e, + 0x73f37a13, 0x6826e00a, 0x73b37a53, 0x6826e006, 0x73737a93, 0x6826e002, 0x73337ad3, 0xb2c01c40, + 0xd9c24288, 0x20806821, 0xe0037008, 0x1c416a60, 0x4780d000, 0x78006820, 0xd5f70600, 0x78006820, + 0xd5010681, 0xe0062504, 0xd50106c1, 0xe0022508, 0xd00007c0, 0x46282510, 0xb508bd70, 0x2244460b, + 0x700a4669, 0x2100466a, 0xbd084798, 0x4614b538, 0xd002078a, 0x300120ff, 0x6842bd38, 0xd803428a, + 0x18d36883, 0xd80d428b, 0x428b68c3, 0x6902d803, 0x428a189a, 0x2002d801, 0x2201bd38, 0x05d21ac9, + 0xe0001889, 0x22081a89, 0x701a466b, 0x705a0c0a, 0x709a0a0a, 0x466a70d9, 0x47a02103, 0xb5ffbd38, + 0x4615b081, 0x27019a01, 0x26006852, 0x02bf1948, 0xd804428a, 0x689b9b01, 0x428318d3, 0x9a01d20f, + 0x428a68d2, 0x9b01d804, 0x18d3691b, 0xd2014283, 0xe0292602, 0x21011a88, 0x184405c9, 0x1a8ce000, + 0x46204639, 0xf904f000, 0xd0022900, 0x360126ff, 0x4639e01a, 0xf0004628, 0x2900f8fb, 0x2601d012, + 0x2009e012, 0x70084669, 0x70480c20, 0x70880a20, 0x9b0470cc, 0x2103466a, 0x47989801, 0xd1030006, + 0x19e41bed, 0xd1ec2d00, 0xb0054630, 0xb5f0bdf0, 0x24006801, 0x0612780a, 0x2270d5fc, 0x6802700a, + 0x71d12103, 0x22806801, 0x6803718a, 0x71592100, 0x23fc6805, 0x6803712b, 0x680373d9, 0x6802701a, + 0x061b7813, 0x7a55d5fc, 0x07177a12, 0x0f3f2201, 0x10560412, 0xf000003b, 0x0910f968, 0x0b0d0b0b, + 0x0b0b0b0b, 0x090d0b0b, 0x0e090b0b, 0xe0026102, 0xe0006101, 0x072a6106, 0x00130f12, 0xf955f000, + 0x0c090910, 0x1815120f, 0x091f1d1b, 0x09090909, 0x61c10a09, 0xbdf04620, 0x03092101, 0x2101e7f9, + 0xe7f602c9, 0x02892101, 0x2101e7f3, 0xe7f00249, 0x310121ff, 0x2180e7ed, 0x2140e7eb, 0x2120e7e9, + 0xb5fee7e7, 0x46074616, 0x2000461d, 0x078b198a, 0x20ffd002, 0xbdfe3001, 0xd00107b3, 0xbdfe2001, + 0x428b687b, 0x68bcd803, 0x4294191c, 0x68fbd20d, 0xd803428b, 0x191c693c, 0xd2014294, 0xbdfe2002, + 0x1ac92201, 0x188c05d2, 0x1acce01b, 0x2006e019, 0x70084669, 0x70480c20, 0x70880a20, 0x78e870cc, + 0x78a87108, 0x78687148, 0x78287188, 0x9b0871c8, 0x2107466a, 0x47984638, 0xd1e02800, 0x1f361d24, + 0x2e001d2d, 0xbdfed1e3, 0x4615b5fe, 0x68424604, 0x184000a8, 0x428a461e, 0x68a3d803, 0x428b18d3, + 0x68e3d808, 0xd803428b, 0x19db6927, 0xd801428b, 0xbdfe2002, 0xd8054282, 0x18d368a3, 0xd3014283, + 0xe00a1a8f, 0x428268e2, 0x6923d903, 0x428318d3, 0x1a88d3ee, 0x05c92101, 0x21041847, 0xf0004638, + 0x2900f817, 0x20ffd002, 0xbdfe3001, 0x46692001, 0x0c387008, 0x0a387048, 0x70cf7088, 0x71080a28, + 0x718e714d, 0x466a9b08, 0x46202106, 0xbdfe4798, 0x09032200, 0xd32c428b, 0x428b0a03, 0x2300d311, + 0xe04e469c, 0x430b4603, 0x2200d43c, 0x428b0843, 0x0903d331, 0xd31c428b, 0x428b0a03, 0x4694d301, + 0x09c3e03f, 0xd301428b, 0x1ac001cb, 0x09834152, 0xd301428b, 0x1ac0018b, 0x09434152, 0xd301428b, + 0x1ac0014b, 0x09034152, 0xd301428b, 0x1ac0010b, 0x08c34152, 0xd301428b, 0x1ac000cb, 0x08834152, + 0xd301428b, 0x1ac0008b, 0x08434152, 0xd301428b, 0x1ac0004b, 0x1a414152, 0x4601d200, 0x46104152, + 0xe05d4770, 0xd0000fca, 0x10034249, 0x4240d300, 0x22004053, 0x0903469c, 0xd32d428b, 0x428b0a03, + 0x22fcd312, 0xba120189, 0x428b0a03, 0x0189d30c, 0x428b1192, 0x0189d308, 0x428b1192, 0x0189d304, + 0x1192d03a, 0x0989e000, 0x428b09c3, 0x01cbd301, 0x41521ac0, 0x428b0983, 0x018bd301, 0x41521ac0, + 0x428b0943, 0x014bd301, 0x41521ac0, 0x428b0903, 0x010bd301, 0x41521ac0, 0x428b08c3, 0x00cbd301, + 0x41521ac0, 0x428b0883, 0x008bd301, 0x41521ac0, 0x0843d2d9, 0xd301428b, 0x1ac0004b, 0x1a414152, + 0x4601d200, 0x41524663, 0x4610105b, 0x4240d301, 0xd5002b00, 0x47704249, 0x105b4663, 0x4240d300, + 0x2000b501, 0x46c046c0, 0xb430bd02, 0x1e644674, 0x1c647825, 0xd20042ab, 0x5d63461d, 0x18e3005b, + 0x4718bc30, 0xfffffffe, 0xffffffff, 0xfffffffe, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +static const flash_algo_t flash_algo_config = { + .init = 0x1, + .uninit = 0x45, + .erase_sector = 0x9d, + .program_page = 0xb5, + .static_base = 0x5f0, + .algo_blob = FLASH_ALGO, +}; + +static const sector_info_t sectors_info[] = { + {0x0, 0x400}, +}; + +static const flash_target_config_t flash_target_config = { + .page_size = 0x100, + .flash_start = 0x0, + .flash_size = 0x40000, + .sectors = sectors_info, +}; + +void flash_set_target_config(flash_t *obj) +{ + obj->flash_algo = &flash_algo_config; + obj->target_config = &flash_target_config; +} diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/flash_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/flash_api.c new file mode 100644 index 00000000000..5bdbb79dfa4 --- /dev/null +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/flash_api.c @@ -0,0 +1,86 @@ +/* mbed Microcontroller Library + * Copyright (c) 2016 ARM Limited + * + * 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. + */ + +#include "flash_api.h" +#include "flash_data.h" +#include "critical.h" + +// This file is automagically generated + +// This is a flash algo binary blob. It is PIC (position independent code) that should be stored in RAM +static uint32_t FLASH_ALGO[] = { + 0xb5104938, 0x60084449, 0xf24c4837, 0x81c15120, 0x1128f64d, 0x880181c1, 0x0101f021, 0x48348001, + 0x44484932, 0x1280f44f, 0x21006001, 0x1201e9c0, 0x52a0f04f, 0xf44f6142, 0x61824280, 0x1020f880, + 0x62411e49, 0xf939f000, 0xd0002800, 0xbd102001, 0x47702000, 0x4a27b508, 0x9200447a, 0x02cff3c1, + 0x48234601, 0x44482300, 0xf92cf000, 0xd0002800, 0xbd082001, 0x491fb508, 0x481d4479, 0x44483920, + 0xf89ff000, 0xd10f2800, 0x4478481a, 0x38324b1a, 0x9000447b, 0x22084816, 0x6181f44f, 0xf0004448, + 0x2800f959, 0x2001d000, 0x4b12bd08, 0x4601447b, 0x3b54480f, 0x5280f44f, 0xf0004448, 0xb508b8b6, + 0x1dc94613, 0x0207f021, 0x4479490a, 0x91003972, 0x48074601, 0xf0004448, 0x2800f93d, 0x2001d000, + 0x0000bd08, 0x00000004, 0x40052000, 0x40020000, 0x00000008, 0x000000a1, 0x0000037c, 0x4604b570, + 0x25006800, 0x061b7803, 0x2370d5fc, 0x20007003, 0x280ce03a, 0xe8dfd236, 0x0a06f000, 0x1a16120e, + 0x2a26221e, 0x6826322e, 0x71f37813, 0x6826e02a, 0x71b37853, 0x6826e026, 0x71737893, 0x6826e022, + 0x713378d3, 0x6826e01e, 0x72f37913, 0x6826e01a, 0x72b37953, 0x6826e016, 0x72737993, 0x6826e012, + 0x723379d3, 0x6826e00e, 0x73f37a13, 0x6826e00a, 0x73b37a53, 0x6826e006, 0x73737a93, 0x6826e002, + 0x73337ad3, 0xb2c01c40, 0xd9c24288, 0x20806821, 0xe0037008, 0x1c416a60, 0x4780d000, 0x78006820, + 0xd5f70600, 0x78006820, 0xd5010681, 0xe0062504, 0xd50106c1, 0xe0022508, 0xd00007c0, 0x46282510, + 0xb508bd70, 0x460b2244, 0x2000f88d, 0x2100466a, 0xbd084798, 0x4614b538, 0xd002070a, 0x7080f44f, + 0x6843bd38, 0xd803428b, 0x441a6882, 0xd80c428a, 0x428b68c3, 0x6902d803, 0x428a441a, 0x2002d801, + 0x1ac9bd38, 0x0100f501, 0x1ac9e000, 0xf88d2208, 0x0c0a2000, 0x2001f88d, 0xf88d0a0a, 0xf88d2002, + 0x466a1003, 0x47a02103, 0xe92dbd38, 0x460745f8, 0x46164698, 0x2000687b, 0x428b198a, 0x68bcd803, + 0x4294441c, 0x68fbd20e, 0xd803428b, 0x441c693c, 0xd2024294, 0xe8bd2002, 0x1acc85f8, 0x0400f504, + 0xe0022500, 0xf44f1acc, 0xfbb45580, 0xfb05f1f5, 0xb1114111, 0x7080f44f, 0xfbb6e7ed, 0xfb05f1f5, + 0xb1a96111, 0xe7e62001, 0xa000f88d, 0xf88d0c20, 0x0a200001, 0x0002f88d, 0x4003f88d, 0x2103466a, + 0x46434638, 0x28004798, 0x1b76d1d5, 0xe001442c, 0x0a09f04f, 0xd1e72e00, 0x4601e7cd, 0x61082000, + 0x477061c8, 0x41fce92d, 0x9d086846, 0x1402eb01, 0xd803428e, 0x44376887, 0xd80a428f, 0x428f68c7, + 0xf8d0d804, 0x4467c010, 0xd802428f, 0xe8bd2002, 0x42a681fc, 0x6887d805, 0x42a74437, 0x1b89d301, + 0x68c6e009, 0xd90342a6, 0x44376907, 0xd3ed42a7, 0xf5011b89, 0x24100100, 0xf6f4fbb1, 0x1416fb04, + 0xf44fb114, 0xe7e27080, 0xf88d2401, 0x0c0c4000, 0x4001f88d, 0xf88d0a0c, 0xf88d4002, 0x0a111003, + 0x1004f88d, 0x2005f88d, 0x3006f88d, 0x2106466a, 0xe7cc47a8, 0x43fee92d, 0x46074616, 0x2000461c, + 0xf8dd198a, 0x074b8028, 0xf44fd003, 0xe8bd7080, 0x077383fe, 0x2001d001, 0x687be7f9, 0xd803428b, + 0x441d68bd, 0xd20c4295, 0x428b68fb, 0x693dd803, 0x4295441d, 0x2002d201, 0x1acde7e9, 0x0500f505, + 0x1acde02e, 0x2007e02c, 0x0000f88d, 0xf88d0c28, 0x0a280001, 0x0002f88d, 0x5003f88d, 0xf88d78e0, + 0x78a00004, 0x0005f88d, 0xf88d7860, 0x78200006, 0x0007f88d, 0xf88d79e0, 0x79a00008, 0x0009f88d, + 0xf88d7960, 0x7920000a, 0x000bf88d, 0x210b466a, 0x46434638, 0x28004798, 0x3508d1b9, 0x34083e08, + 0xd1d02e00, 0x0000e7b3, 0xfffffffe, 0x00000000, 0xffffffff, 0xfffffffe, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +}; + +static const flash_algo_t flash_algo_config = { + .init = 0x1UL, + .uninit = 0x51, + .erase_sector = 0xab, + .program_page = 0xbf, + .static_base = 0x418, + .algo_blob = FLASH_ALGO, +}; + +static const sector_info_t sectors_info[] = { + {0x0, 0x1000}, +}; + +static const flash_target_config_t flash_target_config = { + .page_size = 0x200, + .flash_start = 0x0, + .flash_size = 0x100000, + .sectors = sectors_info, +}; + +void flash_set_target_config(flash_t *obj) +{ + obj->flash_algo = &flash_algo_config; + obj->target_config = &flash_target_config; +} diff --git a/targets/targets.json b/targets/targets.json index a17911c9ef0..c0d94a007c5 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -448,12 +448,12 @@ "KL46Z": { "supported_form_factors": ["ARDUINO"], "core": "Cortex-M0+", - "extra_labels": ["Freescale", "KLXX"], + "extra_labels": ["Freescale", "KLXX", "FLASH_CMSIS_ALGO"], "is_disk_virtual": true, "supported_toolchains": ["GCC_ARM", "ARM", "IAR"], "inherits": ["Target"], "detect_code": ["0220"], - "device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SEMIHOST", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], "release_versions": ["2", "5"], "device_name": "MKL46Z256xxx4" }, @@ -573,12 +573,12 @@ "supported_form_factors": ["ARDUINO"], "core": "Cortex-M4F", "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], - "extra_labels": ["Freescale", "MCUXpresso_MCUS", "KSDK2_MCUS", "FRDM", "KPSDK_MCUS", "KPSDK_CODE", "MCU_K64F"], + "extra_labels": ["Freescale", "MCUXpresso_MCUS", "KSDK2_MCUS", "FRDM", "KPSDK_MCUS", "KPSDK_CODE", "MCU_K64F", "FLASH_CMSIS_ALGO"], "is_disk_virtual": true, "macros": ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED"], "inherits": ["Target"], "detect_code": ["0240"], - "device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "STORAGE", "TRNG"], + "device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "STORAGE", "TRNG", "FLASH"], "features": ["LWIP", "STORAGE"], "release_versions": ["2", "5"], "device_name": "MK64FN1M0xxx12" @@ -587,22 +587,22 @@ "inherits": ["Target"], "core": "Cortex-M4F", "supported_toolchains": ["ARM", "GCC_ARM"], - "extra_labels": ["Freescale", "MCUXpresso_MCUS", "KSDK2_MCUS", "KPSDK_MCUS", "KPSDK_CODE", "MCU_K64F"], + "extra_labels": ["Freescale", "MCUXpresso_MCUS", "KSDK2_MCUS", "KPSDK_MCUS", "KPSDK_CODE", "MCU_K64F", "FLASH_CMSIS_ALGO"], "is_disk_virtual": true, "macros": ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED", "TARGET_K64F"], - "device_has": ["I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "FLASH"], "device_name": "MK64FN1M0xxx12" }, "HEXIWEAR": { "inherits": ["Target"], "core": "Cortex-M4F", - "extra_labels": ["Freescale", "MCUXpresso_MCUS", "KSDK2_MCUS", "MCU_K64F"], + "extra_labels": ["Freescale", "MCUXpresso_MCUS", "KSDK2_MCUS", "MCU_K64F", "FLASH_CMSIS_ALGO"], "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "macros": ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED", "TARGET_K64F"], "is_disk_virtual": true, "default_toolchain": "ARM", "detect_code": ["0214"], - "device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "TRNG"], + "device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "TRNG", "FLASH"], "default_lib": "std", "release_versions": ["2", "5"], "device_name": "MK64FN1M0xxx12" From ba6216e72f8f17dc25aba849d200451fc9ecf7ed Mon Sep 17 00:00:00 2001 From: 0xc0170 Date: Thu, 26 Jan 2017 14:28:39 +0200 Subject: [PATCH 04/10] flash: add get_sector/page_size functions --- hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c | 13 +++++++++++++ hal/flash_api.h | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c b/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c index c8ee7fe57fc..253edfb5c58 100644 --- a/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c +++ b/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c @@ -170,3 +170,16 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, core_util_critical_section_exit(); return ret ? -1 : 0; } + + +uint32_t flash_get_sector_size(flash_t *obj, uint32_t address) +{ + uint32_t sector_index = get_sector_index(obj, address); + return obj->target_config->sectors[sector_index].size; +} + +uint32_t flash_get_page_size(flash_t *obj) +{ + return obj->target_config->page_size; +} + diff --git a/hal/flash_api.h b/hal/flash_api.h index 684af2a54ee..f663ac642a8 100644 --- a/hal/flash_api.h +++ b/hal/flash_api.h @@ -42,6 +42,10 @@ int32_t flash_erase_sector(flash_t *obj, uint32_t address); // maps FlashAlgo to ProgramPage int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size); +uint32_t flash_get_sector_size(flash_t *obj, uint32_t address); + +uint32_t flash_get_page_size(flash_t *obj); + #ifdef __cplusplus } #endif From 3ebcf92063e622cddb7d45d460e3713d8db9cedb Mon Sep 17 00:00:00 2001 From: 0xc0170 Date: Fri, 27 Jan 2017 12:00:08 +0200 Subject: [PATCH 05/10] flash: add doxygen documentation --- hal/flash_api.h | 49 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/hal/flash_api.h b/hal/flash_api.h index f663ac642a8..66a0fa04df6 100644 --- a/hal/flash_api.h +++ b/hal/flash_api.h @@ -30,22 +30,63 @@ typedef struct flash_s flash_t; extern "C" { #endif -// maps to FlashAlgo Init +/** + * \defgroup flash_hal Flash HAL API + * @{ + */ + +/** Initialize the flash peripheral and the flash_t object + * + * @param obj The flash object + * @return 0 for success, -1 for error + */ int32_t flash_init(flash_t *obj); -// maps to FlashAlgo UnInit +/** Uninitialize the flash peripheral and the flash_t object + * + * @param obj The flash object + * @return 0 for success, -1 for error + */ int32_t flash_free(flash_t *obj); -// maps to FlashAlgo EraseSector +/** Erase one sector starting at defined address + * + * The address should be at sector boundary + * @param obj The flash object + * @param address The sector starting address + * @return 0 for success, -1 for error + */ int32_t flash_erase_sector(flash_t *obj, uint32_t address); -// maps FlashAlgo to ProgramPage +/** Program one page starting at defined address + * + * The page should be at page boundary, should not cross multiple sectors + * @param obj The flash object + * @param address The sector starting address + * @param data The data buffer to be programmed + * @param size The number of in bytes + * @return 0 for success, -1 for error + */ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size); +/** Get sector size + * + * @param obj The flash object + * @param address The sector starting address + * @return The size of a sector + */ uint32_t flash_get_sector_size(flash_t *obj, uint32_t address); +/** Get page size + * + * @param obj The flash object + * @param address The page starting address + * @return The size of a page + */ uint32_t flash_get_page_size(flash_t *obj); +/**@}*/ + #ifdef __cplusplus } #endif From 40477af332283a27245fdd38731b28feb9fbabe8 Mon Sep 17 00:00:00 2001 From: 0xc0170 Date: Mon, 6 Feb 2017 15:48:01 +0100 Subject: [PATCH 06/10] flash: fix include header for cmsis algo flash api should include this header file, as it contains required data declarations. --- hal/flash_api.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hal/flash_api.h b/hal/flash_api.h index 66a0fa04df6..cebf7f53dd4 100644 --- a/hal/flash_api.h +++ b/hal/flash_api.h @@ -26,6 +26,10 @@ typedef struct flash_s flash_t; +#if TARGET_FLASH_CMSIS_ALGO +#include "flash_data.h" +#endif + #ifdef __cplusplus extern "C" { #endif From 924f75ab3e3b240b64232a946900b8a79e904489 Mon Sep 17 00:00:00 2001 From: 0xc0170 Date: Mon, 6 Feb 2017 15:53:07 +0100 Subject: [PATCH 07/10] flash: add get flash size function --- hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c | 4 ++++ hal/flash_api.h | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c b/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c index 253edfb5c58..3ed36b747cc 100644 --- a/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c +++ b/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c @@ -183,3 +183,7 @@ uint32_t flash_get_page_size(flash_t *obj) return obj->target_config->page_size; } +uint32_t flash_get_size(flash_t *obj) +{ + return obj->target_config->flash_size; +} diff --git a/hal/flash_api.h b/hal/flash_api.h index cebf7f53dd4..50a4f7e22e2 100644 --- a/hal/flash_api.h +++ b/hal/flash_api.h @@ -89,6 +89,13 @@ uint32_t flash_get_sector_size(flash_t *obj, uint32_t address); */ uint32_t flash_get_page_size(flash_t *obj); +/** Get flash size + * + * @param obj The flash objects + * @return The size of the flash available + */ +uint32_t flash_get_size(flash_t *obj); + /**@}*/ #ifdef __cplusplus From 871eab3d340505bccede92793570aefc49ae3c62 Mon Sep 17 00:00:00 2001 From: 0xc0170 Date: Mon, 6 Feb 2017 16:34:06 +0100 Subject: [PATCH 08/10] flash: add FlashIAP class Flash IAP that provides write/read/program to an internal API. It invokes flash HAL functions. FlashIAP checks for alignments for erase/write/program. HAL functions do not, to avoid duplication per target implementation. --- drivers/FlashIAP.cpp | 175 ++++++++++++++++++ drivers/FlashIAP.h | 142 ++++++++++++++ .../flash_common_algo.c | 32 +--- hal/flash_api.h | 13 +- mbed.h | 1 + 5 files changed, 330 insertions(+), 33 deletions(-) create mode 100644 drivers/FlashIAP.cpp create mode 100644 drivers/FlashIAP.h diff --git a/drivers/FlashIAP.cpp b/drivers/FlashIAP.cpp new file mode 100644 index 00000000000..664ec44df38 --- /dev/null +++ b/drivers/FlashIAP.cpp @@ -0,0 +1,175 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * 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. + */ + +#include +#include "FlashIAP.h" +#include "mbed_assert.h" + + +#ifdef DEVICE_FLASH + +namespace mbed { + +SingletonPtr FlashIAP::_mutex; + +static inline bool is_aligned(uint32_t number, uint32_t alignment) +{ + if ((number % alignment) != 0) { + return false; + } else { + return true; + } +} + +FlashIAP::FlashIAP() +{ + +} + +FlashIAP::~FlashIAP() +{ + +} + +int FlashIAP::init() +{ + int ret = 0; + _mutex->lock(); + if (flash_init(&_flash)) { + ret = -1; + } + _mutex->unlock(); + return ret; +} + +int FlashIAP::deinit() +{ + int ret = 0; + _mutex->lock(); + if (flash_free(&_flash)) { + ret = -1; + } + _mutex->unlock(); + return ret; +} + + +int FlashIAP::read(void *buffer, uint32_t addr, uint32_t size) +{ + _mutex->lock(); + memcpy(buffer, (const void *)addr, size); + _mutex->unlock(); + return 0; +} + +int FlashIAP::program(const void *buffer, uint32_t addr, uint32_t size) +{ + uint32_t page_size = get_page_size(); + uint32_t current_sector_size = flash_get_sector_size(&_flash, addr); + // addr and size should be aligned to page size, and multiple of page size + // page program should not cross sector boundaries + if ((is_aligned(addr, page_size) == false) || + (is_aligned(size, page_size) == false) || + (size < page_size) || + (((addr % current_sector_size) + size) > current_sector_size)) { + return -1; + } + + int ret = 0; + _mutex->lock(); + if (flash_program_page(&_flash, addr, (const uint8_t *)buffer, size)) { + ret = -1; + } + _mutex->unlock(); + return ret; +} + +int FlashIAP::write(const void *buffer, uint32_t addr, uint32_t size) +{ + int ret = 0; + // erase will lock + if (erase(addr, size) != 0) { + return -1; + } + _mutex->lock(); + ret = program(buffer, addr, size); + _mutex->unlock(); + return ret; +} + +bool FlashIAP::is_aligned_to_sector(uint32_t addr, uint32_t size) +{ + uint32_t current_sector_size = flash_get_sector_size(&_flash, addr); + if ((is_aligned(size, current_sector_size) == false) || + (is_aligned(addr, current_sector_size) == false)) { + return false; + } else { + return true; + } +} + +int FlashIAP::erase(uint32_t addr, uint32_t size) +{ + uint32_t current_sector_size = 0UL; + + if (is_aligned_to_sector(addr, size) == false) { + return -1; + } + + int32_t ret = 0; + _mutex->lock(); + while (size) { + ret = flash_erase_sector(&_flash, addr); + if (ret != 0) { + ret = -1; + break; + } + current_sector_size = flash_get_sector_size(&_flash, addr); + if (is_aligned_to_sector(addr, size) == false) { + ret = -1; + break; + } + size -= current_sector_size; + addr += current_sector_size; + } + _mutex->unlock(); + return ret; +} + +uint32_t FlashIAP::get_page_size() const +{ + return flash_get_page_size(&_flash); +} + +uint32_t FlashIAP::get_sector_size(uint32_t addr) const +{ + return flash_get_sector_size(&_flash, addr); +} + +uint32_t FlashIAP::get_flash_size() const +{ + return flash_get_size(&_flash); +} + +} + +#endif diff --git a/drivers/FlashIAP.h b/drivers/FlashIAP.h new file mode 100644 index 00000000000..1f308c83f01 --- /dev/null +++ b/drivers/FlashIAP.h @@ -0,0 +1,142 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * 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 MBED_FLASHIAP_H +#define MBED_FLASHIAP_H + +#ifdef DEVICE_FLASH + +#include "flash_api.h" +#include "platform/SingletonPtr.h" +#include "platform/PlatformMutex.h" + +namespace mbed { + +/** \addtogroup drivers */ +/** @{*/ + +/** Flash IAP driver. It invokes flash HAL functions. + * + * Note Synchronization level: Thread safe + */ +class FlashIAP { +public: + FlashIAP(); + ~FlashIAP(); + + /** Initialize a flash IAP device + * + * Should be called once per lifetime of the object. + * @return 0 on success or a negative error code on failure + */ + int init(); + + /** Deinitialize a flash IAP device + * + * @return 0 on success or a negative error code on failure + */ + int deinit(); + + /** Read data from a flash device. + * + * This method invokes memcpy - reads number of bytes from the address + * + * @param buffer Buffer to write to + * @param addr Flash address to begin reading from + * @param size Size to read in bytes + * @return 0 on success, negative error code on failure + */ + int read(void *buffer, uint32_t addr, uint32_t size); + + /** Write data at defined flash address + * + * A write is equivalent to an erase followed by a program. + * + * @param buffer Buffer of data to be written + * @param addr Address of a page to begin writing to + * @param size Size to write in bytes, must be a multiple of program and sector sizes + * @return 0 on success, negative error code on failure + */ + int write(const void *buffer, uint32_t addr, uint32_t size); + + /** Program data to pages + * + * The sectors must have been erased prior to being programmed + * + * @param buffer Buffer of data to be written + * @param addr Address of a page to begin writing to, must be a multiple of program and sector sizes + * @param size Size to write in bytes, must be a multiple of program and sector sizes + * @return 0 on success, negative error code on failure + */ + int program(const void *buffer, uint32_t addr, uint32_t size); + + /** Erase sectors + * + * The state of an erased sector is undefined until it has been programmed + * + * @param addr Address of a sector to begin erasing, must be a multiple of the sector size + * @param size Size to erase in bytes, must be a multiple of the sector size + * @return 0 on success, negative error code on failure + */ + int erase(uint32_t addr, uint32_t size); + + /** Get the sector size at the defined address + * + * Sector size might differ at address ranges. + * An example <0-0x1000, sector size=1024; 0x10000-0x20000, size=2048> + * + * @return Size of a sector in bytes + */ + uint32_t get_sector_size(uint32_t addr) const; + + /** Get the total size of the underlying device + * + * @return Size of the underlying device in bytes + */ + uint32_t get_flash_size() const; + + /** Get the program page size + * + * @return Size of a program page in bytes + */ + uint32_t get_page_size() const; + +private: + + /** Check if address and size are aligned to a sector + * + * @param number Number that should be aligned + * @param alignment Defined alignment for a number to be checked + * @return true on success, false on failure + */ + bool is_aligned_to_sector(uint32_t addr, uint32_t size); + + flash_t _flash; + static SingletonPtr _mutex; +}; + +} /* namespace mbed */ + +#endif /* DEVICE_FLASH */ + +#endif /* MBED_FLASHIAP_H */ + +/** @}*/ diff --git a/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c b/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c index 3ed36b747cc..4c871d5f012 100644 --- a/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c +++ b/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c @@ -54,7 +54,7 @@ static uint32_t jump_to_flash_algo[] = { 0xBD3046A9 }; -static uint32_t get_sector_index(flash_t *obj, uint32_t address) +static uint32_t get_sector_index(const flash_t *obj, uint32_t address) { // check where address belongs to size_t sector_index = 0; @@ -110,13 +110,6 @@ int32_t flash_free(flash_t *obj) int32_t flash_erase_sector(flash_t *obj, uint32_t address) { - size_t sector_index = get_sector_index(obj, address); - - // erase sector boundary - if ((address % obj->target_config->sectors[sector_index].size) != 0) { - return -1; - } - core_util_critical_section_enter(); flash_algo_init(obj, address, MBED_FLASH_ALGO_ERASE); @@ -137,22 +130,7 @@ int32_t flash_erase_sector(flash_t *obj, uint32_t address) int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size) -{ - // write size boundary - if ((address % obj->target_config->page_size) != 0) { - return -1; // TODO return types - } - // size multiple of sectors - if ((size < obj->target_config->page_size) || (size % obj->target_config->page_size != 0)) { - return -1; - } - - uint32_t sector_index = get_sector_index(obj, address); - // should not cross sector boundary - if (((address % obj->target_config->sectors[sector_index].size) + size) > obj->target_config->sectors[sector_index].size) { - return -1; - } - +{ core_util_critical_section_enter(); flash_algo_init(obj, address, MBED_FLASH_ALGO_PROGRAM); @@ -172,18 +150,18 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, } -uint32_t flash_get_sector_size(flash_t *obj, uint32_t address) +uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address) { uint32_t sector_index = get_sector_index(obj, address); return obj->target_config->sectors[sector_index].size; } -uint32_t flash_get_page_size(flash_t *obj) +uint32_t flash_get_page_size(const flash_t *obj) { return obj->target_config->page_size; } -uint32_t flash_get_size(flash_t *obj) +uint32_t flash_get_size(const flash_t *obj) { return obj->target_config->flash_size; } diff --git a/hal/flash_api.h b/hal/flash_api.h index 50a4f7e22e2..34f8a242b55 100644 --- a/hal/flash_api.h +++ b/hal/flash_api.h @@ -54,8 +54,8 @@ int32_t flash_init(flash_t *obj); int32_t flash_free(flash_t *obj); /** Erase one sector starting at defined address - * - * The address should be at sector boundary + * + * The address should be at sector boundary. This function does not do any check for address alignments * @param obj The flash object * @param address The sector starting address * @return 0 for success, -1 for error @@ -64,7 +64,8 @@ int32_t flash_erase_sector(flash_t *obj, uint32_t address); /** Program one page starting at defined address * - * The page should be at page boundary, should not cross multiple sectors + * The page should be at page boundary, should not cross multiple sectors. + * This function does not do any check for address alignments or if size is aligned to a page size. * @param obj The flash object * @param address The sector starting address * @param data The data buffer to be programmed @@ -79,7 +80,7 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, * @param address The sector starting address * @return The size of a sector */ -uint32_t flash_get_sector_size(flash_t *obj, uint32_t address); +uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address); /** Get page size * @@ -87,14 +88,14 @@ uint32_t flash_get_sector_size(flash_t *obj, uint32_t address); * @param address The page starting address * @return The size of a page */ -uint32_t flash_get_page_size(flash_t *obj); +uint32_t flash_get_page_size(const flash_t *obj); /** Get flash size * * @param obj The flash objects * @return The size of the flash available */ -uint32_t flash_get_size(flash_t *obj); +uint32_t flash_get_size(const flash_t *obj); /**@}*/ diff --git a/mbed.h b/mbed.h index 0e71670a0d0..84c7a263c31 100644 --- a/mbed.h +++ b/mbed.h @@ -80,6 +80,7 @@ #include "drivers/Ethernet.h" #include "drivers/CAN.h" #include "drivers/RawSerial.h" +#include "drivers/FlashIAP.h" // mbed Internal components #include "drivers/Timer.h" From 6bc38f9f1a4f7384165464612c193a8a90d527d5 Mon Sep 17 00:00:00 2001 From: 0xc0170 Date: Mon, 6 Feb 2017 16:48:49 +0100 Subject: [PATCH 09/10] tests: add FlashIAP functional test It currently tests functionality provided by flash IAP API like write/read/program/erase and getters. --- TESTS/mbed_drivers/flashiap/main.cpp | 201 +++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 TESTS/mbed_drivers/flashiap/main.cpp diff --git a/TESTS/mbed_drivers/flashiap/main.cpp b/TESTS/mbed_drivers/flashiap/main.cpp new file mode 100644 index 00000000000..6c94d1be97f --- /dev/null +++ b/TESTS/mbed_drivers/flashiap/main.cpp @@ -0,0 +1,201 @@ + +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * 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. + */ + +#if !DEVICE_FLASH + #error [NOT_SUPPORTED] Flash API not supported for this target +#endif + +#include "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" + +#include "mbed.h" + +using namespace utest::v1; + +void flashiap_init_test() +{ + FlashIAP flash_device; + uint32_t ret = flash_device.init(); + TEST_ASSERT_EQUAL_INT32(ret, 0); + ret = flash_device.deinit(); + TEST_ASSERT_EQUAL_INT32(ret, 0); +} + +void flashiap_program_test() +{ + FlashIAP flash_device; + uint32_t ret = flash_device.init(); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + // get the last sector size (flash size - 1) + uint32_t sector_size = flash_device.get_sector_size(flash_device.get_flash_size() - 1UL); + TEST_ASSERT_NOT_EQUAL(sector_size, 0); + const uint8_t test_value = 0xCE; + uint8_t *data = new uint8_t[sector_size]; + for (uint32_t i = 0; i < sector_size; i++) { + data[i] = test_value; + } + + // the one before the last page in the system + uint32_t address = (flash_device.get_flash_size()) - (sector_size); + TEST_ASSERT_TRUE(address != 0UL); + ret = flash_device.erase(address, sector_size); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + ret = flash_device.program(data, address, sector_size); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + uint8_t *data_flashed = new uint8_t[sector_size]; + ret = flash_device.read(data_flashed, address, sector_size); + TEST_ASSERT_EQUAL_INT32(ret, 0); + TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, sector_size); + delete[] data; + delete[] data_flashed; + + ret = flash_device.deinit(); + TEST_ASSERT_EQUAL_INT32(ret, 0); +} + +void flashiap_write_test() +{ + FlashIAP flash_device; + uint32_t ret = flash_device.init(); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + // get the last sector size + uint32_t sector_size = flash_device.get_sector_size(flash_device.get_flash_size() - 1UL); + TEST_ASSERT_NOT_EQUAL(sector_size, 0); + const uint8_t test_value = 0xCE; + uint8_t *data = new uint8_t[sector_size]; + for (uint32_t i = 0; i < sector_size; i++) { + data[i] = test_value; + } + + // the one before the last page in the system + uint32_t address = (flash_device.get_flash_size()) - (sector_size); + TEST_ASSERT_TRUE(address != 0UL); + ret = flash_device.write(data, address, sector_size); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + uint8_t *data_flashed = new uint8_t[sector_size]; + ret = flash_device.read(data_flashed, address, sector_size); + TEST_ASSERT_EQUAL_INT32(ret, 0); + TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, sector_size); + delete[] data; + delete[] data_flashed; + + ret = flash_device.deinit(); + TEST_ASSERT_EQUAL_INT32(ret, 0); +} + +void flashiap_program_error_test() +{ + FlashIAP flash_device; + uint32_t ret = flash_device.init(); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + // get the last sector size (flash size - 1) + uint32_t sector_size = flash_device.get_sector_size(flash_device.get_flash_size() - 1UL); + TEST_ASSERT_NOT_EQUAL(sector_size, 0); + const uint8_t test_value = 0xCE; + uint8_t *data = new uint8_t[sector_size]; + for (uint32_t i = 0; i < sector_size; i++) { + data[i] = test_value; + } + + // the one before the last page in the system + uint32_t address = (flash_device.get_flash_size()) - (sector_size); + TEST_ASSERT_TRUE(address != 0UL); + + // unaligned address + address += 1; + ret = flash_device.erase(address, sector_size); + TEST_ASSERT_EQUAL_INT32(ret, -1); + ret = flash_device.program(data, address, sector_size); + TEST_ASSERT_EQUAL_INT32(ret, -1); + + // unaligned sector size + sector_size += 1; + ret = flash_device.program(data, address, sector_size); + TEST_ASSERT_EQUAL_INT32(ret, -1); + + delete[] data; + + ret = flash_device.deinit(); + TEST_ASSERT_EQUAL_INT32(ret, 0); +} + +void flashiap_write_error_test() +{ + FlashIAP flash_device; + uint32_t ret = flash_device.init(); + TEST_ASSERT_EQUAL_INT32(ret, 0); + + // get the last sector size + uint32_t sector_size = flash_device.get_sector_size(flash_device.get_flash_size() - 1UL); + TEST_ASSERT_NOT_EQUAL(sector_size, 0); + const uint8_t test_value = 0xCE; + uint8_t *data = new uint8_t[sector_size]; + for (uint32_t i = 0; i < sector_size; i++) { + data[i] = test_value; + } + + // the one before the last page in the system + uint32_t address = (flash_device.get_flash_size()) - (sector_size); + TEST_ASSERT_TRUE(address != 0UL); + + // unaligned address + address += 1; + ret = flash_device.write(data, address, sector_size); + TEST_ASSERT_EQUAL_INT32(ret, -1); + + // unaligned sector size + address -= 1; + sector_size += 1; + ret = flash_device.write(data, address, sector_size); + TEST_ASSERT_EQUAL_INT32(ret, -1); + + delete[] data; + + ret = flash_device.deinit(); + TEST_ASSERT_EQUAL_INT32(ret, 0); +} + +utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) { + greentea_case_failure_abort_handler(source, reason); + return STATUS_CONTINUE; +} + +Case cases[] = { + Case("FlashIAP - init", flashiap_init_test, greentea_failure_handler), + Case("FlashIAP - program", flashiap_program_test, greentea_failure_handler), + Case("FlashIAP - write", flashiap_write_test, greentea_failure_handler), + Case("FlashIAP - program errors", flashiap_program_error_test, greentea_failure_handler), + Case("FlashIAP - write errors", flashiap_write_error_test, greentea_failure_handler), +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(20, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() { + Harness::run(specification); +} From 08730c1f34a7ac76c86a395a3d0166b42405f75c Mon Sep 17 00:00:00 2001 From: 0xc0170 Date: Thu, 9 Feb 2017 17:51:59 +0100 Subject: [PATCH 10/10] flash: add get start flash region Plus fixes in the tests to get properly end of flash (start + size) --- TESTS/mbed_drivers/flashiap/main.cpp | 16 ++++++++-------- TESTS/mbed_hal/flash/functional_tests/main.cpp | 8 ++++---- drivers/FlashIAP.cpp | 5 +++++ drivers/FlashIAP.h | 10 ++++++++-- hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c | 5 +++++ hal/flash_api.h | 11 +++++++++-- 6 files changed, 39 insertions(+), 16 deletions(-) diff --git a/TESTS/mbed_drivers/flashiap/main.cpp b/TESTS/mbed_drivers/flashiap/main.cpp index 6c94d1be97f..19c94bedd76 100644 --- a/TESTS/mbed_drivers/flashiap/main.cpp +++ b/TESTS/mbed_drivers/flashiap/main.cpp @@ -43,7 +43,7 @@ void flashiap_program_test() TEST_ASSERT_EQUAL_INT32(ret, 0); // get the last sector size (flash size - 1) - uint32_t sector_size = flash_device.get_sector_size(flash_device.get_flash_size() - 1UL); + uint32_t sector_size = flash_device.get_sector_size(flash_device.get_flash_start() + flash_device.get_flash_size() - 1UL); TEST_ASSERT_NOT_EQUAL(sector_size, 0); const uint8_t test_value = 0xCE; uint8_t *data = new uint8_t[sector_size]; @@ -52,7 +52,7 @@ void flashiap_program_test() } // the one before the last page in the system - uint32_t address = (flash_device.get_flash_size()) - (sector_size); + uint32_t address = (flash_device.get_flash_start() + flash_device.get_flash_size()) - (sector_size); TEST_ASSERT_TRUE(address != 0UL); ret = flash_device.erase(address, sector_size); TEST_ASSERT_EQUAL_INT32(ret, 0); @@ -78,7 +78,7 @@ void flashiap_write_test() TEST_ASSERT_EQUAL_INT32(ret, 0); // get the last sector size - uint32_t sector_size = flash_device.get_sector_size(flash_device.get_flash_size() - 1UL); + uint32_t sector_size = flash_device.get_sector_size(flash_device.get_flash_start() + flash_device.get_flash_size() - 1UL); TEST_ASSERT_NOT_EQUAL(sector_size, 0); const uint8_t test_value = 0xCE; uint8_t *data = new uint8_t[sector_size]; @@ -87,7 +87,7 @@ void flashiap_write_test() } // the one before the last page in the system - uint32_t address = (flash_device.get_flash_size()) - (sector_size); + uint32_t address = (flash_device.get_flash_start() + flash_device.get_flash_size()) - (sector_size); TEST_ASSERT_TRUE(address != 0UL); ret = flash_device.write(data, address, sector_size); TEST_ASSERT_EQUAL_INT32(ret, 0); @@ -110,7 +110,7 @@ void flashiap_program_error_test() TEST_ASSERT_EQUAL_INT32(ret, 0); // get the last sector size (flash size - 1) - uint32_t sector_size = flash_device.get_sector_size(flash_device.get_flash_size() - 1UL); + uint32_t sector_size = flash_device.get_sector_size(flash_device.get_flash_start() + flash_device.get_flash_size() - 1UL); TEST_ASSERT_NOT_EQUAL(sector_size, 0); const uint8_t test_value = 0xCE; uint8_t *data = new uint8_t[sector_size]; @@ -119,7 +119,7 @@ void flashiap_program_error_test() } // the one before the last page in the system - uint32_t address = (flash_device.get_flash_size()) - (sector_size); + uint32_t address = (flash_device.get_flash_start() + flash_device.get_flash_size()) - (sector_size); TEST_ASSERT_TRUE(address != 0UL); // unaligned address @@ -147,7 +147,7 @@ void flashiap_write_error_test() TEST_ASSERT_EQUAL_INT32(ret, 0); // get the last sector size - uint32_t sector_size = flash_device.get_sector_size(flash_device.get_flash_size() - 1UL); + uint32_t sector_size = flash_device.get_sector_size(flash_device.get_flash_start() + flash_device.get_flash_size() - 1UL); TEST_ASSERT_NOT_EQUAL(sector_size, 0); const uint8_t test_value = 0xCE; uint8_t *data = new uint8_t[sector_size]; @@ -156,7 +156,7 @@ void flashiap_write_error_test() } // the one before the last page in the system - uint32_t address = (flash_device.get_flash_size()) - (sector_size); + uint32_t address = (flash_device.get_flash_start() + flash_device.get_flash_size()) - (sector_size); TEST_ASSERT_TRUE(address != 0UL); // unaligned address diff --git a/TESTS/mbed_hal/flash/functional_tests/main.cpp b/TESTS/mbed_hal/flash/functional_tests/main.cpp index 4e835a12f3d..320ba1255fc 100644 --- a/TESTS/mbed_hal/flash/functional_tests/main.cpp +++ b/TESTS/mbed_hal/flash/functional_tests/main.cpp @@ -60,7 +60,7 @@ void flash_program_page_test() } // the one before the last page in the system - uint32_t address = (test_flash.target_config->flash_start + test_flash.target_config->flash_size) - (2*test_size); + uint32_t address = flash_get_start_address(&test_flash) + flash_get_size(&test_flash) - (2*test_size); // sector size might not be same as page size uint32_t erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address)); @@ -97,7 +97,7 @@ void flash_erase_sector_test() TEST_ASSERT_EQUAL_INT32(ret, 0); uint32_t sector_size = 0x1000; - uint32_t address = (test_flash.target_config->flash_start + test_flash.target_config->flash_size) - (4*sector_size); + uint32_t address = flash_get_start_address(&test_flash) + flash_get_size(&test_flash) - (4*sector_size); // sector size might not be same as page size uint32_t erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address)); ret = flash_erase_sector(&test_flash, erase_sector_boundary); @@ -115,7 +115,7 @@ void flash_erase_sector_error_test() // most common sector size to get an sector address uint32_t sector_size = 0x1000; - uint32_t address = (test_flash.target_config->flash_start + test_flash.target_config->flash_size) - (4*sector_size); + uint32_t address = flash_get_start_address(&test_flash) + flash_get_size(&test_flash) - (4*sector_size); uint32_t erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address)); // unaligned address @@ -136,7 +136,7 @@ void flash_program_page_error_test() uint32_t test_size = flash_get_page_size(&test_flash); // the one before the last page in the system - uint32_t address = (test_flash.target_config->flash_start + test_flash.target_config->flash_size) - (2*test_size); + uint32_t address = flash_get_start_address(&test_flash) + flash_get_size(&test_flash) - (2*test_size); // sector size might not be same as page size uint32_t erase_sector_boundary = ALIGN_DOWN(address, flash_get_sector_size(&test_flash, address)); diff --git a/drivers/FlashIAP.cpp b/drivers/FlashIAP.cpp index 664ec44df38..c9b73f042ed 100644 --- a/drivers/FlashIAP.cpp +++ b/drivers/FlashIAP.cpp @@ -165,6 +165,11 @@ uint32_t FlashIAP::get_sector_size(uint32_t addr) const return flash_get_sector_size(&_flash, addr); } +uint32_t FlashIAP::get_flash_start() const +{ + return flash_get_start_address(&_flash); +} + uint32_t FlashIAP::get_flash_size() const { return flash_get_size(&_flash); diff --git a/drivers/FlashIAP.h b/drivers/FlashIAP.h index 1f308c83f01..18c856eff2c 100644 --- a/drivers/FlashIAP.h +++ b/drivers/FlashIAP.h @@ -107,9 +107,15 @@ class FlashIAP { */ uint32_t get_sector_size(uint32_t addr) const; - /** Get the total size of the underlying device + /** Get the flash start address * - * @return Size of the underlying device in bytes + * @return Flash start address + */ + uint32_t get_flash_start() const; + + /** Get the flash size + * + * @return Flash size */ uint32_t get_flash_size() const; diff --git a/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c b/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c index 4c871d5f012..b3dc03bdc7c 100644 --- a/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c +++ b/hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c @@ -161,6 +161,11 @@ uint32_t flash_get_page_size(const flash_t *obj) return obj->target_config->page_size; } +uint32_t flash_get_start_address(const flash_t *obj) +{ + return obj->target_config->flash_start; +} + uint32_t flash_get_size(const flash_t *obj) { return obj->target_config->flash_size; diff --git a/hal/flash_api.h b/hal/flash_api.h index 34f8a242b55..cc1d5bb0474 100644 --- a/hal/flash_api.h +++ b/hal/flash_api.h @@ -90,10 +90,17 @@ uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address); */ uint32_t flash_get_page_size(const flash_t *obj); -/** Get flash size +/** Get start address for the flash region * * @param obj The flash objects - * @return The size of the flash available + * @return The start address for the flash region + */ +uint32_t flash_get_start_address(const flash_t *obj); + +/** Get the flash region size + * + * @param obj The flash objects + * @return The flash region size */ uint32_t flash_get_size(const flash_t *obj);