From ca2619b0e861bb9be620755feeb52ce865fbec6c Mon Sep 17 00:00:00 2001 From: Kimmo Vaisanen Date: Mon, 27 Aug 2018 12:37:29 +0300 Subject: [PATCH 01/26] Lora: Improve description of callback methods Users often use "show declaration" (or similar) in their IDE to see descriptions of callback methods so the function descriptions should be placed close to function declaration itself. --- features/lorawan/lorawan_types.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/features/lorawan/lorawan_types.h b/features/lorawan/lorawan_types.h index eef09f2d62..473e55ff20 100644 --- a/features/lorawan/lorawan_types.h +++ b/features/lorawan/lorawan_types.h @@ -242,10 +242,6 @@ typedef enum lora_events { * 'link_check_resp' callback. The result is thus transported to the application * via callback function provided. * - * As can be seen from declaration, mbed::Callback *link_check_resp) - * carries two parameters. First one is Demodulation Margin and the second one - * is number of gateways involved in the path to network server. - * * 'battery_level' callback goes in the down direction, i.e., it informs * the stack about the battery level by calling a function provided * by the upper layers. @@ -257,11 +253,16 @@ typedef struct { mbed::Callback events; /** - * Optional + * This callback is optional + * + * The first parameter to callback function is the demodulation margin, and the second + * parameter is the number of gateways that successfully received the last request. */ mbed::Callback link_check_resp; /** + * This callback is optional. If callback is not set, stack will return 255 to gateway. + * * Battery level return value must follow the specification * for DevStatusAns MAC command: * From f60ac631d36bf34c277acf439576aa3d60f99bcc Mon Sep 17 00:00:00 2001 From: Amanda Butler Date: Mon, 27 Aug 2018 09:51:27 -0500 Subject: [PATCH 02/26] Copy edit lorawan_types.h Copy edit for minor grammar nits and consistent tense across docs. --- features/lorawan/lorawan_types.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/lorawan/lorawan_types.h b/features/lorawan/lorawan_types.h index 473e55ff20..6f57c3c061 100644 --- a/features/lorawan/lorawan_types.h +++ b/features/lorawan/lorawan_types.h @@ -255,13 +255,13 @@ typedef struct { /** * This callback is optional * - * The first parameter to callback function is the demodulation margin, and the second + * The first parameter to the callback function is the demodulation margin, and the second * parameter is the number of gateways that successfully received the last request. */ mbed::Callback link_check_resp; /** - * This callback is optional. If callback is not set, stack will return 255 to gateway. + * This callback is optional. If the callback is not set, the stack returns 255 to gateway. * * Battery level return value must follow the specification * for DevStatusAns MAC command: From 37b34f661b5153d674500df527b905de1b85be75 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 3 Sep 2018 09:18:17 +0100 Subject: [PATCH 03/26] fix reading from eeprom added missing current op --- features/nfc/source/nfc/NFCEEPROM.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/features/nfc/source/nfc/NFCEEPROM.cpp b/features/nfc/source/nfc/NFCEEPROM.cpp index 704c53b4e1..518b652e4c 100644 --- a/features/nfc/source/nfc/NFCEEPROM.cpp +++ b/features/nfc/source/nfc/NFCEEPROM.cpp @@ -397,6 +397,7 @@ void NFCEEPROM::continue_read() _driver->read_bytes(_eeprom_address, ac_buffer_builder_write_position(buffer_builder), _ndef_buffer_read_sz - _eeprom_address); } else { // Done, close session + _current_op = nfc_eeprom_read_end_session; _operation_result = NFC_OK; _driver->end_session(); } From 8d31fc144e664ae3b9b1d5b9734a13911d640b80 Mon Sep 17 00:00:00 2001 From: Deepika Date: Tue, 21 Aug 2018 10:12:53 -0500 Subject: [PATCH 04/26] Use MbedCRC for LittleFS (0xEDB88320) CRC used in LittleFS is Reversed ANSI, hence new polynomial added. Reversed polynomials perform shift in reverse direction of standard polynomial, and we do not have option to notify reverse shift to hardware. Hence this option is available in software only. --- drivers/MbedCRC.cpp | 8 ++++ drivers/MbedCRC.h | 25 ++++++++++-- drivers/TableCRC.cpp | 38 ++++++++++++++++++- drivers/TableCRC.h | 3 +- .../filesystem/littlefs/LittleFileSystem.cpp | 7 ++++ .../filesystem/littlefs/littlefs/lfs_util.c | 13 +++++-- hal/crc_api.h | 1 + 7 files changed, 86 insertions(+), 9 deletions(-) diff --git a/drivers/MbedCRC.cpp b/drivers/MbedCRC.cpp index 54243f5820..34e777a251 100644 --- a/drivers/MbedCRC.cpp +++ b/drivers/MbedCRC.cpp @@ -34,6 +34,14 @@ MbedCRC::MbedCRC(): mbed_crc_ctor(); } +template<> +MbedCRC::MbedCRC(): + _initial_value(~(0x0)), _final_xor(~(0x0)), _reflect_data(false), _reflect_remainder(false), + _crc_table((uint32_t *)Table_CRC_32bit_Rev_ANSI) +{ + mbed_crc_ctor(); +} + template<> MbedCRC::MbedCRC(): _initial_value(0), _final_xor(0), _reflect_data(true), _reflect_remainder(true), diff --git a/drivers/MbedCRC.h b/drivers/MbedCRC.h index b1f44c4751..09329e7ba8 100644 --- a/drivers/MbedCRC.h +++ b/drivers/MbedCRC.h @@ -275,7 +275,7 @@ public: p_crc = (uint32_t)(p_crc << (8 - width)); } // Optimized algorithm for 32BitANSI does not need additional reflect_remainder - if ((TABLE == _mode) && (POLY_32BIT_ANSI == polynomial)) { + if ((TABLE == _mode) && (POLY_32BIT_REV_ANSI == polynomial)) { *crc = (p_crc ^ _final_xor) & get_crc_mask(); } else { *crc = (reflect_remainder(p_crc) ^ _final_xor) & get_crc_mask(); @@ -480,9 +480,17 @@ private: } } else { uint32_t *crc_table = (uint32_t *)_crc_table; - for (crc_data_size_t i = 0; i < size; i++) { - p_crc = (p_crc >> 4) ^ crc_table[(p_crc ^ (data[i] >> 0)) & 0xf]; - p_crc = (p_crc >> 4) ^ crc_table[(p_crc ^ (data[i] >> 4)) & 0xf]; + if (POLY_32BIT_REV_ANSI == polynomial) { + for (crc_data_size_t i = 0; i < size; i++) { + p_crc = (p_crc >> 4) ^ crc_table[(p_crc ^ (data[i] >> 0)) & 0xf]; + p_crc = (p_crc >> 4) ^ crc_table[(p_crc ^ (data[i] >> 4)) & 0xf]; + } + } + else { + for (crc_data_size_t byte = 0; byte < size; byte++) { + data_byte = reflect_bytes(data[byte]) ^ (p_crc >> (width - 8)); + p_crc = crc_table[data_byte] ^ (p_crc << 8); + } } } *crc = p_crc & get_crc_mask(); @@ -497,6 +505,11 @@ private: MBED_STATIC_ASSERT(width <= 32, "Max 32-bit CRC supported"); #ifdef DEVICE_CRC + if (POLY_32BIT_REV_ANSI == polynomial) { + _crc_table = (uint32_t *)Table_CRC_32bit_Rev_ANSI; + _mode = TABLE; + return; + } crc_mbed_config_t config; config.polynomial = polynomial; config.width = width; @@ -510,10 +523,14 @@ private: return; } #endif + switch (polynomial) { case POLY_32BIT_ANSI: _crc_table = (uint32_t *)Table_CRC_32bit_ANSI; break; + case POLY_32BIT_REV_ANSI: + _crc_table = (uint32_t *)Table_CRC_32bit_Rev_ANSI; + break; case POLY_8BIT_CCITT: _crc_table = (uint32_t *)Table_CRC_8bit_CCITT; break; diff --git a/drivers/TableCRC.cpp b/drivers/TableCRC.cpp index f3cb42158a..b6e55aaae8 100644 --- a/drivers/TableCRC.cpp +++ b/drivers/TableCRC.cpp @@ -108,12 +108,48 @@ extern const uint16_t Table_CRC_16bit_IBM[MBED_CRC_TABLE_SIZE] = { 0x220, 0x8225, 0x822f, 0x22a, 0x823b, 0x23e, 0x234, 0x8231, 0x8213, 0x216, 0x21c, 0x8219 }; -extern const uint32_t Table_CRC_32bit_ANSI[MBED_OPTIMIZED_CRC_TABLE_SIZE] = { +extern const uint32_t Table_CRC_32bit_ANSI[MBED_CRC_TABLE_SIZE] = { + 0x0, 0x4c11db7, 0x9823b6e, 0xd4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x18aeb13, 0x54bf6a4, 0x808d07d, 0xcc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x315d626, 0x7d4cb91, 0xa97ed48, 0xe56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x29f3d35, 0x65e2082, 0xb1d065b, 0xfdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + +extern const uint32_t Table_CRC_32bit_Rev_ANSI[MBED_OPTIMIZED_CRC_TABLE_SIZE] = { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; + /** @}*/ } // namespace mbed diff --git a/drivers/TableCRC.h b/drivers/TableCRC.h index 6a87159157..478bb25958 100644 --- a/drivers/TableCRC.h +++ b/drivers/TableCRC.h @@ -30,7 +30,8 @@ extern const uint8_t Table_CRC_7Bit_SD[MBED_CRC_TABLE_SIZE]; extern const uint8_t Table_CRC_8bit_CCITT[MBED_CRC_TABLE_SIZE]; extern const uint16_t Table_CRC_16bit_CCITT[MBED_CRC_TABLE_SIZE]; extern const uint16_t Table_CRC_16bit_IBM[MBED_CRC_TABLE_SIZE]; -extern const uint32_t Table_CRC_32bit_ANSI[MBED_OPTIMIZED_CRC_TABLE_SIZE]; +extern const uint32_t Table_CRC_32bit_ANSI[MBED_CRC_TABLE_SIZE]; +extern const uint32_t Table_CRC_32bit_Rev_ANSI[MBED_OPTIMIZED_CRC_TABLE_SIZE]; /** @}*/ } // namespace mbed diff --git a/features/storage/filesystem/littlefs/LittleFileSystem.cpp b/features/storage/filesystem/littlefs/LittleFileSystem.cpp index 74f52f3278..1fa74bafec 100644 --- a/features/storage/filesystem/littlefs/LittleFileSystem.cpp +++ b/features/storage/filesystem/littlefs/LittleFileSystem.cpp @@ -18,7 +18,14 @@ #include "errno.h" #include "lfs.h" #include "lfs_util.h" +#include "MbedCRC.h" +extern "C" void mbed_lfs_crc(uint32_t *crc, const void *buffer, size_t size) +{ + uint32_t initial_xor = *crc; + MbedCRC ct(initial_xor, 0x0, true, false); + ct.compute((void *)buffer, size, (uint32_t *) crc); +} ////// Conversion functions ////// static int lfs_toerror(int err) diff --git a/features/storage/filesystem/littlefs/littlefs/lfs_util.c b/features/storage/filesystem/littlefs/littlefs/lfs_util.c index 9ca0756d96..b63e0ad5e8 100644 --- a/features/storage/filesystem/littlefs/littlefs/lfs_util.c +++ b/features/storage/filesystem/littlefs/littlefs/lfs_util.c @@ -6,11 +6,19 @@ */ #include "lfs_util.h" + // Only compile if user does not provide custom config #ifndef LFS_CONFIG +#ifdef __MBED__ +extern void mbed_lfs_crc(uint32_t *crc, const void *buffer, size_t size); // Software CRC implementation with small lookup table +void lfs_crc(uint32_t *restrict crc, const void *buffer, size_t size) { + mbed_lfs_crc(crc, buffer, size); +} + +#else void lfs_crc(uint32_t *restrict crc, const void *buffer, size_t size) { static const uint32_t rtable[16] = { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, @@ -20,12 +28,11 @@ void lfs_crc(uint32_t *restrict crc, const void *buffer, size_t size) { }; const uint8_t *data = buffer; - for (size_t i = 0; i < size; i++) { *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 0)) & 0xf]; *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 4)) & 0xf]; } } - - #endif + +#endif \ No newline at end of file diff --git a/hal/crc_api.h b/hal/crc_api.h index 2421e46315..29336feb9b 100644 --- a/hal/crc_api.h +++ b/hal/crc_api.h @@ -33,6 +33,7 @@ typedef enum crc_polynomial { POLY_16BIT_CCITT = 0x1021, // x16+x12+x5+1 POLY_16BIT_IBM = 0x8005, // x16+x15+x2+1 POLY_32BIT_ANSI = 0x04C11DB7, // x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 + POLY_32BIT_REV_ANSI = 0xEDB88320 } crc_polynomial_t; typedef struct crc_mbed_config { From a0ad63b47e9a75bda98cbf83688fea3225f90fa2 Mon Sep 17 00:00:00 2001 From: Deepika Date: Tue, 21 Aug 2018 17:18:34 -0500 Subject: [PATCH 05/26] Use the same API name to add mbed CRC: lfs_crc --- .../storage/filesystem/littlefs/LittleFileSystem.cpp | 2 +- .../storage/filesystem/littlefs/littlefs/lfs_util.c | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/features/storage/filesystem/littlefs/LittleFileSystem.cpp b/features/storage/filesystem/littlefs/LittleFileSystem.cpp index 1fa74bafec..8e17af9a2f 100644 --- a/features/storage/filesystem/littlefs/LittleFileSystem.cpp +++ b/features/storage/filesystem/littlefs/LittleFileSystem.cpp @@ -20,7 +20,7 @@ #include "lfs_util.h" #include "MbedCRC.h" -extern "C" void mbed_lfs_crc(uint32_t *crc, const void *buffer, size_t size) +extern "C" void lfs_crc(uint32_t *crc, const void *buffer, size_t size) { uint32_t initial_xor = *crc; MbedCRC ct(initial_xor, 0x0, true, false); diff --git a/features/storage/filesystem/littlefs/littlefs/lfs_util.c b/features/storage/filesystem/littlefs/littlefs/lfs_util.c index b63e0ad5e8..113632b66b 100644 --- a/features/storage/filesystem/littlefs/littlefs/lfs_util.c +++ b/features/storage/filesystem/littlefs/littlefs/lfs_util.c @@ -9,16 +9,7 @@ // Only compile if user does not provide custom config #ifndef LFS_CONFIG - -#ifdef __MBED__ -extern void mbed_lfs_crc(uint32_t *crc, const void *buffer, size_t size); - -// Software CRC implementation with small lookup table -void lfs_crc(uint32_t *restrict crc, const void *buffer, size_t size) { - mbed_lfs_crc(crc, buffer, size); -} - -#else +#ifndef __MBED__ void lfs_crc(uint32_t *restrict crc, const void *buffer, size_t size) { static const uint32_t rtable[16] = { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, @@ -34,5 +25,4 @@ void lfs_crc(uint32_t *restrict crc, const void *buffer, size_t size) { } } #endif - #endif \ No newline at end of file From b7b94b31de12f879ec151d1daae0cd05813e03cd Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 3 Sep 2018 09:20:47 -0500 Subject: [PATCH 06/26] CRC: Removed assertion on NULL buffer When length is zero, the buffer is not accessed. The CRC functions are used inside several other layers where a 0-length buffer may have meanings in different contexts and being able to pass 0-length NULL buffers to CRC as a noop simplifies the code. --- drivers/MbedCRC.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/MbedCRC.h b/drivers/MbedCRC.h index 09329e7ba8..fd4fa1c7f0 100644 --- a/drivers/MbedCRC.h +++ b/drivers/MbedCRC.h @@ -415,7 +415,6 @@ private: int32_t bitwise_compute_partial(const void *buffer, crc_data_size_t size, uint32_t *crc) const { MBED_ASSERT(crc != NULL); - MBED_ASSERT(buffer != NULL); const uint8_t *data = static_cast(buffer); uint32_t p_crc = *crc; @@ -460,7 +459,6 @@ private: int32_t table_compute_partial(const void *buffer, crc_data_size_t size, uint32_t *crc) const { MBED_ASSERT(crc != NULL); - MBED_ASSERT(buffer != NULL); const uint8_t *data = static_cast(buffer); uint32_t p_crc = *crc; From b490de3224cfcb9688404a76eaf03ad5a8399897 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Mon, 27 Aug 2018 15:18:41 +0300 Subject: [PATCH 07/26] Add special handling for "/default" filesystem Allow a FileBase (normally a FileSystemLike) to be set as the default, so it can be looked up as "/default" as well as its actual name. --- platform/FileBase.cpp | 24 +++++++++++++++++++++--- platform/FileBase.h | 7 +++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/platform/FileBase.cpp b/platform/FileBase.cpp index a6ca848a82..ce0229bace 100644 --- a/platform/FileBase.cpp +++ b/platform/FileBase.cpp @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include + #include "platform/FileBase.h" #include "platform/FileLike.h" #include "platform/FileHandle.h" @@ -21,6 +23,7 @@ namespace mbed { FileBase *FileBase::_head = NULL; SingletonPtr FileBase::_mutex; +FileBase *FileBase::_default = NULL; FileBase::FileBase(const char *name, PathType t) : _next(NULL), _name(name), @@ -52,26 +55,41 @@ FileBase::~FileBase() p->_next = _next; } } + + if (_default == this) { + _default == NULL; + } + _mutex->unlock(); if (getPathType() == FilePathType) { - extern void remove_filehandle(FileHandle * file); - remove_filehandle(static_cast(static_cast(this))); + extern void remove_filehandle(FileHandle *file); + remove_filehandle(static_cast(this)); } } +void FileBase::set_as_default() +{ + _mutex->lock(); + _default = this; + _mutex->unlock(); +} + FileBase *FileBase::lookup(const char *name, unsigned int len) { _mutex->lock(); FileBase *p = _head; while (p != NULL) { /* Check that p->_name matches name and is the correct length */ - if (p->_name != NULL && std::strncmp(p->_name, name, len) == 0 && std::strlen(p->_name) == len) { + if (p->_name != NULL && len == std::strlen(p->_name) && std::memcmp(p->_name, name, len) == 0) { _mutex->unlock(); return p; } p = p->_next; } + if (len == (sizeof "default") - 1 && std::memcmp("default", name, len) == 0) { + return _default; + } _mutex->unlock(); return NULL; } diff --git a/platform/FileBase.h b/platform/FileBase.h index 0ef63b40af..25b650145b 100644 --- a/platform/FileBase.h +++ b/platform/FileBase.h @@ -18,9 +18,6 @@ typedef int FILEHANDLE; -#include -#include - #include "platform/platform.h" #include "platform/SingletonPtr.h" #include "platform/PlatformMutex.h" @@ -55,9 +52,11 @@ public: static FileBase *get(int n); - /* disallow copy constructor and assignment operators */ + void set_as_default(); + private: static FileBase *_head; + static FileBase *_default; static SingletonPtr _mutex; FileBase *_next; From 8e6e5f07b9e5e142e06bf2af6046fb8fc28c00ec Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Tue, 4 Sep 2018 11:45:58 +0300 Subject: [PATCH 08/26] Change default filesystem name to /default "/fs" is a tautology - not a good name for the default filing system, as whereever we use it, we know we're specifying a filing system. Rename to "/default". --- .../filesystem/general_filesystem/main.cpp | 394 +++++++++--------- .../storage/system_storage/SystemStorage.cpp | 4 +- 2 files changed, 199 insertions(+), 199 deletions(-) diff --git a/features/storage/TESTS/filesystem/general_filesystem/main.cpp b/features/storage/TESTS/filesystem/general_filesystem/main.cpp index b79659db99..fb2a7da94c 100644 --- a/features/storage/TESTS/filesystem/general_filesystem/main.cpp +++ b/features/storage/TESTS/filesystem/general_filesystem/main.cpp @@ -82,87 +82,87 @@ static void FS_fopen_path_not_valid() //fopen empty file name with r mode static void FS_fopen_empty_path_r_mode() { - int res = !((fd[0] = fopen("fs/" "", "rb")) != NULL); + int res = !((fd[0] = fopen("/default/" "", "rb")) != NULL); TEST_ASSERT_EQUAL(1, res); } //fopen empty file name with w mode static void FS_fopen_empty_path_w_mode() { - int res = !((fd[0] = fopen("fs/" "", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "", "wb")) != NULL); TEST_ASSERT_EQUAL(1, res); } //fopen empty mode static void FS_fopen_invalid_mode() { - int res = !((fd[0] = fopen("fs/" "Invalid_mode", "")) != NULL); + int res = !((fd[0] = fopen("/default/" "Invalid_mode", "")) != NULL); TEST_ASSERT_EQUAL(1, res); } //fopen with valid flowSystemStorage static void FS_fopen_supported_wb_mode() { - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } //fopen with append mode static void FS_fopen_supported_a_mode() { - int res = !((fd[0] = fopen("fs/" "filename", "a")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "a")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } //fopen with read mode static void FS_fopen_supported_r_mode() { - int res = !((fd[0] = fopen("fs/" "filename", "r")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "r")) != NULL); TEST_ASSERT_EQUAL(1, res); } //fopen with append update mode static void FS_fopen_supported_a_update_mode() { - int res = !((fd[0] = fopen("fs/" "filename", "a+")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "a+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } //fopen with read update mode static void FS_fopen_supported_r_update_mode() { - int res = !((fd[0] = fopen("fs/" "filename", "r+")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "r+")) != NULL); TEST_ASSERT_EQUAL(1, res); } //fopen with write update mode static void FS_fopen_supported_w_update_mode() { - int res = !((fd[0] = fopen("fs/" "filename", "w+")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -172,7 +172,7 @@ static void FS_fopen_read_update_create() char write_buf[small_buf_size] = "123456789"; char read_buf[small_buf_size] = ""; - int res = !((fd[0] = fopen("fs/" "filename", "w")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), small_buf_size, fd[0]); @@ -181,7 +181,7 @@ static void FS_fopen_read_update_create() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "r+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "r+")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), small_buf_size, fd[0]); @@ -191,7 +191,7 @@ static void FS_fopen_read_update_create() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -201,7 +201,7 @@ static void FS_fopen_write_update_create() char write_buf[small_buf_size] = "123456789"; char read_buf[small_buf_size] = ""; - int res = !((fd[0] = fopen("fs/" "filename", "w")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), small_buf_size, fd[0]); @@ -210,7 +210,7 @@ static void FS_fopen_write_update_create() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "w+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "w+")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), small_buf_size, fd[0]); @@ -219,7 +219,7 @@ static void FS_fopen_write_update_create() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } /*----------------fclose()------------------*/ @@ -227,13 +227,13 @@ static void FS_fopen_write_update_create() //fclose valid flow static void FS_fclose_valid_flow() { - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -244,7 +244,7 @@ static void FS_fwrite_nmemb_zero() { char buffer[small_buf_size] = "good_day"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(buffer, sizeof(char), 0, fd[0]); @@ -253,7 +253,7 @@ static void FS_fwrite_nmemb_zero() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -263,7 +263,7 @@ static void FS_fwrite_valid_flow() char write_buf[small_buf_size] = "good_day"; char read_buf[small_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), small_buf_size, fd[0]); @@ -272,7 +272,7 @@ static void FS_fwrite_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), small_buf_size, fd[0]); @@ -282,7 +282,7 @@ static void FS_fwrite_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -291,13 +291,13 @@ static void FS_fwrite_with_fopen_r_mode() { char buffer[small_buf_size] = "good_day"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(buffer, sizeof(char), small_buf_size, fd[0]); @@ -306,7 +306,7 @@ static void FS_fwrite_with_fopen_r_mode() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -317,7 +317,7 @@ static void FS_fread_size_zero() { char buffer[small_buf_size] = "good_day"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(buffer, sizeof(char), small_buf_size, fd[0]); @@ -326,7 +326,7 @@ static void FS_fread_size_zero() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(buffer, 0, small_buf_size, fd[0]); @@ -335,7 +335,7 @@ static void FS_fread_size_zero() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -344,7 +344,7 @@ static void FS_fread_nmemb_zero() { char buffer[small_buf_size] = "good_day"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(buffer, sizeof(char), small_buf_size, fd[0]); @@ -353,7 +353,7 @@ static void FS_fread_nmemb_zero() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(buffer, sizeof(char), 0, fd[0]); @@ -362,7 +362,7 @@ static void FS_fread_nmemb_zero() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -371,13 +371,13 @@ static void FS_fread_with_fopen_w_mode() { char buffer[small_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(buffer, sizeof(char), small_buf_size, fd[0]); @@ -386,7 +386,7 @@ static void FS_fread_with_fopen_w_mode() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -396,7 +396,7 @@ static void FS_fread_to_fwrite_file() char read_buf[small_buf_size] = {}; char write_buf[small_buf_size] = "123456789"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), small_buf_size, fd[0]); @@ -408,7 +408,7 @@ static void FS_fread_to_fwrite_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -417,13 +417,13 @@ static void FS_fread_empty_file() { char read_buf[small_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), small_buf_size, fd[0]); @@ -432,7 +432,7 @@ static void FS_fread_empty_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -442,7 +442,7 @@ static void FS_fread_valid_flow_small_file() char write_buf[small_buf_size] = "good_day"; char read_buf[small_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -451,7 +451,7 @@ static void FS_fread_valid_flow_small_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(read_buf), fd[0]); @@ -461,7 +461,7 @@ static void FS_fread_valid_flow_small_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -472,7 +472,7 @@ static void FS_fread_valid_flow_medium_file() char write_buf[medium_buf_size] = { 1 }; char read_buf[medium_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -481,7 +481,7 @@ static void FS_fread_valid_flow_medium_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(read_buf), fd[0]); @@ -491,7 +491,7 @@ static void FS_fread_valid_flow_medium_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -501,7 +501,7 @@ static void FS_fread_valid_flow_large_file() char write_buf[large_buf_size] = { 1 }; char read_buf[large_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -510,7 +510,7 @@ static void FS_fread_valid_flow_large_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(read_buf), fd[0]); @@ -520,7 +520,7 @@ static void FS_fread_valid_flow_large_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -530,7 +530,7 @@ static void FS_fread_valid_flow_small_file_read_more_than_write() char write_buf[small_buf_size] = "good_day"; char read_buf[small_buf_size + 10] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -539,7 +539,7 @@ static void FS_fread_valid_flow_small_file_read_more_than_write() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(read_buf), fd[0]); @@ -549,7 +549,7 @@ static void FS_fread_valid_flow_small_file_read_more_than_write() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -558,13 +558,13 @@ static void FS_fread_valid_flow_small_file_read_more_than_write() //fgetc to an empty file static void FS_fgetc_empty_file() { - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fgetc(fd[0]); @@ -573,7 +573,7 @@ static void FS_fgetc_empty_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -585,7 +585,7 @@ static void FS_fgetc_valid_flow() int ch = 0; unsigned int i = 0; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -594,7 +594,7 @@ static void FS_fgetc_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); for (i = 0; (i < (sizeof(read_buf) - 1) && ((ch = fgetc(fd[0])) != EOF) && (ch != '\n')); i++) { @@ -607,20 +607,20 @@ static void FS_fgetc_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } //fgetc to fopen mode w static void FS_fgetc_with_fopen_w_mode() { - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fgetc(fd[0]); @@ -629,7 +629,7 @@ static void FS_fgetc_with_fopen_w_mode() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -640,13 +640,13 @@ static void FS_fgets_empty_file() { char buffer[small_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); TEST_ASSERT_NULL(fgets(buffer, sizeof(buffer), fd[0])); @@ -654,20 +654,20 @@ static void FS_fgets_empty_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } //fgets with buffer null with zero len of buffer string static void FS_fgets_null_buffer_zero_len() { - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); TEST_ASSERT_NULL(fgets(NULL, 0, fd[0])); @@ -675,20 +675,20 @@ static void FS_fgets_null_buffer_zero_len() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } //fgets with buffer null static void FS_fgets_null_buffer() { - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); TEST_ASSERT_NULL(fgets(NULL, small_buf_size, fd[0])); @@ -696,7 +696,7 @@ static void FS_fgets_null_buffer() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -706,7 +706,7 @@ static void FS_fgets_valid_flow() char write_buf[small_buf_size] = "good_day"; char read_buf[small_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -715,7 +715,7 @@ static void FS_fgets_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); TEST_ASSERT_NOT_NULL(fgets(read_buf, sizeof(read_buf), fd[0])); @@ -724,7 +724,7 @@ static void FS_fgets_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -736,7 +736,7 @@ static void FS_fgets_new_line() write_buf[4] = '\n'; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -745,7 +745,7 @@ static void FS_fgets_new_line() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); TEST_ASSERT_NOT_NULL(fgets(read_buf, sizeof(read_buf), fd[0])); @@ -754,7 +754,7 @@ static void FS_fgets_new_line() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -763,13 +763,13 @@ static void FS_fgets_with_fopen_w_mode() { char buffer[small_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); TEST_ASSERT_NULL(fgets(buffer, sizeof(buffer), fd[0])); @@ -777,7 +777,7 @@ static void FS_fgets_with_fopen_w_mode() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -796,7 +796,7 @@ static void FS_fflush_valid_flow() { char buffer[small_buf_size] = "good_day"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(buffer, sizeof(char), small_buf_size, fd[0]); @@ -808,7 +808,7 @@ static void FS_fflush_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -818,7 +818,7 @@ static void FS_fflush_twice() { char buffer[small_buf_size] = "good_day"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(buffer, sizeof(char), small_buf_size, fd[0]); @@ -833,7 +833,7 @@ static void FS_fflush_twice() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -844,7 +844,7 @@ static void FS_fputc_valid_flow() { int write_ch = 10, read_ch = 0; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fputc(write_ch, fd[0]); @@ -853,7 +853,7 @@ static void FS_fputc_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); read_ch = fgetc(fd[0]); @@ -862,7 +862,7 @@ static void FS_fputc_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -871,13 +871,13 @@ static void FS_fputc_in_read_mode() { int write_ch = 10; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fputc(write_ch, fd[0]); @@ -886,7 +886,7 @@ static void FS_fputc_in_read_mode() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -898,7 +898,7 @@ static void FS_fputs_valid_flow() char write_buf[small_buf_size] = "123456789"; char read_buf[small_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fputs(write_buf, fd[0]); @@ -907,7 +907,7 @@ static void FS_fputs_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -917,7 +917,7 @@ static void FS_fputs_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -926,13 +926,13 @@ static void FS_fputs_in_read_mode() { char buffer[small_buf_size] = "good_day"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fputs(buffer, fd[0]); @@ -941,7 +941,7 @@ static void FS_fputs_in_read_mode() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -950,13 +950,13 @@ static void FS_fputs_in_read_mode() //fseek empty file, SEEK_SET, offset 0 static void FS_fseek_empty_file_seek_set() { - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 0, SEEK_SET); @@ -968,7 +968,7 @@ static void FS_fseek_empty_file_seek_set() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -977,7 +977,7 @@ static void FS_fseek_non_empty_file_seek_set() { char write_buf[small_buf_size] = "123456789"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -986,7 +986,7 @@ static void FS_fseek_non_empty_file_seek_set() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 0, SEEK_SET); @@ -998,7 +998,7 @@ static void FS_fseek_non_empty_file_seek_set() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1007,13 +1007,13 @@ static void FS_fseek_beyond_empty_file_seek_set() { char read_buf[small_buf_size] = ""; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 10, SEEK_SET); @@ -1028,7 +1028,7 @@ static void FS_fseek_beyond_empty_file_seek_set() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1038,7 +1038,7 @@ static void FS_fseek_beyond_non_empty_file_seek_set() char write_buf[small_buf_size] = "123456789"; char read_buf[small_buf_size] = ""; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1047,7 +1047,7 @@ static void FS_fseek_beyond_non_empty_file_seek_set() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], sizeof(write_buf) + 1, SEEK_SET); @@ -1062,20 +1062,20 @@ static void FS_fseek_beyond_non_empty_file_seek_set() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } //fseek empty file, SEEK_CUR, offset 0 static void FS_fseek_empty_file_seek_cur() { - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 0, SEEK_CUR); @@ -1087,7 +1087,7 @@ static void FS_fseek_empty_file_seek_cur() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1096,7 +1096,7 @@ static void FS_fseek_non_empty_file_seek_cur() { char write_buf[small_buf_size] = "123456789"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1105,7 +1105,7 @@ static void FS_fseek_non_empty_file_seek_cur() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 0, SEEK_CUR); @@ -1117,7 +1117,7 @@ static void FS_fseek_non_empty_file_seek_cur() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1126,13 +1126,13 @@ static void FS_fseek_beyond_empty_file_seek_cur() { char read_buf[small_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 1, SEEK_CUR); @@ -1147,7 +1147,7 @@ static void FS_fseek_beyond_empty_file_seek_cur() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1157,7 +1157,7 @@ static void FS_fseek_beyond_non_empty_file_seek_cur() char read_buf[small_buf_size] = {}; char write_buf[small_buf_size] = "123456789"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1166,7 +1166,7 @@ static void FS_fseek_beyond_non_empty_file_seek_cur() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], sizeof(write_buf) + 1, SEEK_CUR); @@ -1181,20 +1181,20 @@ static void FS_fseek_beyond_non_empty_file_seek_cur() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } //fseek empty file, SEEK_END, offset 0 static void FS_fseek_empty_file_seek_end() { - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 0, SEEK_END); @@ -1206,7 +1206,7 @@ static void FS_fseek_empty_file_seek_end() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1215,7 +1215,7 @@ static void FS_fseek_non_empty_file_seek_end() { char write_buf[small_buf_size] = "123456789"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1224,7 +1224,7 @@ static void FS_fseek_non_empty_file_seek_end() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 0, SEEK_END); @@ -1236,7 +1236,7 @@ static void FS_fseek_non_empty_file_seek_end() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1245,13 +1245,13 @@ static void FS_fseek_beyond_empty_file_seek_end() { char read_buf[small_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 1, SEEK_END); @@ -1266,7 +1266,7 @@ static void FS_fseek_beyond_empty_file_seek_end() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1276,7 +1276,7 @@ static void FS_fseek_beyond_non_empty_file_seek_end() char read_buf[small_buf_size] = {}; char write_buf[small_buf_size] = "123456789"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1285,7 +1285,7 @@ static void FS_fseek_beyond_non_empty_file_seek_end() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], sizeof(write_buf) + 1, SEEK_END); @@ -1300,7 +1300,7 @@ static void FS_fseek_beyond_non_empty_file_seek_end() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1309,7 +1309,7 @@ static void FS_fseek_negative_non_empty_file_seek_end() { char write_buf[small_buf_size] = "123456789"; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1318,7 +1318,7 @@ static void FS_fseek_negative_non_empty_file_seek_end() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], -(sizeof(write_buf)), SEEK_END); @@ -1330,7 +1330,7 @@ static void FS_fseek_negative_non_empty_file_seek_end() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1344,7 +1344,7 @@ static void FS_fgetpos_rewrite_check_data() char read_buf[small_buf_size] = {}; fpos_t pos; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fgetpos(fd[0], &pos); @@ -1362,7 +1362,7 @@ static void FS_fgetpos_rewrite_check_data() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(read_buf), fd[0]); @@ -1372,7 +1372,7 @@ static void FS_fgetpos_rewrite_check_data() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1385,7 +1385,7 @@ static void FS_fscanf_valid_flow() char read_buf[small_buf_size] = {}; int num = 0; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fprintf(fd[0], "%d %s", 123, write_buf); @@ -1394,7 +1394,7 @@ static void FS_fscanf_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fscanf(fd[0], "%d", &num); @@ -1408,7 +1408,7 @@ static void FS_fscanf_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1417,7 +1417,7 @@ static void FS_fscanf_empty_file() { int num = 0; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fscanf(fd[0], "%d", &num); @@ -1426,7 +1426,7 @@ static void FS_fscanf_empty_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1437,7 +1437,7 @@ static void FS_fscanf_more_fields_than_exist() char read_buf[small_buf_size] = {}; int num = 0; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fprintf(fd[0], "%d %s", 123, write_buf); @@ -1446,7 +1446,7 @@ static void FS_fscanf_more_fields_than_exist() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fscanf(fd[0], "%d", &num); @@ -1463,7 +1463,7 @@ static void FS_fscanf_more_fields_than_exist() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1472,13 +1472,13 @@ static void FS_fscanf_more_fields_than_exist() //fprintf in mode r static void FS_fprintf_read_mode() { - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fprintf(fd[0], "%d", 123); @@ -1487,7 +1487,7 @@ static void FS_fprintf_read_mode() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1496,10 +1496,10 @@ static void FS_fprintf_read_mode() //freopen point to the same file with two file handler static void FS_freopen_point_to_same_file() { - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); - res = !((fd[1] = freopen("fs/" "new_file_name", "wb", fd[0])) != NULL); + res = !((fd[1] = freopen("/default/" "new_file_name", "wb", fd[0])) != NULL); TEST_ASSERT_EQUAL(0, res); TEST_ASSERT_EQUAL(fd[0], fd[1]); @@ -1507,7 +1507,7 @@ static void FS_freopen_point_to_same_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1517,13 +1517,13 @@ static void FS_freopen_valid_flow() char write_buf[small_buf_size] = "123456789"; char read_buf[small_buf_size] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "wb")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "wb")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); TEST_ASSERT_EQUAL(sizeof(write_buf), write_sz); - res = !((fd[1] = freopen("fs/" "filename", "rb", fd[0])) != NULL); + res = !((fd[1] = freopen("/default/" "filename", "rb", fd[0])) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(read_buf), fd[0]); @@ -1533,7 +1533,7 @@ static void FS_freopen_valid_flow() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1545,7 +1545,7 @@ static void FS_fopen_write_one_byte_file() char write_buf = 1; char read_buf[1] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "w")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(&write_buf, sizeof(char), 1, fd[0]); @@ -1554,7 +1554,7 @@ static void FS_fopen_write_one_byte_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(read_buf), fd[0]); @@ -1564,7 +1564,7 @@ static void FS_fopen_write_one_byte_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1574,7 +1574,7 @@ static void FS_fopen_write_two_byte_file() char write_buf[2] = "1"; char read_buf[2] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "w")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1583,7 +1583,7 @@ static void FS_fopen_write_two_byte_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(read_buf), fd[0]); @@ -1593,7 +1593,7 @@ static void FS_fopen_write_two_byte_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1603,7 +1603,7 @@ static void FS_fopen_write_five_byte_file() char write_buf[5] = "1234"; char read_buf[5] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "w")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1612,7 +1612,7 @@ static void FS_fopen_write_five_byte_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(read_buf), fd[0]); @@ -1622,7 +1622,7 @@ static void FS_fopen_write_five_byte_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1632,7 +1632,7 @@ static void FS_fopen_write_fifteen_byte_file() char write_buf[15] = "12345678901234"; char read_buf[15] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "w")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1641,7 +1641,7 @@ static void FS_fopen_write_fifteen_byte_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(read_buf), fd[0]); @@ -1651,7 +1651,7 @@ static void FS_fopen_write_fifteen_byte_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1663,7 +1663,7 @@ static void FS_fopen_write_five_Kbyte_file() char read_buf[10] = {}; char check_buf[10] = "123456789"; - int res = !((fd[0] = fopen("fs/" "filename", "w")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w")) != NULL); TEST_ASSERT_EQUAL(0, res); memcpy(write_buf, check_buf, sizeof(check_buf) - 1); @@ -1673,7 +1673,7 @@ static void FS_fopen_write_five_Kbyte_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "rb+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "rb+")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(read_buf) - 1, fd[0]); @@ -1683,7 +1683,7 @@ static void FS_fopen_write_five_Kbyte_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1695,7 +1695,7 @@ static void FS_fseek_rewrite_non_empty_file_begining() char check_buf[15] = "abcde678901234"; char read_buf[15] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "w")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1704,7 +1704,7 @@ static void FS_fseek_rewrite_non_empty_file_begining() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "r+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "r+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 0, SEEK_SET); @@ -1716,7 +1716,7 @@ static void FS_fseek_rewrite_non_empty_file_begining() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "r")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "r")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 0, SEEK_SET); @@ -1729,7 +1729,7 @@ static void FS_fseek_rewrite_non_empty_file_begining() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1741,7 +1741,7 @@ static void FS_fseek_rewrite_non_empty_file_middle() char check_buf[15] = "12345abcde1234"; char read_buf[15] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "w")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1750,7 +1750,7 @@ static void FS_fseek_rewrite_non_empty_file_middle() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "r+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "r+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 5, SEEK_SET); @@ -1762,7 +1762,7 @@ static void FS_fseek_rewrite_non_empty_file_middle() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "r")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "r")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 0, SEEK_SET); @@ -1775,7 +1775,7 @@ static void FS_fseek_rewrite_non_empty_file_middle() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1787,7 +1787,7 @@ static void FS_fseek_rewrite_non_empty_file_end() char check_buf[15] = "123456789abcde"; char read_buf[15] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "w")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1796,7 +1796,7 @@ static void FS_fseek_rewrite_non_empty_file_end() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "r+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "r+")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 9, SEEK_SET); @@ -1808,7 +1808,7 @@ static void FS_fseek_rewrite_non_empty_file_end() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "r")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "r")) != NULL); TEST_ASSERT_EQUAL(0, res); res = fseek(fd[0], 0, SEEK_SET); @@ -1821,7 +1821,7 @@ static void FS_fseek_rewrite_non_empty_file_end() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1831,7 +1831,7 @@ static void FS_append_empty_file() char write_buf[17] = "1234567890123456"; char read_buf[17] = {}; - int res = !((fd[0] = fopen("fs/" "filename", "a")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "a")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf), fd[0]); @@ -1840,7 +1840,7 @@ static void FS_append_empty_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "r")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "r")) != NULL); TEST_ASSERT_EQUAL(0, res); int read_sz = fread(read_buf, sizeof(char), sizeof(read_buf), fd[0]); @@ -1850,7 +1850,7 @@ static void FS_append_empty_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1862,7 +1862,7 @@ static void FS_append_non_empty_file() char read_buf[34] = {}; char check_buf[34] = "1234567890123456abcdefghijklmnop"; - int res = !((fd[0] = fopen("fs/" "filename", "a")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "a")) != NULL); TEST_ASSERT_EQUAL(0, res); int write_sz = fwrite(write_buf, sizeof(char), sizeof(write_buf) - 1, fd[0]); @@ -1871,7 +1871,7 @@ static void FS_append_non_empty_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "a+")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "a+")) != NULL); TEST_ASSERT_EQUAL(0, res); write_sz = fwrite(rewrite_buf, sizeof(char), sizeof(rewrite_buf), fd[0]); @@ -1880,7 +1880,7 @@ static void FS_append_non_empty_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "r")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "r")) != NULL); TEST_ASSERT_EQUAL(0, res); memcpy(check_buf, write_buf, sizeof(write_buf) - 1); @@ -1893,7 +1893,7 @@ static void FS_append_non_empty_file() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1904,7 +1904,7 @@ static void FS_write_read_random_data() unsigned int i; // Fill write_buf buffer with random data and write the data into the file - int res = !((fd[0] = fopen("fs/" "filename", "w")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w")) != NULL); TEST_ASSERT_EQUAL(0, res); for (i = 0; i < medium_buf_size; i++) { @@ -1917,7 +1917,7 @@ static void FS_write_read_random_data() TEST_ASSERT_EQUAL(0, res); // Read back the data from the file and store them in data_read - res = !((fd[0] = fopen("fs/" "filename", "r")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "r")) != NULL); TEST_ASSERT_EQUAL(0, res); for (i = 0; i < medium_buf_size; i++) { @@ -1928,7 +1928,7 @@ static void FS_write_read_random_data() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } @@ -1937,7 +1937,7 @@ static void FS_fill_data_and_seek() { unsigned int i, j; - int res = !((fd[0] = fopen("fs/" "filename", "w")) != NULL); + int res = !((fd[0] = fopen("/default/" "filename", "w")) != NULL); TEST_ASSERT_EQUAL(0, res); for (i = 0; i < 256; i++) { @@ -1948,7 +1948,7 @@ static void FS_fill_data_and_seek() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = !((fd[0] = fopen("fs/" "filename", "r")) != NULL); + res = !((fd[0] = fopen("/default/" "filename", "r")) != NULL); TEST_ASSERT_EQUAL(0, res); for (i = 1; i <= 255; i++) { @@ -1978,7 +1978,7 @@ static void FS_fill_data_and_seek() res = fclose(fd[0]); TEST_ASSERT_EQUAL(0, res); - res = remove("fs/" "filename"); + res = remove("/default/" "filename"); TEST_ASSERT_EQUAL(0, res); } diff --git a/features/storage/system_storage/SystemStorage.cpp b/features/storage/system_storage/SystemStorage.cpp index ffccd19389..4bf571c565 100644 --- a/features/storage/system_storage/SystemStorage.cpp +++ b/features/storage/system_storage/SystemStorage.cpp @@ -80,13 +80,13 @@ MBED_WEAK FileSystem *FileSystem::get_default_instance() { #if COMPONENT_SPIF || COMPONENT_DATAFLASH - static LittleFileSystem default_fs("fs", BlockDevice::get_default_instance()); + static LittleFileSystem default_fs("default", BlockDevice::get_default_instance()); return &default_fs; #elif COMPONENT_SD - static FATFileSystem default_fs("fs", BlockDevice::get_default_instance()); + static FATFileSystem default_fs("default", BlockDevice::get_default_instance()); return &default_fs; From f1de1c33fda17723e1ec591907df82c329ed5765 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Tue, 4 Sep 2018 11:55:25 +0300 Subject: [PATCH 09/26] Make "/default" an alias - add real names too Make the built-in FileSystem::get_default_instance() implementation instantiate storage as "flash" or "sd", with "default" as an alias. This will aid interworking between simple and advanced filesystem code on various platforms. The expectation is that the names "sd" or "flash" will be always available if the device is available and configured, regardless of what "default" represents. --- features/storage/system_storage/SystemStorage.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/features/storage/system_storage/SystemStorage.cpp b/features/storage/system_storage/SystemStorage.cpp index 4bf571c565..5ce4146ef7 100644 --- a/features/storage/system_storage/SystemStorage.cpp +++ b/features/storage/system_storage/SystemStorage.cpp @@ -80,15 +80,17 @@ MBED_WEAK FileSystem *FileSystem::get_default_instance() { #if COMPONENT_SPIF || COMPONENT_DATAFLASH - static LittleFileSystem default_fs("default", BlockDevice::get_default_instance()); + static LittleFileSystem flash("flash", BlockDevice::get_default_instance()); + flash.set_as_default(); - return &default_fs; + return &flash; #elif COMPONENT_SD - static FATFileSystem default_fs("default", BlockDevice::get_default_instance()); + static FATFileSystem sdcard("sd", BlockDevice::get_default_instance()); + sdcard.set_as_default(); - return &default_fs; + return &sdcard; #else From 6835a5a06b0d15bf68a2cc40efd7f43bb300970b Mon Sep 17 00:00:00 2001 From: Lari-Matias Orjala Date: Wed, 5 Sep 2018 09:03:58 +0300 Subject: [PATCH 10/26] fix mutex stub for unit tests --- UNITTESTS/stubs/Mutex_stub.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/UNITTESTS/stubs/Mutex_stub.cpp b/UNITTESTS/stubs/Mutex_stub.cpp index c287d3bec0..cd226064f8 100644 --- a/UNITTESTS/stubs/Mutex_stub.cpp +++ b/UNITTESTS/stubs/Mutex_stub.cpp @@ -27,7 +27,12 @@ rtos::Mutex::~Mutex() return; } -osStatus rtos::Mutex::lock(unsigned int) +osStatus rtos::Mutex::lock(void) +{ + return osOK; +} + +osStatus rtos::Mutex::lock(uint32_t millisec) { return osOK; } From 87713d9eab821ddc2133e766ec8581a402f5e844 Mon Sep 17 00:00:00 2001 From: Janne Kiiskila Date: Thu, 6 Sep 2018 01:04:38 +0300 Subject: [PATCH 11/26] IOTCORE-389 - bring back legacy alignment for Arm C6 Quite a few of the scatter files are not (yet) aligned to 8-byte boundaries and therefore the removal of legacy alignment feature (which is under deprecation warning, but it actually not YET deprecated) broke quite a few builds to this error: Error: L6244E: Exec region RW_IRAM1 address (0x200001ac) not aligned on a 8 byte boundary. We must bring this option now back to fix the builds. This option to ld (--legacyalign) can only be removed once all of the scatter files have been fixed. --- tools/profiles/debug.json | 2 +- tools/profiles/develop.json | 2 +- tools/profiles/release.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/profiles/debug.json b/tools/profiles/debug.json index 4966eb831d..dc0ace4e0b 100644 --- a/tools/profiles/debug.json +++ b/tools/profiles/debug.json @@ -23,7 +23,7 @@ "asm": [], "c": ["-D__ASSERT_MSG", "-std=gnu99"], "cxx": ["-fno-rtti", "-std=gnu++98"], - "ld": ["--verbose", "--remove", "--show_full_path"] + "ld": ["--verbose", "--remove", "--show_full_path", "--legacyalign"] }, "ARM": { "common": ["-c", "--gnu", "-Otime", "--split_sections", diff --git a/tools/profiles/develop.json b/tools/profiles/develop.json index adcdc72b83..1006de70a8 100644 --- a/tools/profiles/develop.json +++ b/tools/profiles/develop.json @@ -22,7 +22,7 @@ "asm": [], "c": ["-D__ASSERT_MSG", "-std=gnu99"], "cxx": ["-fno-rtti", "-std=gnu++98"], - "ld": ["--show_full_path"] + "ld": ["--show_full_path", "--legacyalign"] }, "ARM": { "common": ["-c", "--gnu", "-Otime", "--split_sections", diff --git a/tools/profiles/release.json b/tools/profiles/release.json index eab730a186..e0c36c979e 100644 --- a/tools/profiles/release.json +++ b/tools/profiles/release.json @@ -22,7 +22,7 @@ "asm": [], "c": ["-D__ASSERT_MSG", "-std=gnu99"], "cxx": ["-fno-rtti", "-std=gnu++98"], - "ld": ["--show_full_path"] + "ld": ["--show_full_path", "--legacyalign"] }, "ARM": { "common": ["-c", "--gnu", "-Ospace", "--split_sections", From f55615121495c94b75a881ae0c78a542d3139203 Mon Sep 17 00:00:00 2001 From: Jimmy Brisson Date: Tue, 4 Sep 2018 10:47:04 -0500 Subject: [PATCH 12/26] Update mbed-cli subcommand --- UNITTESTS/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/UNITTESTS/README.md b/UNITTESTS/README.md index 2f8a7bc163..180fb49c50 100644 --- a/UNITTESTS/README.md +++ b/UNITTESTS/README.md @@ -69,17 +69,17 @@ pip install "gcovr>=4.1" > In case of running into problems see [troubleshooting](#troubleshooting) section. -`UNITTESTS/mbed_unittest.py` contains testing scripts for Mbed OS unit testing. Mbed CLI supports unit testing through `mbed unittest` command with the same arguments. +`UNITTESTS/mbed_unittest.py` contains testing scripts for Mbed OS unit testing. Mbed CLI supports unit testing through `mbed test --unittests` command with the same arguments. ### Testing with Mbed CLI ``` -mbed unittest +mbed test --unittests ``` A subset of tests can be run by providing `-r` flag for the tool which runs tests matching a regular expression. -e.g. `mbed unittest --run -r features_netsocket` +e.g. `mbed test --unittests --run -r features_netsocket` ### Build manually without Python tools @@ -144,7 +144,7 @@ Run ctest dashboard test and create test results: Python tools use gcovr to build code coverage reports. Generate html report `UNITTESTS/build/coverage/index.html` with: ``` -mbed unittest --coverage html +mbed test --unittests --coverage html ``` To get coverage for a single test suite, run gcovr separately for suite coverage data directory. See [gcovr documentation](https://gcovr.com/guide.html#filter-options) for more information. @@ -211,10 +211,10 @@ A unit test definition file `unittest.cmake` requires variables to be set for a #### Creating unit tests files with Mbed CLI ``` -mbed unittest --new +mbed test --unittests --new ``` -E.g. `mbed unittest --new rtos/Semaphore.cpp` +E.g. `mbed test --unittests --new rtos/Semaphore.cpp` The generator script only creates the files required for a unit test. It does not write unit tests automatically nor does it handle source dependencies. From 0ec25146f5a003131f2b1048704989f7ed0b7034 Mon Sep 17 00:00:00 2001 From: Yossi Levy Date: Wed, 5 Sep 2018 14:13:05 +0300 Subject: [PATCH 13/26] Changes in PR #7774 of PinNames.h should be reverted. This commit reverts those files excpet for K82F and K64F which are left as an example --- .../TARGET_K20XX/TARGET_K20D50M/PinNames.h | 5 ----- .../TARGET_Freescale/TARGET_KLXX/TARGET_KL25Z/PinNames.h | 5 ----- .../TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/PinNames.h | 5 ----- .../TARGET_K66F/TARGET_FRDM/PinNames.h | 5 ----- .../TARGET_KL43Z/TARGET_FRDM/PinNames.h | 5 ----- .../TARGET_MCU_K22F512/TARGET_FRDM/PinNames.h | 5 ----- .../TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h | 5 ----- targets/TARGET_NUVOTON/TARGET_M451/PinNames.h | 5 ----- targets/TARGET_NUVOTON/TARGET_M480/PinNames.h | 5 ----- targets/TARGET_NUVOTON/TARGET_NUC472/PinNames.h | 5 ----- .../TARGET_LPC11UXX/TARGET_LPC11U37H_401/PinNames.h | 5 ----- .../TARGET_LPC176X/TARGET_MBED_LPC1768/PinNames.h | 6 ------ .../TARGET_LPC176X/TARGET_XBED_LPC1768/PinNames.h | 5 ----- .../TARGET_LPC54114/TARGET_LPCXpresso/PinNames.h | 8 +------- .../TARGET_RZ_A1XX/TARGET_GR_LYCHEE/PinNames.h | 5 ----- .../TARGET_AMEBA/TARGET_RTL8195A/PinNames.h | 4 +--- .../TARGET_STM32F0/TARGET_DISCO_F051R8/PinNames.h | 1 - .../TARGET_STM32F4/TARGET_MTB_MTS_DRAGONFLY/PinNames.h | 3 --- .../TARGET_MTB_MXCHIP_EMW3166/PinNames.h | 1 - .../TARGET_STM32F412xG/TARGET_USI_WM_BN_BM_22/PinNames.h | 1 - .../TARGET_STM32F437xG/TARGET_UBLOX_C030/PinNames.h | 2 -- .../TARGET_MTB_UBLOX_ODIN_W2/PinNames.h | 1 - .../TARGET_UBLOX_EVK_ODIN_W2/PinNames.h | 3 +-- .../TARGET_STM32L0/TARGET_NUCLEO_L031K6/PinNames.h | 1 - .../TARGET_DISCO_L475VG_IOT01A/PinNames.h | 1 - .../TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PinNames.h | 1 - .../TARGET_MTB_ADV_WISE_1570/PinNames.h | 3 +-- .../TARGET_EFR32MG12/TARGET_TB_SENSE_12/PinNames.h | 8 +------- 28 files changed, 5 insertions(+), 104 deletions(-) diff --git a/targets/TARGET_Freescale/TARGET_K20XX/TARGET_K20D50M/PinNames.h b/targets/TARGET_Freescale/TARGET_K20XX/TARGET_K20D50M/PinNames.h index 19168198f8..7bba6da7ea 100644 --- a/targets/TARGET_Freescale/TARGET_K20XX/TARGET_K20D50M/PinNames.h +++ b/targets/TARGET_Freescale/TARGET_K20XX/TARGET_K20D50M/PinNames.h @@ -236,11 +236,6 @@ typedef enum { TSI_ELEC0 = PTB16, TSI_ELEC1 = PTB17, - - SPI_MOSI = PTD2, - SPI_MISO = PTD3, - SPI_CLK = PTD1, - SPI_PERSISTENT_MEM_CS = PTC2, // Not connected NC = (int)0xFFFFFFFF diff --git a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL25Z/PinNames.h b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL25Z/PinNames.h index 8b8935d25a..89ebb11aec 100644 --- a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL25Z/PinNames.h +++ b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL25Z/PinNames.h @@ -236,11 +236,6 @@ typedef enum { TSI_ELEC0 = PTB16, TSI_ELEC1 = PTB17, - SPI_MOSI = PTD2, - SPI_MISO = PTD3, - SPI_SCK = PTD1, - SPI_PERSISTENT_MEM_CS = PTD0, - // Not connected NC = (int)0xFFFFFFFF } PinName; diff --git a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/PinNames.h b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/PinNames.h index 559c0ee582..83b2dae7b9 100644 --- a/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/PinNames.h +++ b/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL46Z/PinNames.h @@ -242,11 +242,6 @@ typedef enum { TSI_ELEC0 = PTB16, TSI_ELEC1 = PTB17, - SPI_MOSI = PTD6, - SPI_MISO = PTD7, - SPI_SCK = PTD5, - SPI_PERSISTENT_MEM_CS = PTD4, - // Not connected NC = (int)0xFFFFFFFF } PinName; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/PinNames.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/PinNames.h index 39575f953d..7ff8b86d75 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/PinNames.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/TARGET_FRDM/PinNames.h @@ -242,11 +242,6 @@ typedef enum { DAC0_OUT = 0xFEFE, /* DAC does not have Pin Name in RM */ - SPI_MOSI = PTE3, - SPI_MISO = PTE1, - SPI_SCK = PTE2, - SPI_PERSISTENT_MEM_CS = PTE4, - // Not connected NC = (int)0xFFFFFFFF } PinName; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PinNames.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PinNames.h index 6b46853878..081010164c 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PinNames.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PinNames.h @@ -134,11 +134,6 @@ typedef enum { A4 = PTC2, A5 = PTC1, - SPI_MOSI = PTD6, - SPI_MISO = PTD7, - SPI_SCK = PTD5, - SPI_PERSISTENT_MEM_CS = PTD4, - // Not connected NC = (int)0xFFFFFFFF } PinName; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/TARGET_MCU_K22F512/TARGET_FRDM/PinNames.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/TARGET_MCU_K22F512/TARGET_FRDM/PinNames.h index 34fa2e1678..3533d831c7 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/TARGET_MCU_K22F512/TARGET_FRDM/PinNames.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/TARGET_MCU_K22F512/TARGET_FRDM/PinNames.h @@ -243,11 +243,6 @@ typedef enum { DAC0_OUT = 0xFEFE, /* DAC does not have Pin Name in RM */ - SPI_MOSI = PTD6, - SPI_MISO = PTD7, - SPI_SCK = PTD5, - SPI_PERSISTENT_MEM_CS = PTD4, - // Not connected NC = (int)0xFFFFFFFF } PinName; diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h index 6fd118dbf5..5730e040c1 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/PinNames.h @@ -197,11 +197,6 @@ typedef enum { SPIS_PSELMISO = P1_3, SPIS_PSELSS = P1_1, SPIS_PSELSCK = P1_4, - - SPI_MOSI = p20, - SPI_MISO = p21, - SPI_SCK = p19, - SPI_PERSISTENT_MEM_CS = p17, I2C_SDA0 = p26, I2C_SCL0 = p27, diff --git a/targets/TARGET_NUVOTON/TARGET_M451/PinNames.h b/targets/TARGET_NUVOTON/TARGET_M451/PinNames.h index e67c71ce01..4599c86ca9 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/PinNames.h +++ b/targets/TARGET_NUVOTON/TARGET_M451/PinNames.h @@ -128,11 +128,6 @@ typedef enum { SW2 = PA_15, SW3 = PA_14, - SPI_MOSI = PD_13, - SPI_MISO = PD_14, - SPI_SCK = PD_15, - SPI_PERSISTENT_MEM_CS = PD_12, - } PinName; #ifdef __cplusplus diff --git a/targets/TARGET_NUVOTON/TARGET_M480/PinNames.h b/targets/TARGET_NUVOTON/TARGET_M480/PinNames.h index a1f37e9dbe..816d5ece49 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/PinNames.h +++ b/targets/TARGET_NUVOTON/TARGET_M480/PinNames.h @@ -128,11 +128,6 @@ typedef enum { SW2 = PG_15, SW3 = PF_11, - SPI_MOSI = D11, - SPI_MISO = D12, - SPI_SCK = D13, - SPI_PERSISTENT_MEM_CS = D10, - } PinName; #ifdef __cplusplus diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/PinNames.h b/targets/TARGET_NUVOTON/TARGET_NUC472/PinNames.h index e9c9d02646..4beecb4b88 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/PinNames.h +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/PinNames.h @@ -131,11 +131,6 @@ typedef enum { SW1 = PC_12, SW2 = PC_13, - SPI_MOSI = PF_0, - SPI_MISO = PD_15, - SPI_SCK = PD_14, - SPI_PERSISTENT_MEM_CS = PD_13, - } PinName; #ifdef __cplusplus diff --git a/targets/TARGET_NXP/TARGET_LPC11UXX/TARGET_LPC11U37H_401/PinNames.h b/targets/TARGET_NXP/TARGET_LPC11UXX/TARGET_LPC11U37H_401/PinNames.h index 4eeef0a2c5..56e1f557f4 100644 --- a/targets/TARGET_NXP/TARGET_LPC11UXX/TARGET_LPC11U37H_401/PinNames.h +++ b/targets/TARGET_NXP/TARGET_LPC11UXX/TARGET_LPC11U37H_401/PinNames.h @@ -148,11 +148,6 @@ typedef enum { SDSCLK = P1_29, SDSSEL = P1_12, - SPI_MOSI = SDMOSI, - SPI_MISO = SDMISO, - SPI_SCK = SDSCLK, - SPI_PERSISTENT_MEM_CS = SDSSEL, - // Not connected NC = (int)0xFFFFFFFF, } PinName; diff --git a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_MBED_LPC1768/PinNames.h b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_MBED_LPC1768/PinNames.h index da5360291a..fa0b722f70 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_MBED_LPC1768/PinNames.h +++ b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_MBED_LPC1768/PinNames.h @@ -149,12 +149,6 @@ typedef enum { I2C_SDA2 = P0_10, // pin used by application board I2C_SCL = I2C_SCL2, I2C_SDA = I2C_SDA2, - - SPI_MOSI = p5, - SPI_MISO = p6, - SPI_SCK = p7, - SPI_PERSISTENT_MEM_CS = p8 - } PinName; typedef enum { diff --git a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_XBED_LPC1768/PinNames.h b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_XBED_LPC1768/PinNames.h index 0e036ca1ea..50bdb1bb57 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/TARGET_XBED_LPC1768/PinNames.h +++ b/targets/TARGET_NXP/TARGET_LPC176X/TARGET_XBED_LPC1768/PinNames.h @@ -117,11 +117,6 @@ typedef enum { I2C_SCL = D15, I2C_SDA = D14, - SPI_MOSI = p5, - SPI_MISO = p6, - SPI_SCK = p7, - SPI_PERSISTENT_MEM_CS = p8, - // Not connected NC = (int)0xFFFFFFFF } PinName; diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/TARGET_LPCXpresso/PinNames.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/TARGET_LPCXpresso/PinNames.h index 51f5340e21..7857ad12e5 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/TARGET_LPCXpresso/PinNames.h +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/TARGET_LPCXpresso/PinNames.h @@ -128,13 +128,7 @@ typedef enum { A2 = P1_8, A3 = P1_10, A4 = P1_4, - A5 = P1_5, - - SPI_MOSI = P0_20, - SPI_MISO = P0_18, - SPI_SCK = P0_19, - SPI_PERSISTENT_MEM_CS = P1_2 - + A5 = P1_5 } PinName; diff --git a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_GR_LYCHEE/PinNames.h b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_GR_LYCHEE/PinNames.h index ed201fe48d..d60a4b5a55 100644 --- a/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_GR_LYCHEE/PinNames.h +++ b/targets/TARGET_RENESAS/TARGET_RZ_A1XX/TARGET_GR_LYCHEE/PinNames.h @@ -89,11 +89,6 @@ typedef enum { // Standardized button names BUTTON1 = USER_BUTTON0, - SPI_MOSI = P5_6, - SPI_MISO = P5_7, - SPI_SCK = P5_4, - SPI_PERSISTENT_MEM_CS = P5_5, - // Not connected NC = (int)0xFFFFFFFF } PinName; diff --git a/targets/TARGET_Realtek/TARGET_AMEBA/TARGET_RTL8195A/PinNames.h b/targets/TARGET_Realtek/TARGET_AMEBA/TARGET_RTL8195A/PinNames.h index a9d0fb4e5c..60895420ed 100644 --- a/targets/TARGET_Realtek/TARGET_AMEBA/TARGET_RTL8195A/PinNames.h +++ b/targets/TARGET_Realtek/TARGET_AMEBA/TARGET_RTL8195A/PinNames.h @@ -216,9 +216,7 @@ typedef enum { D15 = PB_2, D16 = PA_1, D17 = PA_0, - D18 = PE_5, - - SPI_PERSISTENT_MEM_CS = D9 + D18 = PE_5 } PinName; diff --git a/targets/TARGET_STM/TARGET_STM32F0/TARGET_DISCO_F051R8/PinNames.h b/targets/TARGET_STM/TARGET_STM32F0/TARGET_DISCO_F051R8/PinNames.h index 4296e71217..6b25d5c481 100644 --- a/targets/TARGET_STM/TARGET_STM32F0/TARGET_DISCO_F051R8/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32F0/TARGET_DISCO_F051R8/PinNames.h @@ -228,7 +228,6 @@ typedef enum { SPI_MISO = PA_6, SPI_SCK = PA_5, SPI_CS = PB_6, - SPI_PERSISTENT_MEM_CS = PB_6, PWM_OUT = PB_3, /**** OSCILLATOR pins ****/ diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTB_MTS_DRAGONFLY/PinNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTB_MTS_DRAGONFLY/PinNames.h index 6eb0cc1805..42fa8e5fa1 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTB_MTS_DRAGONFLY/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_MTB_MTS_DRAGONFLY/PinNames.h @@ -186,12 +186,9 @@ typedef enum { SPI_MOSI = SPI1_MOSI, SPI_MISO = SPI1_MISO, SPI_SCK = SPI1_SCK, - SPI_CS1 = PA_3, //LCD CS SPI_CS2 = PA_15, //SD Card CS - SPI_PERSISTENT_MEM_CS = SPI_CS2, - SERIAL_TX = PA_2, SERIAL_RX = PA_3, SERIAL_RTS = PA_0, diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_MTB_MXCHIP_EMW3166/PinNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_MTB_MXCHIP_EMW3166/PinNames.h index 019e9caa97..80e698307c 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_MTB_MXCHIP_EMW3166/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_MTB_MXCHIP_EMW3166/PinNames.h @@ -219,7 +219,6 @@ typedef enum { SPI_MISO = P_7, SPI_SCK = P_6, SPI_CS = P_5, - SPI_PERSISTENT_MEM_CS = P_33, // STDIO for console print #ifdef MBED_CONF_TARGET_STDIO_UART_TX diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_USI_WM_BN_BM_22/PinNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_USI_WM_BN_BM_22/PinNames.h index 1e7f950e48..42969ea6bc 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_USI_WM_BN_BM_22/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F412xG/TARGET_USI_WM_BN_BM_22/PinNames.h @@ -271,7 +271,6 @@ typedef enum { SPI_MISO = P_25, SPI_SCK = P_24, SPI_CS = P_22, - SPI_PERSISTENT_MEM_CS = P_36, // STDIO for console print #ifdef MBED_CONF_TARGET_STDIO_UART_TX diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/TARGET_UBLOX_C030/PinNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/TARGET_UBLOX_C030/PinNames.h index ad5aef1971..2f9f84c09c 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/TARGET_UBLOX_C030/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/TARGET_UBLOX_C030/PinNames.h @@ -151,8 +151,6 @@ typedef enum { SPI_MISO = D12, SPI_CLK = D13, SPI_NSS = D10, - SPI_PERSISTENT_MEM_CS = SPI_NSS, - // STDIO for console print #ifdef MBED_CONF_TARGET_STDIO_UART_TX diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/TARGET_MTB_UBLOX_ODIN_W2/PinNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/TARGET_MTB_UBLOX_ODIN_W2/PinNames.h index 702b174ff4..c61f4dd431 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/TARGET_MTB_UBLOX_ODIN_W2/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/TARGET_MTB_UBLOX_ODIN_W2/PinNames.h @@ -176,7 +176,6 @@ typedef enum { SPI_MISO = SPI0_MISO, SPI_SCK = SPI0_SCK, SPI_CS = SPI0_CS, - SPI_PERSISTENT_MEM_CS = PG_4, // STDIO for console print #ifdef MBED_CONF_TARGET_STDIO_UART_TX diff --git a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/TARGET_UBLOX_EVK_ODIN_W2/PinNames.h b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/TARGET_UBLOX_EVK_ODIN_W2/PinNames.h index da5e2951a0..b876c11f1e 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/TARGET_UBLOX_EVK_ODIN_W2/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/TARGET_UBLOX_EVK_ODIN_W2/PinNames.h @@ -167,13 +167,12 @@ typedef enum { SPI0_SCK = D13, SPI0_CS = D10, SPI1_CS = D9, - SPI_MOSI = SPI0_MOSI, SPI_MISO = SPI0_MISO, SPI_SCK = SPI0_SCK, SPI_CS = SPI0_CS, - SPI_PERSISTENT_MEM_CS = SPI_CS, + // Standardized button names BUTTON1 = SW0, diff --git a/targets/TARGET_STM/TARGET_STM32L0/TARGET_NUCLEO_L031K6/PinNames.h b/targets/TARGET_STM/TARGET_STM32L0/TARGET_NUCLEO_L031K6/PinNames.h index bd6f3b00f1..910facf89a 100644 --- a/targets/TARGET_STM/TARGET_STM32L0/TARGET_NUCLEO_L031K6/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32L0/TARGET_NUCLEO_L031K6/PinNames.h @@ -133,7 +133,6 @@ typedef enum { SPI_MISO = PB_4, SPI_SCK = PB_3, SPI_CS = PA_11, - SPI_PERSISTENT_MEM_CS = PA_11, PWM_OUT = PB_0, /**** OSCILLATOR pins ****/ diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PinNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PinNames.h index 7e427cc1bd..c1197d596c 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PinNames.h @@ -239,7 +239,6 @@ typedef enum { SPI_MISO = D12, SPI_SCK = D13, SPI_CS = D10, - SPI_PERSISTENT_MEM_CS = D10, PWM_OUT = D9, #ifdef DEVICE_QSPI QSPI_PIN_IO0 = PE_12, diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PinNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PinNames.h index a5686fc166..8e2bf1d467 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L476xG/TARGET_NUCLEO_L476RG/PinNames.h @@ -208,7 +208,6 @@ typedef enum { SPI_MISO = PA_6, SPI_SCK = PA_5, SPI_CS = PB_6, - SPI_PERSISTENT_MEM_CS = PB_6, PWM_OUT = PB_3, /**** USB pins ****/ diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_MTB_ADV_WISE_1570/PinNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_MTB_ADV_WISE_1570/PinNames.h index 769163db2c..06bb5f4438 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_MTB_ADV_WISE_1570/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L486xG/TARGET_MTB_ADV_WISE_1570/PinNames.h @@ -124,8 +124,7 @@ typedef enum { SPI_SCK = PA_5, SPI_CS0 = PA_4, SPI_CS = SPI_CS0, - SPI_PERSISTENT_MEM_CS = PB_12, - + I2C1_SDA = PB_11, I2C1_SCL = PB_10, diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFR32MG12/TARGET_TB_SENSE_12/PinNames.h b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFR32MG12/TARGET_TB_SENSE_12/PinNames.h index 936b30acfa..39e905f421 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFR32MG12/TARGET_TB_SENSE_12/PinNames.h +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/TARGET_EFR32MG12/TARGET_TB_SENSE_12/PinNames.h @@ -74,13 +74,7 @@ typedef enum { /* Board Controller */ STDIO_UART_TX = USBTX, - STDIO_UART_RX = USBRX, - - SPI_MOSI = PC6, - SPI_MISO = PC7, - SPI_SCK = PC8, - SPI_PERSISTENT_MEM_CS = PC9 - + STDIO_UART_RX = USBRX } PinName; #ifdef __cplusplus From 4fb4994563a7de324f2f12cf71f06d5b25807f65 Mon Sep 17 00:00:00 2001 From: Antti Yli-Tokola Date: Thu, 6 Sep 2018 16:08:49 +0300 Subject: [PATCH 14/26] Update mbed-coap to version 4.6.3 - Bug fix: Remove timed out blockwise message from resend queue. If blockwise message was timed out message was still kept in the resend queue which causes unnecessary reconnections on client side. - Documentation: Document all the available macros. --- features/frameworks/mbed-coap/CHANGELOG.md | 7 ++ .../mbed-coap/mbed-coap/sn_config.h | 91 ++++++++++++++++--- features/frameworks/mbed-coap/module.json | 2 +- .../mbed-coap/source/sn_coap_protocol.c | 1 + 4 files changed, 85 insertions(+), 16 deletions(-) diff --git a/features/frameworks/mbed-coap/CHANGELOG.md b/features/frameworks/mbed-coap/CHANGELOG.md index 1cbbbee6b3..70c9706541 100644 --- a/features/frameworks/mbed-coap/CHANGELOG.md +++ b/features/frameworks/mbed-coap/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## [v4.6.3](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.6.3) + + - Bug fix: Remove timed out blockwise message from resend queue. If blockwise message was timed out message was still kept in the resend queue which causes unnecessary reconnections on client side. + - Documentation: Document all the available macros. + +-[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.6.2...v4.6.3) + ## [v4.6.2](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.6.2) Do not clear block2 in subsequent block request. diff --git a/features/frameworks/mbed-coap/mbed-coap/sn_config.h b/features/frameworks/mbed-coap/mbed-coap/sn_config.h index 8c1477bcdb..5794af5cbc 100644 --- a/features/frameworks/mbed-coap/mbed-coap/sn_config.h +++ b/features/frameworks/mbed-coap/mbed-coap/sn_config.h @@ -36,7 +36,6 @@ /** * \def SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE - * * \brief For Message blockwising * Init value for the maximum payload size to be sent and received at one blockwise message * Setting of this value to 0 with SN_COAP_BLOCKWISE_ENABLED will disable this feature, and @@ -45,19 +44,8 @@ */ #undef SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* 0 */ // < Must be 2^x and x is at least 4. Suitable values: 0, 16, 32, 64, 128, 256, 512 and 1024 -/** - * \def COAP_DISABLE_OBS_FEATURE - * - * \brief Disables CoAP 'obs' sending feature - * as part of registration message, this might be - * needed to be enabled for some strict LWM2M server implementation. - * By default, this feature is disabled. - */ -#undef COAP_DISABLE_OBS_FEATURE - /** * \def SN_COAP_DISABLE_RESENDINGS - * * \brief Disables resending feature. Resending feature should not be needed * when using CoAP with TCP transport for example. By default resendings are * enabled. Set to 1 to disable. @@ -66,15 +54,20 @@ /** * \def SN_COAP_RESENDING_QUEUE_SIZE_MSGS - * * \brief Sets the number of messages stored * in the resending queue. Default is 2 */ #undef SN_COAP_RESENDING_QUEUE_SIZE_MSGS /* 2 */ // < Default re-sending queue size - defines how many messages can be stored. Setting this to 0 disables feature +/** + * \def DEFAULT_RESPONSE_TIMEOUT + * \brief Sets the CoAP re-send interval in seconds. + * By default is 10 seconds. + */ +#undef DEFAULT_RESPONSE_TIMEOUT + /** * \def SN_COAP_RESENDING_QUEUE_SIZE_BYTES - * * \brief Sets the size of the re-sending buffer. * Setting this to 0 disables this feature. * By default, this feature is disabled. @@ -83,7 +76,6 @@ /** * \def SN_COAP_MAX_INCOMING_MESSAGE_SIZE - * * \brief Sets the maximum size (in bytes) that * mbed Client will allow to be handled while * receiving big payload in blockwise mode. @@ -115,6 +107,75 @@ */ #undef SN_COAP_BLOCKWISE_ENABLED /* 0 */ +/** + * \def SN_COAP_RESENDING_MAX_COUNT + * \brief Defines how many times CoAP library tries to re-send the CoAP packet. + * By default value is 3. + */ +#undef SN_COAP_RESENDING_MAX_COUNT /* 3 */ + +/** + * \def SN_COAP_MAX_ALLOWED_RESENDING_COUNT + * \brief Maximum allowed count of re-sending that can be set at runtime via + * 'sn_coap_protocol_set_retransmission_parameters()' API. + * By default value is 6. + */ +#undef SN_COAP_MAX_ALLOWED_RESENDING_COUNT /* 6 */ + +/** + * \def SN_COAP_MAX_ALLOWED_RESPONSE_TIMEOUT + * \brief Maximum allowed re-send interval in seconds that can be set at runtime via + * 'sn_coap_protocol_set_retransmission_parameters()' API. + * By default value is 40. + */ +#undef SN_COAP_MAX_ALLOWED_RESPONSE_TIMEOUT /* 40 */ + +/** + * \def SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_MSGS + * \brief Maximum allowed count of messages that can be stored into resend buffer at runtime via + * 'sn_coap_protocol_set_retransmission_buffer()' API. + * By default value is 6. + */ +#undef SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_MSGS /* 6 */ + +/** + * \def SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_BYTES + * \brief Maximum size of messages in bytes that can be stored into resend buffer at runtime via + * 'sn_coap_protocol_set_retransmission_buffer()' API. + * By default value is 512. + */ +#undef SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_BYTES /* 512 */ + +/** + * \def SN_COAP_MAX_ALLOWED_DUPLICATION_MESSAGE_COUNT + * \brief Maximum allowed number of saved messages for message duplicate searching + * that can be set via 'sn_coap_protocol_set_duplicate_buffer_size' API. + * By default value is 6. + */ +#undef SN_COAP_MAX_ALLOWED_DUPLICATION_MESSAGE_COUNT + +/** + * \def SN_COAP_DUPLICATION_MAX_TIME_MSGS_STORED + * \brief Maximum time in seconds howe long message is kept for duplicate detection. + * By default 60 seconds. + */ +#undef SN_COAP_DUPLICATION_MAX_TIME_MSGS_STORED + +/** + * \def SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED + * \brief Maximum time in seconds how long (messages and payload) are be stored for blockwising. + * Longer time will increase the memory consumption in lossy networks. + * By default 60 seconds. + */ +#undef SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED + +/** + * \def SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE + * \brief Maximum size of blockwise message that can be received. + * By default 65535 bytes. + */ +#undef SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE + #ifdef MBED_CLIENT_USER_CONFIG_FILE #include MBED_CLIENT_USER_CONFIG_FILE #endif diff --git a/features/frameworks/mbed-coap/module.json b/features/frameworks/mbed-coap/module.json index 717c79a7f5..97bf7341db 100644 --- a/features/frameworks/mbed-coap/module.json +++ b/features/frameworks/mbed-coap/module.json @@ -1,6 +1,6 @@ { "name": "mbed-coap", - "version": "4.6.2", + "version": "4.6.3", "description": "COAP library", "keywords": [ "coap", diff --git a/features/frameworks/mbed-coap/source/sn_coap_protocol.c b/features/frameworks/mbed-coap/source/sn_coap_protocol.c index 2970678698..377e341550 100644 --- a/features/frameworks/mbed-coap/source/sn_coap_protocol.c +++ b/features/frameworks/mbed-coap/source/sn_coap_protocol.c @@ -1559,6 +1559,7 @@ static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle) /* Notify the application about the time out */ removed_blocwise_msg_ptr->coap_msg_ptr->coap_status = COAP_STATUS_BUILDER_BLOCK_SENDING_FAILED; removed_blocwise_msg_ptr->coap_msg_ptr->msg_id = removed_blocwise_msg_ptr->msg_id; + sn_coap_protocol_delete_retransmission(handle, removed_blocwise_msg_ptr->msg_id); handle->sn_coap_rx_callback(removed_blocwise_msg_ptr->coap_msg_ptr, NULL, removed_blocwise_msg_ptr->param); } From ee03d835273b9050dbc5f6ec41cd635979967f28 Mon Sep 17 00:00:00 2001 From: Maciej Bocianski Date: Wed, 5 Sep 2018 13:59:03 +0200 Subject: [PATCH 15/26] QSPI driver: API parameters fix --- drivers/QSPI.cpp | 10 +++++----- drivers/QSPI.h | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/QSPI.cpp b/drivers/QSPI.cpp index e0cb3b62d1..9a75d79727 100644 --- a/drivers/QSPI.cpp +++ b/drivers/QSPI.cpp @@ -91,7 +91,7 @@ qspi_status_t QSPI::set_frequency(int hz) return ret_status; } -qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_length) +qspi_status_t QSPI::read(int address, char *rx_buffer, size_t *rx_length) { qspi_status_t ret_status = QSPI_STATUS_ERROR; @@ -115,7 +115,7 @@ qspi_status_t QSPI::read(unsigned int address, char *rx_buffer, size_t *rx_lengt return ret_status; } -qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *tx_length) +qspi_status_t QSPI::write(int address, const char *tx_buffer, size_t *tx_length) { qspi_status_t ret_status = QSPI_STATUS_ERROR; @@ -139,7 +139,7 @@ qspi_status_t QSPI::write(unsigned int address, const char *tx_buffer, size_t *t return ret_status; } -qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned int address, char *rx_buffer, size_t *rx_length) +qspi_status_t QSPI::read(int instruction, int alt, int address, char *rx_buffer, size_t *rx_length) { qspi_status_t ret_status = QSPI_STATUS_ERROR; @@ -163,7 +163,7 @@ qspi_status_t QSPI::read(unsigned int instruction, unsigned int alt, unsigned in return ret_status; } -qspi_status_t QSPI::write(unsigned int instruction, unsigned int alt, unsigned int address, const char *tx_buffer, size_t *tx_length) +qspi_status_t QSPI::write(int instruction, int alt, int address, const char *tx_buffer, size_t *tx_length) { qspi_status_t ret_status = QSPI_STATUS_ERROR; @@ -187,7 +187,7 @@ qspi_status_t QSPI::write(unsigned int instruction, unsigned int alt, unsigned i return ret_status; } -qspi_status_t QSPI::command_transfer(unsigned int instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length) +qspi_status_t QSPI::command_transfer(int instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length) { qspi_status_t ret_status = QSPI_STATUS_ERROR; diff --git a/drivers/QSPI.h b/drivers/QSPI.h index c166e4bc55..f5df0a18fa 100644 --- a/drivers/QSPI.h +++ b/drivers/QSPI.h @@ -118,7 +118,7 @@ public: * @returns * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads. */ - qspi_status_t read(unsigned int address, char *rx_buffer, size_t *rx_length); + qspi_status_t read(int address, char *rx_buffer, size_t *rx_length); /** Write to QSPI peripheral using custom write instruction * @@ -129,12 +129,12 @@ public: * @returns * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads. */ - qspi_status_t write(unsigned int address, const char *tx_buffer, size_t *tx_length); + qspi_status_t write(int address, const char *tx_buffer, size_t *tx_length); /** Read from QSPI peripheral using custom read instruction, alt values * * @param instruction Instruction value to be used in instruction phase - * @param alt Alt value to be used in instruction phase + * @param alt Alt value to be used in Alternate-byte phase. Use -1 for ignoring Alternate-byte phase * @param address Address to be accessed in QSPI peripheral * @param rx_buffer Buffer for data to be read from the peripheral * @param rx_length Pointer to a variable containing the length of rx_buffer, and on return this variable will be updated with the actual number of bytes read @@ -142,12 +142,12 @@ public: * @returns * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads. */ - qspi_status_t read(unsigned int instruction, unsigned int alt, unsigned int address, char *rx_buffer, size_t *rx_length); + qspi_status_t read(int instruction, int alt, int address, char *rx_buffer, size_t *rx_length); /** Write to QSPI peripheral using custom write instruction, alt values * * @param instruction Instruction value to be used in instruction phase - * @param alt Alt value to be used in instruction phase + * @param alt Alt value to be used in Alternate-byte phase. Use -1 for ignoring Alternate-byte phase * @param address Address to be accessed in QSPI peripheral * @param tx_buffer Buffer containing data to be sent to peripheral * @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written @@ -155,12 +155,12 @@ public: * @returns * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads. */ - qspi_status_t write(unsigned int instruction, unsigned int alt, unsigned int address, const char *tx_buffer, size_t *tx_length); + qspi_status_t write(int instruction, int alt, int address, const char *tx_buffer, size_t *tx_length); /** Perform a transaction to write to an address(a control register) and get the status results * * @param instruction Instruction value to be used in instruction phase - * @param address Some instruction might require address. Use -1 for ignoring the address value + * @param address Some instruction might require address. Use -1 if no address * @param tx_buffer Buffer containing data to be sent to peripheral * @param tx_length Pointer to a variable containing the length of data to be transmitted, and on return this variable will be updated with the actual number of bytes written * @param rx_buffer Buffer for data to be read from the peripheral @@ -169,7 +169,7 @@ public: * @returns * Returns QSPI_STATUS_SUCCESS on successful reads and QSPI_STATUS_ERROR on failed reads. */ - qspi_status_t command_transfer(unsigned int instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length); + qspi_status_t command_transfer(int instruction, int address, const char *tx_buffer, size_t tx_length, const char *rx_buffer, size_t rx_length); protected: /** Acquire exclusive access to this SPI bus From 1caf262855af5c1a1eece7cbcb72554053d7885c Mon Sep 17 00:00:00 2001 From: jeromecoutant Date: Tue, 7 Aug 2018 14:30:23 +0200 Subject: [PATCH 16/26] python scripts : table print with github policy --- tools/build_api.py | 8 ++++---- tools/memap.py | 4 ++-- tools/test_api.py | 16 ++++++++-------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tools/build_api.py b/tools/build_api.py index c3140b455e..4a3de865d3 100644 --- a/tools/build_api.py +++ b/tools/build_api.py @@ -1161,7 +1161,7 @@ def mcu_toolchain_matrix(verbose_html=False, platform_filter=None, release_version - get the matrix for this major version number """ # Only use it in this function so building works without extra modules - from prettytable import PrettyTable + from prettytable import PrettyTable, HEADER release_version = _lowercase_release_version(release_version) version_release_targets = {} version_release_target_names = {} @@ -1183,7 +1183,7 @@ def mcu_toolchain_matrix(verbose_html=False, platform_filter=None, # All tests status table print columns = prepend_columns + unique_supported_toolchains - table_printer = PrettyTable(columns) + table_printer = PrettyTable(columns, junction_char="|", hrules=HEADER) # Align table for col in columns: table_printer.align[col] = "c" @@ -1271,10 +1271,10 @@ def print_build_memory_usage(report): Positional arguments: report - Report generated during build procedure. """ - from prettytable import PrettyTable + from prettytable import PrettyTable, HEADER columns_text = ['name', 'target', 'toolchain'] columns_int = ['static_ram', 'total_flash'] - table = PrettyTable(columns_text + columns_int) + table = PrettyTable(columns_text + columns_int, junction_char="|", hrules=HEADER) for col in columns_text: table.align[col] = 'l' diff --git a/tools/memap.py b/tools/memap.py index eab3864c82..00c5aa36f5 100644 --- a/tools/memap.py +++ b/tools/memap.py @@ -19,7 +19,7 @@ import json from argparse import ArgumentParser from copy import deepcopy from collections import defaultdict -from prettytable import PrettyTable +from prettytable import PrettyTable, HEADER from jinja2 import FileSystemLoader, StrictUndefined from jinja2.environment import Environment @@ -726,7 +726,7 @@ class MemapParser(object): columns = ['Module'] columns.extend(self.print_sections) - table = PrettyTable(columns) + table = PrettyTable(columns, junction_char="|", hrules=HEADER) table.align["Module"] = "l" for col in self.print_sections: table.align[col] = 'r' diff --git a/tools/test_api.py b/tools/test_api.py index 848b5f8405..c5de7318f6 100644 --- a/tools/test_api.py +++ b/tools/test_api.py @@ -32,7 +32,7 @@ import threading import ctypes import functools from colorama import Fore, Back, Style -from prettytable import PrettyTable +from prettytable import PrettyTable, HEADER from copy import copy, deepcopy from time import sleep, time @@ -766,7 +766,7 @@ class SingleTestRunner(object): result_dict[test[TEST_INDEX]][test[TOOLCHAIN_INDEX]] = test[RESULT_INDEX] pt_cols = ["Target", "Test ID", "Test Description"] + unique_target_toolchains - pt = PrettyTable(pt_cols) + pt = PrettyTable(pt_cols, junction_char="|", hrules=HEADER) for col in pt_cols: pt.align[col] = "l" pt.padding_width = 1 # One space between column edges and contents (default) @@ -794,7 +794,7 @@ class SingleTestRunner(object): result = "Test summary:\n" # Pretty table package is used to print results pt = PrettyTable(["Result", "Target", "Toolchain", "Test ID", "Test Description", - "Elapsed Time (sec)", "Timeout (sec)", "Loops"]) + "Elapsed Time (sec)", "Timeout (sec)", "Loops"], junction_char="|", hrules=HEADER) pt.align["Result"] = "l" # Left align pt.align["Target"] = "l" # Left align pt.align["Toolchain"] = "l" # Left align @@ -1328,7 +1328,7 @@ def print_muts_configuration_from_json(json_data, join_delim=", ", platform_filt # Prepare pretty table object to display all MUTs pt_cols = ["index"] + muts_info_cols - pt = PrettyTable(pt_cols) + pt = PrettyTable(pt_cols, junction_char="|", hrules=HEADER) for col in pt_cols: pt.align[col] = "l" @@ -1366,7 +1366,7 @@ def print_test_configuration_from_json(json_data, join_delim=", "): # Prepare pretty table object to display test specification pt_cols = ["mcu"] + sorted(toolchains_info_cols) - pt = PrettyTable(pt_cols) + pt = PrettyTable(pt_cols, junction_char="|", hrules=HEADER) for col in pt_cols: pt.align[col] = "l" @@ -1455,7 +1455,7 @@ def get_avail_tests_summary_table(cols=None, result_summary=True, join_delim=',' 'duration'] if cols is None else cols # All tests status table print - pt = PrettyTable(test_properties) + pt = PrettyTable(test_properties, junction_char="|", hrules=HEADER) for col in test_properties: pt.align[col] = "l" pt.align['duration'] = "r" @@ -1495,7 +1495,7 @@ def get_avail_tests_summary_table(cols=None, result_summary=True, join_delim=',' if result_summary and not platform_filter: # Automation result summary test_id_cols = ['automated', 'all', 'percent [%]', 'progress'] - pt = PrettyTable(test_id_cols) + pt = PrettyTable(test_id_cols, junction_char="|", hrules=HEADER) pt.align['automated'] = "r" pt.align['all'] = "r" pt.align['percent [%]'] = "r" @@ -1509,7 +1509,7 @@ def get_avail_tests_summary_table(cols=None, result_summary=True, join_delim=',' # Test automation coverage table print test_id_cols = ['id', 'automated', 'all', 'percent [%]', 'progress'] - pt = PrettyTable(test_id_cols) + pt = PrettyTable(test_id_cols, junction_char="|", hrules=HEADER) pt.align['id'] = "l" pt.align['automated'] = "r" pt.align['all'] = "r" From df777805fe1381a3bb0af266c4423c96bd6f4322 Mon Sep 17 00:00:00 2001 From: Simon Butcher Date: Thu, 6 Sep 2018 19:28:32 +0100 Subject: [PATCH 17/26] Update Mbed TLS version to 2.13.1 --- features/mbedtls/VERSION.txt | 2 +- features/mbedtls/importer/Makefile | 2 +- features/mbedtls/inc/mbedtls/config.h | 30 ++++++++- features/mbedtls/inc/mbedtls/platform_util.h | 41 ++++++++++++ features/mbedtls/inc/mbedtls/threading.h | 11 ++++ features/mbedtls/inc/mbedtls/version.h | 8 +-- features/mbedtls/src/platform_util.c | 68 ++++++++++++++++++++ features/mbedtls/src/threading.c | 47 ++++++++++++++ features/mbedtls/src/x509.c | 11 +--- 9 files changed, 204 insertions(+), 16 deletions(-) diff --git a/features/mbedtls/VERSION.txt b/features/mbedtls/VERSION.txt index b50aaeaa41..e97cf88ec7 100644 --- a/features/mbedtls/VERSION.txt +++ b/features/mbedtls/VERSION.txt @@ -1 +1 @@ -mbedtls-2.13.0 +mbedtls-2.13.1 diff --git a/features/mbedtls/importer/Makefile b/features/mbedtls/importer/Makefile index 02594acd04..a8d55cf91a 100644 --- a/features/mbedtls/importer/Makefile +++ b/features/mbedtls/importer/Makefile @@ -27,7 +27,7 @@ # # Set the mbed TLS release to import (this can/should be edited before import) -MBED_TLS_RELEASE ?= mbedtls-2.13.0 +MBED_TLS_RELEASE ?= mbedtls-2.13.1 # Translate between mbed TLS namespace and mbed namespace TARGET_PREFIX:=../ diff --git a/features/mbedtls/inc/mbedtls/config.h b/features/mbedtls/inc/mbedtls/config.h index 34569f05e3..5d1d5686cf 100644 --- a/features/mbedtls/inc/mbedtls/config.h +++ b/features/mbedtls/inc/mbedtls/config.h @@ -152,12 +152,21 @@ /** * \def MBEDTLS_HAVE_TIME_DATE * - * System has time.h and time(), gmtime() and the clock is correct. + * System has time.h, time(), and an implementation for + * mbedtls_platform_gmtime_r() (see below). * The time needs to be correct (not necesarily very accurate, but at least * the date should be correct). This is used to verify the validity period of * X.509 certificates. * * Comment if your system does not have a correct clock. + * + * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that + * behaves similarly to the gmtime_r() function from the C standard. Refer to + * the documentation for mbedtls_platform_gmtime_r() for more information. + * + * \note It is possible to configure an implementation for + * mbedtls_platform_gmtime_r() at compile-time by using the macro + * MBEDTLS_PLATFORM_GMTIME_R_ALT. */ //#define MBEDTLS_HAVE_TIME_DATE @@ -3115,6 +3124,25 @@ */ //#define MBEDTLS_PLATFORM_ZEROIZE_ALT +/** + * Uncomment the macro to let Mbed TLS use your alternate implementation of + * mbedtls_platform_gmtime_r(). This replaces the default implementation in + * platform_util.c. + * + * gmtime() is not a thread-safe function as defined in the C standard. The + * library will try to use safer implementations of this function, such as + * gmtime_r() when available. However, if Mbed TLS cannot identify the target + * system, the implementation of mbedtls_platform_gmtime_r() will default to + * using the standard gmtime(). In this case, calls from the library to + * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex + * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the + * library are also guarded with this mutex to avoid race conditions. However, + * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will + * unconditionally use the implementation for mbedtls_platform_gmtime_r() + * supplied at compile time. + */ +//#define MBEDTLS_PLATFORM_GMTIME_R_ALT + /* \} name SECTION: Customisation configuration options */ /* Target and application specific configurations */ diff --git a/features/mbedtls/inc/mbedtls/platform_util.h b/features/mbedtls/inc/mbedtls/platform_util.h index 84f0732eeb..164a1a05f9 100644 --- a/features/mbedtls/inc/mbedtls/platform_util.h +++ b/features/mbedtls/inc/mbedtls/platform_util.h @@ -25,7 +25,17 @@ #ifndef MBEDTLS_PLATFORM_UTIL_H #define MBEDTLS_PLATFORM_UTIL_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_time.h" +#include +#endif /* MBEDTLS_HAVE_TIME_DATE */ #ifdef __cplusplus extern "C" { @@ -55,6 +65,37 @@ extern "C" { */ void mbedtls_platform_zeroize( void *buf, size_t len ); +#if defined(MBEDTLS_HAVE_TIME_DATE) +/** + * \brief Platform-specific implementation of gmtime_r() + * + * The function is a thread-safe abstraction that behaves + * similarly to the gmtime_r() function from Unix/POSIX. + * + * Mbed TLS will try to identify the underlying platform and + * make use of an appropriate underlying implementation (e.g. + * gmtime_r() for POSIX and gmtime_s() for Windows). If this is + * not possible, then gmtime() will be used. In this case, calls + * from the library to gmtime() will be guarded by the mutex + * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is + * enabled. It is recommended that calls from outside the library + * are also guarded by this mutex. + * + * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will + * unconditionally use the alternative implementation for + * mbedtls_platform_gmtime_r() supplied by the user at compile time. + * + * \param tt Pointer to an object containing time (in seconds) since the + * epoch to be converted + * \param tm_buf Pointer to an object where the results will be stored + * + * \return Pointer to an object of type struct tm on success, otherwise + * NULL + */ +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ); +#endif /* MBEDTLS_HAVE_TIME_DATE */ + #ifdef __cplusplus } #endif diff --git a/features/mbedtls/inc/mbedtls/threading.h b/features/mbedtls/inc/mbedtls/threading.h index 5112ebb747..75298bf8a3 100644 --- a/features/mbedtls/inc/mbedtls/threading.h +++ b/features/mbedtls/inc/mbedtls/threading.h @@ -99,6 +99,17 @@ extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); #if defined(MBEDTLS_FS_IO) extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; #endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +/* This mutex may or may not be used in the default definition of + * mbedtls_platform_gmtime_r(), but in order to determine that, + * we need to check POSIX features, hence modify _POSIX_C_SOURCE. + * With the current approach, this declaration is orphaned, lacking + * an accompanying definition, in case mbedtls_platform_gmtime_r() + * doesn't need it, but that's not a problem. */ +extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + #endif /* MBEDTLS_THREADING_C */ #ifdef __cplusplus diff --git a/features/mbedtls/inc/mbedtls/version.h b/features/mbedtls/inc/mbedtls/version.h index 17b8ba450b..326b8bd451 100644 --- a/features/mbedtls/inc/mbedtls/version.h +++ b/features/mbedtls/inc/mbedtls/version.h @@ -40,16 +40,16 @@ */ #define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MINOR 13 -#define MBEDTLS_VERSION_PATCH 0 +#define MBEDTLS_VERSION_PATCH 1 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x020D0000 -#define MBEDTLS_VERSION_STRING "2.13.0" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.13.0" +#define MBEDTLS_VERSION_NUMBER 0x020D0100 +#define MBEDTLS_VERSION_STRING "2.13.1" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.13.1" #if defined(MBEDTLS_VERSION_C) diff --git a/features/mbedtls/src/platform_util.c b/features/mbedtls/src/platform_util.c index 1a57de9393..ca5fe4fb87 100644 --- a/features/mbedtls/src/platform_util.c +++ b/features/mbedtls/src/platform_util.c @@ -20,6 +20,14 @@ * This file is part of Mbed TLS (https://tls.mbed.org) */ +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -27,6 +35,7 @@ #endif #include "mbedtls/platform_util.h" +#include "mbedtls/threading.h" #include #include @@ -65,3 +74,62 @@ void mbedtls_platform_zeroize( void *buf, size_t len ) memset_func( buf, 0, len ); } #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +#include +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define PLATFORM_UTIL_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */ + +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ) +{ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL ); +#elif !defined(PLATFORM_UTIL_USE_GMTIME) + return( gmtime_r( tt, tm_buf ) ); +#else + struct tm *lt; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + lt = gmtime( tt ); + + if( lt != NULL ) + { + memcpy( tm_buf, lt, sizeof( struct tm ) ); + } + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + return( ( lt == NULL ) ? NULL : tm_buf ); +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +} +#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ diff --git a/features/mbedtls/src/threading.c b/features/mbedtls/src/threading.c index 7a32e672c7..7c90c7c595 100644 --- a/features/mbedtls/src/threading.c +++ b/features/mbedtls/src/threading.c @@ -19,6 +19,14 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -29,6 +37,36 @@ #include "mbedtls/threading.h" +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) + +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ + +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define THREADING_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */ + +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + #if defined(MBEDTLS_THREADING_PTHREAD) static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) { @@ -114,6 +152,9 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * #if defined(MBEDTLS_FS_IO) mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); #endif +#if defined(THREADING_USE_GMTIME) + mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); +#endif } /* @@ -124,6 +165,9 @@ void mbedtls_threading_free_alt( void ) #if defined(MBEDTLS_FS_IO) mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); #endif +#if defined(THREADING_USE_GMTIME) + mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); +#endif } #endif /* MBEDTLS_THREADING_ALT */ @@ -136,5 +180,8 @@ void mbedtls_threading_free_alt( void ) #if defined(MBEDTLS_FS_IO) mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; #endif +#if defined(THREADING_USE_GMTIME) +mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; +#endif #endif /* MBEDTLS_THREADING_C */ diff --git a/features/mbedtls/src/x509.c b/features/mbedtls/src/x509.c index 2e6795f750..52b5b649f7 100644 --- a/features/mbedtls/src/x509.c +++ b/features/mbedtls/src/x509.c @@ -29,10 +29,6 @@ * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ -/* Ensure gmtime_r is available even with -std=c99; must be included before - * config.h, which pulls in glibc's features.h. Harmless on other platforms. */ -#define _POSIX_C_SOURCE 200112L - #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -67,6 +63,7 @@ #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_util.h" #include #endif @@ -901,11 +898,7 @@ static int x509_get_current_time( mbedtls_x509_time *now ) int ret = 0; tt = mbedtls_time( NULL ); -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - lt = gmtime_s( &tm_buf, &tt ) == 0 ? &tm_buf : NULL; -#else - lt = gmtime_r( &tt, &tm_buf ); -#endif + lt = mbedtls_platform_gmtime_r( &tt, &tm_buf ); if( lt == NULL ) ret = -1; From 862aa39edc572a362242aec07e2111223ded79be Mon Sep 17 00:00:00 2001 From: Maciej Bocianski Date: Wed, 5 Sep 2018 09:58:20 +0200 Subject: [PATCH 18/26] DISCO_L475VG_IOT01A remove old QSPI pins --- .../TARGET_DISCO_L475VG_IOT01A/PinNames.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PinNames.h b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PinNames.h index c1197d596c..721cfbc2d1 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L475xG/TARGET_DISCO_L475VG_IOT01A/PinNames.h @@ -240,14 +240,6 @@ typedef enum { SPI_SCK = D13, SPI_CS = D10, PWM_OUT = D9, -#ifdef DEVICE_QSPI - QSPI_PIN_IO0 = PE_12, - QSPI_PIN_IO1 = PE_13, - QSPI_PIN_IO2 = PE_14, - QSPI_PIN_IO3 = PE_15, - QSPI_PIN_SCK = PE_10, - QSPI_PIN_CSN = PE_11, -#endif /**** USB pins ****/ USB_OTG_FS_DM = PA_11, From 9bb03447128afef455bbc1e09940079ae00277f5 Mon Sep 17 00:00:00 2001 From: Maciej Bocianski Date: Wed, 5 Sep 2018 10:53:35 +0200 Subject: [PATCH 19/26] fix example code in QSPI.h --- drivers/QSPI.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/QSPI.h b/drivers/QSPI.h index f5df0a18fa..fc8f6b3b0f 100644 --- a/drivers/QSPI.h +++ b/drivers/QSPI.h @@ -44,8 +44,12 @@ namespace mbed { * * #include "mbed.h" * + * #define CMD_WRITE 0x02 + * #define CMD_READ 0x03 + * #define ADDRESS 0x1000 + * * // hardware ssel (where applicable) - * QSPI qspi_device(QSPI_PIN_IO0, QSPI_PIN_IO1, QSPI_PIN_IO2, QSPI_PIN_IO3, QSPI_PIN_SCK, QSPI_PIN_CSN); // io0, io1, io2, io3, sclk, ssel + * QSPI qspi_device(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3, QSPI_FLASH1_SCK, QSPI_FLASH1_CSN); // io0, io1, io2, io3, sclk, ssel * * * int main() { @@ -53,10 +57,14 @@ namespace mbed { * char rx_buf[4]; * int buf_len = sizeof(tx_buf); * - * int result = qspi_device.write( 0x12 , 0x100000 , 0 , tx_buf, &buf_len ); - * if( !result ) printf("Write failed"); - * int result = qspi_device.read( 0x13 , 0x100000 , 0 , rx_buf, &buf_len ); - * if( !result ) printf("Read failed"); + * qspi_status_t result = qspi_device.write(CMD_WRITE, 0, ADDRESS, tx_buf, &buf_len); + * if (result != QSPI_STATUS_OK) { + * printf("Write failed"); + * } + * result = qspi_device.read(CMD_READ, 0, ADDRESS, rx_buf, &buf_len); + * if (result != QSPI_STATUS_OK) { + * printf("Read failed"); + * } * * } * @endcode From 72f1ecb369e0846d98a0396a5501f5008890f51f Mon Sep 17 00:00:00 2001 From: toyowata Date: Thu, 6 Sep 2018 18:36:12 +0900 Subject: [PATCH 20/26] Fix typo --- TEST_APPS/readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/TEST_APPS/readme.md b/TEST_APPS/readme.md index 178be60d61..814e768df2 100644 --- a/TEST_APPS/readme.md +++ b/TEST_APPS/readme.md @@ -21,8 +21,8 @@ You need Icetea and mbed-cli that supports Icetea, installed. Depending on a device, there might be a default network interface type defined in the mbed-os/targets/targets.json, which is used to locate a test-config file by default. If there is not, or you want to use a different interface than the default, you need to provide a relevant test-config -file to the mbed test with --test-config option. -The test-config file contains the necessary information for the test application, there are some test-config files located under mbed-os/tools/test-configs. -Devices which have their network drivers residing inside mbed-os can use generic test-configs like HeapBlockDeviceAndEthernetInterface.json and HeapBlockDeviceAndWifiInterface.json. Otherwise you need to use a device specific test-config. +The test-config file contains the necessary information for the test application, there are some test-config files located under mbed-os/tools/test_configs. +Devices which have their network drivers residing inside mbed-os can use generic test_configs like HeapBlockDeviceAndEthernetInterface.json and HeapBlockDeviceAndWifiInterface.json. Otherwise you need to use a device specific test-config. ### Running the tests @@ -42,10 +42,10 @@ Some devices may offer multiple network interfaces to operate with. For example, The tests can be run for either one of those using already existing test-config -files. To run the tests with Wi-Fi interface: -`>mbed test -m UBLOX_EVK_ODIN_W2 -t --icetea --test-config tools/test-configs/HeapBlockDeviceAndWifiInterface.json` +`>mbed test -m UBLOX_EVK_ODIN_W2 -t --icetea --test-config tools/test_configs/HeapBlockDeviceAndWifiInterface.json` To run the tests with ethernet interface: -`>mbed test -m UBLOX_EVK_ODIN_W2 -t --icetea --test-config tools/test-configs/HeapBlockDeviceAndEthernetInterface.json` +`>mbed test -m UBLOX_EVK_ODIN_W2 -t --icetea --test-config tools/test_configs/HeapBlockDeviceAndEthernetInterface.json` #### Providing Wi-Fi access point information From 564483eccfda072fba8fa855df8fd2a0c05570cd Mon Sep 17 00:00:00 2001 From: Jammu Kekkonen Date: Fri, 31 Aug 2018 14:13:55 +0300 Subject: [PATCH 21/26] Fix memory reservation for Softdevice in NRF52_DK --- .../device/TOOLCHAIN_ARM_STD/nRF52832.sct | 10 +++++----- .../device/TOOLCHAIN_GCC_ARM/NRF52832.ld | 10 +++++----- .../device/TOOLCHAIN_IAR/nRF52832.icf | 10 +++++----- tools/toolchains/__init__.py | 9 +++++++-- tools/toolchains/arm.py | 4 ++-- tools/toolchains/gcc.py | 2 +- tools/toolchains/iar.py | 2 +- 7 files changed, 26 insertions(+), 21 deletions(-) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct index d58db0e15d..e33232db83 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct @@ -9,13 +9,13 @@ #define MBED_APP_SIZE 0x80000 #endif -/* If app_start is 0, do not set aside space for the softdevice */ -#if MBED_APP_START == 0 - #define MBED_RAM_START 0x20000000 - #define MBED_RAM_SIZE 0x10000 -#else +/* If softdevice is present, set aside space for it */ +#if defined(SOFTDEVICE_PRESENT) #define MBED_RAM_START 0x200031D0 #define MBED_RAM_SIZE 0xCE30 +#else + #define MBED_RAM_START 0x20000000 + #define MBED_RAM_SIZE 0x10000 #endif #define MBED_RAM0_START MBED_RAM_START diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld index fd76160066..1d2bdfc7df 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld @@ -25,13 +25,13 @@ #define MBED_APP_SIZE 0x80000 #endif -/* If app_start is 0, do not set aside space for the softdevice */ -#if MBED_APP_START == 0 - #define MBED_RAM_START 0x20000000 - #define MBED_RAM_SIZE 0x10000 -#else +/* If softdevice is present, set aside space for it */ +#if defined(SOFTDEVICE_PRESENT) #define MBED_RAM_START 0x200031D0 #define MBED_RAM_SIZE 0xCE30 +#else + #define MBED_RAM_START 0x20000000 + #define MBED_RAM_SIZE 0x10000 #endif #define MBED_RAM0_START MBED_RAM_START diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf index 5400c6e5f3..de450f5516 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf @@ -11,13 +11,13 @@ if (!isdefinedsymbol(MBED_APP_SIZE)) { define symbol MBED_APP_SIZE = 0x80000; } -/* If app_start is 0, do not set aside space for the softdevice */ -if (MBED_APP_START == 0) { - define symbol MBED_RAM_START = 0x20000000; - define symbol MBED_RAM_SIZE = 0x10000; -} else { +/* If softdevice is present, set aside space for it */ +if (isdefinedsymbol(SOFTDEVICE_PRESENT)) { define symbol MBED_RAM_START = 0x200031D0; define symbol MBED_RAM_SIZE = 0xCE30; +} else { + define symbol MBED_RAM_START = 0x20000000; + define symbol MBED_RAM_SIZE = 0x10000; } define symbol MBED_RAM0_START = MBED_RAM_START; diff --git a/tools/toolchains/__init__.py b/tools/toolchains/__init__.py index edf901bcab..0a12895bed 100644 --- a/tools/toolchains/__init__.py +++ b/tools/toolchains/__init__.py @@ -706,8 +706,8 @@ class mbedToolchain: self._add_defines_from_region(region) if region.active: for define in [ - ("%s_START" % active_region_name, region.start), - ("%s_SIZE" % active_region_name, region.size) + ("%s_START" % active_region_name, "0x%x" % region.start), + ("%s_SIZE" % active_region_name, "0x%x" % region.size) ]: define_string = self.make_ld_define(*define) self.ld.append(define_string) @@ -747,6 +747,11 @@ class mbedToolchain: self.config_data = config_data # new configuration data can change labels, so clear the cache self.labels = None + # pass info about softdevice presence to linker (see NRF52) + if "SOFTDEVICE_PRESENT" in config_data[1]: + define_string = self.make_ld_define("SOFTDEVICE_PRESENT", config_data[1]["SOFTDEVICE_PRESENT"].macro_value) + self.ld.append(define_string) + self.flags["ld"].append(define_string) self.add_regions() # Creates the configuration header if needed: diff --git a/tools/toolchains/arm.py b/tools/toolchains/arm.py index cbee5e5a03..d37c94e92b 100644 --- a/tools/toolchains/arm.py +++ b/tools/toolchains/arm.py @@ -325,7 +325,7 @@ class ARM(mbedToolchain): @staticmethod def make_ld_define(name, value): - return "--predefine=\"-D%s=0x%x\"" % (name, value) + return "--predefine=\"-D%s=%s\"" % (name, value) @staticmethod def redirect_symbol(source, sync, build_dir): @@ -426,7 +426,7 @@ class ARMC6(ARM_STD): self.flags["ld"] += ["--import_cmse_lib_out=%s" % secure_file] # Add linking time preprocessor macro __DOMAIN_NS if target.core == "Cortex-M23-NS" or self.target.core == "Cortex-M33-NS": - define_string = self.make_ld_define("__DOMAIN_NS", 1) + define_string = self.make_ld_define("__DOMAIN_NS", "0x1") self.flags["ld"].append(define_string) asm_cpu = { diff --git a/tools/toolchains/gcc.py b/tools/toolchains/gcc.py index 65f30477c4..f094fb9702 100644 --- a/tools/toolchains/gcc.py +++ b/tools/toolchains/gcc.py @@ -293,7 +293,7 @@ class GCC(mbedToolchain): @staticmethod def make_ld_define(name, value): - return "-D%s=0x%x" % (name, value) + return "-D%s=%s" % (name, value) @staticmethod def redirect_symbol(source, sync, build_dir): diff --git a/tools/toolchains/iar.py b/tools/toolchains/iar.py index ac73cf0d81..c09a015ec9 100644 --- a/tools/toolchains/iar.py +++ b/tools/toolchains/iar.py @@ -273,7 +273,7 @@ class IAR(mbedToolchain): @staticmethod def make_ld_define(name, value): - return "--config_def %s=0x%x" % (name, value) + return "--config_def %s=%s" % (name, value) @staticmethod def redirect_symbol(source, sync, build_dir): From 3c8e3ed12601fc67ec3537b460b0d93c74020cb4 Mon Sep 17 00:00:00 2001 From: Russ Butler Date: Fri, 31 Aug 2018 18:31:52 -0500 Subject: [PATCH 22/26] Fix memory allocation on STM32L4 devices Depending on initial size allocated on STM32L4 devices with TWO_RAM_REGIONS set a crash may occur. This is because there is a mismatch between the size newlib is expecting and the size actually returned by _sbrk. This is because the STM32L4 implementation of _sbrk is performing alignment internally. This patch fixes this problem by removing the code in __wrap__sbrk which performs the alignment. --- targets/TARGET_STM/TARGET_STM32L4/l4_retarget.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32L4/l4_retarget.c b/targets/TARGET_STM/TARGET_STM32L4/l4_retarget.c index c80d087a73..a190d09ee3 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/l4_retarget.c +++ b/targets/TARGET_STM/TARGET_STM32L4/l4_retarget.c @@ -38,8 +38,6 @@ extern uint32_t __mbed_sbrk_start; extern uint32_t __mbed_krbs_start; -#define STM32L4_HEAP_ALIGN 32 -#define STM32L4_ALIGN_UP(X, ALIGN) (((X) + (ALIGN) - 1) & ~((ALIGN) - 1)) /** * The default implementation of _sbrk() (in platform/mbed_retarget.cpp) for GCC_ARM requires one-region model (heap and * stack share one region), which doesn't fit two-region model (heap and stack are two distinct regions), for example, @@ -50,8 +48,8 @@ extern uint32_t __mbed_krbs_start; void *__wrap__sbrk(int incr) { static uint32_t heap_ind = (uint32_t) &__mbed_sbrk_start; - uint32_t heap_ind_old = STM32L4_ALIGN_UP(heap_ind, STM32L4_HEAP_ALIGN); - uint32_t heap_ind_new = STM32L4_ALIGN_UP(heap_ind_old + incr, STM32L4_HEAP_ALIGN); + uint32_t heap_ind_old = heap_ind; + uint32_t heap_ind_new = heap_ind_old + incr; if (heap_ind_new > &__mbed_krbs_start) { errno = ENOMEM; From 256ba0426135ffde56aafab0bca2b04104adf881 Mon Sep 17 00:00:00 2001 From: Russ Butler Date: Thu, 6 Sep 2018 16:07:03 +0100 Subject: [PATCH 23/26] Fix comparison warning on STM32L4 devices Cast the pointer used in l4_retarget to uint32_t before comparing it to fix the warning: "comparison between pointer and integer" --- targets/TARGET_STM/TARGET_STM32L4/l4_retarget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/TARGET_STM/TARGET_STM32L4/l4_retarget.c b/targets/TARGET_STM/TARGET_STM32L4/l4_retarget.c index a190d09ee3..3bc57b31f9 100644 --- a/targets/TARGET_STM/TARGET_STM32L4/l4_retarget.c +++ b/targets/TARGET_STM/TARGET_STM32L4/l4_retarget.c @@ -51,7 +51,7 @@ void *__wrap__sbrk(int incr) uint32_t heap_ind_old = heap_ind; uint32_t heap_ind_new = heap_ind_old + incr; - if (heap_ind_new > &__mbed_krbs_start) { + if (heap_ind_new > (uint32_t)&__mbed_krbs_start) { errno = ENOMEM; return (void *) - 1; } From 179a3b67b1d29ea08607ec413fd8af56ef96ca00 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Thu, 16 Aug 2018 13:01:32 +0300 Subject: [PATCH 24/26] Add Socket test plan I'm submitting a test plan for Mbed OS sockets, so that we have reference that describes wanted behaviour, required test environment, and priorities of test cases. This servers as a both documentation and specification. It needs to live with source code, as opposed to Handbook, because it will be extend, modified and fixed for faster cycle than what should be done for Handbook. Part of this document (How to run -section) will be submitted to Handbook with links to this. --- TESTS/netsocket/README.md | 1672 ++++++++++++++++++++++++++ TESTS/netsocket/eth_environment.png | Bin 0 -> 142664 bytes TESTS/netsocket/wifi_environment.png | Bin 0 -> 128762 bytes 3 files changed, 1672 insertions(+) create mode 100644 TESTS/netsocket/README.md create mode 100644 TESTS/netsocket/eth_environment.png create mode 100644 TESTS/netsocket/wifi_environment.png diff --git a/TESTS/netsocket/README.md b/TESTS/netsocket/README.md new file mode 100644 index 0000000000..536a7a9860 --- /dev/null +++ b/TESTS/netsocket/README.md @@ -0,0 +1,1672 @@ +Network Socket test plan +======================== + +This is a test plan for Mbed OS Socket API. This describes all test +cases and their intended behaviour. When API document is not clear, this +should be used as a reference for implementing correct behaviour. + +**NOTE:** As testing is a moving target, this test plan might define more test cases than what are +implemented in Mbed OS. Refer to [test case priorities](#test-case-priorities) for list of test cases that target must pass to be compliant with Mbed OS socket API. + + +Target API +---------- + +Target for this plan is to test + +- [Socket](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/Socket.h) +- [UDPSocket](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/UDPSocket.h) +- [TCPSocket](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/TCPSocket.h) +- [TCPServer](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/TCPServer.h) + +Reference documentation: https://os.mbed.com/docs/latest/reference/network-socket.html + +Tools to be used +---------------- + +- Mbed OS +- Standard Mbed OS development tools as described in https://os.mbed.com/docs/latest/tools/index.html +- Test server + +These test cases itself do not require any special tooling, other than +the test server described in "Test environment" chapter. + +Test environment +---------------- + +As a general guideline, network connectivity with public Internet access +is required. This satisfies Socket tests but specific connectivity +methods might require some extra configuration or devices within the +network. + +Test environment consist of DUTs, network connection and test +server. Arm provides public test server, but it can be installed locally +as well, if isolated test environment is required. + +### Public Test server + +Address: `echo.mbedcloudtesting.com` + +Both IPv4 and IPv6 addresses are available from public DNS service which +currently are following: + +```.sh +$ host echo.mbedcloudtesting.com +echo.mbedcloudtesting.com has address 52.215.34.155 +echo.mbedcloudtesting.com has IPv6 address 2a05:d018:21f:3800:8584:60f8:bc9f:e614 +``` + +**Open services in the test server** + +- Echo Protocol, [RFC 862](https://tools.ietf.org/html/rfc862) is + enabled in both TCP and UDP. Port 7. +- Discard Protocol, [RFC 863](https://tools.ietf.org/html/rfc863) is + enabled in both TCP and UDP. Port 9 +- Character generator protocol, [RFC 864](https://tools.ietf.org/html/rfc864) is + enabled in both TCP and UDP. Port 19. Output pattern should follow + the proposed example pattern in RFC. +- Daytime protocol, [RFC 867](https://tools.ietf.org/html/rfc867) in + both TCP and UDP. Port 13. +- Time protocol, [RFC 868](https://tools.ietf.org/html/rfc868) in + both TCP and UDP. Port 37. + +Firewall should be configured to allow this traffic to test server. + +**Example configuration for Debian/Ubuntu Linux** + +These services are available on many operating systems and its out of +scope of this document to describe how to install them. This is an +example how to install these into Debian/Ubuntu based Linux distribution +using standard Inet Daemon. + +```.sh +$ sudo apt install inetutils-inetd +$ nano /etc/inetd.conf +``` + + +Enable following services from /etc/inetd.conf + +``` +#:INTERNAL: Internal services +discard stream tcp6 nowait root internal +discard dgram udp6 wait root internal +echo stream tcp6 nowait root internal +echo dgram udp6 wait root internal +chargen stream tcp6 nowait root internal +chargen dgram udp6 wait root internal +daytime stream tcp6 nowait root internal +time stream tcp6 nowait root internal +``` + + +**Testing the connectivity** + +Connection to test server can be used with NMAP tool like this + +```.sh +$ nmap -sT -p7,9,13,37 echo.mbedcloudtesting.com + +Starting Nmap 7.12 ( https://nmap.org ) at 2018-04-05 16:17 EEST +Nmap scan report for echo.mbedcloudtesting.com (52.215.34.155) +Host is up (0.065s latency). +Other addresses for echo.mbedcloudtesting.com (not scanned): 2a05:d018:21f:3800:8584:60f8:bc9f:e614 +rDNS record for 52.215.34.155: ec2-52-215-34-155.eu-west-1.compute.amazonaws.com +PORT STATE SERVICE +7/tcp open echo +9/tcp open discard +13/tcp open daytime +37/tcp open time + +Nmap done: 1 IP address (1 host up) scanned in 0.17 seconds + +$ sudo nmap -sT -p7,9,13,37 echo.mbedcloudtesting.com + +Starting Nmap 7.12 ( https://nmap.org ) at 2018-04-05 16:16 EEST +Nmap scan report for echo.mbedcloudtesting.com (52.215.34.155) +Host is up (0.068s latency). +Other addresses for echo.mbedcloudtesting.com (not scanned): 2a05:d018:21f:3800:8584:60f8:bc9f:e614 +rDNS record for 52.215.34.155: ec2-52-215-34-155.eu-west-1.compute.amazonaws.com +PORT STATE SERVICE +7/tcp open echo +9/tcp open discard +13/tcp open daytime +37/tcp open time + +Nmap done: 1 IP address (1 host up) scanned in 0.20 seconds +``` + +### Ethernet test environment + +![Ethernet](eth_environment.png) + +Ethernet test environment consist of devices, ethernet switch, optional +firewall that allows connecting to Echo server. + + + +### Wifi test environment + +![Wifi](wifi_environment.png) + +Wifi test environment is equiwalent of the ethernet one, except that it +have two separate access point, or one with dual SSID. Connectivity to +echo server is required, but it can be hosted locally, as specified in +Ethernet environment. + + + +Test case priorities +-------------------- + +Please refer to following table for priorities of test cases. Priorities +are labelled as MUST and SHOULD. MUST means this is a requirement and +therefore mandatory to pass the test. SHOULD means it is recommended to +pass the test if the driver implements the feature in question. + +| | Test case | Priority | +|-----|-----------------------------------------|----------| +| 1 | UDPSOCKET_OPEN_DESTRUCT | MUST | +| 2 | UDPSOCKET_OPEN_LIMIT | MUST | +| 3 | UDPSOCKET_OPEN_TWICE | MUST | +| 4 | UDPSOCKET_OPEN_CLOSE_REPEAT | MUST | +| 5 | UDPSOCKET_BIND_PORT | SHOULD | +| 6 | UDPSOCKET_BIND_PORT_FAIL | SHOULD | +| 7 | UDPSOCKET_BIND_ADDRESS_PORT | SHOULD | +| 8 | UDPSOCKET_BIND_ADDRESS_NULL | SHOULD | +| 9 | UDPSOCKET_BIND_ADDRESS_INVALID | SHOULD | +| 10 | UDPSOCKET_BIND_WRONG_TYPE | SHOULD | +| 11 | UDPSOCKET_BIND_ADDRESS | SHOULD | +| 12 | UDPSOCKET_BIND_UNOPENED | SHOULD | +| 13 | UDPSOCKET_SENDTO_INVALID | MUST | +| 14 | UDPSOCKET_SENDTO_REPEAT | MUST | +| 15 | UDPSOCKET_BIND_SENDTO | SHOULD | +| 16 | UDPSOCKET_ECHOTEST | MUST | +| 17 | UDPSOCKET_ECHOTEST_NONBLOCK | MUST | +| 18 | UDPSOCKET_RECV_TIMEOUT | SHOULD | +| 19 | UDPSOCKET_SENDTO_TIMEOUT | SHOULD | +| 20 | TCPSOCKET_OPEN_DESTRUCT | MUST | +| 21 | TCPSOCKET_OPEN_LIMIT | MUST | +| 22 | TCPSOCKET_OPEN_TWICE | MUST | +| 23 | TCPSOCKET_OPEN_CLOSE_REPEAT | MUST | +| 24 | TCPSOCKET_BIND_PORT | SHOULD | +| 25 | TCPSOCKET_BIND_PORT_FAIL | SHOULD | +| 26 | TCPSOCKET_BIND_ADDRESS_PORT | SHOULD | +| 27 | TCPSOCKET_BIND_ADDRESS_NULL | SHOULD | +| 28 | TCPSOCKET_BIND_ADDRESS_INVALID | SHOULD | +| 29 | TCPSOCKET_BIND_WRONG_TYPE | SHOULD | +| 30 | TCPSOCKET_BIND_ADDRESS | SHOULD | +| 31 | TCPSOCKET_BIND_UNOPENED | SHOULD | +| 32 | TCPSOCKET_CONNECT_INVALID | MUST | +| 33 | TCPSOCKET_SEND_REPEAT | MUST | +| 34 | TCPSOCKET_ECHOTEST | MUST | +| 35 | TCPSOCKET_ECHOTEST_NONBLOCK | MUST | +| 36 | TCPSOCKET_RECV_TIMEOUT | SHOULD | +| 37 | TCPSOCKET_SEND_TIMEOUT | SHOULD | +| 38 | TCPSOCKET_ENDPOINT_CLOSE | MUST | +| 39 | TCPSERVER_ACCEPT | SHOULD | +| 40 | TCPSERVER_LISTEN | SHOULD | +| 41 | TCPSERVER_LISTEN_WITHOUT_BIND | SHOULD | +| 42 | TCPSERVER_ACCEPT_WITHOUT_LISTEN | SHOULD | +| 43 | UDPSOCKET_ECHOTEST_BURST | MUST | +| 44 | UDPSOCKET_ECHOTEST_BURST_NONBLOCK | MUST | +| 45 | TCPSOCKET_ECHOTEST_BURST | MUST | +| 46 | TCPSOCKET_ECHOTEST_BURST_NONBLOCK | MUST | +| 47 | TCPSOCKET_RECV_100K | MUST | +| 48 | TCPSOCKET_RECV_100K_NONBLOCK | MUST | +| 49 | TCPSOCKET_THREAD_PER_SOCKET_SAFETY | MUST | +| 50 | TCPSOCKET_SETSOCKOPT_KEEPALIVE_VALID | SHOULD | +| 51 | TCPSOCKET_SETSOCKOPT_KEEPALIVE_INVALID | SHOULD | + + +Building test binaries +-------------------------- + +For testing the board and driver, testing should be done against Mbed OS +master to get latest up to date test cases and drivers. + +To create build environment: + +```.sh +mbed new network_test +cd network_test +cd mbed-os +git checkout master +cd .. +``` + +Also, when building socket testcases, special macro is required to +enable all test, so create `mbed_app.json` file with following +content at minimum: + +``` +{ + "macros": ["MBED_EXTENDED_TESTS"] +} +``` + +WiFi tests require some more configuration, so for WiFi purposes, +the `mbed_app.json` might look like this: + +``` +{ + "config": { + "wifi-secure-ssid": { + "help": "WiFi SSID for WPA2 secured network", + "value": "\"test-network\"" + }, + "wifi-unsecure-ssid": { + "help": "WiFi SSID for unsecure netwrok", + "value": "\"unsecure-test-net\"" + }, + "wifi-password": { + "help": "WiFi Password", + "value": "\"password\"" + }, + "wifi-secure-protocol": { + "help": "WiFi security protocol, valid values are WEP, WPA, WPA2, WPA/WPA2", + "value": "\"WPA2\"" + }, + "wifi-ch-secure": { + "help": "Channel number of secure SSID", + "value": 6 + }, + "wifi-ch-unsecure": { + "help": "Channel number of unsecure SSID", + "value": 6 + }, + "ap-mac-secure": { + "help": "BSSID of secure AP in form of AA:BB:CC:DD:EE:FF", + "value": "\"58:8b:f3:99:f2:9c\"" + }, + "ap-mac-unsecure": { + "help": "BSSID of unsecure AP in form of \"AA:BB:CC:DD:EE:FF\"", + "value": "\"58:8b:f3:99:c2:08\"" + }, + "max-scan-size": { + "help": "How many networks may appear in Wifi scan result", + "value": 30 + }, + "header-file": { + "help" : "String for including your driver header file", + "value" : "\"MyWifiInterface.h\"" + }, + "object-construction" : { + "value" : "new MyWifiInterface()" + }, + "connect-statement" : { + "help" : "Must use 'net' variable name", + "value" : "net->wifiInterface()->connect(MBED_CONF_APP_WIFI_SECURE_SSID, MBED_CONF_APP_WIFI_PASSWORD, NSAPI_SECURITY_WPA_WPA2)" + }, + "echo-server-addr" : { + "help" : "IP address of echo server", + "value" : "\"echo.mbedcloudtesting.com\"" + }, + "echo-server-port" : { + "help" : "Port of echo server", + "value" : "7" + } + }, + "macros": ["MBED_EXTENDED_TESTS"] +} +``` + +Now build test binaries +```.sh +mbed test --compile -t -m -n mbed-os-tests-network-*,mbed-os-tests-netsocket* +``` + +Running tests +------------- + +When device is connected to network, or in case of wireless device near +the access point. + +```.sh +mbed test -n mbed-os-tests-network-*,mbed-os-tests-netsocket* +``` + +Test cases for Socket class +--------------------------- + +These test are equal for UDPSocket and TCPSocket but are described here +because of identical API and behaviour. Socket class is abstract so it +cannot be instantiated, therefore these test cases are implemented using +both TCPSocket and UDPSocket. + +### SOCKET_OPEN_DESTRUCT + +**Description:** + +Call `Socket::open()` and then destruct the socket + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create a object by calling `new Socket()` +2. Call `Socket::open(stack)` +3. Call "delete" for the object +4. Repeat 1000 times. + +**Expected result:** + +`Socket::open()` should always return NSAPI_ERROR_OK + + + +### SOCKET_OPEN_LIMIT + +**Description:** + + Call `Socket::open()` until it runs out of memory or other internal limit +in the stack is reached. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create a object by calling `new Socket()` +2. Call `Socket::open(stack)` +3. repeat until `NSAPI_ERROR_NO_MEMORY` or `NSAPI_ERROR_NO_SOCKET` + error is returned. +4. Call "delete" for all previously allocated sockets. +5. repeat + +**Expected result:** + +Should be able to reserve at least 4 sockets. After freeing all sockets, +should be able to reserve same number of sockets. + + + +### SOCKET_OPEN_TWICE + +**Description:** + +Call `Socket::open()` twice + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create a object by calling `new Socket()` +2. Call `Socket::open(stack)` +3. Call `Socket::open(stack)` +4. delete the socket + +**Expected result:** + +`Socket::open()` should first return `NSAPI_ERROR_OK` and second +call `NSAPI_ERROR_PARAMETER`. + + + +### SOCKET_OPEN_CLOSE_REPEAT + +**Description:** + +Call `Socket::open()` followed by `Socket::close()` and then again +`Socket::open()`. Should allow you to reuse the same object. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create a object by calling `new Socket()` +2. Call `Socket::open(stack)` +3. Call `Socket::close(stack)` +4. Call `Socket::open(stack)` +5. Call `Socket::close(stack)` +6. delete the socket + +**Expected result:** + +All `Socket::open()` and `Socket::close()` calls should return +NSAPI_ERROR_OK. + + +### SOCKET_BIND_PORT + +**Description:** + +Call `Socket::bind(port)` + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create a object by calling `new Socket()` +2. Call `Socket::open(stack)` +3. Call `Socket::bind();` +4. destroy socket + +**Expected result:** + +All calls return NSAPI_ERROR_OK + + + +### SOCKET_BIND_PORT_FAIL + +**Description:** + +Call `Socket::bind(port)` on port number that is already used + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create a object by calling `new Socket()` +2. Call `Socket::open(stack)` +3. Call `Socket::bind();` +4. Repeat 1-3 for a new socket. +5. destroy both sockets + +**Expected result:** + +Second `Socket::bind()` should return NSAPI_ERROR_PARAMETER + + + +### SOCKET_BIND_ADDRESS_PORT + +**Description:** + +Call `Socket::bind(addr, port)` + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create a object by calling `new Socket()` +2. Call `Socket::open(stack)` +3. Get address by calling NetworkInterface::get_ip_address(); +4. Call `Socket::bind(address, );` +5. destroy socket + +**Expected result:** + +All calls return NSAPI_ERROR_OK + + + +### SOCKET_BIND_ADDRESS_NULL + +**Description:** + +Call `Socket::bind(NULL, port)` + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create a object by calling `new Socket()` +2. Call `Socket::open(stack)` +3. Call `Socket::bind(NULL, );` +4. destroy socket + +**Expected result:** + +`Socket::bind()` should return NSAPI_ERROR_OK + + + +### SOCKET_BIND_ADDRESS_INVALID + +**Description:** + +Call `Socket::bind(address, port)` with and address that is not assigned +to us. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create a object by calling `new Socket()` +2. Call `Socket::open(stack)` +3. Check whether device is IPv4 or IPv6 connected. + 1. For IPv4: Call `Socket::bind("190.2.3.4", );` + 2. For IPv6: Call `Socket::bind("fe80::ff01", );` + +4. destroy socket + +**Expected result:** + +`Socket::bind()` should return NSAPI_ERROR_PARAMETER + + + +### SOCKET_BIND_ADDRESS_WRONG_TYPE + +**Description:** + +Call `Socket::bind(SocketAddress)` with and address that is not wrong type +for the connection. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create a object by calling `new Socket()` +2. Call `Socket::open(stack)` +3. Check whether device is IPv4 or IPv6 connected. + 1. For IPv4: Create `SocketAddress("fe80::ff01", );` + 2. For IPv6: Create `SocketAddress("190.2.3.4", );` + +4. Call `Socket::bind(address);` +5. destroy socket + +**Expected result:** + +`Socket::bind()` should return NSAPI_ERROR_PARAMETER + + + +### SOCKET_BIND_ADDRESS + +**Description:** + +Call `Socket::bind(SocketAddress)` + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create a object by calling `new Socket()` +2. Call `Socket::open(stack)` +3. Get address by calling NetworkInterface::get_ip_address(); +4. Create a SocketAddress object using this address and any non-used + port number. +5. Call `Socket::bind(address);` +6. destroy socket + +**Expected result:** + +All calls return NSAPI_ERROR_OK + + + +### SOCKET_BIND_UNOPENED + +**Description:** + +Call `Socket::bind()` on socket that has not been opened + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create a object by calling `new Socket()` +2. Call `Socket::bind();` +3. destroy socket + +**Expected result:** + +NSAPI_ERROR_NO_SOCKET + + + +Test cases for UDPSocket class +------------------------------ + +### UDPSOCKET_OPEN_DESTRUCT + +**Description:** Run SOCKET_OPEN_DESTRUCT for UDPSocket + +### UDPSOCKET_OPEN_LIMIT + +**Description:** Run SOCKET_OPEN_LIMIT for UDPSocket + +### UDPSOCKET_OPEN_TWICE + +**Description:** Run SOCKET_OPEN_TWICE for UDPSocket + +### UDPSOCKET_OPEN_CLOSE_REPEAT + +**Description:** Run SOCKET_OPEN_CLOSE_REPEAT for UDPSocket + +### UDPSOCKET_BIND_PORT + +**Description:** Run SOCKET_BIND_PORT for UDPSocket + +### UDPSOCKET_BIND_PORT_FAIL + +**Description:** Run SOCKET_BIND_PORT_FAIL for UDPSocket + +### UDPSOCKET_BIND_ADDRESS_PORT + +**Description:** Run SOCKET_BIND_ADDRESS_PORT for UDPSocket + +### UDPSOCKET_BIND_ADDRESS_NULL + +**Description:** Run SOCKET_BIND_ADDRESS_NULL for UDPSocket + +### UDPSOCKET_BIND_ADDRESS_INVALID + +**Description:** Run SOCKET_BIND_ADDRESS_INVALID for UDPSocket + +### UDPSOCKET_BIND_WRONG_TYPE + +**Description:** Run SOCKET_BIND_WRONG_TYPE for UDPSocket + +### UDPSOCKET_BIND_ADDRESS + +**Description:** Run SOCKET_BIND_ADDRESS for UDPSocket + +### UDPSOCKET_BIND_UNOPENED + +**Description:** Run SOCKET_BIND_UNOPENED for UDPSocket + +### UDPSOCKET_SENDTO_INVALID + +**Description:** + +Call `UDPSocket::sendto()` with invalid parameters. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. UDPSocket is open + +**Test steps:** + +1. Call `UDPSocket:sendto( NULL, 9, NULL, 0);` +2. Call `UDPSocket:sendto( "", 9, NULL, 0);` +3. Call `UDPSocket:sendto( "", 0, NULL, 0);` +4. Call `UDPSocket:sendto(NULL, 9, "hello", 5);` +5. Call `UDPSocket:sendto(NULL, 0, "hello", 5);` +6. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 0, "hello", 5);` +7. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 9,NULL, 0);` +8. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 9, "hello", 5);` +9. destroy the socket + +**Expected result:** + +All sendto() calls should return some error code except: + +- step 6 should return 5 +- step 7 should return 0 +- step 8 should return 5 + + + +### UDPSOCKET_SENDTO_REPEAT + +**Description:** + +Repeatedly send small packets. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. UDPSocket is open + +**Test steps:** + +1. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 9, "hello", 5);` +2. repeat 100 times +3. Fail if `NSAPI_ERROR_NO_MEMORY` is returned two times in a row, + wait 1 second before retry +4. destroy the socket + +**Expected result:** + +All sendto() calls should return 5. + + + +### UDPSOCKET_BIND_SENDTO + +**Description:** + + Bind the socket to specific port before sending. Verify from DUT2 that +packet was coming from correct port. + +Requires two devices with LAN connectivity (Eth, WiFi or mesh). For +Cellular or WAN connectivity, skip this test. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. UDPSocket is open + +**Test steps:** + +1. DUT1&2: Call `UDPSocket::bind();` +2. DUT2: Get devices IP address +3. DUT1: Call `UDPSocket::sendto( dut2, port, "hello", 5);` +4. DUT2: Call `UDPSocket::recvfrom();` +5. destroy the sockets + +**Expected result:** + +`UDPSocket::bind()` should return NSAPI_ERROR_OK. + +`UDPSocket::sendto()` call should return 5. + +`UDPSocket::recvfrom()` should return 5 and port number should match the +one used in bind() call. Data should contain "hello" + + + +### UDPSOCKET_ECHOTEST + +**Description:** + +Repeatedly send packets to echo server and read incoming packets back. +Verify working of different packet sizes. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. UDPSocket is open + +**Test steps:** + +1. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 7, , );` +2. Wait for incomming packet. If timeout happens, retry + sending&receiving, max 3 times. +3. Verify incomming content was the same that was sent +4. Repeat 1200 times +5. destroy the socket + +**Expected result:** + +All sendto() calls should return the packet size. All recvfrom() calls +should return the same sized packet that was send with same content. +Calculate packet loss rate, maximum tolerated packet loss rate is 30% + + + +### UDPSOCKET_ECHOTEST_NONBLOCK + +**Description:** + +Repeatedly send packets to echo server and read incoming packets back. +Verify working of different packet sizes. Use socket in non-blocking +mode + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. UDPSocket is open + +**Test steps:** + +1. Call `UDPSocket::set_blocking(false)` +2. Register event handler with `UDPSocket::sigio()` +3. Create another thread that constantly waits signal from sigio() + handler, when received try `UDPSocket::recvfrom()` +4. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 7, , );` +5. Wait for incomming packet for one second. If nothing received retry, + max 3 times. +6. Verify incomming content was the same that was sent +7. Repeat 1200 times +8. destroy the socket + +**Expected result:** + +All sendto() calls should return the packet size. All recvfrom() calls +should return the same sized packet that was send with same content or +NSAPI_ERROR_WOULD_BLOCK. + +Calculate packet loss rate, maximum tolerated packet loss rate is 30% + + + +### UDPSOCKET_RECV_TIMEOUT + +**Description:** + +Test whether timeouts are obeyed in UDPSockets. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Call `UDPSocket::set_timeout(100)` +2. Call `UDPSocket::sendto("echo.mbedcloudtesting.com", 7, , 100);` +3. Repeat 5 times + 1. record a time in millisecond precission + 2. Call `UDPSocket::recvfrom()` + 3. record a time in millisecond precission + +4. repeat testcase 10 times. + +**Expected result:** + +Each `sendto()` calls should return 100. + +Within each loop, one `recvfrom()` may return the received packet size +(100). Other calls should return NSAPI_ERROR_WOULD_BLOCK. + +When NSAPI_ERROR_WOULD_BLOCK is received, check that time consumed is +more that 100 milliseconds but less than 200 milliseconds. + +After repeating for 10 times, at least 5 packets must have been +received. + + +### UDPSOCKET_SENDTO_TIMEOUT + +**Description:** + +Test whether timeouts are obeyed in UDPSockets. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Record time +2. Call `UDPSocket::sendto("echo.mbedcloudtesting.com", 9, , 100);` +3. Record time +4. Call `UDPSocket::set_timeout(1000)` +5. Call `UDPSocket::sendto("echo.mbedcloudtesting.com", 9, , 100);` +6. Record time + +**Expected result:** + +Each sendto() call should return 100. + +All sendto() calls should return faster than 100 milliseconds because +UDP sending should not block that long. + + +Test cases for TCPSocket class +------------------------------ + +### TCPSOCKET_OPEN_DESTRUCT + +**Description:** Run SOCKET_OPEN_DESTRUCT for TCPSocket + +### TCPSOCKET_OPEN_LIMIT + +**Description:** Run SOCKET_OPEN_LIMIT for TCPSocket + +### TCPSOCKET_OPEN_TWICE + +**Description:** Run SOCKET_OPEN_TWICE for TCPSocket + +### TCPSOCKET_OPEN_CLOSE_REPEAT + +**Description:** Run SOCKET_OPEN_CLOSE_REPEAT for TCPSocket + +### TCPSOCKET_BIND_PORT + +**Description:** Run SOCKET_BIND_PORT for TCPSocket + +### TCPSOCKET_BIND_PORT_FAIL + +**Description:** Run SOCKET_BIND_PORT_FAIL for TCPSocket + +### TCPSOCKET_BIND_ADDRESS_PORT + +**Description:** Run SOCKET_BIND_ADDRESS_PORT for TCPSocket + +### TCPSOCKET_BIND_ADDRESS_NULL + +**Description:** Run SOCKET_BIND_ADDRESS_NULL for TCPSocket + +### TCPSOCKET_BIND_ADDRESS_INVALID + +**Description:** Run SOCKET_BIND_ADDRESS_INVALID for TCPSocket + +### TCPSOCKET_BIND_WRONG_TYPE + +**Description:** Run SOCKET_BIND_WRONG_TYPE for TCPSocket + +### TCPSOCKET_BIND_ADDRESS + +**Description:** Run SOCKET_BIND_ADDRESS for TCPSocket + +### TCPSOCKET_BIND_UNOPENED + +**Description:** Run SOCKET_BIND_UNOPENED for TCPSocket + +### TCPSOCKET_CONNECT_INVALID + +**Description:** + +Call `TCPSocket::connect()` with invalid parameters. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. TCPSocket is open + +**Test steps:** + +1. Call `TCPSocket:connect( NULL, 9);` +2. Call `TCPSocket:connect( "", 9);` +3. Call `TCPSocket:connect( "", 0);` +4. Call `TCPSocket:connect( "echo.mbedcloudtesting.com", 0);` +5. Call `TCPSocket:connect( "echo.mbedcloudtesting.com", 9);` +6. destroy the socket + +**Expected result:** + +All connect() calls should return some error code except the number 5 +should return NSAPI_ERROR_OK. + + + +### TCPSOCKET_SEND_REPEAT + +**Description:** + +Repeatedly send small packets. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. TCPSocket is open + +**Test steps:** + +1. Call `TCPSocket::connect("echo.mbedcloudtesting.com", 9);` +2. Call `TCPSocket::send("hello", 5);` +3. repeat 1000 times +4. destroy the socket + +**Expected result:** + +`TCPSocket::connect()` should return NSAPI_ERROR_OK + +All send() calls should return 5. + + + +### TCPSOCKET_ECHOTEST + +**Description:** + +Repeatedly send packets to echo server and read incoming packets back. +Verify working of different packet sizes. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. TCPSocket is open + +**Test steps:** + +1. Call `TCPSocket::connect("echo.mbedcloudtesting.com", 7);` +2. Call `TCPSocket::send(, );` + 1. If less than was returned, size = sent bytes + +3. Call `TCPSocket::recv(buffer, );` +4. Verify incomming content was the same that was sent +5. Repeat 1200 times +6. destroy the socket + +**Expected result:** + +All send() calls should return the packet size or less. All recv() calls +should return the same sized packet that was send with same content. + +NOTE: This is stream so recv() might return less data than what was +requested. In this case you need to keep calling recv() until all data +that you have sent is returned. + + +### TCPSOCKET_ECHOTEST_NONBLOCK + +**Description:** + +Repeatedly send packets to echo server and read incoming packets back. +Verify working of different packet sizes. Use socket in non-blocking +mode + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. TCPSocket is open + +**Test steps:** + +1. Call `TCPSocket::connect("echo.mbedcloudtesting.com", 7);` +2. Call `TCPSocket::set_blocking(false)` +3. Register event handler with `TCPSocket::sigio()` +4. Create another thread that constantly waits signal from `sigio()` + handler, when received try `TCPSocket::recv(buf+index, - index)`, where index is the amount of data + already received. +5. Call `TCPSocket:send(, );` + 1. If less than was returned, try immeadiately + sending remaining bytes. + 2. If NSAPI_ERROR_WOULD_BLOCK is returned, wait for sigio() call + to happen. + +6. Wait for incomming packet for one second. +7. Verify incomming content was the same that was sent, set index for + receiving thread to zero. +8. Repeat 1200 times +9. destroy the socket + +**Expected result:** + +All send() calls should return the packet size or less. All recv() calls +should return NSAPI_ERROR_WOULD_BLOCK or packet size that is equal or +less than what has been sent. + +### TCPSOCKET_RECV_TIMEOUT + +**Description:** + +Test whether timeouts are obeyed in TCPSockets. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. TCPSocket is open + +**Test steps:** + +1. Call `TCPSocket::connect("echo.mbedcloudtesting.com", 7);` +2. Call `TCPSocket::set_timeout(100);` +3. Call `TCPSocket::send(;, 100);` +4. Repeat 5 times + 1. record a time in millisecond precission + 2. Call `TCPSocket::recv()` + 3. record a time in millisecond precission + +5. repeat testcase 10 times. + +**Expected result:** + +Each send() call should return 100. + +Within each loop, one recv() may return the received packet size (100). +Other calls should return NSAPI_ERROR_WOULD_BLOCK. + +When NSAPI_ERROR_WOULD_BLOCK is received, check that time consumed is +more that 100 milliseconds but less than 200 milliseconds. + + +### TCPSOCKET_SEND_TIMEOUT + +**Description:** + +Repeatedly send small packets in a given time limit + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. TCPSocket is open + +**Test steps:** + +1. Call `TCPSocket:connect("echo.mbedcloudtesting.com", 9);` +3. Call `TCPSocket:set_blocking(false);` +3. Call `TCPSocket:send("hello", 5);` +4. repeat 10 times +5. destroy the socket + +**Expected result:** + +`TCPSocket::connect()` should return NSAPI_ERROR_OK + +All send() calls should return in less than 800 milliseconds + + +### TCPSOCKET_ENDPOINT_CLOSE + +**Description:** + +Test whether we tolerate endpoint closing the connection. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. TCPSocket is open + +**Test steps:** + +1. Call `TCPSocket::connect("echo.mbedcloudtesting.com", 13);` +2. Call `TCPSocket::recv(, 30);` +3. Repeat until recv() returns 0 +4. Call `TCPSocket::close();` +5. delete socket + +**Expected result:** +Connect should return NSAPI_ERROR_OK. + +First recv() should return more that zero. Something between 10 and 30 +bytes (datetime string) + +Second recv() should return zero because endpoint closed the connection. +(EOF). close() should return NSAPI_ERROR_OK + +### TCPSOCKET_SETSOCKOPT_KEEPALIVE_VALID + +**Description:** + +Test we are able to request setting valid TCP keepalive values + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Call `TCPSocket::setsockopt(keepalive, [0,1 or 7200]);` +2. Call `TCPSocket::connect("echo.mbedcloudtesting.com", 9);` +3. Call `TCPSocket::getsockopt(keepalive);` + +**Postconditions:** + +1. Call `TCPSocket::close();` +2. delete socket + +**Expected result:** + +`TCPSocket::getsockopt(keepalive)` returns same value as was set with +`TCPSocket::setsockopt()` or NSAPI_ERROR_UNSUPPORTED + +### TCPSOCKET_SETSOCKOPT_KEEPALIVE_INVALID + +**Description:** + +Test we are able to detect if an invalid TCP keepalive value is tried to +be set + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Call `TCPSocket::setsockopt(keepalive, [-1 or 7201]);` +2. Call `TCPSocket::getsockopt(keepalive);` + +**Postconditions:** + +1. Call `TCPSocket::close();` +2. delete socket + +**Expected result:** + +`TCPSocket::setsockopt(keepalive)` returns error code or +NSAPI_ERROR_UNSUPPORTED + +`TCPSocket::getsockopt()` returns 0 or NSAPI_ERROR_UNSUPPORTED + + +Test cases for TCPServer class +------------------------------ + +These tests require two devices under test and connectivity between +them. Therefore they can only be ran with LAN connectivity (Eth, Wifi or +Mesh) or if there is no firewall between devices. + + +### TCPSERVER_ACCEPT + +**Description:** + + Test that `TCPServer::bind()`, `TCPServer::listen()` +and `TCPServer::accept()` works. + +Requires 2 devices. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. DUT1: `TCPServer::bind()` +2. DUT1: `TCPServer::listen()` +3. DUT1: Create a new `TCPSocket` +4. DUT1: `TCPServer::accept()` +5. DUT2: Create a new `TCPSocket` +6. DUT2: `TCPSocket::connect(, )` +7. DUT1: should receive new socket from accept(), + call `TCPSocket::send("hello",5)` for it +8. DUT2: call `TCPSocket::recv(buffer, 5)` +9. DUT2: Verify that it received "hello" +10. destroy all sockets. + +**Expected result:** + +On DUT1 accept() call blocks until connection is received. Other calls +should return NSAPI_ERROR_OK + +On DUT2 all calls should return NSAPI_ERROR_OK + + + +### TCPSERVER_LISTEN + +**Description:** + + Test that `TCPServer::listen()` has the backlog functionality. + +Requires 2 devices. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. DUT1: `TCPServer::bind()` +2. DUT1: `TCPServer::listen(2)` +3. loop 2 times: + 1. DUT2: Create a new TCPSocket + 2. DUT2: `TCPSocket::connect(, )` + +4. loop 2 times: + 1. DUT1: Create a new TCPSocket + 2. DUT1: `TCPServer::accept()` + 3. DUT1: should receive new socket from accept(), + call `TCPSocket::send("hello",5)` for it + +5. DUT2: call `TCPSocket::recv(buffer, 5)` for both socket. +6. DUT2: Verify that it received "hello" +7. destroy all sockets. + +**Expected result:** + +DUT2 should receive connection before the server have called accept(), +because backlog must be minimum of 2. + + +### TCPSERVER_LISTEN_WITHOUT_BIND + +**Description:** + + Call `TCPServer::listen()` without calling bind() first. Should fail, +because no listening port have been defined. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create TCPServer +2. Call `TCPServer::listen()` + +**Expected result:** + +Should +return NSAPI_ERROR_UNSUPPORTED, NSAPI_ERROR_PARAMETER, NSAPI_ERROR_NO_ADDRESS +or NSAPI_ERROR_DEVICE_ERROR + + +### TCPSERVER_ACCEPT_WITHOUT_LISTEN + +**Description:** + + Call `TCPServer::accept()` without calling listen() first. Should fail, +because socket is not listening for connections. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up + +**Test steps:** + +1. Create TCPServer +2. Call `TCPServer::bind()` +3. Create new TCPSocket. +4. Call `TCPServer::accept()` + +**Expected result:** + +Should return NSAPI_ERROR_UNSUPPORTED, NSAPI_ERROR_PARAMETER +or NSAPI_ERROR_DEVICE_ERROR + + +Performance tests +----------------- + + +### UDPSOCKET_ECHOTEST_BURST + +**Description:** + +Send burst of packets to echo server and read incoming packets back. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. UDPSocket is open + +**Test steps:** + +1. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 7, , 100);` +2. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 7, , 200);` +3. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 7, , 300);` +4. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 7, , 120);` +5. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 7, , 500);` +6. Wait for incomming packets for five second. +7. Verify incomming content was the same that was sent. Allow + packet reordering. +8. Repeat 100 times +9. destroy the socket + +**Expected result:** + +All sendto() calls should return the packet size. + +All recvfrom() calls should return the same sized packet that was send +with same content. Allow packet reordering. + +Calculate packet loss rate, maximum tolerated packet loss rate is 30% + +Calculate number of succesfull rounds, it should be higher than 70 + + +### UDPSOCKET_ECHOTEST_BURST_NONBLOCK + +**Description:** + +Send burst of packets to echo server and read incoming packets back. Use +socket in non-blocking mode + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. UDPSocket is open + +**Test steps:** + +1. Call `UDPSocket::set_blocking(false)` +2. Register event handler with `UDPSocket::sigio()` +3. Create another thread that constantly waits signal from sigio() + handler, when received try `UDPSocket::recvfrom()` +4. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 7, , 100);` +5. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 7, , 200);` +6. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 7, , 300);` +7. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 7, , 120);` +8. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 7, , 500);` +9. Wait for incomming packets for five second. +10. Verify incomming content was the same that was sent. Allow + packet reordering. +11. Repeat 100 times +12. destroy the socket + +**Expected result:** + +All sendto() calls should return the packet size. + +All recvfrom() calls should return the same sized packet that was send +with same content. Allow packet reordering. + +Calculate packet loss rate, maximum tolerated packet loss rate is 30% + +Calculate number of succesfull rounds, it should be higher than 70 + + + +### TCPSOCKET_ECHOTEST_BURST + +**Description:** + +Send burst of packets to echo server and read incoming packets back. + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. TCPSocket is open + +**Test steps:** + +1. Call `TCPSocket::connect("echo.mbedcloudtesting.com", 7);` +2. Call `TCPSocket::send(, 100);` +3. Call `TCPSocket::send(, 200);` +4. Call `TCPSocket::send(, 300);` +5. Call `TCPSocket::send(, 120);` +6. Call `TCPSocket::send(, 500);` +7. Call `TCPSocket::recv(buf, 1220)` +8. Verify incomming content was the same that was sent. +9. Repeat 100 times +10. destroy the socket + +**Expected result:** + +All send() calls should return the packet size. + +NOTE: This is stream so recv() might return less data than what was +requested. In this case you need to keep calling recv() with remaining +size until all data that you have sent is returned. + +Consecutive calls to recv() should return all the data that has been +send. Total amount of returned must match 1220. + + +### TCPSOCKET_ECHOTEST_BURST_NONBLOCK + +**Description:** + +Send burst of packets to echo server and read incoming packets back. Use +socket in non-blocking mode + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. TCPSocket is open + +**Test steps:** + +1. Register event handler with `TCPSocket::sigio()` +2. Call `TCPSocket::connect("echo.mbedcloudtesting.com", 7);` +3. Call `TCPSocket::set_blocking(false)` +4. Create another thread that constantly waits signal from sigio() + handler, when received try `TCPSocket::recv()` +5. For randomly generated packets, sized 100, 200, 300, 120 and 500 do + 1. Call `TCPSocket::send(packet, size);` + 2. If less than size is sent, repeat with remaining. + 3. If NSAPI_ERROR_WOULD_BLOCK returned, wait for next sigio() + +6. Wait for incomming packets for five second. +7. Verify incomming content was the same that was sent. Allow recv() to + return smaller piezes. +8. Repeat 100 times +9. destroy the socket + +**Expected result:** + +All send() calls should return NSAPI_ERROR_WOULD_BLOCK or size which +is equal or less than requested. + +All recv() calls should return value that is less or equal to what have +been sent. With consecutive calls, size should match. + +When recv() returns NSAPI_ERROR_WOULD_BLOCK wait for next sigio() +event. No other error codes allowed. + + +### TCPSOCKET_RECV_100K + +**Description:** + +Download 100kB of data + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. TCPSocket is open + +**Test steps:** + +1. Call `TCPSocket::connect("echo.mbedcloudtesting.com", 19);` +2. Call `TCPSocket::recv(buffer, 100);` +3. Verify input according to known pattern. +4. Loop until 100kB of data received. +5. close socket. + +**Expected result:** + +Each recv() call should return equal or less than 100 bytes of data. No +errors should be returned. + +Measure time taken for receiving, report speed + +### TCPSOCKET_RECV_100K_NONBLOCK + +**Description:** + +Download 100kB of data + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. TCPSocket is open + +**Test steps:** + +1. Call `TCPSocket::connect("echo.mbedcloudtesting.com", 19);` +2. Call `TCPSocket::set_blocking(false)` +3. Create another thread that constantly waits signal from sigio() + handler, when received try `TCPSocket::recv()` + 1. Call `TCPSocket::recv(buffer, 100);` + 2. Verify input according to known pattern. + +4. Wait until 100kB of data received. +5. close socket. + +**Expected result:** + +Each recv() call should return equal or less than 100 bytes of data or +NSAPI_ERROR_WOULD_BLOCK in which case thread should wait for another +sigio(). No errors should be returned. + +Measure time taken for receiving, report speed + +### TCPSOCKET_THREAD_PER_SOCKET_SAFETY + +**Description:** + +Run two threads which both exercise the underlying stack and driver +through a dedicated socket + +**Preconditions:** + +1. Network interface and stack are initialised +2. Network connection is up +3. 2 TCPSockets are open and one additional thread has been created +4. Both threads get their own socket instance + +**Test steps:** + +1. Call `TCPSocket::connect("echo.mbedcloudtesting.com", 7)` + in both threads - in the main thread executing the test case and on + the additional one; +2. On main thread + 1. For randomly generated packets, sized 1001, 901, 801,...,101,1 + do + 1. Call `TCPSocket::send(packet, size);` + 2. Verify incoming content was the same that was sent. + Allow recv() to return smaller piezes. + +3. Simultaneously with the earlier step do on the additional thread + 1. For randomly generated packets, sized 10 do + 1. Call `TCPSocket::send(packet, size);` + 2. Verify incomming content was the same that was sent. + Allow recv() to return smaller piezes. + 3. stop the thread if inconsistensies were found and report it + to main thread + +4. Kill the additional thread +5. Close and destroy the sockets + +**Expected result:** + +Echo server returns data to both threads and received data matches to +send data. The additional thread isn't stopped prematurely + +Subset for driver test +---------------------- + +### For physical layer driver (emac, PPP): + +- TCPSERVER_ACCEPT +- TCPSERVER_LISTEN +- TCPSOCKET_ECHOTEST +- TCPSOCKET_ECHOTEST_BURST +- TCPSOCKET_ECHOTEST_BURST_NONBLOCK +- TCPSOCKET_ECHOTEST_NONBLOCK +- TCPSOCKET_RECV_100K +- TCPSOCKET_RECV_100K_NONBLOCK +- TCPSOCKET_RECV_TIMEOUT +- TCPSOCKET_SEND_REPEAT +- UDPSOCKET_BIND_SENDTO +- UDPSOCKET_ECHOTEST +- UDPSOCKET_ECHOTEST_NONBLOCK +- UDPSOCKET_RECV_TIMEOUT +- UDPSOCKET_SENDTO_INVALID +- UDPSOCKET_SENDTO_REPEAT +- UDPSOCKET_SENDTO_TIMEOUT + +### For socket layer driver (AT-driven, external IP stack): + +All Socket, UDPSocket, TCPSocket and TCPServer testcases. diff --git a/TESTS/netsocket/eth_environment.png b/TESTS/netsocket/eth_environment.png new file mode 100644 index 0000000000000000000000000000000000000000..0d66872e3d7ceb0bbd0fe0d3032dffbb44ee79dc GIT binary patch literal 142664 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 N$_g6t<#MJ${{tr6Nbvvw literal 0 HcmV?d00001 diff --git a/TESTS/netsocket/wifi_environment.png b/TESTS/netsocket/wifi_environment.png new file mode 100644 index 0000000000000000000000000000000000000000..b135af10f63c39ec6f653dfb5d8c1fd7bb92bd53 GIT binary patch literal 128762 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%0AE;U@7&Nh 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 bA>N|;t&T6)%iSzw8iTWH zIwVKfM6pCm<$5&&sbLyyZOS(7*-%boaEj0czGMbhK{#8ySR$%zT2U>U-~&>Y!uhX| z4F;Y293Lf<&e;l;3w5m+mFgUf*(n^}lXoW1v!5>NEQhkPJ$B{jOW!iy9G3J`7vyo_hLP@FWtf>i7b5-HcZBM#&m&t?tcZ zjc4ror~oVBJYfHXD7S^3)hT!1o=l2ZqFA#M7hbO&F#`O0$3B^A)~BPCVk{D@#kSLI zoVeZX8hn6X`R{nihLP?b)eB~%vIJuOq&k5PZa7Zl_rI^bROr7QI0^jeM;HDtjhXzM zMP9fD<#5>A1wcJ(*RelS`g!NVr03eUdb0DPI;9<^dZl4>@&u(u6;jD!AJo>VcZ^?d zyVxQ755N5+YBKs#3Rig4d?>NDo)sb+;JdF!d7X~aJxu7y#SP1r+oxtx+s}$u+{t3% zhUm?twEg&~-nY{$rDh*KGNgn@`=}6#-JX5n(&_AU~*2SgZSWA^pSt%cv)NBrEFqK|Bp)vQ#U{6 z6G*zV&K2-2JI7@Iwa55&6z{9BIGFLE55&Y&qXM<%i*t{|nqiTD z)_-~}`imC9B-5e1sCkJ}yH4`PYNMY}&+snUbj*nVW7V+2I?0|ZA+B~nsCYN0g*H^#8tqDqe?H=Y(O|GZ5b19<}o8 z??TP{$?|;UlJTO41UxpnN{uL#kBv#X1y^H@A8N_|98mu&EKQU3?5{viQKKv>0X=;i zE&g;e$lF~_NE*&HGp`sa@u(PCIZ{^SYfWvcF+M|7C%)vyQtH6P$wyO{I59g!U8{lc zv$0B++FuF9%ai0_2chMvUeo%Qb!w8ng4dUEr7y7QRwsIJX~2N*!MQ|oV3V=YgoPB* z<`%yF_Y?UX^G2H+nkcv|zPC{>YQ{7De+dFj`sd9IJ?IR_m)ATk~0?nomf z?`x1NBu3tk!N7ltE?G(^$smcv(j37&}6aEQn!YRd8va2 znuVm-5e$B8EkN{TH;fRZJ;zc4uoGCZ`e625{i-`he!92cQV>IsZwtj%Kd|Hb$~F1N zj(q(OLy?|WX<5Y8a1vXi{ibhXKZ@-E@hP~6>R$R`?S?EDxF&lwKa#>_@UMjv+TM2Q z|BJsgx-h$fEtHYTjLGI;<_oW>?vT1#+{VQ`YcnR(LN3h@3uf zZuOoh4$!}9qNJ35Jg$A=S!`e^AG(-#DAS_l)~WjE#KM*;H_P@kr@ga5zQD4V2_zE3 z#4F{Ox0f}n5Qfx`3V9d;=3YBZm5V%ALHZZhUv$}BUtzg}5_~8}wzvh*QUV%tFiY4D zY|n7JA4pdc;~_47$fYc(m~z^a8N^(UM#THznJ+^9QtOB%f!vUap46f)981VK=rQrb|gxA`wRB1uL`G zFgsxA3}eFNG$T;K+L*o{WHC*d6pXbR>0iidkuwZ9V!x$ay+A+*r((v+z zALczL2FM=cNkY#S2m(Z-(}2cGfSZK%{B%JUuLDQiv;}$VB3>Ho|Dq?5URZy?;UX1h zn8fBKyX+8{5J@5pi?Ii%&Tf|tQi3K1?Wk-Xl!-Lvsw}Xd2yrNMa=qj+)1{wWVRE__ zOEWF`J^ME|7cWT}cS9o-Ij4+(#}-!mr4^oMq6HL4AR7x zg3r4HV61Cy7B_`N2&>7nZn(C4=vSCuQ>)HQJ58~5cmzGby3Gzm!b0E(#E-UTDwK9% zGw4IcXX6>oCp=EH}I z!>?oX!6u%u?AI;#v9BiSIpdd8zt`to-pH*)rd5f_wHrwg2~4sD&&~k{;0}z)ZzQys z+3GnEOb$YP+7#r#Q@A`bSe2vpm$TLCe>b!L;`T5;iM)ENn$h4d6&p2qR02MznTz;0 z7eytTUEX+{KA_gsT{FqL6{%>N$%5`ny<#eAb5Kj-t+5_O_23GM#a0Vwbu$eUd_^ha z^SsSYXj8)5^~&)g>d;`MF;iBHH8+dm!hNeRL1tz8h?ipiK+F0xfOETv?Bu@q%iCR@ zS7C|i*y257@nQPt7Ng^Pxnb*c-UTE_T{zJdwpL2V7MQsNG&4eWJ4%^L+JR1C#wJ1w z2a*R8wnmQ~R|hcWE>jAgX@RGuMS+?R^VFtHQ;eHfPG?{_t7j_jWTI6HEjkM?@!h+s zkdvb->fU0-)gYup`Eq&S`Z7$UmLf@K(VP8WDdZzZAbA{Ju7sEpc>iku#22HbN|EHc zI)5;#>Y#`!-v*=hjwR$Wq~#)S!{ayjw;NXj6UrX(TeQtTYNS>t#hK+hG8U6?IfIFd zbMkBHfJ+#)tyd_Ci6$6-s65`RNGVGYgIsNwr7>xW(A?W^_Q~YA!~#Y%ApAC(&xF~3 zIU1Gu*VVgv^6ba;O#Gjj+-o-(0yu`3<{4(WZPPlgZOX5Ybwk=_G0cWEfUQZKLejDm z(Lf{Zo0!irN&2oVUzKknU8q1q%%#*~?y2pPsTL}rfBD6)?H;MfkRUePnQ=#;wotMR z@7!w6eOys<(l`rOZv@%-KzXh(I*|W4KOp#RGOdlciqd}CMYDO|ad`A_k91DpQaku~ zi-+|}Lxt6vLgWP=ONZT!cv-+EOsgVf2uA1EJt4AN7@QH8I#j^pbI+zY8oV6kwPH3Q zCo2t?h|ULxCNfGQ2@c~esBKjUzln3G^2g2j36)6Jk&Rx5SBNCL-S<~@cqdl4W5%s# zE8nQU-fUJa9u&9L z20h60(G1h6z~lzQv^suh5FAU(BWNWHYF0XZZcuRI;{7x(lOw^*_dy9a*)F#uw$_nW zX+878;CXd&U45-N7-Iv4$C^|$8HUn+<|QtpoiM1){Ne!5#viBcryTx8lQ^)mq?Iid z7F@cOX?Y9$;k^Vy3u$Vir#r){(6g@?VwqcY10#lbc}8D;6_1Ib zmGl;cp&>Ll4mLt|@enu_QR29Wgr8bitwBq#(ho85TMXaE@l$emCo>6*4u0jE?ycRrYf=$xg-w z-H;abnB9gyZ&P5ANvCfmqsE>amFcXXU-&%9vyb62ZF4Z-i@GDkRvR~^X9xlx0CQRf zoT7S3-8bL{a~0<9^yo9Jq)neWr>(|Rtm>{Q5cKM&6N0~9mHL#V1dN_sO~Ld0WuA<> z;eH;|WDXNZ2Sm{z@y~8iN&7_W-R{eG4 z=c*NE2b2I|fe!}4ko$1K#ObL32!0f2Tcd$UrUsltEtFS=f#0F{z53?0qPUrj$k#I> z^q$J)o~-vJ-hSmKaZFvQclh|)RAtu%vIOK=j5mr?R|l<3@!5?Yf}rC|vdo1p?Q!P?2Ztbo34qpJJtQ$M&nnnD1zR>C`&WqnEw9ZV1OM*EeWY=7eE38`9|JgH)Ve zUR*yEPNUx~efU0+@M4}xQ5{=w?F`7^yB}o#;HCVb+rHQjTi~V{j(dbXSe1U_NGG>+OkZ-g+yW-XOX*O)}qVu7y!8Eyz)^_`U(9H&4Qex z4&4j~R(D`UjeoYAW~@|Z0j3@IOSd@&$0O-_2R0Sh8-X&6h)mFCl3ey&;vv>g!iS9~ zVH1<9Q=DPD#hB-Y**0Y@*#^p~zw}vVFZ1Y22^asB+SV3Jw>nq4TC!7+C;A#BMue-5 z|2aM(WF;Wc9p%FGVtN-9l1kR0Q_ytx9mZTAwbPskItwn*I$`OAYotMLLgJpm@qh7P zTb~YKLhl1guJE1B+zd49pX=d>OPu+#St9GJ9w$|Pqz9sJ=()1r*mn{C_>kqthuM(e zAT10UArxf6J@tAnZ-BqhAURKKwRvt0=xv8IcNFU2Zd@JNpw`dCoXIbb#rCC-)75Z{vpLERB! zXc+V`iBkQQuYiHZk78Zf*P6;(T=`oyV_%`#S(fLb9X)CgJCuQadNWBX?QAA}OQC)f z%1vCeP!L~ zq<}4VO6ZF!qr|(lhg6}sQ3JHNF)GQtsOXYh-%pu2yJ-Nav)?~ecBVJw;3;GeFYJ5N z#==h&c|JMlvCM(a(@r>SVmx3@1d}D41u2p_ics~q-?R-p4o;}AoRxs)Evv$(>R4)h z0vjlX4|InH!rkCAR|2f^qep=&Zh`zA$D9^YHzfH5`34Bfs2`f zaRwFp>HU&RZOBp2+BnWNQAi0!T3C9ep(9o3C4Q;`06>hTBrBzph%XqQcEfi`?4z1U zOI5R5+Y1GGc>7!`(IAWp@v1Bs_3%C8q9rPaCh4^u?t(IHO1ys?T>=$GqG{IWK*8NQHD<%|5`-Kzq_!U9NFW7Y(bp*W6=z#1pew zObdfIm?z8FF{ke~0Eu-RTK5bh zD?NlEslRYE=a(5`S}zR>ShA|>8Vy1J*1zi6$4RKRE0BQ80c1Ulh3vBY zM!$Sbi?hI5+lB%H0d@ZS7wV`yr5o={^US)x1n0vU0t2uorxgpTeZEBp->ZesM;mC$ z`hEL%IvlCqnJkVt#a#g!XIN1@;@=nW- z))V=QN68vAz*MdJL6dAp+>zn0dBLqfnO(7~2l1*8HiPNSa6K9yTj%cAk)=3(`MopE ziVUL=%T5HSnY!q|`r^P%$-a?FjgQNAN3Sb6t1uPKO&UNIagsG2-fKQ_fuE~}G;5)_ zVyyAl@QYa|9Ft(VXpeVj&u6mwz(Rp6Y4p!AW+4**FT9y^+vM4QA-1_EJC*EzXa0d# zm9oIIN{QkG=U=qn8zhVShQ8R_hL8G{_Dop&4_vRdzC1Y}`uS$c$L{YeLs(FP1BO0< zZE>EL{8xVOV+c~0hvY?`Ps~NHe~;ukI<3_AEGjl06dygX%N^WCd>+wPpAP#Bnvd~a zNs~yZCIh(!`u+4eGEd z;Y-@kCMC==Hk6W07vKI=3Qo-$3>??(W57tWxwFm`tk-|}weTCvuFJqGqE$fJ(==Z2 zV)~dR!8yU`CmSCGt2czPZn%ewbot0(=U`1P>SZa*)Sqnpj@G1l2WJMdS&cUbl^u?y zzhGfiR$+cckQZhG62uX=IJR1f@xkYBI!m(Qmr`;WmGFYr9H#2hd%a|=Ik1@NR`hO; z$jo@lmgn7r^V0O9+~3=RV&kDW&u4ig0JWcc<{!s>%byBTvPWEpWj-W9G^%m6w3>@m z7=L$J-zlthN<%JBw^~Wszejx+`k;hI&P~P9`XUxT{BET;QW<7prrQnv)4-ZiW!2;D zXVgh78qvvu=dnlE(RvTj*47}ingEf(*g6NCT!0K&)i24LIRfL|Y%WS!U=}5qL}n_+ zdLaBJYjf}L-DABk*Lit4(Mxw`+6 zJiXiTwMs=K-gC8$Vjto_;W@R6a=?cogB24aU?K#h(5h)_tCO-cm$g1w|5Q!z^QXQk z-_>+U=o*Aaf&2S=P{-*>X+08MZcedFqJoY|#nz6p=hpA$GLDgQExGP(iBh}B0gIMc zAhtRk*?F4hru)@AV+x!#-~*=P*Bs2mSWG#f99qJc8nr@k8NYA8io(x9ayx3T=k@Nx z<7k(Ai!79;F5o$8fMRp%mB^!zNtS$tfU{?yCj)EQJ(j7@~lf z7{+b~Yssy(MA|_ELka6&k52bu(tx7Mfao)Y_ag68qke_v;K4A^F#{Ta`b4_iwyw=S zsOOHuX?b2j@_dsPQqBw#Tlw>p8qb%epCgD%zd4|T#1!2Clr6tYa z2_cqlo4Q`Xy;-Pps}_sh*Wy|@6&bw;;_fLTYHM>UNZ^W|r=+>y#UE>_oN-?FobRRw zBKxX8*?P9+FZYZ&QEuF?_n0={&ctFzX6frt(DWN>ssvvMhVKE8_O0=jxC-{AJOj^V zvNh(q?YzR!%@si>6lIbSKkAd+f(HpNKQEENylZiYg+orIEj)Rl^K?n92xTrU+a0aB z9tW<5EZ(IHBJD;ruj(nK{?o(bej-V&AoIU~=Du_FqLQQjDZag9&SO0xIIbjnLwLL4rHYpd0!g5(0B68@WlyJIg=AGp|M5yT{bF9W>o!sre^?fn z1~=xGQYS{u^J!E%$;d6;cCTK+ZX8xitH{!{3|E!aeYhzkcj~SljHD{268V;%A|c4GyPT>A2rH%g%T1H>OHhV&vsTW&->rvwNwM=5w*@p z9cX68mg{bRp?rMsV%JFyIl0F~YGWkmC|J4vQ z4bbF9;H~}pX$aM3Jv9iNn46o3K|c)*`b)6Ipb#hiyiJOvIo$i+ei|I?$L%D!_>+vh z_2jbz#G4O5HZvkK$3J?**)%(M9buaqy^T~@T~(^(Qt2z&rb%0ypeEm9X$e}n&sp#K zM=f#T)YWO96X8AMu$&?D5w{%?yXR=C=NjwqoxjxnmOv03{RpqSi0rCT_Py2kp!}i* zQrCie-JL+Msy};L=6U2T{*J9RwF~vM!3=hi_10mdTnqHU^#OF-s~Tcx;kS&nlG#hy zqq8#--J&Dh^O)B0v>_T2AH#I@(b;zI6b8F#!)H(R*%3L!d^-7AIVK?fs`l@($%_OW zWZ9!(M7@LFHq3o3D?wc7URzdc7q=_KP*jHT!$YTL{vf4G9ZiKJC_5$!f<6zXsU4?F zLPY(oA~Wdp2WW_?X6N>DSRGHV?X^~y$@4J>+vPmXc$_#2tMnV5zq!{a4n@W26_gL9 zu=6#EdgUS3MV~o38E*!UPDBaHoeZJ0spQJ-%;Nypb{o)nXn4UX$2S(r&F1Yf%3~@f z+(deZt7tJjdH#F{btbqeo>F0a$VMNKc43*D!}bo=5-3rdqv-BapAsMZElFkNOFVM` zKGB_bGFT#Zw(jygkvuJEQf=*g=Y}t&%>bZ*yF>hlmq>M|c~aQ>Tn{3cA^B_K`}+_B ze6d@n@6vr(+wiL`Yxg4Zx29~yFt>k6(GlI$E#0W*_C5L68bQ_~Dm$nUs`R&$iKbX| zO2LlxPsT&+geqv&Uj*Jd~G| zn1_ogH1*k7nx}6RpIA9Lc50rAs}7Gg=}fmxO|X>ojOT2|?fUrL5J^Y7duj*2)&L)? zTP@yU*Ff?Zez;&kR6wNJn$EZ<=Em2}?+*@s!f!$$?E1&8)a#JdTiD8cqDL#v*g|b& z759j@1pnX(@P1kxl24X=T#%r95WypgUk#@;ZVWoPhjm%(sc`u1m-i#;k270lz@MFq zNZNUne_(kD?BMguFMC<^7as2uXpajUS&X&r$OO`QaYIj|t~GYUL1crgAOtZlZ}RB= z1zI!J4`*}F8G`Scq!0HdLecu8g!KoY79Z>6mXsItzBs&5}$nBnCO$!;&j#QY6pmW7yR2Ui-uHmf#ppu)B3aOfXwcd{H@p{biOX46-8n z1QVHX4mxwsCRwnl8Fy&@5WhSN;A(v}pm~D?_3#1mpFbch0EPj;e)gn`elo(HrFliW zA#t!6Bz)hzEpvp~^ylO*${+B2%R}E@{Rz2!;@&bB-H@iTACh2>+lNSt zj-oLy|3dJMSfgxVG#}fc@1k}XdEuazOl?(FYio?g`~I$)Qus1Cyfr7wxoCZ?n6CUi zO|DH6;c$CW`4-LTY_!AQBSuc%T_WNFdIjXv^{R=9lSx>~2~?|I7tjW3sv>gXs2py9 z_I-(}D?*ACRkjio=RZ}JK3tT6ImP07&!x;rSf}UoC)r=pC-=I`pJ)mf-**y`7IP95 z!GS*?hpp+5%lJfTlYO9`b=*s?z91|~MWdFhSc5Is9D4iC0nD{a`X^mw zX`jAcUYV0@GkojA2NIx=!T}Nf1Kj-_bN^Ph5R+Kc8M&#ect@g;d@RD_Z}r!#0Qq2? z`lfzF9P%Y=jL5@O=15e;A4O%LFifjShwE-Yt0|j%uUmTL)?Il0HgNs&n?M|ULMcsL zA4>#1rhSIIMx)?in{u~iL9Kq}ARFJ7bqKB=<;TR>7Y$i$^AHC69||FaOJE@alkXjDI< zx@PWm@%IboHRP=^cq$;u`3WHQ{tA%&u^rVJz@QPz@$}JhzzLpvZYpW$KMqv;HRyTJ zo!#_6VBQGa{fKog(K$i}FUE&3($MsKnIJ?HG`YZY5;if_!qlvs4i9c=7_-Y{hXh28 z>^;czl{S}kLnC_q&f-hkFf!-4d=Sw%t?Iv>TuD2jy;2<5mhgt{8%Ffac~;R;TxVV^ zZrlV_KE-brDXlmAbJCZ`vA_z>fO7?L$A{D%0aYPCtoeJVTGxqB>V!%5ju^ge;^PA8 zknk|9v^sa9eK8@s#WBo3Csh#yxk?@cJaAqY4nMf5kODH&O@C(Gg~2D#nmk1`mg7lm za__iZ3BTnO<9hF@{~a$=Uk*%0{qjXicC5C?UU_IeJds*a=k5Z!S@-{TuX0S+X-f6B z9@5|NcT!>N*Erk!D=!5xf_6Ady^3k%=bDYou85_3vH=U* zx-+?~sYxJ$?Rop#S8M7t-V3Z~xs<>>5Ozs@ABm}ixuXUvM%VEZ@dWsgjZpRf2cBXf z7B!CKh6H*eb6%}8KwveELUW9+Y`~%Y0TsQVmUk+H^E^i6Z-sKL*4V=;A7VP#8pMb5 ztp96mp0CMc=`;7tK7=!yrRnKp6ie$ZH>C^ayc{E>IoUWY+W%Vfl4$^TTXuWciyD5G zwF*RkwyRkVf%tTa!WvWP!D9mpENiDic^i70VnZ4dFK!0CL($KTV=zBdDo>S>Pa)3Y zN75W#O|b(t{myB-=qlfZpib}uV*h)HHuQ)PynJl-8Z&T`(LGMdKU5fDjgor@BscwPr!HhX zSajd`!T67Z;aI>Cx1P;?_Me$9XsyZrR&9{x8=>{frS`SxHCWI~w{(W#X= zganZcJHlv``>@- zW?g(O$u>8ftKA985y3J5_;9=w7LVxa;}v2hNiPfDK_5H^Wul6`XF5 Date: Mon, 27 Aug 2018 10:18:36 -0500 Subject: [PATCH 25/26] Copy edit requested section of README.md Copy edit for active voice, inclusion of articles and U.S. spelling. --- TESTS/netsocket/README.md | 102 ++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 54 deletions(-) diff --git a/TESTS/netsocket/README.md b/TESTS/netsocket/README.md index 536a7a9860..7922826ac7 100644 --- a/TESTS/netsocket/README.md +++ b/TESTS/netsocket/README.md @@ -1,54 +1,53 @@ Network Socket test plan ======================== -This is a test plan for Mbed OS Socket API. This describes all test -cases and their intended behaviour. When API document is not clear, this -should be used as a reference for implementing correct behaviour. +This is a test plan for the Mbed OS Socket API. This describes all test +cases and their intended behaviors. When an API document is not clear, use +this as a reference for implementing correct behavior. -**NOTE:** As testing is a moving target, this test plan might define more test cases than what are -implemented in Mbed OS. Refer to [test case priorities](#test-case-priorities) for list of test cases that target must pass to be compliant with Mbed OS socket API. +**NOTE:** Because testing is a moving target, this test plan might define more test cases than Mbed OS +implements. Refer to [test case priorities](#test-case-priorities) for a list of test cases that the target must pass to be compliant with the Mbed OS socket API. Target API ---------- -Target for this plan is to test +The target for this plan is to test: -- [Socket](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/Socket.h) -- [UDPSocket](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/UDPSocket.h) -- [TCPSocket](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/TCPSocket.h) -- [TCPServer](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/TCPServer.h) +- [Socket](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/Socket.h). +- [UDPSocket](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/UDPSocket.h). +- [TCPSocket](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/TCPSocket.h). +- [TCPServer](https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/TCPServer.h). Reference documentation: https://os.mbed.com/docs/latest/reference/network-socket.html -Tools to be used +Tools to use ---------------- -- Mbed OS -- Standard Mbed OS development tools as described in https://os.mbed.com/docs/latest/tools/index.html -- Test server +- Mbed OS. +- Standard Mbed OS development tools as described in https://os.mbed.com/docs/latest/tools/index.html. +- Test server. -These test cases itself do not require any special tooling, other than +These test cases themselves do not require any special tooling, other than the test server described in "Test environment" chapter. Test environment ---------------- As a general guideline, network connectivity with public Internet access -is required. This satisfies Socket tests but specific connectivity +is required. This satisfies Socket tests, but specific connectivity methods might require some extra configuration or devices within the network. -Test environment consist of DUTs, network connection and test -server. Arm provides public test server, but it can be installed locally -as well, if isolated test environment is required. +The test environment consist of DUTs, network connection and the test +server. Arm provides a public test server, but it can be installed locally +as well, if an isolated test environment is required. -### Public Test server +### Public test server Address: `echo.mbedcloudtesting.com` -Both IPv4 and IPv6 addresses are available from public DNS service which -currently are following: +Both IPv4 and IPv6 addresses are available from a public DNS service: ```.sh $ host echo.mbedcloudtesting.com @@ -58,10 +57,10 @@ echo.mbedcloudtesting.com has IPv6 address 2a05:d018:21f:3800:8584:60f8:bc9f:e61 **Open services in the test server** -- Echo Protocol, [RFC 862](https://tools.ietf.org/html/rfc862) is +- Echo protocol, [RFC 862](https://tools.ietf.org/html/rfc862) is enabled in both TCP and UDP. Port 7. -- Discard Protocol, [RFC 863](https://tools.ietf.org/html/rfc863) is - enabled in both TCP and UDP. Port 9 +- Discard protocol, [RFC 863](https://tools.ietf.org/html/rfc863) is + enabled in both TCP and UDP. Port 9. - Character generator protocol, [RFC 864](https://tools.ietf.org/html/rfc864) is enabled in both TCP and UDP. Port 19. Output pattern should follow the proposed example pattern in RFC. @@ -70,22 +69,21 @@ echo.mbedcloudtesting.com has IPv6 address 2a05:d018:21f:3800:8584:60f8:bc9f:e61 - Time protocol, [RFC 868](https://tools.ietf.org/html/rfc868) in both TCP and UDP. Port 37. -Firewall should be configured to allow this traffic to test server. +Configure the firewall to allow this traffic to access the test server. **Example configuration for Debian/Ubuntu Linux** -These services are available on many operating systems and its out of -scope of this document to describe how to install them. This is an -example how to install these into Debian/Ubuntu based Linux distribution -using standard Inet Daemon. +These services are available on many operating systems, and installing them is out of +scope of this document. Below is an +example of how to install these services into a Debian/Ubuntu based Linux distribution +using standard Inet Daemon: ```.sh $ sudo apt install inetutils-inetd $ nano /etc/inetd.conf ``` - -Enable following services from /etc/inetd.conf +Enable following services from /etc/inetd.conf: ``` #:INTERNAL: Internal services @@ -99,10 +97,9 @@ daytime stream tcp6 nowait root internal time stream tcp6 nowait root internal ``` - **Testing the connectivity** -Connection to test server can be used with NMAP tool like this +You can connect to the test server with an NMAP tool like this: ```.sh $ nmap -sT -p7,9,13,37 echo.mbedcloudtesting.com @@ -140,27 +137,23 @@ Nmap done: 1 IP address (1 host up) scanned in 0.20 seconds ![Ethernet](eth_environment.png) -Ethernet test environment consist of devices, ethernet switch, optional -firewall that allows connecting to Echo server. +The Ethernet test environment consists of devices, an ethernet switch and an optional +firewall that allows connecting to the Echo server. +### Wi-Fi test environment +![Wi-Fi](wifi_environment.png) -### Wifi test environment - -![Wifi](wifi_environment.png) - -Wifi test environment is equiwalent of the ethernet one, except that it -have two separate access point, or one with dual SSID. Connectivity to +The Wi-Fi test environment is equivalent to the Ethernet test environment, except that the +Wi-Fi test environment has two separate access points or one with dual SSID. Connectivity to echo server is required, but it can be hosted locally, as specified in -Ethernet environment. - - +the Ethernet environment. Test case priorities -------------------- -Please refer to following table for priorities of test cases. Priorities -are labelled as MUST and SHOULD. MUST means this is a requirement and +Please refer to the following table for priorities of test cases. Priorities +are labeled as MUST and SHOULD. MUST means this is a requirement and therefore mandatory to pass the test. SHOULD means it is recommended to pass the test if the driver implements the feature in question. @@ -222,10 +215,10 @@ pass the test if the driver implements the feature in question. Building test binaries -------------------------- -For testing the board and driver, testing should be done against Mbed OS -master to get latest up to date test cases and drivers. +For testing the board and driver, test against the Mbed OS +master branch to get the most recent, up-to-date test cases and drivers. -To create build environment: +To create a build environment: ```.sh mbed new network_test @@ -235,8 +228,8 @@ git checkout master cd .. ``` -Also, when building socket testcases, special macro is required to -enable all test, so create `mbed_app.json` file with following +Also, building socket test cases requires a special macro to +enable all tests, so create an `mbed_app.json` file with the following content at minimum: ``` @@ -245,7 +238,7 @@ content at minimum: } ``` -WiFi tests require some more configuration, so for WiFi purposes, +Wi-Fi tests require some more configuration, so for Wi-Fi purposes, the `mbed_app.json` might look like this: ``` @@ -311,7 +304,8 @@ the `mbed_app.json` might look like this: } ``` -Now build test binaries +Now build test binaries: + ```.sh mbed test --compile -t -m -n mbed-os-tests-network-*,mbed-os-tests-netsocket* ``` From 4599726f1f9ae91ceb924653141299e6f2e99bc6 Mon Sep 17 00:00:00 2001 From: adbridge Date: Tue, 11 Sep 2018 15:04:50 +0100 Subject: [PATCH 26/26] Update Mbed version block --- platform/mbed_version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/mbed_version.h b/platform/mbed_version.h index 8fe2258b24..a300bc1bed 100644 --- a/platform/mbed_version.h +++ b/platform/mbed_version.h @@ -29,21 +29,21 @@ * * @note 99 is default value for development version (master branch) */ -#define MBED_MAJOR_VERSION 5 +#define MBED_MAJOR_VERSION 5 /** MBED_MINOR_VERSION * Mbed OS minor version * * @note 99 is default value for development version (master branch) */ -#define MBED_MINOR_VERSION 10 +#define MBED_MINOR_VERSION 10 /** MBED_PATCH_VERSION * Mbed OS patch version * * @note 99 is default value for development version (master branch) */ -#define MBED_PATCH_VERSION 0 +#define MBED_PATCH_VERSION 0 #define MBED_ENCODE_VERSION(major, minor, patch) ((major)*10000 + (minor)*100 + (patch))