Mbed OS Device Management example for various ST boards.

DEPRECATED

This example application is not maintained and not recommended. It uses an old version of Mbed OS, Pelion DM and Arm toolchain. It doesn't work with Mbed Studio.

Please use: https://os.mbed.com/teams/mbed-os-examples/code/mbed-os-example-pelion/

This example is known to work great on the following platforms:

  • DISCO_L475E_IOT01A - onboard WiFI and onboard QSPI flash. Board specific example using onboard sensors is available here.
  • DISCO_F413H - onboard WiFI and onboard QSPI flash.
  • DISCO_F469NI - WizFi310 WiFI shield and onboard QSPI flash (see WiFi shield instructions).
  • DISCO_F746NG - onboard Ethernet and using onboard QSPI flash.
  • DISCO_F769NI - onboard Ethernet and using onboard QSPI flash.
  • DISCO_L496AG - WizFi310 WiFI shield and onboard QSPI flash (see WiFi shield instructions).
  • NUCLEO_F207ZG - onboard Ethernet and wired SD card (SD card wiring instructions).
  • NUCLEO_F412ZG - WizFi310 WiFI shield and SD card shield (see WiFi shield instructions).
  • NUCLEO_F429ZI - onboard Ethernet and wired SD card (SD card wiring instructions).
  • NUCLEO_F746ZG - onboard Ethernet and wired SD card (SD card wiring instructions).
  • NUCLEO_F767ZI - onboard Ethernet and wired SD card (SD card wiring instructions).
  • NUCLEO_L476RG - WizFi310 WiFI shield and SD card shield (see WiFi shield instructions).
  • NUCLEO_L496ZG - WizFi310 WiFI shield and SD card shield (see WiFi shield instructions).
  • NUCLEO_L4R5ZI - WizFi310 WiFI shield and SD card shield (see WiFi shield instructions).

Follow the Quick-Start instructions: https://cloud.mbed.com/quick-start

DISCO_L475E_IOT01A DISCO_F413H DISCO_F746NG NUCLEO_F429ZI, NUCLEO_F767ZI, NUCLEO_F746ZG,NUCLEO_F207ZG

Example functionality

This example showcases the following device functionality:

  • Read ADC temperature and ADC vref, and report them as Pelion LWM2M resources (see image below).
  • On user button click, increment Pelion LWM2M button resource.
  • Allow the user to change the state of the board LED from Pelion LWM2M led_state resource and PUT request.

/media/uploads/screamer/pelion_st_adc_reading.png

SD card wiring

The ST Nucleo family of boards don't have storage onboard and therefore you will need an SD card. A limitation on ST Nucleo 144 boards is that there's a conflict between Ethernet and SPI pins on Arduino D11. Due to this, the SD card must be wired to different SPI bus that doesn't conflict with other functionality. The image below provide instructions on how to wire an SD card to a non-conflicting SPI instance.

/media/uploads/screamer/st_nucleo_144_sd.jpeg?v=4

If you are not a first-time Pelion Device Management user your device's SD card may already have connect and update certificates on it. If this is the case, remove and manually format your micro SD card, flash the binary to the device and then re-insert your micro SD card.

WiFi shield setup/wiring

Some ST Nucleo and Discovery boards don't have IP connectivity option, but bundled with a WiFi shield, they can take benefit of full device management capabilities. See links to reference images below on how to wire WizFI310 WiFi shield and/or SD card shield:

Use this example with Mbed CLI

1. Import the application into your desktop:

mbed import /teams/ST/code/pelion-example-common

cd pelion-example-common

2. Install the CLOUD_SDK_API_KEY

mbed config -G CLOUD_SDK_API_KEY <PELION_DM_API_KEY>

For instructions on how to generate your API key, please see the documentation.

3. Initialize firmware credentials (done once per repository). You can use the following command:

mbed dm init -d "<your company name in Pelion DM>" --model-name "<product model identifier>" -q --force

