Mbed OS and Pelion Device Management example over WIFI for DISCO_L475VG_IOT01 board

Dependencies:   X_NUCLEO_COMMON ST_INTERFACES

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 on the following platforms:

DISCO_L475E_IOT01A

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

Example functionality

This example showcases the following device functionality:

  • Read onboard temperature and humidity sensors, 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.
  • Uses all onboard sensors and reports them as Pelion LWM2M resources.

/media/uploads/screamer/pelion_st_humidity_reading.png?v=2

Use this example with Mbed CLI

1. Import the application into your desktop:

mbed import https://os.mbed.com/teams/ST/code/pelion-example-disco-iot01

cd pelion-example-disco-iot01

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 DISCO_L475VG_IOT01A

(supported toolchains : GCC_ARM / ARM / IAR)

5. You can connect on a virtual terminal/COM port to the platform using:

mbed sterm -b 115200

This should give you an output similar to:

[BOOT] Mbed Bootloader
[BOOT] ARM: 00000000000000000000
[BOOT] OEM: 00000000000000000000
[BOOT] Layout: 0 80096F4
[BOOT] Active firmware integrity check:
[BOOT] SHA256: 0660E360D432225D5251461998FD8617B017098C5F1F90D5FB607BF8C27ED530
[BOOT] Version: 1553615309
[BOOT] Slot 0 is empty
[BOOT] Active firmware up-to-date
[BOOT] Application's start address: 0x8010400
[BOOT] Application's jump address: 0x8011041
[BOOT] Application's stack address: 0x20018000
[BOOT] Forwarding to application...

Starting Simple Pelion Device Management Client example
You can hold the user button during boot to format the storage and change the device identity.

Sensors configuration:
Invalid new address!
HTS221  humidity & temperature    = 0xBC
LPS22HB pressure & temperature    = 0xB1
LIS3MDL magnetometer              = 0x3D
LSM6DSL accelerometer & gyroscope = 0x6A

Connecting to the network using Wifi...
Connected to the network successfully. IP address: 192.168.1.3
Initializing Pelion Device Management Client...
Initialized Pelion Client. Registering...
Registered to Pelion Device Management. Endpoint Name: 0169********************001002d5

ADC temp:     23.0037 C,  vref:      0.3661 V
HTS221 temp:   28.700 C,  humidity:   31.90 %
LPS22HB temp:  29.600 C,  pressure: 1032.01 mbar
LIS3MDL mag:    0.217 x,  -0.284 y,  -0.053 z [gauss]
LSM6DSL acc:    0.005 x,  -0.014 y,   1.029 z [g]
LSM6DSL gyro:   0.910 x,  -0.910 y,   1.120 z [dps]
VL53L0X dist:    1855 mm
Committer:
screamer
Date:
Mon Mar 11 11:28:07 2019 +0000
Revision:
31:da14aa77f977
Parent:
10:b27c962b3c3f
Revert back to Mbed OS 5.10.4 due to issues to fit in RAM2 on GCC_ARM

Who changed what in which revision?

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