If above command do not work for your Mbed CLI, please consider upgrading Mbed CLI to version 1.8.x or above.

4. Compile and program:

mbed compile -t <toolchain> -m <TARGET_BOARD>

(supported toolchains : GCC_ARM / ARM / IAR)

Committer:
screamer
Date:
Mon Dec 10 20:14:17 2018 +0000
Revision:
0:ea30ba97a865
Initial revision

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 0:ea30ba97a865 1 /* mbed Microcontroller Library
screamer 0:ea30ba97a865 2 * Copyright (c) 2018 ARM Limited
screamer 0:ea30ba97a865 3 *
screamer 0:ea30ba97a865 4 * Licensed under the Apache License, Version 2.0 (the "License");
screamer 0:ea30ba97a865 5 * you may not use this file except in compliance with the License.
screamer 0:ea30ba97a865 6 * You may obtain a copy of the License at
screamer 0:ea30ba97a865 7 *
screamer 0:ea30ba97a865 8 * http://www.apache.org/licenses/LICENSE-2.0
screamer 0:ea30ba97a865 9 *
screamer 0:ea30ba97a865 10 * Unless required by applicable law or agreed to in writing, software
screamer 0:ea30ba97a865 11 * distributed under the License is distributed on an "AS IS" BASIS,
screamer 0:ea30ba97a865 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
screamer 0:ea30ba97a865 13 * See the License for the specific language governing permissions and
screamer 0:ea30ba97a865 14 * limitations under the License.
screamer 0:ea30ba97a865 15 */
screamer 0:ea30ba97a865 16 #include "greentea-client/test_env.h"
screamer 0:ea30ba97a865 17 #include "unity.h"
screamer 0:ea30ba97a865 18 #include "utest.h"
screamer 0:ea30ba97a865 19 #include "QSPIFBlockDevice.h"
screamer 0:ea30ba97a865 20 #include "mbed_trace.h"
screamer 0:ea30ba97a865 21 #include "rtos/Thread.h"
screamer 0:ea30ba97a865 22 #include <stdlib.h>
screamer 0:ea30ba97a865 23
screamer 0:ea30ba97a865 24 using namespace utest::v1;
screamer 0:ea30ba97a865 25
screamer 0:ea30ba97a865 26 #define TEST_BLOCK_COUNT 10
screamer 0:ea30ba97a865 27 #define TEST_ERROR_MASK 16
screamer 0:ea30ba97a865 28 #define QSPIF_TEST_NUM_OF_THREADS 5
screamer 0:ea30ba97a865 29
screamer 0:ea30ba97a865 30 const struct {
screamer 0:ea30ba97a865 31 const char *name;
screamer 0:ea30ba97a865 32 bd_size_t (BlockDevice::*method)() const;
screamer 0:ea30ba97a865 33 } ATTRS[] = {
screamer 0:ea30ba97a865 34 {"read size", &BlockDevice::get_read_size},
screamer 0:ea30ba97a865 35 {"program size", &BlockDevice::get_program_size},
screamer 0:ea30ba97a865 36 {"erase size", &BlockDevice::get_erase_size},
screamer 0:ea30ba97a865 37 {"total size", &BlockDevice::size},
screamer 0:ea30ba97a865 38 };
screamer 0:ea30ba97a865 39
screamer 0:ea30ba97a865 40 static SingletonPtr<PlatformMutex> _mutex;
screamer 0:ea30ba97a865 41
screamer 0:ea30ba97a865 42
screamer 0:ea30ba97a865 43 // Mutex is protecting rand() per srand for buffer writing and verification.
screamer 0:ea30ba97a865 44 // Mutex is also protecting printouts for clear logs.
screamer 0:ea30ba97a865 45 // Mutex is NOT protecting Block Device actions: erase/program/read - which is the purpose of the multithreaded test!
screamer 0:ea30ba97a865 46 void basic_erase_program_read_test(QSPIFBlockDevice &blockD, bd_size_t block_size, uint8_t *write_block,
screamer 0:ea30ba97a865 47 uint8_t *read_block, unsigned addrwidth)
screamer 0:ea30ba97a865 48 {
screamer 0:ea30ba97a865 49 int err = 0;
screamer 0:ea30ba97a865 50 _mutex->lock();
screamer 0:ea30ba97a865 51 // Find a random block
screamer 0:ea30ba97a865 52 bd_addr_t block = (rand() * block_size) % blockD.size();
screamer 0:ea30ba97a865 53
screamer 0:ea30ba97a865 54 // Use next random number as temporary seed to keep
screamer 0:ea30ba97a865 55 // the address progressing in the pseudorandom sequence
screamer 0:ea30ba97a865 56 unsigned seed = rand();
screamer 0:ea30ba97a865 57
screamer 0:ea30ba97a865 58 // Fill with random sequence
screamer 0:ea30ba97a865 59 srand(seed);
screamer 0:ea30ba97a865 60 for (bd_size_t i_ind = 0; i_ind < block_size; i_ind++) {
screamer 0:ea30ba97a865 61 write_block[i_ind] = 0xff & rand();
screamer 0:ea30ba97a865 62 }
screamer 0:ea30ba97a865 63 // Write, sync, and read the block
screamer 0:ea30ba97a865 64 utest_printf("\ntest %0*llx:%llu...", addrwidth, block, block_size);
screamer 0:ea30ba97a865 65 _mutex->unlock();
screamer 0:ea30ba97a865 66
screamer 0:ea30ba97a865 67 err = blockD.erase(block, block_size);
screamer 0:ea30ba97a865 68 TEST_ASSERT_EQUAL(0, err);
screamer 0:ea30ba97a865 69
screamer 0:ea30ba97a865 70 err = blockD.program(write_block, block, block_size);
screamer 0:ea30ba97a865 71 TEST_ASSERT_EQUAL(0, err);
screamer 0:ea30ba97a865 72
screamer 0:ea30ba97a865 73 err = blockD.read(read_block, block, block_size);
screamer 0:ea30ba97a865 74 TEST_ASSERT_EQUAL(0, err);
screamer 0:ea30ba97a865 75
screamer 0:ea30ba97a865 76 _mutex->lock();
screamer 0:ea30ba97a865 77 // Check that the data was unmodified
screamer 0:ea30ba97a865 78 srand(seed);
screamer 0:ea30ba97a865 79 int val_rand;
screamer 0:ea30ba97a865 80 for (bd_size_t i_ind = 0; i_ind < block_size; i_ind++) {
screamer 0:ea30ba97a865 81 val_rand = rand();
screamer 0:ea30ba97a865 82 if ((0xff & val_rand) != read_block[i_ind]) {
screamer 0:ea30ba97a865 83 utest_printf("\n Assert Failed Buf Read - block:size: %llx:%llu \n", block, block_size);
screamer 0:ea30ba97a865 84 utest_printf("\n pos: %llu, exp: %02x, act: %02x, wrt: %02x \n", i_ind, (0xff & val_rand), read_block[i_ind],
screamer 0:ea30ba97a865 85 write_block[i_ind]);
screamer 0:ea30ba97a865 86 }
screamer 0:ea30ba97a865 87 TEST_ASSERT_EQUAL(0xff & val_rand, read_block[i_ind]);
screamer 0:ea30ba97a865 88 }
screamer 0:ea30ba97a865 89 _mutex->unlock();
screamer 0:ea30ba97a865 90 }
screamer 0:ea30ba97a865 91
screamer 0:ea30ba97a865 92 void test_qspif_random_program_read_erase()
screamer 0:ea30ba97a865 93 {
screamer 0:ea30ba97a865 94 utest_printf("\nTest Random Program Read Erase Starts..\n");
screamer 0:ea30ba97a865 95
screamer 0:ea30ba97a865 96 QSPIFBlockDevice blockD(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3,
screamer 0:ea30ba97a865 97 QSPI_FLASH1_SCK, QSPI_FLASH1_CSN, QSPIF_POLARITY_MODE_0, MBED_CONF_QSPIF_QSPI_FREQ);
screamer 0:ea30ba97a865 98
screamer 0:ea30ba97a865 99 int err = blockD.init();
screamer 0:ea30ba97a865 100 TEST_ASSERT_EQUAL(0, err);
screamer 0:ea30ba97a865 101
screamer 0:ea30ba97a865 102 for (unsigned atr = 0; atr < sizeof(ATTRS) / sizeof(ATTRS[0]); atr++) {
screamer 0:ea30ba97a865 103 static const char *prefixes[] = {"", "k", "M", "G"};
screamer 0:ea30ba97a865 104 for (int i_ind = 3; i_ind >= 0; i_ind--) {
screamer 0:ea30ba97a865 105 bd_size_t size = (blockD.*ATTRS[atr].method)();
screamer 0:ea30ba97a865 106 if (size >= (1ULL << 10 * i_ind)) {
screamer 0:ea30ba97a865 107 utest_printf("%s: %llu%sbytes (%llubytes)\n",
screamer 0:ea30ba97a865 108 ATTRS[atr].name, size >> 10 * i_ind, prefixes[i_ind], size);
screamer 0:ea30ba97a865 109 break;
screamer 0:ea30ba97a865 110 }
screamer 0:ea30ba97a865 111 }
screamer 0:ea30ba97a865 112 }
screamer 0:ea30ba97a865 113
screamer 0:ea30ba97a865 114 bd_size_t block_size = blockD.get_erase_size();
screamer 0:ea30ba97a865 115 unsigned addrwidth = ceil(log(float(blockD.size() - 1)) / log(float(16))) + 1;
screamer 0:ea30ba97a865 116
screamer 0:ea30ba97a865 117 uint8_t *write_block = new (std::nothrow) uint8_t[block_size];
screamer 0:ea30ba97a865 118 uint8_t *read_block = new (std::nothrow) uint8_t[block_size];
screamer 0:ea30ba97a865 119 if (!write_block || !read_block) {
screamer 0:ea30ba97a865 120 utest_printf("\n Not enough memory for test");
screamer 0:ea30ba97a865 121 goto end;
screamer 0:ea30ba97a865 122 }
screamer 0:ea30ba97a865 123
screamer 0:ea30ba97a865 124 for (int b = 0; b < TEST_BLOCK_COUNT; b++) {
screamer 0:ea30ba97a865 125 basic_erase_program_read_test(blockD, block_size, write_block, read_block, addrwidth);
screamer 0:ea30ba97a865 126 }
screamer 0:ea30ba97a865 127
screamer 0:ea30ba97a865 128 err = blockD.deinit();
screamer 0:ea30ba97a865 129 TEST_ASSERT_EQUAL(0, err);
screamer 0:ea30ba97a865 130
screamer 0:ea30ba97a865 131 end:
screamer 0:ea30ba97a865 132 delete[] write_block;
screamer 0:ea30ba97a865 133 delete[] read_block;
screamer 0:ea30ba97a865 134 }
screamer 0:ea30ba97a865 135
screamer 0:ea30ba97a865 136 void test_qspif_unaligned_erase()
screamer 0:ea30ba97a865 137 {
screamer 0:ea30ba97a865 138
screamer 0:ea30ba97a865 139 utest_printf("\nTest Unaligned Erase Starts..\n");
screamer 0:ea30ba97a865 140
screamer 0:ea30ba97a865 141 QSPIFBlockDevice blockD(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3,
screamer 0:ea30ba97a865 142 QSPI_FLASH1_SCK, QSPI_FLASH1_CSN, QSPIF_POLARITY_MODE_0, MBED_CONF_QSPIF_QSPI_FREQ);
screamer 0:ea30ba97a865 143
screamer 0:ea30ba97a865 144 int err = blockD.init();
screamer 0:ea30ba97a865 145 TEST_ASSERT_EQUAL(0, err);
screamer 0:ea30ba97a865 146
screamer 0:ea30ba97a865 147 for (unsigned atr = 0; atr < sizeof(ATTRS) / sizeof(ATTRS[0]); atr++) {
screamer 0:ea30ba97a865 148 static const char *prefixes[] = {"", "k", "M", "G"};
screamer 0:ea30ba97a865 149 for (int i_ind = 3; i_ind >= 0; i_ind--) {
screamer 0:ea30ba97a865 150 bd_size_t size = (blockD.*ATTRS[atr].method)();
screamer 0:ea30ba97a865 151 if (size >= (1ULL << 10 * i_ind)) {
screamer 0:ea30ba97a865 152 utest_printf("%s: %llu%sbytes (%llubytes)\n",
screamer 0:ea30ba97a865 153 ATTRS[atr].name, size >> 10 * i_ind, prefixes[i_ind], size);
screamer 0:ea30ba97a865 154 break;
screamer 0:ea30ba97a865 155 }
screamer 0:ea30ba97a865 156 }
screamer 0:ea30ba97a865 157 }
screamer 0:ea30ba97a865 158
screamer 0:ea30ba97a865 159 bd_addr_t addr = 0;
screamer 0:ea30ba97a865 160 bd_size_t sector_erase_size = blockD.get_erase_size(addr);
screamer 0:ea30ba97a865 161 unsigned addrwidth = ceil(log(float(blockD.size() - 1)) / log(float(16))) + 1;
screamer 0:ea30ba97a865 162
screamer 0:ea30ba97a865 163 utest_printf("\ntest %0*llx:%llu...", addrwidth, addr, sector_erase_size);
screamer 0:ea30ba97a865 164
screamer 0:ea30ba97a865 165 //unaligned start address
screamer 0:ea30ba97a865 166 addr += 1;
screamer 0:ea30ba97a865 167 err = blockD.erase(addr, sector_erase_size - 1);
screamer 0:ea30ba97a865 168 TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_INVALID_ERASE_PARAMS, err);
screamer 0:ea30ba97a865 169
screamer 0:ea30ba97a865 170 err = blockD.erase(addr, sector_erase_size);
screamer 0:ea30ba97a865 171 TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_INVALID_ERASE_PARAMS, err);
screamer 0:ea30ba97a865 172
screamer 0:ea30ba97a865 173 err = blockD.erase(addr, 1);
screamer 0:ea30ba97a865 174 TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_INVALID_ERASE_PARAMS, err);
screamer 0:ea30ba97a865 175
screamer 0:ea30ba97a865 176 //unaligned end address
screamer 0:ea30ba97a865 177 addr = 0;
screamer 0:ea30ba97a865 178
screamer 0:ea30ba97a865 179 err = blockD.erase(addr, 1);
screamer 0:ea30ba97a865 180 TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_INVALID_ERASE_PARAMS, err);
screamer 0:ea30ba97a865 181
screamer 0:ea30ba97a865 182 err = blockD.erase(addr, sector_erase_size + 1);
screamer 0:ea30ba97a865 183 TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_INVALID_ERASE_PARAMS, err);
screamer 0:ea30ba97a865 184
screamer 0:ea30ba97a865 185 //erase size exceeds flash device size
screamer 0:ea30ba97a865 186 err = blockD.erase(addr, blockD.size() + 1);
screamer 0:ea30ba97a865 187 TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_INVALID_ERASE_PARAMS, err);
screamer 0:ea30ba97a865 188
screamer 0:ea30ba97a865 189 // Valid erase
screamer 0:ea30ba97a865 190 err = blockD.erase(addr, sector_erase_size);
screamer 0:ea30ba97a865 191 TEST_ASSERT_EQUAL(QSPIF_BD_ERROR_OK, err);
screamer 0:ea30ba97a865 192
screamer 0:ea30ba97a865 193 err = blockD.deinit();
screamer 0:ea30ba97a865 194 TEST_ASSERT_EQUAL(0, err);
screamer 0:ea30ba97a865 195 }
screamer 0:ea30ba97a865 196
screamer 0:ea30ba97a865 197
screamer 0:ea30ba97a865 198
screamer 0:ea30ba97a865 199 static void test_qspif_thread_job(void *vBlockD/*, int thread_num*/)
screamer 0:ea30ba97a865 200 {
screamer 0:ea30ba97a865 201 static int thread_num = 0;
screamer 0:ea30ba97a865 202 thread_num++;
screamer 0:ea30ba97a865 203 QSPIFBlockDevice *blockD = (QSPIFBlockDevice *)vBlockD;
screamer 0:ea30ba97a865 204 utest_printf("\n Thread %d Started \n", thread_num);
screamer 0:ea30ba97a865 205
screamer 0:ea30ba97a865 206 bd_size_t block_size = blockD->get_erase_size();
screamer 0:ea30ba97a865 207 unsigned addrwidth = ceil(log(float(blockD->size() - 1)) / log(float(16))) + 1;
screamer 0:ea30ba97a865 208
screamer 0:ea30ba97a865 209 uint8_t *write_block = new (std::nothrow) uint8_t[block_size];
screamer 0:ea30ba97a865 210 uint8_t *read_block = new (std::nothrow) uint8_t[block_size];
screamer 0:ea30ba97a865 211 if (!write_block || !read_block) {
screamer 0:ea30ba97a865 212 utest_printf("\n Not enough memory for test");
screamer 0:ea30ba97a865 213 goto end;
screamer 0:ea30ba97a865 214 }
screamer 0:ea30ba97a865 215
screamer 0:ea30ba97a865 216 for (int b = 0; b < TEST_BLOCK_COUNT; b++) {
screamer 0:ea30ba97a865 217 basic_erase_program_read_test((*blockD), block_size, write_block, read_block, addrwidth);
screamer 0:ea30ba97a865 218 }
screamer 0:ea30ba97a865 219
screamer 0:ea30ba97a865 220 end:
screamer 0:ea30ba97a865 221 delete[] write_block;
screamer 0:ea30ba97a865 222 delete[] read_block;
screamer 0:ea30ba97a865 223 }
screamer 0:ea30ba97a865 224
screamer 0:ea30ba97a865 225 void test_qspif_multi_threads()
screamer 0:ea30ba97a865 226 {
screamer 0:ea30ba97a865 227
screamer 0:ea30ba97a865 228 utest_printf("\nTest Multi Threaded Erase/Program/Read Starts..\n");
screamer 0:ea30ba97a865 229
screamer 0:ea30ba97a865 230 QSPIFBlockDevice blockD(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3,
screamer 0:ea30ba97a865 231 QSPI_FLASH1_SCK, QSPI_FLASH1_CSN, QSPIF_POLARITY_MODE_0, MBED_CONF_QSPIF_QSPI_FREQ);
screamer 0:ea30ba97a865 232
screamer 0:ea30ba97a865 233 int err = blockD.init();
screamer 0:ea30ba97a865 234 TEST_ASSERT_EQUAL(0, err);
screamer 0:ea30ba97a865 235
screamer 0:ea30ba97a865 236 for (unsigned atr = 0; atr < sizeof(ATTRS) / sizeof(ATTRS[0]); atr++) {
screamer 0:ea30ba97a865 237 static const char *prefixes[] = {"", "k", "M", "G"};
screamer 0:ea30ba97a865 238 for (int i_ind = 3; i_ind >= 0; i_ind--) {
screamer 0:ea30ba97a865 239 bd_size_t size = (blockD.*ATTRS[atr].method)();
screamer 0:ea30ba97a865 240 if (size >= (1ULL << 10 * i_ind)) {
screamer 0:ea30ba97a865 241 utest_printf("%s: %llu%sbytes (%llubytes)\n",
screamer 0:ea30ba97a865 242 ATTRS[atr].name, size >> 10 * i_ind, prefixes[i_ind], size);
screamer 0:ea30ba97a865 243 break;
screamer 0:ea30ba97a865 244 }
screamer 0:ea30ba97a865 245 }
screamer 0:ea30ba97a865 246 }
screamer 0:ea30ba97a865 247
screamer 0:ea30ba97a865 248 rtos::Thread qspif_bd_thread[QSPIF_TEST_NUM_OF_THREADS];
screamer 0:ea30ba97a865 249
screamer 0:ea30ba97a865 250 osStatus threadStatus;
screamer 0:ea30ba97a865 251 int i_ind;
screamer 0:ea30ba97a865 252
screamer 0:ea30ba97a865 253 for (i_ind = 0; i_ind < QSPIF_TEST_NUM_OF_THREADS; i_ind++) {
screamer 0:ea30ba97a865 254 threadStatus = qspif_bd_thread[i_ind].start(test_qspif_thread_job, (void *)&blockD);
screamer 0:ea30ba97a865 255 if (threadStatus != 0) {
screamer 0:ea30ba97a865 256 utest_printf("\n Thread %d Start Failed!", i_ind + 1);
screamer 0:ea30ba97a865 257 }
screamer 0:ea30ba97a865 258 }
screamer 0:ea30ba97a865 259
screamer 0:ea30ba97a865 260 for (i_ind = 0; i_ind < QSPIF_TEST_NUM_OF_THREADS; i_ind++) {
screamer 0:ea30ba97a865 261 qspif_bd_thread[i_ind].join();
screamer 0:ea30ba97a865 262 }
screamer 0:ea30ba97a865 263
screamer 0:ea30ba97a865 264 err = blockD.deinit();
screamer 0:ea30ba97a865 265 TEST_ASSERT_EQUAL(0, err);
screamer 0:ea30ba97a865 266 }
screamer 0:ea30ba97a865 267
screamer 0:ea30ba97a865 268
screamer 0:ea30ba97a865 269
screamer 0:ea30ba97a865 270
screamer 0:ea30ba97a865 271 // Test setup
screamer 0:ea30ba97a865 272 utest::v1::status_t test_setup(const size_t number_of_cases)
screamer 0:ea30ba97a865 273 {
screamer 0:ea30ba97a865 274 GREENTEA_SETUP(60, "default_auto");
screamer 0:ea30ba97a865 275 return verbose_test_setup_handler(number_of_cases);
screamer 0:ea30ba97a865 276 }
screamer 0:ea30ba97a865 277
screamer 0:ea30ba97a865 278 Case cases[] = {
screamer 0:ea30ba97a865 279 Case("Testing unaligned erase blocks", test_qspif_unaligned_erase),
screamer 0:ea30ba97a865 280 Case("Testing read write random blocks", test_qspif_random_program_read_erase),
screamer 0:ea30ba97a865 281 Case("Testing Multi Threads Erase Program Read", test_qspif_multi_threads)
screamer 0:ea30ba97a865 282 };
screamer 0:ea30ba97a865 283
screamer 0:ea30ba97a865 284 Specification specification(test_setup, cases);
screamer 0:ea30ba97a865 285
screamer 0:ea30ba97a865 286
screamer 0:ea30ba97a865 287 int main()
screamer 0:ea30ba97a865 288 {
screamer 0:ea30ba97a865 289 mbed_trace_init();
screamer 0:ea30ba97a865 290 utest_printf("MAIN STARTS\n");
screamer 0:ea30ba97a865 291 return !Harness::run(specification);
screamer 0:ea30ba97a865 292 }