Merge remote-tracking branch 'upstream/master' into offir-mbed-qspif

pull/8352/head
Offir Kochalsky 2018-10-09 14:21:03 +03:00
commit a30abf48b0
1560 changed files with 197954 additions and 27544 deletions

6
.gitignore vendored
View File

@ -88,3 +88,9 @@ tags
.vscode/
features/FEATURE_BLE/targets/TARGET_CORDIO/stack_backup/
.pytest_cache
log
# Icetea related file
test_suite.json

View File

@ -162,7 +162,7 @@ matrix:
- python tools/make.py -t GCC_ARM -m K64F --source=. --build=BUILD/K64F/GCC_ARM -j0
# Check that example compiles without rtos
- sed -n '/``` cpp/,/```/{/```$/Q;/```/d;p;}' $EVENTS/README.md > main.cpp
- rm -r rtos features/cellular features/netsocket features/nanostack features/lwipstack features/frameworks/greentea-client features/frameworks/utest features/frameworks/unity BUILD
- rm -r rtos features/cellular features/netsocket features/nanostack features/lwipstack features/frameworks/greentea-client features/frameworks/utest features/frameworks/unity components BUILD
- python tools/make.py -t GCC_ARM -m DISCO_F401VC --source=. --build=BUILD/DISCO_F401VC/GCC_ARM -j0
# Run local equeue tests
- make -C $EVENTS/equeue test
@ -187,12 +187,11 @@ matrix:
- env:
- NAME=littlefs
- LITTLEFS=features/filesystem/littlefs
- LITTLEFS=features/storage/filesystem/littlefs
install:
# Install dependencies
- sudo apt-get install gcc-arm-embedded fuse libfuse-dev
- pip install -r requirements.txt
- git clone https://github.com/armmbed/spiflash-driver.git
# Print versions
- arm-none-eabi-gcc --version
- gcc --version
@ -268,3 +267,4 @@ matrix:
script:
- echo 'Checking that there is no GPL licence text in code'
- ! git grep -q --ignore-case "gnu general public";
- ! git grep -q --ignore-case "gnu library general public";

View File

@ -33,3 +33,9 @@ We have a [developer website](https://os.mbed.com) for asking questions, engagin
## Getting started for contributors
We also have a [contributing and publishing guide](https://os.mbed.com/contributing/) that covers licensing, contributor agreements and style guidelines.
## Documentation
For more information about Mbed OS, please see [our published documentation](https://os.mbed.com/docs/latest). It includes published Doxygen for our APIs, step-by-step tutorials, porting information and background reference materials about our architecture and tools.
To contribute to this documentation, please see the [mbed-os-5-docs repo](https://github.com/ARMmbed/mbed-os-5-docs).

View File

@ -36,9 +36,6 @@ class SystemResetTest(BaseHostTest):
def __init__(self):
super(SystemResetTest, self).__init__()
self.reset = False
cycle_s = self.get_config_item('program_cycle_s')
self.program_cycle_s = cycle_s if cycle_s is not None else DEFAULT_CYCLE_PERIOD
self.test_steps_sequence = self.test_steps()
# Advance the coroutine to it's first yield statement.
self.test_steps_sequence.send(None)
@ -61,14 +58,16 @@ class SystemResetTest(BaseHostTest):
"""Reset the device and check the status
"""
system_reset = yield
self.reset = False
wait_after_reset = self.get_config_item('forced_reset_timeout')
wait_after_reset = wait_after_reset if wait_after_reset is not None else DEFAULT_CYCLE_PERIOD
self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DUMMY)
time.sleep(self.program_cycle_s)
time.sleep(wait_after_reset)
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
system_reset = yield
if self.reset == False:
raise RuntimeError('Platform did not reset as expected.')

View File

@ -0,0 +1,145 @@
"""
Copyright (c) 2018 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
"""
This script is the host script for trng test sequence, it send the
step signaling sequence and receive and transmit data to the device after
reset if necesarry (default loading and storing mechanism while reseting the device
is NVstore, in case NVstore isn't enabled we'll use current infrastructure,
for more details see main.cpp file)
"""
import time
from mbed_host_tests import BaseHostTest
from mbed_host_tests.host_tests_runner.host_test_default import DefaultTestSelector
from time import sleep
DEFAULT_CYCLE_PERIOD = 1.0
MSG_VALUE_DUMMY = '0'
MSG_TRNG_READY = 'ready'
MSG_TRNG_BUFFER = 'buffer'
MSG_TRNG_TEST_STEP1 = 'check_step1'
MSG_TRNG_TEST_STEP2 = 'check_step2'
MSG_KEY_SYNC = '__sync'
MSG_KEY_RESET_COMPLETE = 'reset_complete'
MSG_KEY_TEST_SUITE_ENDED = 'Test_suite_ended'
MSG_KEY_EXIT = 'exit'
class TRNGResetTest(BaseHostTest):
"""Test for the TRNG API.
"""
def __init__(self):
super(TRNGResetTest, self).__init__()
self.did_reset = False
self.ready = False
self.suite_ended = False
self.buffer = 0
self.test_steps_sequence = self.test_steps()
# Advance the coroutine to it's first yield statement.
self.test_steps_sequence.send(None)
#define callback functions for msg handling
def setup(self):
self.register_callback(MSG_TRNG_READY, self.cb_device_ready)
self.register_callback(MSG_TRNG_BUFFER, self.cb_trng_buffer)
self.register_callback(MSG_KEY_TEST_SUITE_ENDED, self.cb_device_test_suit_ended)
self.register_callback(MSG_KEY_RESET_COMPLETE, self.cb_reset_complete)
#receive sent data from device before reset
def cb_trng_buffer(self, key, value, timestamp):
"""Acknowledge device rebooted correctly and feed the test execution
"""
self.buffer = value
try:
if self.test_steps_sequence.send(value):
self.notify_complete(True)
except (StopIteration, RuntimeError) as exc:
self.notify_complete(False)
def cb_device_ready(self, key, value, timestamp):
"""Acknowledge device rebooted correctly and feed the test execution
"""
self.ready = True
try:
if self.test_steps_sequence.send(value):
self.notify_complete(True)
except (StopIteration, RuntimeError) as exc:
self.notify_complete(False)
def cb_reset_complete(self, key, value, timestamp):
"""Acknowledge reset complete
"""
self.did_reset = True
try:
if self.test_steps_sequence.send(value):
self.notify_complete(True)
except (StopIteration, RuntimeError) as exc:
self.notify_complete(False)
def cb_device_test_suit_ended(self, key, value, timestamp):
"""Acknowledge device finished a test step correctly and feed the test execution
"""
self.suite_ended = True
try:
if self.test_steps_sequence.send(value):
self.notify_complete(True)
except (StopIteration, RuntimeError) as exc:
self.notify_complete(False)
#define test steps and actions
def test_steps(self):
"""Test step 1
"""
wait_for_communication = yield
self.ready = False
self.did_reset = False
self.suite_ended = False
self.send_kv(MSG_TRNG_TEST_STEP1, MSG_VALUE_DUMMY)
wait_for_communication = yield
if self.buffer == 0:
raise RuntimeError('Phase 1: No buffer received.')
self.reset()
"""Test step 2 (After reset)
"""
wait_for_communication = yield
if self.did_reset == False:
raise RuntimeError('Phase 1: Platform did not reset as expected.')
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
wait_for_communication = yield
if self.ready == False:
raise RuntimeError('Phase 1: Platform not ready as expected.')
self.send_kv(MSG_TRNG_TEST_STEP2, self.buffer)
wait_for_communication = yield
if self.suite_ended == False:
raise RuntimeError('Test failed.')
self.send_kv(MSG_KEY_EXIT, MSG_VALUE_DUMMY)
# The sequence is correct -- test passed.
yield

View File

@ -125,11 +125,41 @@ void test_any_polynomial()
}
}
void test_thread(void)
{
char test[] = "123456789";
uint32_t crc;
MbedCRC<POLY_32BIT_ANSI, 32> ct;
TEST_ASSERT_EQUAL(0, ct.compute((void *)test, strlen((const char*)test), &crc));
TEST_ASSERT_EQUAL(0xCBF43926, crc);
}
void test_thread_safety()
{
char test[] = "123456789";
uint32_t crc;
MbedCRC<POLY_16BIT_IBM, 16> ct;
TEST_ASSERT_EQUAL(0, ct.compute_partial_start(&crc));
TEST_ASSERT_EQUAL(0, ct.compute_partial((void *)&test, 4, &crc));
Thread t1(osPriorityNormal1, 320);
t1.start(callback(test_thread));
TEST_ASSERT_EQUAL(0, ct.compute_partial((void *)&test[4], 5, &crc));
TEST_ASSERT_EQUAL(0, ct.compute_partial_stop(&crc));
TEST_ASSERT_EQUAL(0xBB3D, crc);
// Wait for the thread to finish
t1.join();
}
Case cases[] = {
Case("Test supported polynomials", test_supported_polynomials),
Case("Test partial CRC", test_partial_crc),
Case("Test SD CRC polynomials", test_sd_crc),
Case("Test not supported polynomials", test_any_polynomial)
Case("Test not supported polynomials", test_any_polynomial),
Case("Test thread safety", test_thread_safety)
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)

View File

@ -24,8 +24,8 @@
#include <stdio.h>
#include <stdarg.h>
#ifndef MBED_MEM_TRACING_ENABLED
#error [NOT_SUPPORTED] test not supported
#if !MBED_MEM_TRACING_ENABLED
#error [NOT_SUPPORTED] test not supported
#endif
using utest::v1::Case;

View File

@ -473,11 +473,14 @@ void ticker_speed_test(void)
/* ---- Test fire_interrupt function. ---- */
counter = NUM_OF_CALLS;
/* Disable ticker interrupt which would interfere with speed test */
core_util_critical_section_enter();
start = us_ticker_read();
while (counter--) {
intf->fire_interrupt();
}
stop = us_ticker_read();
core_util_critical_section_exit();
TEST_ASSERT(diff_us(start, stop, us_ticker_info) < (NUM_OF_CALLS * (MAX_FUNC_EXEC_TIME_US + DELTA_FUNC_EXEC_TIME_US)));
@ -569,7 +572,7 @@ utest::v1::status_t lp_ticker_teardown(const Case *const source, const size_t pa
utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(30, "default_auto");
GREENTEA_SETUP(80, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}

View File

@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_QSPI_FLASH_MX25R6435F_H
#define MBED_QSPI_FLASH_MX25R6435F_H
#ifndef MBED_QSPI_FLASH_MX25RXX35F_H
#define MBED_QSPI_FLASH_MX25RXX35F_H
#define QSPI_FLASH_CHIP_STRING "macronix MX25R6435F"
#define QSPI_FLASH_CHIP_STRING "macronix MX25RXX35F"
// Command for reading status register
#define QSPI_CMD_RDSR 0x05
@ -52,6 +52,8 @@
#define QSPI_PAGE_PROG_MAX_TIME 11500 // 10ms
#define QSPI_PAGE_SIZE 256 // 256B
#define QSPI_SECTOR_SIZE 4096 // 4kB
#define QSPI_SECTOR_COUNT 32 // adjusted to MX25R1035F smallest one from MX25RXX35F family
// Commands for reading
#define QSPI_CMD_READ_1IO_FAST 0x0B // 1-1-1 mode
@ -79,7 +81,7 @@
#define QSPI_ERASE_BLOCK_32_MAX_TIME 3450000 // 3s
#define QSPI_ERASE_BLOCK_64_MAX_TIME 4025000 // 3.5s
// max frequency for basic rw operation
// max frequency for basic rw operation (for fast mode)
#define QSPI_COMMON_MAX_FREQUENCY 32000000
#define QSPI_STATUS_REG_SIZE 1
@ -107,21 +109,28 @@
#define CONFIG1_BIT_LH (1 << 1) // 0 = Ultra Low power mode, 1 = High performance mode
// single quad enable flag for both dual and quad mode
#define QUAD_ENABLE() \
#define EXTENDED_SPI_ENABLE() \
\
uint8_t reg_data[QSPI_STATUS_REG_SIZE]; \
const int32_t reg_size = QSPI_STATUS_REG_SIZE + QSPI_CONFIG_REG_0_SIZE; \
uint8_t reg_data[reg_size] = { 0 }; \
\
if (read_register(STATUS_REG, reg_data, \
QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
if (read_register(CONFIG_REG0, reg_data + QSPI_STATUS_REG_SIZE, \
QSPI_CONFIG_REG_0_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
if (write_enable(qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
WAIT_FOR(WRSR_MAX_TIME, qspi); \
\
reg_data[0] = STATUS_BIT_QE; \
qspi.cmd.build(QSPI_CMD_WRSR); \
\
if (qspi_command_transfer(&qspi.handle, qspi.cmd.get(), \
reg_data, QSPI_STATUS_REG_SIZE, NULL, 0) != QSPI_STATUS_OK) { \
if (write_register(QSPI_CMD_WRSR, reg_data, \
reg_size, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
WAIT_FOR(WRSR_MAX_TIME, qspi); \
@ -137,20 +146,28 @@
#define QUAD_DISABLE() \
#define EXTENDED_SPI_DISABLE() \
\
uint8_t reg_data[QSPI_STATUS_REG_SIZE]; \
const int32_t reg_size = QSPI_STATUS_REG_SIZE + QSPI_CONFIG_REG_0_SIZE; \
uint8_t reg_data[reg_size] = { 0 }; \
\
if (read_register(STATUS_REG, reg_data, \
QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
if (read_register(CONFIG_REG0, reg_data + QSPI_STATUS_REG_SIZE, \
QSPI_CONFIG_REG_0_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
if (write_enable(qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
WAIT_FOR(WRSR_MAX_TIME, qspi); \
\
reg_data[0] = 0; \
qspi.cmd.build(QSPI_CMD_WRSR); \
reg_data[0] &= ~(STATUS_BIT_QE); \
\
if (qspi_command_transfer(&qspi.handle, qspi.cmd.get(), \
reg_data, QSPI_STATUS_REG_SIZE, NULL, 0) != QSPI_STATUS_OK) { \
if (write_register(QSPI_CMD_WRSR, reg_data, \
reg_size, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
WAIT_FOR(WRSR_MAX_TIME, qspi); \
@ -168,7 +185,6 @@
#define FAST_MODE_ENABLE() \
\
qspi_status_t ret; \
const int32_t reg_size = QSPI_STATUS_REG_SIZE + QSPI_CONFIG_REG_0_SIZE; \
uint8_t reg_data[reg_size]; \
\
@ -181,12 +197,58 @@
return QSPI_STATUS_ERROR; \
} \
\
reg_data[2] |= CONFIG1_BIT_LH; \
qspi.cmd.build(QSPI_CMD_WRSR); \
if (write_enable(qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
return qspi_command_transfer(&qspi.handle, qspi.cmd.get(), \
reg_data, reg_size, NULL, 0)
reg_data[2] |= CONFIG1_BIT_LH; \
if (write_register(QSPI_CMD_WRSR, reg_data, \
reg_size, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
WAIT_FOR(WRSR_MAX_TIME, qspi); \
\
if (read_register(CONFIG_REG0, reg_data, \
QSPI_CONFIG_REG_0_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
return ((reg_data[1] & CONFIG1_BIT_LH) != 0 ? \
QSPI_STATUS_OK : QSPI_STATUS_ERROR)
#define FAST_MODE_DISABLE() \
\
const int32_t reg_size = QSPI_STATUS_REG_SIZE + QSPI_CONFIG_REG_0_SIZE; \
uint8_t reg_data[reg_size]; \
\
if (read_register(STATUS_REG, reg_data, \
QSPI_STATUS_REG_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
if (read_register(CONFIG_REG0, reg_data + QSPI_STATUS_REG_SIZE, \
QSPI_CONFIG_REG_0_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
if (write_enable(qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
reg_data[2] &= ~(CONFIG1_BIT_LH); \
if (write_register(QSPI_CMD_WRSR, reg_data, \
reg_size, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
WAIT_FOR(WRSR_MAX_TIME, qspi); \
\
if (read_register(CONFIG_REG0, reg_data, \
QSPI_CONFIG_REG_0_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
return ((reg_data[1] & CONFIG1_BIT_LH) == 0 ? \
QSPI_STATUS_OK : QSPI_STATUS_ERROR)
#endif // MBED_QSPI_FLASH_MX25R6435F_H
#endif // MBED_QSPI_FLASH_MX25RXX35F_H

View File

@ -58,18 +58,24 @@
#define QSPI_CMD_WRITE_1IO 0x02 // 1-1-1 mode
#define QSPI_CMD_WRITE_2IO 0xD2 // 1-2-2 mode
#define QSPI_CMD_WRITE_4IO 0x12 // 1-4-4 mode
#define QSPI_CMD_WRITE_DPI 0xD2 // 2-2-2 mode
#define QSPI_CMD_WRITE_QPI 0x12 // 4-4-4 mode
// write operations max time [us] (datasheet max time + 15%)
#define QSPI_PAGE_PROG_MAX_TIME 5750 // 5ms
#define QSPI_PAGE_SIZE 256 // 256B
#define QSPI_SECTOR_SIZE 4096 // 4kB
#define QSPI_SECTOR_COUNT 4096
// Commands for reading
#define QSPI_CMD_READ_1IO_FAST 0x0B // 1-1-1 mode
#define QSPI_CMD_READ_1IO 0x03 // 1-1-1 mode
#define QSPI_CMD_READ_2IO 0xBB // 1-2-2 mode
#define QSPI_CMD_READ_DPI 0xBB // 2-2-2 mode
#define QSPI_CMD_READ_1I2O 0x3B // 1-1-2 mode
#define QSPI_CMD_READ_4IO 0xEB // 1-4-4 mode
#define QSPI_CMD_READ_QPI 0xEB // 4-4-4 mode
#define QSPI_CMD_READ_1I4O 0x6B // 1-1-4 mode
@ -88,7 +94,7 @@
#define QSPI_CMD_ERASE_CHIP 0x60 // or 0xC7
// erase operations max time [us] (datasheet max time + 15%)
#define QSPI_ERASE_SECTOR_MAX_TIME 276000 // 240 ms
#define QSPI_ERASE_SECTOR_MAX_TIME 920000 // 0.8s
#define QSPI_ERASE_BLOCK_32_MAX_TIME 3000000 // 3s
#define QSPI_ERASE_BLOCK_64_MAX_TIME 3500000 // 3.5s
@ -155,28 +161,122 @@
#define DUAL_ENABLE() \
/* TODO: add implementation */ \
return QSPI_STATUS_OK
\
uint8_t reg_data[QSPI_CONFIG_REG_2_SIZE]; \
\
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
if (read_register(QSPI_CMD_RDCR2, reg_data, \
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
if (write_enable(qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
reg_data[0] = reg_data[0] & ~(CONFIG2_BIT_DE); \
if (write_register(QSPI_CMD_WRCR2, reg_data, \
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
qspi.cmd.configure(MODE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8); \
WAIT_FOR(WRSR_MAX_TIME, qspi); \
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
if (read_register(QSPI_CMD_RDCR2, reg_data, \
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
return ((reg_data[0] & (CONFIG2_BIT_DE)) == 0 ? \
QSPI_STATUS_OK : QSPI_STATUS_ERROR)
#define DUAL_DISABLE() \
/* TODO: add implementation */ \
return QSPI_STATUS_OK
\
uint8_t reg_data[QSPI_CONFIG_REG_2_SIZE]; \
\
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
if (read_register(QSPI_CMD_RDCR2, reg_data, \
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
if (write_enable(qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
reg_data[0] = reg_data[0] | (CONFIG2_BIT_DE); \
if (write_register(QSPI_CMD_WRCR2, reg_data, \
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
WAIT_FOR(WRSR_MAX_TIME, qspi); \
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); \
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
if (read_register(QSPI_CMD_RDCR2, reg_data, \
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
return ((reg_data[0] & CONFIG2_BIT_DE) != 1 ? \
QSPI_STATUS_OK : QSPI_STATUS_ERROR)
#define QUAD_ENABLE() \
/* TODO: add implementation */ \
return QSPI_STATUS_OK
\
uint8_t reg_data[QSPI_CONFIG_REG_2_SIZE]; \
\
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
if (read_register(QSPI_CMD_RDCR2, reg_data, \
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
if (write_enable(qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
reg_data[0] = reg_data[0] & ~(CONFIG2_BIT_QE); \
if (write_register(QSPI_CMD_WRCR2, reg_data, \
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
qspi.cmd.configure(MODE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8); \
WAIT_FOR(WRSR_MAX_TIME, qspi); \
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
if (read_register(QSPI_CMD_RDCR2, reg_data, \
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
return ((reg_data[0] & (CONFIG2_BIT_QE)) == 0 ? \
QSPI_STATUS_OK : QSPI_STATUS_ERROR)
#define QUAD_DISABLE() \
/* TODO: add implementation */ \
return QSPI_STATUS_OK
#define FAST_MODE_ENABLE() \
/* TODO: add implementation */ \
return QSPI_STATUS_OK
\
uint8_t reg_data[QSPI_CONFIG_REG_2_SIZE]; \
\
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
if (read_register(QSPI_CMD_RDCR2, reg_data, \
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
if (write_enable(qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
reg_data[0] = reg_data[0] | (CONFIG2_BIT_QE); \
if (write_register(QSPI_CMD_WRCR2, reg_data, \
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
WAIT_FOR(WRSR_MAX_TIME, qspi); \
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8); \
memset(reg_data, 0, QSPI_CONFIG_REG_2_SIZE); \
if (read_register(QSPI_CMD_RDCR2, reg_data, \
QSPI_CONFIG_REG_2_SIZE, qspi) != QSPI_STATUS_OK) { \
return QSPI_STATUS_ERROR; \
} \
\
return ((reg_data[0] & CONFIG2_BIT_QE) != 1 ? \
QSPI_STATUS_OK : QSPI_STATUS_ERROR)
#endif // MBED_QSPI_FLASH_N25Q128A_H

View File

@ -16,7 +16,7 @@
#ifndef MBED_QSPI_FLASH_CONFIG_H
#define MBED_QSPI_FLASH_CONFIG_H
#include "../../MX25R6435F_config.h"
#include "../../MX25RXX35F_config.h"
// NRF doesn't uses read/write opcodes, instead it uses commands id's.
// Before sending it to H/W opcodes are mapped to id's in Mbed hal qspi implementation
@ -29,5 +29,9 @@
#undef QSPI_CMD_READ_1IO
#define QSPI_CMD_READ_1IO QSPI_CMD_READ_1IO_FAST
#ifdef QSPI_SECTOR_COUNT
#undef QSPI_SECTOR_COUNT
#define QSPI_SECTOR_COUNT 2048 // for MX25R6435F
#endif
#endif // MBED_QSPI_FLASH_CONFIG_H

View File

@ -16,7 +16,7 @@
#ifndef MBED_QSPI_FLASH_CONFIG_H
#define MBED_QSPI_FLASH_CONFIG_H
#include "../../MX25R6435F_config.h"
#include "../../MX25RXX35F_config.h"
#endif // MBED_QSPI_FLASH_CONFIG_H

View File

@ -0,0 +1,26 @@
/* mbed Microcontroller Library
* Copyright (c) 2018-2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_QSPI_FLASH_CONFIG_H
#define MBED_QSPI_FLASH_CONFIG_H
#include "../../MX25RXX35F_config.h"
#ifdef QSPI_SECTOR_COUNT
#undef QSPI_SECTOR_COUNT
#define QSPI_SECTOR_COUNT 1024 // for MX25R3235F
#endif
#endif // MBED_QSPI_FLASH_CONFIG_H

View File

@ -23,6 +23,8 @@
#include "NORDIC/NRF52840_DK/flash_config.h"
#elif defined(TARGET_DISCO_F413ZH)
#include "STM/DISCO_F413ZH/flash_config.h"
#elif defined(TARGET_EFM32GG11_STK3701)
#include "SiliconLabs/EFM32GG11_STK3701/flash_config.h"
#endif
#endif // MBED_FLASH_CONFIGS_H

View File

@ -52,7 +52,7 @@ uint8_t rx_buf[DATA_SIZE_1024];
#define TEST_FLASH_ADDRESS 0x0
#define TEST_REPEAT_SINGLE 1
#define TEST_REPEAT_MULTIPLE 16
#define TEST_REPEAT_MULTIPLE 4
// write block of data in single write operation
#define WRITE_SINGLE 1
@ -74,6 +74,13 @@ uint8_t rx_buf[DATA_SIZE_1024];
#define QCSN static_cast<PinName>(QSPI_FLASH1_CSN)
static uint32_t gen_flash_address()
{
srand(ticker_read(get_us_ticker_data()));
uint32_t address = (((uint32_t)rand()) % QSPI_SECTOR_COUNT) * QSPI_SECTOR_SIZE;
return address;
}
static void log_data(const char *str, uint8_t *data, uint32_t size)
{
utest_printf("%s: ", str);
@ -100,7 +107,6 @@ static void _qspi_write_read_test(Qspi &qspi, qspi_bus_width_t write_inst_width,
size_t buf_len = data_size;
for (uint32_t tc = 0; tc < test_count; tc++) {
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8);
srand(ticker_read(get_us_ticker_data()));
for (uint32_t i = 0; i < data_size; i++) {
@ -125,6 +131,11 @@ static void _qspi_write_read_test(Qspi &qspi, qspi_bus_width_t write_inst_width,
WAIT_FOR(WAIT_MAX_TIME, qspi);
}
// switching to extended-SPI/DPI/QPI mode here for write operation
// for DPI/QPI qspi.cmd is automatically switched to 2_2_2/4_4_4 mode
ret = mode_enable(qspi, write_inst_width, write_addr_width, write_data_width);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
const uint32_t write_size = data_size / write_count;
for (uint32_t wc = 0, write_start = flash_addr; wc < write_count; wc++, write_start += write_size) {
ret = write_enable(qspi);
@ -140,18 +151,32 @@ static void _qspi_write_read_test(Qspi &qspi, qspi_bus_width_t write_inst_width,
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
TEST_ASSERT_EQUAL(write_size, buf_len);
if(is_extended_mode(write_inst_width, write_addr_width, write_data_width)) {
// on some flash chips in extended-SPI mode, control commands works only in 1-1-1 mode
// so switching back to 1-1-1 mode
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8);
}
WAIT_FOR(PAGE_PROG_MAX_TIME, qspi);
timer.stop();
write_time = timer.read_us();
}
// switching back to single channel SPI
ret = mode_disable(qspi, write_inst_width, write_addr_width, write_data_width);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
if (read_frequency != QSPI_NONE) {
qspi_frequency(&qspi.handle, read_frequency);
WAIT_FOR(WAIT_MAX_TIME, qspi);
}
// switching to extended-SPI/DPI/QPI mode here for read operation
// for DPI/QPI qspi.cmd is automatically switched to 2_2_2/4_4_4 mode
ret = mode_enable(qspi, read_inst_width, read_addr_width, read_data_width);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
memset(rx_buf, 0, sizeof(rx_buf));
const uint32_t read_size = data_size / read_count;
qspi.cmd.configure(read_inst_width, read_addr_width, read_data_width, read_alt_width, read_addr_size, read_alt_size, read_dummy_cycles);
@ -168,6 +193,17 @@ static void _qspi_write_read_test(Qspi &qspi, qspi_bus_width_t write_inst_width,
timer.stop();
read_time = timer.read_us();
}
qspi.cmd.set_dummy_cycles(0);
if(is_extended_mode(read_inst_width, read_addr_width, read_data_width)) {
// on some flash chips in extended-SPI mode, control commands works only in 1-1-1 mode
// so switching back to 1-1-1 mode
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8);
}
// switching back to single channel SPI
ret = mode_disable(qspi, read_inst_width, read_addr_width, read_data_width);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
for (uint32_t i = 0; i < data_size; i++) {
if (tx_buf[i] != rx_buf[i]) {
@ -217,43 +253,29 @@ void qspi_write_read_test(void)
{
qspi_status_t ret;
Qspi qspi;
uint32_t addr = flash_addr;
if (addr == 0) {
// if no specified address selected, use random one to extend flash life
addr = gen_flash_address();
}
qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0);
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8);
flash_init(qspi);
if (is_dual_cmd(write_inst_width, write_addr_width, write_data_width) ||
is_dual_cmd(read_inst_width, read_addr_width, read_data_width)) {
ret = dual_enable(qspi);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
WAIT_FOR(WRSR_MAX_TIME, qspi);
}
if (is_quad_cmd(write_inst_width, write_addr_width, write_data_width) ||
is_quad_cmd(read_inst_width, read_addr_width, read_data_width)) {
ret = quad_enable(qspi);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
WAIT_FOR(WRSR_MAX_TIME, qspi);
}
ret = write_enable(qspi);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
WAIT_FOR(WRSR_MAX_TIME, qspi);
// switch memory to high performance mode (if available)
ret = fast_mode_enable(qspi);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
WAIT_FOR(WRSR_MAX_TIME, qspi);
#ifdef QSPI_TEST_LOG_FLASH_STATUS
//utest_printf("Status register:\r\n");
log_register(STATUS_REG, QSPI_STATUS_REG_SIZE, qspi, "Status register");
//utest_printf("Config register 0:\r\n");
log_register(CONFIG_REG0, QSPI_CONFIG_REG_0_SIZE, qspi, "Config register 0");
#ifdef CONFIG_REG1
//utest_printf("Config register 1:\r\n");
log_register(CONFIG_REG1, QSPI_CONFIG_REG_1_SIZE, qspi, "Config register 1");
#endif
#ifdef CONFIG_REG2
//utest_printf("Config register 2:\r\n");
log_register(CONFIG_REG2, QSPI_CONFIG_REG_2_SIZE, qspi, "Config register 2");
#endif
#endif
@ -262,23 +284,10 @@ void qspi_write_read_test(void)
write_addr_size, write_alt_size, write_frequency, write_count, read_inst_width,
read_addr_width, read_data_width, read_alt_width, read_cmd, read_dummy_cycles,
read_addr_size, read_alt_size, read_frequency, read_count, test_count,
data_size, flash_addr);
data_size, addr);
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8);
if (is_dual_cmd(write_inst_width, write_addr_width, write_data_width) ||
is_dual_cmd(read_inst_width, read_addr_width, read_data_width)) {
ret = dual_disable(qspi);
ret = fast_mode_disable(qspi);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
WAIT_FOR(WRSR_MAX_TIME, qspi);
}
if (is_quad_cmd(write_inst_width, write_addr_width, write_data_width) ||
is_quad_cmd(read_inst_width, read_addr_width, read_data_width)) {
ret = quad_disable(qspi);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
WAIT_FOR(WRSR_MAX_TIME, qspi);
}
qspi_free(&qspi.handle);
}
@ -315,16 +324,12 @@ void qspi_init_free_test(void)
flash_init(qspi);
#ifdef QSPI_TEST_LOG_FLASH_STATUS
//utest_printf("Status register:\r\n");
log_register(STATUS_REG, QSPI_STATUS_REG_SIZE, qspi, "Status register");
//utest_printf("Config register 0:\r\n");
log_register(CONFIG_REG0, QSPI_CONFIG_REG_0_SIZE, qspi, "Config register 0");
#ifdef CONFIG_REG1
//utest_printf("Config register 1:\r\n");
log_register(CONFIG_REG1, QSPI_CONFIG_REG_1_SIZE, qspi, "Config register 1");
#endif
#ifdef CONFIG_REG2
//utest_printf("Config register 2:\r\n");
log_register(CONFIG_REG2, QSPI_CONFIG_REG_2_SIZE, qspi, "Config register 2");
#endif
#endif
@ -338,37 +343,33 @@ void qspi_frequency_test(void)
{
Qspi qspi;
qspi_status_t ret;
int freq = QSPI_COMMON_MAX_FREQUENCY;
ret = qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, QSPI_COMMON_MAX_FREQUENCY, 0);
ret = qspi_init(&qspi.handle, QPIN_0, QPIN_1, QPIN_2, QPIN_3, QSCK, QCSN, freq, 0);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
ret = qspi_frequency(&qspi.handle, QSPI_COMMON_MAX_FREQUENCY);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
// check if the memory is working properly
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8);
flash_init(qspi);
_qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS);
_qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, freq, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, freq, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS);
ret = qspi_frequency(&qspi.handle, QSPI_COMMON_MAX_FREQUENCY / 2);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
freq /= 2;
// check if the memory is working properly
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8);
flash_init(qspi);
_qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS);
_qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, freq, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, freq, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS);
ret = qspi_frequency(&qspi.handle, QSPI_COMMON_MAX_FREQUENCY / 4);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
freq /= 2;
// check if the memory is working properly
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8);
flash_init(qspi);
_qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS);
_qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, freq, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, freq, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS);
ret = qspi_frequency(&qspi.handle, QSPI_COMMON_MAX_FREQUENCY / 8);
TEST_ASSERT_EQUAL(QSPI_STATUS_OK, ret);
freq /= 2;
// check if the memory is working properly
qspi.cmd.configure(MODE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8);
flash_init(qspi);
_qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_NONE, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS);
_qspi_write_read_test(qspi, WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, freq, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, freq, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS);
qspi_free(&qspi.handle);
}
@ -387,69 +388,184 @@ Case cases[] = {
// read/x1 write/x1 - read/write block of data in single write/read operation
// read/x4 write/x4 - read/write block of data in adjacent locations in multiple write/read operations
// repeat/xN - test repeat count (new data pattern each time)
// 1-1-1 - single channel SPI
// 1-1-2 - Dual data (extended SPI)
// 1-2-2 - Dual I/O (extended SPI)
// 1-1-4 - Quad data (extended SPI)
// 1-4-4 - Quad I/O (extended SPI)
// 2-2-2 - DPI (multi-channel SPI)
// 4-4-4 - QPI (multi-channel SPI)
Case("qspi write(1-1-1)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-1)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-1)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-2)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-2-2)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-2-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_2_2_2
Case("qspi write(1-1-1)/x1 read(2-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x4 read(2-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(2-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(2-2-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
Case("qspi write(1-1-1)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-4)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-1-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(1-4-4)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef QSPI_CMD_WRITE_2IO
Case("qspi write(1-1-1)/x1 read(1-4-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_4_4_4
Case("qspi write(1-1-1)/x1 read(4-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x4 read(4-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(4-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-1-1)/x1 read(4-4-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef WRITE_1_2_2
Case("qspi write(1-2-2)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-1-1)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-1-1)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-1-2)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-1-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-2-2)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-2-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_2_2_2
Case("qspi write(1-2-2)/x1 read(2-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x4 read(2-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(2-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(2-2-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
Case("qspi write(1-2-2)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-1-4)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-1-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-4-4)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(1-4-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_4_4_4
Case("qspi write(1-2-2)/x1 read(4-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x4 read(4-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(4-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-2-2)/x1 read(4-4-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#ifdef QSPI_CMD_WRITE_4IO
#endif
#ifdef WRITE_2_2_2
Case("qspi write(2-2-2)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-1-1)/x1 repeat/x4 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-1-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-2-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_2_2_2
Case("qspi write(2-2-2)/x1 read(2-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x4 read(2-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(2-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(2-2-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
Case("qspi write(2-2-2)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-1-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(1-4-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_4_4_4
Case("qspi write(2-2-2)/x1 read(4-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x4 read(4-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(4-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(2-2-2)/x1 read(4-4-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#endif
#ifdef WRITE_1_4_4
Case("qspi write(1-4-4)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-1)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-1)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-2)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-2-2)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-2-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_2_2_2
Case("qspi write(1-4-4)/x1 read(2-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x4 read(2-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(2-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(2-2-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
Case("qspi write(1-4-4)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-4)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-1-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-4-4)/x1 repeat/x16 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(1-4-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_4_4_4
Case("qspi write(1-4-4)/x1 read(4-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x4 read(4-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(4-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(1-4-4)/x1 read(4-4-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#endif
#ifdef WRITE_4_4_4
Case("qspi write(4-4-4)/x1 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x4 read(1-1-1)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-1-1)/x4 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-1-1)/x1 repeat/x4 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_1, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x4 read(1-1-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-1-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-1-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x4 read(1-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-2-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_2_2_2
Case("qspi write(4-4-4)/x1 read(2-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x4 read(2-2-2)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(2-2-2)/x4 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(2-2-2)/x1 repeat/x4 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_2_2_2, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
Case("qspi write(4-4-4)/x1 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x4 read(1-1-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-1-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-1-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_1_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x4 read(1-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(1-4-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_1_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#ifdef READ_4_4_4
Case("qspi write(4-4-4)/x1 read(4-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x4 read(4-4-4)/x1 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_MULTIPLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_SINGLE, DATA_SIZE_1024, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(4-4-4)/x4 repeat/x1 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_MULTIPLE, TEST_REPEAT_SINGLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
Case("qspi write(4-4-4)/x1 read(4-4-4)/x1 repeat/x4 test", qspi_write_read_test<WRITE_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, WRITE_SINGLE, READ_4_4_4, ADDR_SIZE_24, ALT_SIZE_8, QSPI_COMMON_MAX_FREQUENCY, READ_SINGLE, TEST_REPEAT_MULTIPLE, DATA_SIZE_256, TEST_FLASH_ADDRESS>),
#endif
#endif
};

View File

@ -26,6 +26,12 @@
#include "flash_configs/flash_configs.h"
#include "mbed.h"
static qspi_status_t extended_enable(Qspi &qspi);
static qspi_status_t extended_disable(Qspi &qspi);
static qspi_status_t dual_enable(Qspi &qspi);
static qspi_status_t dual_disable(Qspi &qspi);
static qspi_status_t quad_enable(Qspi &qspi);
static qspi_status_t quad_disable(Qspi &qspi);
void QspiCommand::configure(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width,
qspi_bus_width_t data_width, qspi_bus_width_t alt_width,
@ -44,6 +50,11 @@ void QspiCommand::configure(qspi_bus_width_t inst_width, qspi_bus_width_t addr_w
_cmd.dummy_count = dummy_cycles;
}
void QspiCommand::set_dummy_cycles(int dummy_cycles)
{
_cmd.dummy_count = dummy_cycles;
}
void QspiCommand::build(int instruction, int address, int alt)
{
_cmd.instruction.disabled = (instruction == QSPI_NONE);
@ -188,46 +199,116 @@ qspi_status_t erase(uint32_t erase_cmd, uint32_t flash_addr, Qspi &qspi)
return qspi_command_transfer(&qspi.handle, qspi.cmd.get(), NULL, 0, NULL, 0);
}
qspi_status_t dual_enable(Qspi &qspi)
qspi_status_t mode_enable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
{
if(is_extended_mode(inst_width, addr_width, data_width)) {
return extended_enable(qspi);
} else if(is_dual_mode(inst_width, addr_width, data_width)) {
return dual_enable(qspi);
} else if(is_quad_mode(inst_width, addr_width, data_width)) {
return quad_enable(qspi);
} else {
return QSPI_STATUS_OK;
}
}
qspi_status_t mode_disable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
{
if(is_extended_mode(inst_width, addr_width, data_width)) {
return extended_disable(qspi);
} else if(is_dual_mode(inst_width, addr_width, data_width)) {
return dual_disable(qspi);
} else if(is_quad_mode(inst_width, addr_width, data_width)) {
return quad_disable(qspi);
} else {
return QSPI_STATUS_OK;
}
}
static qspi_status_t extended_enable(Qspi &qspi)
{
#ifdef EXTENDED_SPI_ENABLE
EXTENDED_SPI_ENABLE();
#else
return QSPI_STATUS_OK;
#endif
}
static qspi_status_t extended_disable(Qspi &qspi)
{
#ifdef EXTENDED_SPI_DISABLE
EXTENDED_SPI_DISABLE();
#else
return QSPI_STATUS_OK;
#endif
}
static qspi_status_t dual_enable(Qspi &qspi)
{
#ifdef DUAL_ENABLE
DUAL_ENABLE();
#else
QUAD_ENABLE();
return QSPI_STATUS_OK;
#endif
}
qspi_status_t dual_disable(Qspi &qspi)
static qspi_status_t dual_disable(Qspi &qspi)
{
#ifdef DUAL_DISABLE
DUAL_DISABLE();
#else
QUAD_DISABLE();
return QSPI_STATUS_OK;
#endif
}
qspi_status_t quad_enable(Qspi &qspi)
static qspi_status_t quad_enable(Qspi &qspi)
{
#ifdef QUAD_ENABLE
QUAD_ENABLE();
#else
return QSPI_STATUS_OK;
#endif
}
qspi_status_t quad_disable(Qspi &qspi)
static qspi_status_t quad_disable(Qspi &qspi)
{
#ifdef QUAD_DISABLE
QUAD_DISABLE();
#else
return QSPI_STATUS_OK;
#endif
}
qspi_status_t fast_mode_enable(Qspi &qspi)
{
#ifdef FAST_MODE_ENABLE
FAST_MODE_ENABLE();
#else
return QSPI_STATUS_OK;
#endif
}
bool is_dual_cmd(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
qspi_status_t fast_mode_disable(Qspi &qspi)
{
return (inst_width == QSPI_CFG_BUS_DUAL) || (addr_width == QSPI_CFG_BUS_DUAL) || (data_width == QSPI_CFG_BUS_DUAL);
#ifdef FAST_MODE_DISABLE
FAST_MODE_DISABLE();
#else
return QSPI_STATUS_OK;
#endif
}
bool is_quad_cmd(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
bool is_extended_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
{
return (inst_width == QSPI_CFG_BUS_QUAD) || (addr_width == QSPI_CFG_BUS_QUAD) || (data_width == QSPI_CFG_BUS_QUAD);
return (inst_width == QSPI_CFG_BUS_SINGLE) && ((addr_width != QSPI_CFG_BUS_SINGLE) || (data_width != QSPI_CFG_BUS_SINGLE));
}
bool is_dual_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
{
return (inst_width == QSPI_CFG_BUS_DUAL) && (addr_width == QSPI_CFG_BUS_DUAL) && (data_width == QSPI_CFG_BUS_DUAL);
}
bool is_quad_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width)
{
return (inst_width == QSPI_CFG_BUS_QUAD) && (addr_width == QSPI_CFG_BUS_QUAD) && (data_width == QSPI_CFG_BUS_QUAD);
}

View File

@ -34,6 +34,8 @@ public:
qspi_bus_width_t alt_width, qspi_address_size_t addr_size, qspi_alt_size_t alt_size,
int dummy_cycles = 0);
void set_dummy_cycles(int dummy_cycles);
void build(int instruction, int address = QSPI_NONE, int alt = QSPI_NONE);
qspi_command_t *get();
@ -51,8 +53,10 @@ struct Qspi {
#define MODE_1_1_1 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE
#define MODE_1_1_2 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_DUAL
#define MODE_1_2_2 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_DUAL
#define MODE_1_1_4 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_SINGLE
#define MODE_2_2_2 QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_DUAL
#define MODE_1_1_4 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_QUAD
#define MODE_1_4_4 QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_QUAD
#define MODE_4_4_4 QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_QUAD, QSPI_CFG_BUS_QUAD
#define WRITE_1_1_1 MODE_1_1_1, QSPI_CMD_WRITE_1IO
#ifdef QSPI_CMD_WRITE_2IO
@ -61,6 +65,12 @@ struct Qspi {
#ifdef QSPI_CMD_WRITE_4IO
#define WRITE_1_4_4 MODE_1_4_4, QSPI_CMD_WRITE_4IO
#endif
#ifdef QSPI_CMD_WRITE_DPI
#define WRITE_2_2_2 MODE_2_2_2, QSPI_CMD_WRITE_DPI
#endif
#ifdef QSPI_CMD_WRITE_QPI
#define WRITE_4_4_4 MODE_4_4_4, QSPI_CMD_WRITE_QPI
#endif
#define READ_1_1_1 MODE_1_1_1, QSPI_CMD_READ_1IO, QSPI_READ_1IO_DUMMY_CYCLE
@ -68,7 +78,12 @@ struct Qspi {
#define READ_1_2_2 MODE_1_2_2, QSPI_CMD_READ_2IO, QSPI_READ_2IO_DUMMY_CYCLE
#define READ_1_1_4 MODE_1_1_4, QSPI_CMD_READ_1I4O, QSPI_READ_1I4O_DUMMY_CYCLE
#define READ_1_4_4 MODE_1_4_4, QSPI_CMD_READ_4IO, QSPI_READ_4IO_DUMMY_CYCLE
#ifdef QSPI_CMD_READ_DPI
#define READ_2_2_2 MODE_2_2_2, QSPI_CMD_READ_DPI, QSPI_READ_2IO_DUMMY_CYCLE
#endif
#ifdef QSPI_CMD_READ_QPI
#define READ_4_4_4 MODE_4_4_4, QSPI_CMD_READ_QPI, QSPI_READ_4IO_DUMMY_CYCLE
#endif
#define ADDR_SIZE_8 QSPI_CFG_ADDR_SIZE_8
#define ADDR_SIZE_16 QSPI_CFG_ADDR_SIZE_16
@ -120,26 +135,21 @@ QspiStatus flash_wait_for(uint32_t time_us, Qspi &qspi);
void flash_init(Qspi &qspi);
qspi_status_t write_enable(Qspi &qspi);
qspi_status_t write_disable(Qspi &qspi);
void log_register(uint32_t cmd, uint32_t reg_size, Qspi &qspi, const char *str = NULL);
qspi_status_t dual_enable(Qspi &qspi);
qspi_status_t dual_disable(Qspi &qspi);
qspi_status_t quad_enable(Qspi &qspi);
qspi_status_t quad_disable(Qspi &qspi);
qspi_status_t mode_enable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width);
qspi_status_t mode_disable(Qspi &qspi, qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width);
qspi_status_t fast_mode_enable(Qspi &qspi);
qspi_status_t fast_mode_disable(Qspi &qspi);
qspi_status_t erase(uint32_t erase_cmd, uint32_t flash_addr, Qspi &qspi);
bool is_dual_cmd(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width);
bool is_quad_cmd(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width);
bool is_extended_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width);
bool is_dual_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width);
bool is_quad_mode(qspi_bus_width_t inst_width, qspi_bus_width_t addr_width, qspi_bus_width_t data_width);
#define WAIT_FOR(timeout, q) TEST_ASSERT_EQUAL_MESSAGE(sOK, flash_wait_for(timeout, q), "flash_wait_for failed!!!")

View File

@ -47,6 +47,8 @@
using namespace utest::v1;
static char info[512] = {0};
/* The following ticker frequencies are possible:
* high frequency ticker: 250 KHz (1 tick per 4 us) - 8 Mhz (1 tick per 1/8 us)
* low power ticker: 8 KHz (1 tick per 125 us) - 64 KHz (1 tick per ~15.6 us)
@ -140,6 +142,11 @@ void sleep_usticker_test()
const ticker_irq_handler_type us_ticker_irq_handler_org = set_us_ticker_irq_handler(us_ticker_isr);
/* Give some time Green Tea to finish UART transmission before entering
* sleep mode.
*/
busy_wait_ms(SERIAL_FLUSH_TIME_MS);
/* Test only sleep functionality. */
sleep_manager_lock_deep_sleep();
TEST_ASSERT_FALSE_MESSAGE(sleep_manager_can_deep_sleep(), "deep sleep should be locked");
@ -147,7 +154,8 @@ void sleep_usticker_test()
/* Testing wake-up time 10 us. */
for (timestamp_t i = 100; i < 1000; i += 100) {
/* note: us_ticker_read() operates on ticks. */
const timestamp_t next_match_timestamp = overflow_protect(us_ticker_read() + us_to_ticks(i, ticker_freq),
const timestamp_t start_timestamp = us_ticker_read();
const timestamp_t next_match_timestamp = overflow_protect(start_timestamp + us_to_ticks(i, ticker_freq),
ticker_width);
us_ticker_set_interrupt(next_match_timestamp);
@ -156,9 +164,11 @@ void sleep_usticker_test()
const unsigned int wakeup_timestamp = us_ticker_read();
TEST_ASSERT(
compare_timestamps(us_to_ticks(sleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp,
wakeup_timestamp));
sprintf(info, "Delta ticks: %u, Ticker width: %u, Expected wake up tick: %d, Actual wake up tick: %d, delay ticks: %d, wake up after ticks: %d",
us_to_ticks(sleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp, wakeup_timestamp, us_to_ticks(i, ticker_freq) , wakeup_timestamp - start_timestamp);
TEST_ASSERT_MESSAGE(compare_timestamps(us_to_ticks(sleep_mode_delta_us, ticker_freq),
ticker_width, next_match_timestamp, wakeup_timestamp), info);
}
set_us_ticker_irq_handler(us_ticker_irq_handler_org);
@ -189,7 +199,8 @@ void deepsleep_lpticker_test()
/* Testing wake-up time 10 ms. */
for (timestamp_t i = 20000; i < 200000; i += 20000) {
/* note: lp_ticker_read() operates on ticks. */
const timestamp_t next_match_timestamp = overflow_protect(lp_ticker_read() + us_to_ticks(i, ticker_freq), ticker_width);
const timestamp_t start_timestamp = lp_ticker_read();
const timestamp_t next_match_timestamp = overflow_protect(start_timestamp + us_to_ticks(i, ticker_freq), ticker_width);
lp_ticker_set_interrupt(next_match_timestamp);
@ -197,7 +208,11 @@ void deepsleep_lpticker_test()
const timestamp_t wakeup_timestamp = lp_ticker_read();
TEST_ASSERT(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp, wakeup_timestamp));
sprintf(info, "Delta ticks: %u, Ticker width: %u, Expected wake up tick: %d, Actual wake up tick: %d, delay ticks: %d, wake up after ticks: %d",
us_to_ticks(deepsleep_mode_delta_us, ticker_freq), ticker_width, next_match_timestamp, wakeup_timestamp, us_to_ticks(i, ticker_freq) , wakeup_timestamp - start_timestamp);
TEST_ASSERT_MESSAGE(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, ticker_freq), ticker_width,
next_match_timestamp, wakeup_timestamp), info);
}
set_lp_ticker_irq_handler(lp_ticker_irq_handler_org);
@ -240,8 +255,12 @@ void deepsleep_high_speed_clocks_turned_off_test()
TEST_ASSERT_UINT32_WITHIN(1000, 0, ticks_to_us(us_ticks_diff, us_ticker_freq));
sprintf(info, "Delta ticks: %u, Ticker width: %u, Expected wake up tick: %d, Actual wake up tick: %d",
us_to_ticks(deepsleep_mode_delta_us, lp_ticker_freq), lp_ticker_width, wakeup_time, lp_ticks_after_sleep);
/* Check if we have woken-up after expected time. */
TEST_ASSERT(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, lp_ticker_freq), lp_ticker_width, wakeup_time, lp_ticks_after_sleep));
TEST_ASSERT_MESSAGE(compare_timestamps(us_to_ticks(deepsleep_mode_delta_us, lp_ticker_freq), lp_ticker_width,
wakeup_time, lp_ticks_after_sleep), info);
}
#endif

View File

@ -0,0 +1,197 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "base64b.h"
using namespace std;
static char IntToBase64Char(uint8_t intVal)
{
const char *base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
return base64Digits[intVal & 0x3F];
}
#define BASE_64_PAD 0xFF
static base64_result_e Base64CharToInt(char base64, uint8_t *intVal)
{
if (NULL == intVal) {
return BASE64_INVALID_PARAMETER;
}
if ((base64 >= 'A') && (base64 <= 'Z')) {
*intVal = base64 - 'A' ;
} else if ((base64 >= 'a') && (base64 <= 'z')) {
*intVal = base64 - 'a' + 26;
} else if ((base64 >= '0') && (base64 <= '9')) {
*intVal = base64 - '0' + 52;
} else if (base64 == '+') {
*intVal = 62;
} else if (base64 == '/') {
*intVal = 63;
} else if (base64 == '=') {
*intVal = BASE_64_PAD;
} else {
return BASE64_ERROR;
}
return BASE64_SUCCESS;
}
base64_result_e trng_DecodeNBase64(const char *string,
uint32_t stringMaxSize,
void *buffer,
uint32_t bufferSize,
uint32_t *lengthWritten,
uint32_t *charsProcessed)
{
base64_result_e result = BASE64_SUCCESS;
uint32_t bitOffset = 0;
uint8_t *writePtr = (uint8_t *)buffer;
uint8_t *bufferEnd = (uint8_t *)buffer + bufferSize;
uint8_t tempVal = 0;
uint32_t currPos = 0;
uint32_t localBytesWritten = 0;
uint32_t localCharsProcessed = 0;
bool isEndOfString = false;
if ((NULL == string) || (NULL == buffer) || (bufferSize == 0)) {
return BASE64_INVALID_PARAMETER;
}
*writePtr = 0;
while (( currPos < stringMaxSize ) &&
( string[currPos] != 0 ) &&
( writePtr < bufferEnd ) &&
( !isEndOfString )) {
uint8_t val;
if (string[currPos] == 0) {
break;
}
result = Base64CharToInt(string[currPos++], &val);
if (result != BASE64_SUCCESS) {
break;
}
if (val != BASE_64_PAD) {
if (bitOffset <= 2) {
tempVal |= val << (2 - bitOffset);
if (bitOffset == 2) {
*writePtr++ = tempVal;
tempVal = 0;
}
} else {
*writePtr++ = (uint8_t)(tempVal | (val >> (bitOffset - 2)));
tempVal = (uint8_t)(val << (10 - bitOffset));
}
} else { // found BASE_64_PAD
// At most two pad characters may occur at the end of the encoded stream
if (bitOffset == 2) {
isEndOfString = true; // The last padding byte has been processed.
} else if (bitOffset != 4) {
return BASE64_ERROR; // Incorrect padding
}
}
bitOffset = (bitOffset + 6) & 0x7;
if (bitOffset == 0) {
localBytesWritten = (uint32_t)(writePtr - (uint8_t *)buffer);
localCharsProcessed = currPos;
}
}
if (charsProcessed == NULL) {
localBytesWritten = (uint32_t)(writePtr - (uint8_t *)buffer);
} else {
*charsProcessed = localCharsProcessed;
}
if (lengthWritten != NULL) {
*lengthWritten = localBytesWritten;
} else if (bufferSize != localBytesWritten) {
return BASE64_BUFFER_TOO_SMALL;
}
// Check if additional bytes should have been processed but buffer isn't sufficient.
if (( result == BASE64_SUCCESS ) &&
( !isEndOfString ) &&
( currPos < stringMaxSize ) &&
( string[currPos] != 0 ) &&
( string[currPos] != '=' ) ) {
return BASE64_BUFFER_TOO_SMALL;
}
if (result != BASE64_SUCCESS) {
return result;
}
return BASE64_SUCCESS;
}
base64_result_e trng_EncodeBase64(const void *buffer, uint32_t bufferSize, char *string, uint32_t stringSize)
{
uint32_t bitOffset = 0;
const uint8_t *readPtr = (const uint8_t *)buffer;
const uint8_t *bufferEnd = (const uint8_t *)buffer + bufferSize;
char *writePtr = string;
char *stringEnd = string + stringSize - 1;
if ((NULL == string) || (NULL == buffer) || (stringSize == 0)) {
return BASE64_INVALID_PARAMETER;
}
stringSize--;
while (readPtr < bufferEnd && writePtr < stringEnd) {
uint8_t tempVal = 0;
switch (bitOffset) {
case 0:
*writePtr++ = IntToBase64Char(*readPtr >> 2); // take upper 6 bits
break;
case 6:
tempVal = *readPtr++ << 4;
if (readPtr < bufferEnd) {
tempVal |= *readPtr >> 4;
}
*writePtr++ = IntToBase64Char(tempVal);
break;
case 4:
tempVal = *readPtr++ << 2;
if (readPtr < bufferEnd) {
tempVal |= *readPtr >> 6;
}
*writePtr++ = IntToBase64Char(tempVal);
break;
case 2:
*writePtr++ = IntToBase64Char(*readPtr++);
break;
default:
return BASE64_ERROR; // we should never reach this code.
}
bitOffset = (bitOffset + 6) & 0x7;
}
while (bitOffset > 0 && writePtr < stringEnd) {
*writePtr++ = '=';
bitOffset = (bitOffset + 6) & 0x7;
}
*writePtr = 0;
if ((readPtr < bufferEnd) || (bitOffset != 0)) {
return (BASE64_BUFFER_TOO_SMALL);
}
return (BASE64_SUCCESS);
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#include <stdlib.h>
#include <string>
typedef enum {
BASE64_SUCCESS = 0,
BASE64_INVALID_PARAMETER = 1,
BASE64_BUFFER_TOO_SMALL = 2,
BASE64_ERROR = 3,
} base64_result_e;
base64_result_e trng_EncodeBase64(const void *buffer, uint32_t bufferSize, char *string, uint32_t stringSize);
base64_result_e trng_DecodeNBase64(const char *string, uint32_t stringMaxSize, void *buffer, uint32_t bufferSize,
uint32_t *lengthWritten, uint32_t *charsProcessed);

View File

@ -0,0 +1,247 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* The test is based on the assumption that trng will generate random data, random so
* there will not be any similar patterns in it, that kind of data will be impossible to
* compress, if compression will occur the test will result in failure.
*
* The test is composed out of three parts:
* the first, generate a trng buffer and try to compress it, at the end of first part
* we will reset the device.
* In second part we will generate a trng buffer with a different buffer size and try to
* compress it.
* In the third part we will again generate a trng buffer to see that the same trng output
* is not generated as the stored trng buffer from part one (before reseting), the new trng data will
* be concatenated to the trng data from the first part and then try to compress it
* together, if there are similar patterns the compression will succeed.
*
* We need to store and load the first part data before and after reset, the mechanism
* we will use is the mbed greentea platform for sending and receving the data from the device
* to the host running the test and back, the problem with this mechanism is that it doesn't
* handle well certain characters, especially non ASCII ones, so we use the base64 algorithm
* to ensure all characters will be transmitted correctly.
*/
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"
#include "hal/trng_api.h"
#include "base64b.h"
#include "pithy.h"
#include <stdio.h>
#if !DEVICE_TRNG
#error [NOT_SUPPORTED] TRNG API not supported for this target
#endif
#define MSG_VALUE_DUMMY "0"
#define MSG_VALUE_LEN 64
#define MSG_KEY_LEN 32
#define BUFFER_LEN (MSG_VALUE_LEN/2)
#define MSG_TRNG_READY "ready"
#define MSG_TRNG_BUFFER "buffer"
#define MSG_TRNG_EXIT "exit"
#define MSG_TRNG_TEST_STEP1 "check_step1"
#define MSG_TRNG_TEST_STEP2 "check_step2"
#define MSG_TRNG_TEST_SUITE_ENDED "Test_suite_ended"
#define RESULT_SUCCESS 0
using namespace utest::v1;
static int fill_buffer_trng(uint8_t *buffer, trng_t *trng_obj, size_t trng_len)
{
size_t temp_size = 0, output_length = 0;
int trng_res = 0;
uint8_t *temp_in_buf = buffer;
trng_init(trng_obj);
memset(buffer, 0, BUFFER_LEN);
while (true) {
trng_res = trng_get_bytes(trng_obj, temp_in_buf, trng_len - temp_size, &output_length);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, trng_res, "trng_get_bytes error!");
temp_size += output_length;
temp_in_buf += output_length;
if (temp_size >= trng_len) {
break;
}
}
temp_in_buf = NULL;
trng_free(trng_obj);
return 0;
}
void print_array(uint8_t *buffer, size_t size)
{
for (size_t i=0; i < size; i++) {
utest_printf("%02x", buffer[i]);
}
utest_printf("\n");
}
static void compress_and_compare(char *key, char *value)
{
trng_t trng_obj;
uint8_t *out_comp_buf, *buffer;
uint8_t *input_buf, *temp_buf;
size_t comp_sz = 0;
unsigned int result = 0;
#define OUT_COMP_BUF_SIZE ((BUFFER_LEN * 5) + 32)
#define TEMP_BUF_SIZE (BUFFER_LEN * 2)
out_comp_buf = new uint8_t[OUT_COMP_BUF_SIZE];
buffer = new uint8_t[BUFFER_LEN];
temp_buf = new uint8_t[BUFFER_LEN * 2];
input_buf = new uint8_t[BUFFER_LEN * 4];
/*At the begining of step 2 load trng buffer from step 1*/
if (strcmp(key, MSG_TRNG_TEST_STEP2) == 0) {
/*Using base64 to decode data sent from host*/
uint32_t lengthWritten = 0;
uint32_t charsProcessed = 0;
result = trng_DecodeNBase64((const char *)value,
MSG_VALUE_LEN,
buffer,
BUFFER_LEN,
&lengthWritten,
&charsProcessed);
TEST_ASSERT_EQUAL(0, result);
memcpy(input_buf, buffer, BUFFER_LEN);
}
if (strcmp(key, MSG_TRNG_TEST_STEP1) == 0) {
/*Fill buffer with trng values*/
result = fill_buffer_trng(buffer, &trng_obj, BUFFER_LEN);
TEST_ASSERT_EQUAL(0, result);
memcpy(input_buf, buffer, BUFFER_LEN);
}
/*pithy_Compress will try to compress the random data, if it succeeded it means the data is not really random*/
else if (strcmp(key, MSG_TRNG_TEST_STEP2) == 0) {
comp_sz = pithy_Compress((char *)buffer,
BUFFER_LEN,
(char *)out_comp_buf,
OUT_COMP_BUF_SIZE,
9);
if (comp_sz <= BUFFER_LEN){
print_array(buffer, BUFFER_LEN);
}
TEST_ASSERT_MESSAGE(comp_sz > BUFFER_LEN,
"TRNG_TEST_STEP1: trng_get_bytes was able to compress thus not random");
/*pithy_Compress will try to compress the random data with a different buffer size*/
result = fill_buffer_trng(temp_buf, &trng_obj, TEMP_BUF_SIZE);
TEST_ASSERT_EQUAL(0, result);
comp_sz = pithy_Compress((char *)temp_buf,
TEMP_BUF_SIZE,
(char *)out_comp_buf,
OUT_COMP_BUF_SIZE,
9);
if (comp_sz <= TEMP_BUF_SIZE){
print_array(temp_buf, TEMP_BUF_SIZE);
}
TEST_ASSERT_MESSAGE(comp_sz > TEMP_BUF_SIZE,
"TRNG_TEST_STEP2: trng_get_bytes was able to compress thus not random");
memcpy(input_buf + BUFFER_LEN, temp_buf, TEMP_BUF_SIZE);
/*pithy_Compress will try to compress the random data from before reset concatenated with new random data*/
comp_sz = pithy_Compress((char *)input_buf,
TEMP_BUF_SIZE + BUFFER_LEN,
(char *)out_comp_buf,
OUT_COMP_BUF_SIZE,
9);
if (comp_sz <= TEMP_BUF_SIZE + BUFFER_LEN){
print_array(input_buf, TEMP_BUF_SIZE + BUFFER_LEN);
}
TEST_ASSERT_MESSAGE(comp_sz > TEMP_BUF_SIZE + BUFFER_LEN,
"TRNG_TEST_STEP3: concatenated buffer after reset was able to compress thus not random");
greentea_send_kv(MSG_TRNG_TEST_SUITE_ENDED, MSG_VALUE_DUMMY);
}
/*At the end of step 1 store trng buffer and reset the device*/
if (strcmp(key, MSG_TRNG_TEST_STEP1) == 0) {
int result = 0;
/*Using base64 to encode data sending from host*/
result = trng_EncodeBase64(buffer,
BUFFER_LEN,
(char *)out_comp_buf,
OUT_COMP_BUF_SIZE);
TEST_ASSERT_EQUAL(RESULT_SUCCESS, result);
greentea_send_kv(MSG_TRNG_BUFFER, (const char *)out_comp_buf);
}
delete[] out_comp_buf;
delete[] buffer;
delete[] input_buf;
delete[] temp_buf;
}
/*This method call first and second steps, it directs by the key received from the host*/
void trng_test()
{
greentea_send_kv(MSG_TRNG_READY, MSG_VALUE_DUMMY);
char key[MSG_KEY_LEN + 1] = { };
char *value = new char[MSG_VALUE_LEN + 1];
do {
memset(key, 0, MSG_KEY_LEN + 1);
memset(value, 0, MSG_VALUE_LEN + 1);
greentea_parse_kv(key, value, MSG_KEY_LEN, MSG_VALUE_LEN);
if (strcmp(key, MSG_TRNG_TEST_STEP1) == 0) {
/*create trng data buffer and try to compress it, store it for later checks*/
compress_and_compare(key, value);
}
if (strcmp(key, MSG_TRNG_TEST_STEP2) == 0) {
/*create another trng data buffer and concatenate it to the stored trng data buffer
try to compress them both*/
compress_and_compare(key, value);
}
} while (strcmp(key, MSG_TRNG_EXIT) != 0);
delete[] value;
}
Case cases[] = {
Case("TRNG: trng_test", trng_test),
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "trng_reset");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main()
{
bool ret = !Harness::run(specification);
return ret;
}

View File

@ -0,0 +1,795 @@
//
// pithy.c
// http://github.com/johnezang/pithy
// Licensed under the terms of the BSD License, as specified below.
//
/*
Copyright (c) 2011, John Engelhart
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Zang Industries nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#if defined(__arm__) && defined(__ARM_NEON__)
#include <arm_neon.h>
#endif
#include "pithy.h"
#define kBlockLog 20ul
#define kBlockSize ((size_t)(1 << kBlockLog))
// The maximum size that can be compressed while still allowing for the worst case compression expansion.
#define PITHY_UNCOMPRESSED_MAX_LENGTH 0xdb6db6bfu // 0xdb6db6bf == 3681400511, or 3510.857 Mbytes.
typedef const char *pithy_hashOffset_t;
enum {
PITHY_LITERAL = 0,
PITHY_COPY_1_BYTE_OFFSET = 1,
PITHY_COPY_2_BYTE_OFFSET = 2,
PITHY_COPY_3_BYTE_OFFSET = 3
};
#if defined (__GNUC__) && (__GNUC__ >= 3)
#define PITHY_ATTRIBUTES(attr, ...) __attribute__((attr, ##__VA_ARGS__))
#define PITHY_EXPECTED(cond, expect) __builtin_expect((long)(cond), (expect))
#define PITHY_EXPECT_T(cond) PITHY_EXPECTED(cond, 1u)
#define PITHY_EXPECT_F(cond) PITHY_EXPECTED(cond, 0u)
#define PITHY_PREFETCH(ptr) __builtin_prefetch(ptr)
#else // defined (__GNUC__) && (__GNUC__ >= 3)
#define PITHY_ATTRIBUTES(attr, ...)
#define PITHY_EXPECTED(cond, expect) (cond)
#define PITHY_EXPECT_T(cond) (cond)
#define PITHY_EXPECT_F(cond) (cond)
#define PITHY_PREFETCH(ptr)
#endif // defined (__GNUC__) && (__GNUC__ >= 3)
#define PITHY_STATIC_INLINE static inline PITHY_ATTRIBUTES(always_inline)
#define PITHY_ALIGNED(x) PITHY_ATTRIBUTES(aligned(x))
#if defined(NS_BLOCK_ASSERTIONS) && !defined(NDEBUG)
#define NDEBUG
#endif
#ifdef NDEBUG
#define DCHECK(condition)
#else
#define DCHECK(condition) do { \
if(PITHY_EXPECT_F(!(condition))) { \
fprintf(stderr, "%s / %s @ %ld: Invalid parameter not satisfying: %s", \
__FILE__, __PRETTY_FUNCTION__, (long)__LINE__, #condition); fflush(stderr); \
abort(); \
} \
} while(0)
#endif
PITHY_STATIC_INLINE const char *pithy_Parse32WithLimit(const char *p, const char *l, size_t *OUTPUT);
PITHY_STATIC_INLINE char *pithy_Encode32(char *ptr, uint32_t v);
PITHY_STATIC_INLINE uint32_t pithy_GetUint32AtOffset(uint64_t v, uint32_t offset);
PITHY_STATIC_INLINE uint32_t pithy_HashBytes(uint32_t bytes, uint32_t shift);
PITHY_STATIC_INLINE size_t pithy_FindMatchLength(const char *s1, const char *s2, const char *s2_limit);
PITHY_STATIC_INLINE char *pithy_EmitLiteral(char *op, const char *literal, size_t len, int allow_fast_path);
PITHY_STATIC_INLINE char *pithy_EmitCopyGreaterThan63(char *op, size_t offset, size_t len);
PITHY_STATIC_INLINE char *pithy_EmitCopyLessThan63(char *op, size_t offset, size_t len);
PITHY_STATIC_INLINE char *pithy_EmitCopy(char *op, size_t offset, size_t len);
PITHY_STATIC_INLINE uint16_t pithy_Load16(const void *p) { uint16_t t; memcpy(&t, p, sizeof(t)); return (t); }
PITHY_STATIC_INLINE uint32_t pithy_Load32(const void *p) { uint32_t t; memcpy(&t, p, sizeof(t)); return (t); }
PITHY_STATIC_INLINE uint64_t pithy_Load64(const void *p) { uint64_t t; memcpy(&t, p, sizeof(t)); return (t); }
PITHY_STATIC_INLINE void pithy_Store16(void *p, uint16_t v) { memcpy(p, &v, sizeof(v)); }
PITHY_STATIC_INLINE void pithy_Store32(void *p, uint32_t v) { memcpy(p, &v, sizeof(v)); }
PITHY_STATIC_INLINE void pithy_Store64(void *p, uint64_t v) { memcpy(p, &v, sizeof(v)); }
#define pithy_Move64(dst,src) pithy_Store64(dst, pithy_Load64(src));
#define pithy_Move128(dst,src) pithy_Move64(dst, src); pithy_Move64(dst + 8ul, src + 8ul);
#ifdef __BIG_ENDIAN__
#ifdef _MSC_VER
#include <stdlib.h>
#define pithy_bswap_16(x) _byteswap_ushort(x)
#define pithy_bswap_32(x) _byteswap_ulong(x)
#define pithy_bswap_64(x) _byteswap_uint64(x)
#elif defined(__APPLE__)
// Mac OS X / Darwin features
#include <libkern/OSByteOrder.h>
#define pithy_bswap_16(x) OSSwapInt16(x)
#define pithy_bswap_32(x) OSSwapInt32(x)
#define pithy_bswap_64(x) OSSwapInt64(x)
#else
#include <byteswap.h>
#endif
#endif // __BIG_ENDIAN__
// Conversion functions.
#ifdef __BIG_ENDIAN__
#define pithy_FromHost16(x) ((uint16_t)pithy_bswap_16(x))
#define pithy_ToHost16(x) ((uint16_t)pithy_bswap_16(x))
#define pithy_FromHost32(x) ((uint32_t)pithy_bswap_32(x))
#define pithy_ToHost32(x) ((uint32_t)pithy_bswap_32(x))
#define pithy_IsLittleEndian() (0)
#else // !defined(__BIG_ENDIAN__)
#define pithy_FromHost16(x) ((uint16_t)(x))
#define pithy_ToHost16(x) ((uint16_t)(x))
#define pithy_FromHost32(x) ((uint32_t)(x))
#define pithy_ToHost32(x) ((uint32_t)(x))
#define pithy_IsLittleEndian() (1)
#endif // !defined(__BIG_ENDIAN__)
#define pithy_LoadHost16(p) pithy_ToHost16(pithy_Load16((const void *)(p)))
#define pithy_StoreHost16(p, v) pithy_Store16((void *)(p), pithy_FromHost16(v))
#define pithy_LoadHost32(p) pithy_ToHost32(pithy_Load32((p)))
#define pithy_StoreHost32(p, v) pithy_Store32((p), pithy_FromHost32(v))
PITHY_STATIC_INLINE void pithy_StoreHost24(char *p, uint32_t v)
{
*p++ = (v & 0xffu);
*p++ = ((v >> 8) & 0xffu);
*p++ = ((v >> 16) & 0xffu);
}
#if defined (__GNUC__) && (__GNUC__ >= 3)
#define pithy_Log2Floor(n) ({typeof(n) _n = (n); _n == 0 ? (int)-1 : (int)(31 ^ __builtin_clz(_n));})
#define pithy_FindLSBSetNonZero32(n) ((int)__builtin_ctz((uint32_t)(n)))
#define pithy_FindLSBSetNonZero64(n) ((int)__builtin_ctzll((uint64_t)(n)))
#define pithy_FindMSBSetNonZero32(n) ((int)__builtin_clz((uint32_t)(n)))
#define pithy_FindMSBSetNonZero64(n) ((int)__builtin_clzll((uint64_t)(n)))
#else // Portable versions, !GNUC || GNUC < 3
PITHY_STATIC_INLINE int pithy_Log2Floor(uint32_t n)
{
if (n == 0u) {
return (-1);
}
int i = 0, log = 0;
uint32_t value = n;
for (i = 4; i >= 0; --i) {
int shift = (1 << i);
uint32_t x = value >> shift;
if (x != 0u) {
value = x;
log += shift;
}
}
DCHECK(value == 1);
return (log);
}
PITHY_STATIC_INLINE int pithy_FindLSBSetNonZero32(uint32_t n)
{
int i = 0, rc = 31, shift = 0;
for (i = 4, shift = 1 << 4; i >= 0; --i) {
const uint32_t x = n << shift;
if (x != 0u) {
n = x;
rc -= shift;
}
shift >>= 1;
}
return (rc);
}
PITHY_STATIC_INLINE int pithy_FindLSBSetNonZero64(uint64_t n)
{
const uint32_t bottomBits = n;
if (bottomBits == 0u) {
return (32 + pithy_FindLSBSetNonZero32((n >> 32)));
} else {
return (pithy_FindLSBSetNonZero32(bottomBits));
}
}
PITHY_STATIC_INLINE int pithy_FindMSBSetNonZero32(uint32_t n)
{
int i;
uint32_t x, rc = 32, shift = 1 << 4;
for (i = 3; i >= 0; --i) {
x = n >> shift;
if (x != 0) {
rc -= shift;
n = x;
}
shift >>= 1;
}
x = n >> shift;
return (rc - ((x != 0) ? 2 : n));
}
PITHY_STATIC_INLINE int pithy_FindMSBSetNonZero64(uint64_t n)
{
const uint32_t upperBits = n >> 32;
if (upperBits == 0u) {
return (32 + pithy_FindMSBSetNonZero32((n)));
} else {
return (pithy_FindMSBSetNonZero32(upperBits));
}
}
#endif // End portable versions.
PITHY_STATIC_INLINE const char *pithy_Parse32WithLimit(const char *p, const char *l, size_t *resultOut)
{
const unsigned char *ptr = (const unsigned char *)p, *limit = (const unsigned char *)l;
size_t resultShift = 0ul, result = 0ul;
uint32_t encodedByte = 0u;
for (resultShift = 0ul; resultShift <= 28ul; resultShift += 7ul) {
if (ptr >= limit) {
return (NULL);
}
encodedByte = *(ptr++);
result |= (encodedByte & 127u) << resultShift;
if (encodedByte < ((resultShift == 28ul) ? 16u : 128u)) {
goto done;
}
}
return (NULL);
done:
*resultOut = result;
return ((const char *)ptr);
}
PITHY_STATIC_INLINE char *pithy_Encode32(char *sptr, uint32_t v)
{
unsigned char *ptr = (unsigned char *)sptr;
if (v < (1u << 7)) {
*(ptr++) = v;
} else if (v < (1u << 14)) {
*(ptr++) = v | 0x80u;
*(ptr++) = (v >> 7);
} else if (v < (1u << 21)) {
*(ptr++) = v | 0x80u;
*(ptr++) = (v >> 7) | 0x80u;
*(ptr++) = (v >> 14);
} else if (v < (1u << 28)) {
*(ptr++) = v | 0x80u;
*(ptr++) = (v >> 7) | 0x80u;
*(ptr++) = (v >> 14) | 0x80u;
*(ptr++) = (v >> 21);
} else {
*(ptr++) = v | 0x80u;
*(ptr++) = (v >> 7) | 0x80u;
*(ptr++) = (v >> 14) | 0x80u;
*(ptr++) = (v >> 21) | 0x80u;
*(ptr++) = (v >> 28);
}
return ((char *)ptr);
}
PITHY_STATIC_INLINE uint32_t pithy_GetUint32AtOffset(uint64_t v, uint32_t offset)
{
DCHECK(offset <= 4);
return (v >> (pithy_IsLittleEndian() ? (8u * offset) : (32u - (8u * offset))));
}
PITHY_STATIC_INLINE uint32_t pithy_HashBytes(uint32_t bytes, uint32_t shift)
{
uint32_t kMul = 0x1e35a7bdU;
return ((bytes * kMul) >> shift);
}
PITHY_STATIC_INLINE size_t pithy_FindMatchLength(const char *s1, const char *s2, const char *s2_limit)
{
DCHECK(s2_limit >= s2);
const char *ms1 = s1, *ms2 = s2;
#if defined(__LP64__)
while (PITHY_EXPECT_T(ms2 < (s2_limit - 8ul))) {
uint64_t x = pithy_Load64(ms1) ^ pithy_Load64(ms2);
if (PITHY_EXPECT_F(x == 0ul)) {
ms1 += 8ul;
ms2 += 8ul;
} else {
return ((ms1 - s1) + ((unsigned int)(pithy_IsLittleEndian() ? (pithy_FindLSBSetNonZero64(x) >> 3) :
(pithy_FindMSBSetNonZero64(x) >> 3))));
}
}
#else
while (PITHY_EXPECT_T(ms2 < (s2_limit - 4u ))) {
uint32_t x = pithy_Load32(ms1) ^ pithy_Load32(ms2);
if (PITHY_EXPECT_F(x == 0u)) {
ms1 += 4u;
ms2 += 4u;
} else {
return ((ms1 - s1) + ((unsigned int)(pithy_IsLittleEndian() ?
(pithy_FindLSBSetNonZero32(x) >> 3) : (pithy_FindMSBSetNonZero32(x) >> 3))));
}
}
#endif
while (PITHY_EXPECT_T(ms2 < s2_limit)) {
if (PITHY_EXPECT_T(*ms1 == *ms2)) {
ms1++;
ms2++;
} else {
return (ms1 - s1);
}
}
return (ms1 - s1);
}
PITHY_STATIC_INLINE char *pithy_EmitLiteral(char *op, const char *literal, size_t len, int allow_fast_path)
{
int n = len - 1l;
if (PITHY_EXPECT_T(n < 60l)) {
*op++ = PITHY_LITERAL | (n << 2);
if (PITHY_EXPECT_T(allow_fast_path) && PITHY_EXPECT_T(len <= 16ul)) {
pithy_Move128(op, literal);
return (op + len);
}
} else {
char *base = op;
int count = 0;
op++;
while (n > 0l) {
*op++ = n & 0xff;
n >>= 8;
count++;
}
DCHECK((count >= 1) && (count <= 4));
*base = PITHY_LITERAL | ((59 + count) << 2);
}
memcpy(op, literal, len);
return (op + len);
}
PITHY_STATIC_INLINE char *pithy_EmitCopyGreaterThan63(char *op, size_t offset, size_t len)
{
DCHECK((len < 65536ul) && (len >= 63ul) && (offset < kBlockSize));
if (PITHY_EXPECT_T(offset < 65536ul)) {
if (PITHY_EXPECT_T(len < (256ul + 63ul))) {
*op++ = PITHY_COPY_2_BYTE_OFFSET | (62 << 2);
pithy_StoreHost16(op, offset);
op += 2ul;
*op++ = (len - 63ul);
} else {
*op++ = PITHY_COPY_2_BYTE_OFFSET | (63 << 2);
pithy_StoreHost16(op, offset);
op += 2ul;
pithy_StoreHost16(op, len);
op += 2ul;
}
} else {
if (PITHY_EXPECT_T(len < (256ul + 63ul))) {
*op++ = PITHY_COPY_3_BYTE_OFFSET | (62 << 2);
pithy_StoreHost24(op, offset);
op += 3ul;
*op++ = (len - 63ul);
} else {
*op++ = PITHY_COPY_3_BYTE_OFFSET | (63 << 2);
pithy_StoreHost24(op, offset);
op += 3ul;
pithy_StoreHost16(op, len);
op += 2ul;
}
}
return (op);
}
PITHY_STATIC_INLINE char *pithy_EmitCopyLessThan63(char *op, size_t offset, size_t len)
{
DCHECK((len < 63ul) && (len >= 4ul) && (offset < kBlockSize));
if (PITHY_EXPECT_T(len < 12ul) && PITHY_EXPECT_T(offset < 2048ul)) {
int lenMinus4 = len - 4l;
DCHECK(lenMinus4 < 8l);
*op++ = PITHY_COPY_1_BYTE_OFFSET | (lenMinus4 << 2) | ((offset >> 8) << 5);
*op++ = offset & 0xff;
} else {
if (PITHY_EXPECT_T(offset < 65536ul)) {
*op++ = PITHY_COPY_2_BYTE_OFFSET | ((len - 1ul) << 2);
pithy_StoreHost16(op, offset);
op += 2ul;
} else {
*op++ = PITHY_COPY_3_BYTE_OFFSET | ((len - 1ul) << 2);
pithy_StoreHost24(op, offset);
op += 3ul;
}
}
return (op);
}
PITHY_STATIC_INLINE char *pithy_EmitCopy(char *op, size_t offset, size_t len)
{
while (PITHY_EXPECT_F(len >= 63ul)) {
op = pithy_EmitCopyGreaterThan63(op, offset, (len >= 65539ul) ? 65535ul : len);
len -= (len >= 65539ul) ? 65535ul : len;
}
DCHECK((len > 0ul) ? ((len >= 4ul) && (len < 63ul)) : 1);
if ( PITHY_EXPECT_T(len > 0ul)) {
op = pithy_EmitCopyLessThan63(op, offset, len);
len -= len;
}
return (op);
}
size_t pithy_MaxCompressedLength(size_t inputLength)
{
return ((inputLength >= PITHY_UNCOMPRESSED_MAX_LENGTH) ? 0ul : 32ul + inputLength + (inputLength / 6ul));
}
size_t pithy_Compress(const char *uncompressed,
size_t uncompressedLength,
char *compressedOut,
size_t compressedOutLength,
int compressionLevel)
{
if ((pithy_MaxCompressedLength(uncompressedLength) > compressedOutLength) ||
(uncompressedLength >= PITHY_UNCOMPRESSED_MAX_LENGTH) ||
(uncompressedLength == 0ul)) {
return (0ul);
}
char *compressedPtr = compressedOut;
size_t hashTableSize = 0x100ul, maxHashTableSize = 1 << (12ul + (((compressionLevel < 0) ? 0 :
(compressionLevel > 9) ? 9 : compressionLevel) / 2ul));
while ((hashTableSize < maxHashTableSize) && (hashTableSize < uncompressedLength)) {
hashTableSize <<= 1;
}
pithy_hashOffset_t stackHashTable[hashTableSize], *heapHashTable = NULL, *hashTable = stackHashTable;
if ((sizeof(pithy_hashOffset_t) * hashTableSize) >= (1024ul * 128ul)) {
if ((heapHashTable = malloc(sizeof(pithy_hashOffset_t) * hashTableSize)) == NULL) {
return (0ul);
}
hashTable = heapHashTable;
}
size_t x = 0ul;
for (x = 0ul; x < hashTableSize; x++) {
hashTable[x] = uncompressed;
}
#ifndef NDEBUG
char *const compressedOutEnd = compressedOut + compressedOutLength;
#endif
compressedPtr = pithy_Encode32(compressedPtr, uncompressedLength);
DCHECK(compressedPtr <= compressedOutEnd);
{
const char *uncompressedPtr = uncompressed;
const char *uncompressedEnd = uncompressed + uncompressedLength;
const char *nextEmitUncompressedPtr = uncompressedPtr;
DCHECK((hashTableSize & (hashTableSize - 1l)) == 0);
const int shift = 32 - pithy_Log2Floor(hashTableSize);
DCHECK((UINT32_MAX >> shift) == (hashTableSize - 1l));
size_t skip = 32ul;
if (PITHY_EXPECT_T(uncompressedLength >= 15ul)) {
const char *uncompressedEndLimit = uncompressed + uncompressedLength - 15ul;
uint32_t uncompressedBytes;
uint32_t nextUncompressedBytes = pithy_Load32(++uncompressedPtr);
uint32_t nextUncompressedBytesHash = pithy_HashBytes(nextUncompressedBytes, shift);
while (1) {
DCHECK(nextEmitUncompressedPtr < uncompressedPtr);
const char *nextUncompressedPtr = uncompressedPtr, *matchCandidatePtr = NULL;
skip = (((skip - 32ul) * 184ul) >> 8) + 32ul;
do {
uncompressedPtr = nextUncompressedPtr;
uncompressedBytes = nextUncompressedBytes;
uint32_t uncompressedBytesHash = nextUncompressedBytesHash;
DCHECK(uncompressedBytesHash == pithy_HashBytes(uncompressedBytes, shift));
size_t skipBytesBetweenHashLookups = skip >> 5;
skip += ((skip * 7ul) >> 11) + 1ul;
nextUncompressedPtr = uncompressedPtr + skipBytesBetweenHashLookups;
if (PITHY_EXPECT_F(nextUncompressedPtr > uncompressedEndLimit)) {
goto emit_remainder;
}
nextUncompressedBytes = pithy_Load32(nextUncompressedPtr);
nextUncompressedBytesHash = pithy_HashBytes(nextUncompressedBytes, shift);
matchCandidatePtr = hashTable[uncompressedBytesHash];
DCHECK((matchCandidatePtr >= uncompressed) && (matchCandidatePtr < uncompressedPtr));
hashTable[uncompressedBytesHash] = uncompressedPtr;
} while ((PITHY_EXPECT_T(uncompressedBytes != pithy_Load32(matchCandidatePtr))) ||
PITHY_EXPECT_F((uncompressedPtr - matchCandidatePtr) >= ((int)(kBlockSize - 2ul))));
DCHECK((nextEmitUncompressedPtr + 16ul) <= uncompressedEnd);
compressedPtr = pithy_EmitLiteral(compressedPtr,
nextEmitUncompressedPtr,
uncompressedPtr - nextEmitUncompressedPtr,
1);
DCHECK(compressedPtr <= compressedOutEnd);
uint64_t uncompressedBytes64 = 0ul;
do {
if (compressionLevel > 2) {
DCHECK((uncompressedPtr + 5ul) <= uncompressedEnd);
uncompressedBytes64 = pithy_Load64((uint64_t*)uncompressedPtr + 1ul);
hashTable[pithy_HashBytes(pithy_GetUint32AtOffset(uncompressedBytes64, 0u), shift)] =
uncompressedPtr + 1ul;
if (compressionLevel > 4) {
hashTable[pithy_HashBytes(pithy_GetUint32AtOffset(uncompressedBytes64, 1u), shift)] =
uncompressedPtr + 2ul;
}
}
DCHECK((matchCandidatePtr >= uncompressed) &&
(matchCandidatePtr <= uncompressedPtr) &&
((matchCandidatePtr + 4ul) <= uncompressedEnd) &&
((uncompressedPtr + 4ul) <= uncompressedEnd));
size_t matchCandidateLength = 4ul + pithy_FindMatchLength(matchCandidatePtr + 4ul,
uncompressedPtr + 4ul,
uncompressedEnd);
DCHECK(((matchCandidatePtr + matchCandidateLength) >= uncompressed) &&
((matchCandidatePtr + matchCandidateLength) <= uncompressedEnd));
DCHECK(0 == memcmp(uncompressedPtr, matchCandidatePtr, matchCandidateLength));
compressedPtr = pithy_EmitCopy(compressedPtr,
uncompressedPtr - matchCandidatePtr,
matchCandidateLength);
DCHECK(compressedPtr <= compressedOutEnd);
uncompressedPtr += matchCandidateLength;
DCHECK(uncompressedPtr <= uncompressedEnd);
nextEmitUncompressedPtr = uncompressedPtr;
if (PITHY_EXPECT_F(uncompressedPtr >= uncompressedEndLimit)) {
goto emit_remainder;
}
DCHECK(((uncompressedPtr - 3ul) >= uncompressed) && (uncompressedPtr <= uncompressedEnd));
uncompressedBytes64 = pithy_Load64((uint64_t*)uncompressedPtr - 3ul);
if (compressionLevel > 0) {
if (compressionLevel > 8) {
hashTable[pithy_HashBytes(pithy_GetUint32AtOffset(uncompressedBytes64, 0u), shift)] =
uncompressedPtr - 3ul;
}
if (compressionLevel > 6) {
hashTable[pithy_HashBytes(pithy_GetUint32AtOffset(uncompressedBytes64, 1u), shift)] =
uncompressedPtr - 2ul;
}
hashTable[pithy_HashBytes(pithy_GetUint32AtOffset(uncompressedBytes64, 2u), shift)] =
uncompressedPtr - 1ul;
}
uncompressedBytes = pithy_GetUint32AtOffset(uncompressedBytes64, 3u);
uint32_t uncompressedBytesHash = pithy_HashBytes(uncompressedBytes, shift);
matchCandidatePtr = hashTable[uncompressedBytesHash];
DCHECK((matchCandidatePtr >= uncompressed) && (matchCandidatePtr < uncompressedPtr));
hashTable[uncompressedBytesHash] = uncompressedPtr;
} while (PITHY_EXPECT_F(uncompressedBytes == pithy_Load32(matchCandidatePtr)) &&
PITHY_EXPECT_T((uncompressedPtr - matchCandidatePtr) < ((int)(kBlockSize - 2ul))));
nextUncompressedBytes = pithy_GetUint32AtOffset(uncompressedBytes64, 4u);
nextUncompressedBytesHash = pithy_HashBytes(nextUncompressedBytes, shift);
uncompressedPtr++;
}
}
emit_remainder:
if (nextEmitUncompressedPtr < uncompressedEnd) {
compressedPtr = pithy_EmitLiteral(compressedPtr,
nextEmitUncompressedPtr,
uncompressedEnd - nextEmitUncompressedPtr,
0);
}
}
pithy_Store32(compressedPtr, 0);
compressedPtr += 4;
DCHECK((size_t)(compressedPtr - compressedOut) <= compressedOutLength);
if (heapHashTable != NULL) {
free(heapHashTable);
heapHashTable = NULL;
hashTable = NULL;
}
return (compressedPtr - compressedOut);
}
static const uint32_t pithy_wordmask[] = {
0u, 0xffu, 0xffffu, 0xffffffu, 0xffffffffu
};
static const uint16_t pithy_charTable[256] = {
0x0001, 0x0804, 0x1001, 0x1801, 0x0002, 0x0805, 0x1002, 0x1802,
0x0003, 0x0806, 0x1003, 0x1803, 0x0004, 0x0807, 0x1004, 0x1804,
0x0005, 0x0808, 0x1005, 0x1805, 0x0006, 0x0809, 0x1006, 0x1806,
0x0007, 0x080a, 0x1007, 0x1807, 0x0008, 0x080b, 0x1008, 0x1808,
0x0009, 0x0904, 0x1009, 0x1809, 0x000a, 0x0905, 0x100a, 0x180a,
0x000b, 0x0906, 0x100b, 0x180b, 0x000c, 0x0907, 0x100c, 0x180c,
0x000d, 0x0908, 0x100d, 0x180d, 0x000e, 0x0909, 0x100e, 0x180e,
0x000f, 0x090a, 0x100f, 0x180f, 0x0010, 0x090b, 0x1010, 0x1810,
0x0011, 0x0a04, 0x1011, 0x1811, 0x0012, 0x0a05, 0x1012, 0x1812,
0x0013, 0x0a06, 0x1013, 0x1813, 0x0014, 0x0a07, 0x1014, 0x1814,
0x0015, 0x0a08, 0x1015, 0x1815, 0x0016, 0x0a09, 0x1016, 0x1816,
0x0017, 0x0a0a, 0x1017, 0x1817, 0x0018, 0x0a0b, 0x1018, 0x1818,
0x0019, 0x0b04, 0x1019, 0x1819, 0x001a, 0x0b05, 0x101a, 0x181a,
0x001b, 0x0b06, 0x101b, 0x181b, 0x001c, 0x0b07, 0x101c, 0x181c,
0x001d, 0x0b08, 0x101d, 0x181d, 0x001e, 0x0b09, 0x101e, 0x181e,
0x001f, 0x0b0a, 0x101f, 0x181f, 0x0020, 0x0b0b, 0x1020, 0x1820,
0x0021, 0x0c04, 0x1021, 0x1821, 0x0022, 0x0c05, 0x1022, 0x1822,
0x0023, 0x0c06, 0x1023, 0x1823, 0x0024, 0x0c07, 0x1024, 0x1824,
0x0025, 0x0c08, 0x1025, 0x1825, 0x0026, 0x0c09, 0x1026, 0x1826,
0x0027, 0x0c0a, 0x1027, 0x1827, 0x0028, 0x0c0b, 0x1028, 0x1828,
0x0029, 0x0d04, 0x1029, 0x1829, 0x002a, 0x0d05, 0x102a, 0x182a,
0x002b, 0x0d06, 0x102b, 0x182b, 0x002c, 0x0d07, 0x102c, 0x182c,
0x002d, 0x0d08, 0x102d, 0x182d, 0x002e, 0x0d09, 0x102e, 0x182e,
0x002f, 0x0d0a, 0x102f, 0x182f, 0x0030, 0x0d0b, 0x1030, 0x1830,
0x0031, 0x0e04, 0x1031, 0x1831, 0x0032, 0x0e05, 0x1032, 0x1832,
0x0033, 0x0e06, 0x1033, 0x1833, 0x0034, 0x0e07, 0x1034, 0x1834,
0x0035, 0x0e08, 0x1035, 0x1835, 0x0036, 0x0e09, 0x1036, 0x1836,
0x0037, 0x0e0a, 0x1037, 0x1837, 0x0038, 0x0e0b, 0x1038, 0x1838,
0x0039, 0x0f04, 0x1039, 0x1839, 0x003a, 0x0f05, 0x103a, 0x183a,
0x003b, 0x0f06, 0x103b, 0x183b, 0x003c, 0x0f07, 0x103c, 0x183c,
0x0801, 0x0f08, 0x103d, 0x183d, 0x1001, 0x0f09, 0x103e, 0x183e,
0x1801, 0x0f0a, 0x103f, 0x183f, 0x2001, 0x0f0b, 0x1040, 0x1840
};
int pithy_GetDecompressedLength(const char *compressed, size_t compressedLength, size_t *decompressedOutLengthResult)
{
const char *compressedEnd = compressed + compressedLength;
size_t decompressedLength = 0ul;
if (pithy_Parse32WithLimit(compressed, compressedEnd, &decompressedLength) != NULL) {
*decompressedOutLengthResult = decompressedLength;
return (1);
} else {
return (0);
}
}
int pithy_Decompress(const char *compressed, size_t compressedLength, char *decompressedOut,
size_t decompressedOutLength)
{
const char *nextCompressedPtr = NULL, *compressedEnd = (compressed + compressedLength);
size_t parsedDecompressedLength = 0ul;
if (((nextCompressedPtr = pithy_Parse32WithLimit(compressed, compressedEnd, &parsedDecompressedLength)) == NULL) ||
(parsedDecompressedLength > decompressedOutLength)) {
return (0);
}
char *decompressedPtr = decompressedOut, *decompressedEnd = decompressedOut + parsedDecompressedLength;
while (1) {
const char *compressedPtr = nextCompressedPtr;
DCHECK(compressedPtr <= compressedEnd);
if (PITHY_EXPECT_F(compressedPtr >= compressedEnd)) {
break;
}
const unsigned char c = *((const unsigned char *)(compressedPtr++));
const unsigned char cLowerBits = (c & 0x3u);
const int spaceLeft = (decompressedEnd - decompressedPtr);
if ((cLowerBits == PITHY_LITERAL)) {
size_t literalLength = (c >> 2) + 1;
if (PITHY_EXPECT_T(literalLength <= 16ul) && PITHY_EXPECT_T((compressedEnd - compressedPtr) >= 16l) &&
PITHY_EXPECT_T(spaceLeft >= 16l)) {
pithy_Move128(decompressedPtr, compressedPtr);
} else {
if (PITHY_EXPECT_F(literalLength > 60)) {
if (PITHY_EXPECT_F((compressedPtr + 4) > compressedEnd)) {
break;
}
size_t literalLengthBytes = literalLength - 60;
literalLength = (pithy_LoadHost32(compressedPtr) & pithy_wordmask[literalLengthBytes]) + 1;
compressedPtr += literalLengthBytes;
}
if (PITHY_EXPECT_F(spaceLeft < (int)literalLength) ||
PITHY_EXPECT_F((compressedPtr + literalLength) > compressedEnd)) {
break;
}
memcpy(decompressedPtr, compressedPtr, literalLength);
}
nextCompressedPtr = compressedPtr + literalLength;
decompressedPtr += literalLength;
} else {
const uint32_t entry = pithy_charTable[c];
const size_t trailer = pithy_LoadHost32(compressedPtr) & pithy_wordmask[cLowerBits];
size_t length = entry & 0xffu;
const size_t copyOffset = ((entry & 0x700u) + trailer);
compressedPtr += cLowerBits;
DCHECK((compressedPtr <= compressedEnd) && (copyOffset > 0ul) && (spaceLeft > 0l) && (length > 0ul));
if (PITHY_EXPECT_F((decompressedPtr - decompressedOut) <= ((int)copyOffset - 1l))) {
break;
}
if (PITHY_EXPECT_T(length <= 16ul) &&
PITHY_EXPECT_T(copyOffset >= 16ul) &&
PITHY_EXPECT_T(spaceLeft >= 16l)) {
pithy_Move128(decompressedPtr, decompressedPtr - copyOffset);
} else {
if (PITHY_EXPECT_F(length >= 63ul)) {
if (PITHY_EXPECT_T(length == 63ul)) {
if (PITHY_EXPECT_F((compressedPtr + 1) > compressedEnd)) {
break;
}
length = (*((unsigned char *)compressedPtr++)) + 63ul;
} else {
if (PITHY_EXPECT_F((compressedPtr + 2) > compressedEnd)) {
break;
}
length = pithy_LoadHost16(compressedPtr);
compressedPtr += 2ul;
}
}
char *copyFrom = decompressedPtr - copyOffset, *copyTo = decompressedPtr;
int copyLength = (int)length;
if (PITHY_EXPECT_F(copyLength > 256l) && PITHY_EXPECT_T(copyOffset > (size_t)copyLength)) {
if (PITHY_EXPECT_F(spaceLeft < copyLength)) {
break;
}
memcpy(copyTo, copyFrom, copyLength);
} else {
if (PITHY_EXPECT_T(spaceLeft >= (copyLength + 24)) && PITHY_EXPECT_T(copyLength > 0l)) {
while ((copyTo - copyFrom) < 16l) {
pithy_Move128(copyTo, copyFrom);
copyLength -= copyTo - copyFrom;
copyTo += copyTo - copyFrom;
}
while (copyLength > 0l) {
pithy_Move128(copyTo, copyFrom);
copyFrom += 16l;
copyTo += 16l;
copyLength -= 16l;
}
} else {
if (PITHY_EXPECT_F(spaceLeft < copyLength) || PITHY_EXPECT_F(copyLength <= 0l)) {
break;
}
do {
*copyTo++ = *copyFrom++;
} while (--copyLength > 0l);
}
}
}
nextCompressedPtr = compressedPtr;
decompressedPtr += length;
}
}
return (decompressedPtr == decompressedEnd);
}

View File

@ -0,0 +1,63 @@
//
// pithy.h
// http://github.com/johnezang/pithy
// Licensed under the terms of the BSD License, as specified below.
//
/*
Copyright (c) 2011, John Engelhart
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Zang Industries nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _PITHY_H_
#define _PITHY_H_
// compressionLevel >= 0 && compressionLevel <= 9. Values out side this range will be clamped to this range.
size_t pithy_Compress (const char *uncompressed, size_t uncompressedLength, char *compressedOut,
size_t compressedOutLength, int compressionLevel);
int pithy_Decompress(const char *compressed, size_t compressedLength, char *decompressedOut,
size_t decompressedOutLength);
size_t pithy_MaxCompressedLength(size_t inputLength);
int pithy_GetDecompressedLength(const char *compressed, size_t compressedLength,
size_t *decompressedOutLengthResult);
#endif // _PITHY_H_
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -66,11 +66,13 @@ void test_case_malloc_free_size()
TEST_ASSERT_EQUAL_UINT32(stats_start.total_size + ALLOCATION_SIZE_DEFAULT * (i + 1), stats_current.total_size);
TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_cnt + 1, stats_current.alloc_cnt);
TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_fail_cnt, stats_current.alloc_fail_cnt);
// Library header 0x4-0x8, stats header 0x8 and alignment addition 0x4
TEST_ASSERT_INT_WITHIN(0x8, stats_start.overhead_size + 0xC , stats_current.overhead_size);
// Free memory and assert back to starting size
free(data);
mbed_stats_heap_get(&stats_current);
TEST_ASSERT_EQUAL_UINT32(stats_start.current_size, stats_current.current_size);
TEST_ASSERT_EQUAL_UINT32(stats_start.overhead_size, stats_current.overhead_size);
TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_cnt, stats_current.alloc_cnt);
TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_fail_cnt, stats_current.alloc_fail_cnt);
}
@ -93,10 +95,14 @@ void test_case_allocate_zero()
TEST_ASSERT_EQUAL_UINT32(stats_start.current_size, stats_current.current_size);
TEST_ASSERT_EQUAL_UINT32(stats_start.total_size, stats_current.total_size);
TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_fail_cnt, stats_current.alloc_fail_cnt);
// Library header 0x4-0x8, stats header 0x8 and alignment addition 0x4
if (NULL != data) {
TEST_ASSERT_INT_WITHIN(0x8, stats_start.overhead_size + 0xC , stats_current.overhead_size);
}
// Free memory and assert back to starting size
free(data);
mbed_stats_heap_get(&stats_current);
TEST_ASSERT_EQUAL_UINT32(stats_start.overhead_size, stats_current.overhead_size);
TEST_ASSERT_EQUAL_UINT32(stats_start.current_size, stats_current.current_size);
TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_cnt, stats_current.alloc_cnt);
TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_fail_cnt, stats_current.alloc_fail_cnt);
@ -121,6 +127,7 @@ void test_case_allocate_fail()
TEST_ASSERT_EQUAL_UINT32(stats_start.total_size, stats_current.total_size);
TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_cnt, stats_current.alloc_cnt);
TEST_ASSERT_EQUAL_UINT32(stats_start.alloc_fail_cnt + i + 1, stats_current.alloc_fail_cnt);
TEST_ASSERT_EQUAL_UINT32(stats_start.overhead_size, stats_current.overhead_size);
}
}

View File

@ -43,7 +43,7 @@ void test_system_reset()
int main(void)
{
GREENTEA_SETUP(2, "system_reset");
GREENTEA_SETUP(30, "system_reset");
test_system_reset();
GREENTEA_TESTSUITE_RESULT(0); // Fail on any error.

View File

@ -450,38 +450,6 @@ void test_mem_pool_free_realloc_first_complex(AllocType atype)
}
}
/* Robustness checks for free() function.
*
* Given block from the MemoryPool has been successfully deallocated.
* When free operation is executed on this block again.
* Then operation fails with osErrorResource status.
*
* */
void test_mem_pool_free_on_freed_block()
{
MemoryPool<int, 1> mem_pool;
int *p_block;
osStatus status;
/* Allocate memory block. */
p_block = mem_pool.alloc();
/* Show that memory pool block has been allocated. */
TEST_ASSERT_NOT_NULL(p_block);
/* Free memory block. */
status = mem_pool.free(p_block);
/* Check operation status. */
TEST_ASSERT_EQUAL(osOK, status);
/* Free memory block again. */
status = mem_pool.free(p_block);
/* Check operation status. */
TEST_ASSERT_EQUAL(osErrorResource, status);
}
/* Robustness checks for free() function.
* Function under test is called with invalid parameters.
*
@ -601,7 +569,6 @@ Case cases[] = {
Case("Test: fail (out of free blocks).", test_mem_pool_alloc_fail_wrapper<int, 3>),
Case("Test: free() - robust (free block twice).", test_mem_pool_free_on_freed_block),
Case("Test: free() - robust (free called with invalid param - NULL).", free_block_invalid_parameter_null),
Case("Test: free() - robust (free called with invalid param).", free_block_invalid_parameter)
};

View File

@ -267,28 +267,6 @@ void test_free_null()
TEST_ASSERT_EQUAL(osErrorParameter, status);
}
/** Test same message memory deallocation twice
Given an empty mailbox
Then allocate message memory
When try to free it second time
Then it return appropriate error code
*/
void test_free_twice()
{
osStatus status;
Mail<uint32_t, 4> mail_box;
uint32_t *mail = mail_box.alloc();
TEST_ASSERT_NOT_EQUAL(NULL, mail);
status = mail_box.free(mail);
TEST_ASSERT_EQUAL(osOK, status);
status = mail_box.free(mail);
TEST_ASSERT_EQUAL(osErrorResource, status);
}
/** Test get from empty mailbox with timeout set
Given an empty mailbox
@ -517,7 +495,6 @@ Case cases[] = {
Case("Test message send order", test_order),
Case("Test get with timeout on empty mailbox", test_get_empty_timeout),
Case("Test get without timeout on empty mailbox", test_get_empty_no_timeout),
Case("Test message free twice", test_free_twice),
Case("Test null message free", test_free_null),
Case("Test invalid message free", test_free_wrong),
Case("Test message send/receive single thread and order", test_single_thread_order),

View File

@ -48,9 +48,9 @@ volatile bool mutex_defect = false;
bool manipulate_protected_zone(const int thread_delay)
{
bool result = true;
osStatus stat;
osStatus stat = stdio_mutex.lock();
TEST_ASSERT_EQUAL(osOK, stat);
stdio_mutex.lock();
core_util_critical_section_enter();
if (changing_counter == true) {
@ -68,8 +68,8 @@ bool manipulate_protected_zone(const int thread_delay)
changing_counter = false;
core_util_critical_section_exit();
stat = stdio_mutex.unlock();
TEST_ASSERT_EQUAL(osOK, stat);
stdio_mutex.unlock();
return result;
}
@ -118,11 +118,10 @@ void test_multiple_threads(void)
void test_dual_thread_nolock_lock_thread(Mutex *mutex)
{
osStatus stat = mutex->lock(osWaitForever);
TEST_ASSERT_EQUAL(osOK, stat);
osStatus stat;
mutex->lock();
stat = mutex->unlock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex->unlock();
}
void test_dual_thread_nolock_trylock_thread(Mutex *mutex)
@ -130,8 +129,7 @@ void test_dual_thread_nolock_trylock_thread(Mutex *mutex)
bool stat_b = mutex->trylock();
TEST_ASSERT_EQUAL(true, stat_b);
osStatus stat = mutex->unlock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex->unlock();
}
/** Test dual thread no-lock
@ -140,13 +138,13 @@ void test_dual_thread_nolock_trylock_thread(Mutex *mutex)
Given two threads A & B and a mutex
When thread A creates a mutex and starts thread B
and thread B calls @a lock and @a unlock
Then returned statuses are osOK
Then @a lock and @a unlock operations are successfully performed.
Test dual thread second thread trylock
Given two threads A & B and a mutex
When thread A creates a mutex and starts thread B
and thread B calls @a trylock and @a unlock
Then returned statuses are true and osOK
Then @a trylock and @a unlock operations are successfully performed.
*/
template <void (*F)(Mutex *)>
void test_dual_thread_nolock(void)
@ -161,8 +159,7 @@ void test_dual_thread_nolock(void)
void test_dual_thread_lock_unlock_thread(Mutex *mutex)
{
osStatus stat = mutex->lock(osWaitForever);
TEST_ASSERT_EQUAL(osOK, stat);
mutex->lock();
}
/** Test dual thread lock unlock
@ -180,13 +177,11 @@ void test_dual_thread_lock_unlock(void)
osStatus stat;
Thread thread(osPriorityNormal, TEST_STACK_SIZE);
stat = mutex.lock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex.lock();
thread.start(callback(test_dual_thread_lock_unlock_thread, &mutex));
stat = mutex.unlock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex.unlock();
wait_ms(TEST_DELAY);
}
@ -202,9 +197,9 @@ void test_dual_thread_lock_lock_thread(Mutex *mutex)
Timer timer;
timer.start();
osStatus stat = mutex->lock(TEST_DELAY);
TEST_ASSERT_EQUAL(osErrorTimeout, stat);
TEST_ASSERT_UINT32_WITHIN(5000, TEST_DELAY * 1000, timer.read_us());
bool stat = mutex->trylock_for(TEST_DELAY);
TEST_ASSERT_EQUAL(false, stat);
TEST_ASSERT_UINT32_WITHIN(5000, TEST_DELAY*1000, timer.read_us());
}
/** Test dual thread lock
@ -228,46 +223,40 @@ void test_dual_thread_lock(void)
osStatus stat;
Thread thread(osPriorityNormal, TEST_STACK_SIZE);
stat = mutex.lock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex.lock();
thread.start(callback(F, &mutex));
wait_ms(TEST_LONG_DELAY);
stat = mutex.unlock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex.unlock();
}
/** Test single thread lock recursive
Given a mutex and a single running thread
When thread calls @a lock twice and @a unlock twice on the mutex
Then the returned statuses are osOK
Then @a lock and @a unlock operations are successfully performed.
*/
void test_single_thread_lock_recursive(void)
{
Mutex mutex;
osStatus stat;
stat = mutex.lock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex.lock();
stat = mutex.lock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex.lock();
stat = mutex.unlock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex.unlock();
stat = mutex.unlock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex.unlock();
}
/** Test single thread trylock
Given a mutex and a single running thread
When thread calls @a trylock and @a unlock on the mutex
Then the returned statuses are osOK
Then @a trylock and @a unlock operations are successfully performed.
*/
void test_single_thread_trylock(void)
{
@ -276,26 +265,23 @@ void test_single_thread_trylock(void)
bool stat_b = mutex.trylock();
TEST_ASSERT_EQUAL(true, stat_b);
osStatus stat = mutex.unlock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex.unlock();
}
/** Test single thread lock
Given a mutex and a single running thread
When thread calls @a lock and @a unlock on the mutex
Then the returned statuses are osOK
Then @a lock and @a unlock operations are successfully performed.
*/
void test_single_thread_lock(void)
{
Mutex mutex;
osStatus stat;
stat = mutex.lock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex.lock();
stat = mutex.unlock();
TEST_ASSERT_EQUAL(osOK, stat);
mutex.unlock();
}
utest::v1::status_t test_setup(const size_t number_of_cases)

View File

@ -334,7 +334,7 @@ void test_isr_calls_fail()
utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(5, "default_auto");
GREENTEA_SETUP(10, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}

View File

@ -61,13 +61,13 @@ void increment(counter_t *counter)
void increment_with_yield(counter_t *counter)
{
Thread::yield();
ThisThread::yield();
(*counter)++;
}
void increment_with_wait(counter_t *counter)
{
Thread::wait(100);
ThisThread::sleep_for(100);
(*counter)++;
}
@ -286,59 +286,69 @@ end:
delete thread;
}
void signal_wait()
void flags_wait()
{
osEvent evt = Thread::signal_wait(0x1);
TEST_ASSERT_EQUAL(osEventSignal, evt.status);
TEST_ASSERT_EQUAL(0x1, evt.value.signals);
uint32_t flags = ThisThread::flags_wait_all(0x1);
TEST_ASSERT_EQUAL(0x1, flags);
}
void signal_wait_tout()
void flags_wait_tout()
{
osEvent evt = Thread::signal_wait(0x2, 50);
TEST_ASSERT_EQUAL(osEventTimeout, evt.status);
uint32_t flags = ThisThread::flags_wait_all_for(0x2, 50);
TEST_ASSERT_EQUAL(0x1, flags);
}
void signal_wait_multibit()
void flags_wait_multibit()
{
osEvent evt = Thread::signal_wait(0x1 | 0x2, 50);
TEST_ASSERT_EQUAL(osEventSignal, evt.status);
TEST_ASSERT_EQUAL(0x3, evt.value.signals);
uint32_t flags = ThisThread::flags_wait_all(0x1 | 0x2);
TEST_ASSERT_EQUAL(0x3, flags);
}
void signal_wait_multibit_tout()
void flags_wait_multibit_any()
{
osEvent evt = Thread::signal_wait(0x1 | 0x2, 50);
TEST_ASSERT_EQUAL(osEventTimeout, evt.status);
uint32_t flags = ThisThread::flags_wait_any(0x1 | 0x2);
TEST_ASSERT_NOT_EQUAL(0x0, flags);
}
void flags_wait_multibit_tout()
{
uint32_t flags = ThisThread::flags_wait_all_for(0x1 | 0x2, 50);
TEST_ASSERT_NOT_EQUAL(0x3, flags);
}
/**
Testing thread signal: wait
Testing thread flags: wait
Given two threads (A & B) are started
when thread A executes @a signal_wait(0x1)
and thread B execute @a signal_set(0x1)
when thread A executes @a flags_wait_all(0x1)
and thread B execute @a flags_set(0x1)
then thread A exits the wait and continues execution
Testing thread signal: timeout
Testing thread flags: timeout
Given two threads (A & B) are started
when thread A executes @a signal_wait(0x1 | 0x2, 50) with a timeout of 50ms
and thread B execute @a signal_set(0x2)
then thread A keeps waiting for correct signal until it timeouts
when thread A executes @a flags_wait_all_for(0x1 | 0x2, 50) with a timeout of 50ms
and thread B execute @a flags_set(0x2)
then thread A keeps waiting for correct flags until it timeouts
Testing thread signal: multi-bit
Testing thread flags: multi-bit
Given two threads (A & B) are started
when thread A executes @a signal_wait(0x1 | 0x2)
and thread B execute @a signal_set(0x1 | 0x2)
when thread A executes @a flags_wait_all(0x1 | 0x2)
and thread B execute @a flags_set(0x1 | 0x2)
then thread A exits the wait and continues execution
Testing thread signal: multi-bit timeout
Testing thread flags: multi-bit any
Given two threads (A & B) are started
when thread A executes @a signal_wait(0x1, 50) with a timeout of 50ms
and thread B execute @a signal_set(0x2)
then thread A keeps waiting for correct signal until it timeouts
when thread A executes @a flags_wait_any(0x1 | 0x2)
and thread B execute @a flags_set(0x1)
then thread A exits the wait and continues execution
Testing thread flags: multi-bit timeout
Given two threads (A & B) are started
when thread A executes @a flags_wait_all_for(0x1, 50) with a timeout of 50ms
and thread B execute @a flags_set(0x2)
then thread A keeps waiting for correct flags until it timeouts
*/
template <int S, void (*F)()>
void test_thread_signal()
void test_thread_flags_set()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
@ -348,37 +358,37 @@ void test_thread_signal()
t_wait.start(callback(F));
Thread::yield();
ThisThread::yield();
Thread::State state = t_wait.get_state();
TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, state);
int32_t res = t_wait.signal_set(S);
int32_t res = t_wait.flags_set(S);
t_wait.join();
}
void signal_clr()
void flags_clear()
{
Thread::yield();
ThisThread::yield();
int32_t sig = Thread::signal_clr(0x1);
int32_t sig = ThisThread::flags_clear(0x1);
TEST_ASSERT_EQUAL(0x1, sig);
/* Signal cleared we should get timeout */
osEvent evt = Thread::signal_wait(0x1, 0);
TEST_ASSERT_EQUAL(osOK, evt.status);
/* Flags cleared we should get timeout */
uint32_t flags = ThisThread::flags_wait_all_for(0x1, 0);
TEST_ASSERT_EQUAL(0, flags);
}
/** Testing thread signals: signal clear
/** Testing thread flags: flags clear
Given two threads (A & B) are started
when thread A executes @a signal_set(0x1)
and thread B execute @a signal_clr(0x1)
and thread B execute @a signal_wait(0x1, 0)
then thread B @a signal_wait status should be osOK indicating a timeout
when thread A executes @a flags_set(0x1)
and thread B execute @a flags_clear(0x1)
and thread B execute @a flags_wait_all_for(0x1, 0)
then thread B @a flags_wait_all_for return should be 0 indicating no flags set
*/
void test_thread_signal_clr()
void test_thread_flags_clear()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
@ -386,26 +396,26 @@ void test_thread_signal_clr()
Thread t_wait(osPriorityNormal, THREAD_STACK_SIZE);
t_wait.start(callback(signal_clr));
t_wait.start(callback(flags_clear));
int32_t res = t_wait.signal_set(0x1);
int32_t res = t_wait.flags_set(0x1);
TEST_ASSERT_EQUAL(0x1, res);
t_wait.join();
}
void thread_wait_signal()
void thread_wait_flags()
{
Thread::signal_wait(0x1);
ThisThread::flags_wait_all(0x1);
}
void stack_info()
{
Thread::signal_wait(0x1);
ThisThread::flags_wait_all(0x1);
thread_wait_signal();
thread_wait_flags();
Thread::signal_wait(0x1);
ThisThread::flags_wait_all(0x1);
}
/** Testing thread stack info
@ -429,26 +439,26 @@ void test_thread_stack_info()
Thread t(osPriorityNormal, THREAD_STACK_SIZE);
t.start(callback(stack_info));
Thread::yield();
ThisThread::yield();
TEST_ASSERT_EQUAL(THREAD_STACK_SIZE, t.stack_size());
TEST_ASSERT_EQUAL(THREAD_STACK_SIZE, t.free_stack() + t.used_stack());
uint32_t last_stack = t.used_stack();
t.signal_set(0x1);
Thread::yield();
t.flags_set(0x1);
ThisThread::yield();
TEST_ASSERT_EQUAL(THREAD_STACK_SIZE, t.free_stack() + t.used_stack());
TEST_ASSERT(last_stack <= t.used_stack());
last_stack = t.used_stack();
t.signal_set(0x1);
Thread::yield();
t.flags_set(0x1);
ThisThread::yield();
TEST_ASSERT_EQUAL(THREAD_STACK_SIZE, t.free_stack() + t.used_stack());
TEST_ASSERT(last_stack >= t.used_stack());
t.signal_set(0x1);
t.flags_set(0x1);
t.join();
}
@ -483,9 +493,9 @@ void test_thread_name()
const char tname[] = "Amazing thread";
Thread t(osPriorityNormal, THREAD_STACK_SIZE, NULL, tname);
t.start(callback(thread_wait_signal));
t.start(callback(thread_wait_flags));
TEST_ASSERT_EQUAL(strcmp(tname, t.get_name()), 0);
t.signal_set(0x1);
t.flags_set(0x1);
t.join();
}
@ -537,7 +547,7 @@ void test_delay()
t.start(callback(test_delay_thread));
Thread::yield();
ThisThread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingDelay, t.get_state());
@ -545,18 +555,18 @@ void test_delay()
TEST_ASSERT_EQUAL(Thread::Deleted, t.get_state());
}
void test_signal_thread()
void test_thread_flags_thread()
{
Thread::signal_wait(0x1);
ThisThread::flags_wait_all(0x1);
}
/** Testing thread states: wait signal
/** Testing thread states: wait flags
Given the thread is running
when thread waits for a signal
then its state, as reported by @a get_state, is @a WaitingSignal
when thread waits for flags
then its state, as reported by @a get_state, is @a WaitingThreadFlag
*/
void test_signal()
void test_thread_flags()
{
char *dummy = new (std::nothrow) char[THREAD_STACK_SIZE];
delete[] dummy;
@ -564,18 +574,18 @@ void test_signal()
Thread t(osPriorityNormal, THREAD_STACK_SIZE);
t.start(callback(test_signal_thread));
t.start(callback(test_thread_flags_thread));
Thread::yield();
ThisThread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, t.get_state());
t.signal_set(0x1);
t.flags_set(0x1);
}
void test_evt_flag_thread(osEventFlagsId_t evtflg)
void test_evt_flag_thread(EventFlags *evtflg)
{
osEventFlagsWait(evtflg, 0x1, osFlagsWaitAny, osWaitForever);
evtflg->wait_any(0x1);
}
/** Testing thread states: wait evt flag
@ -591,22 +601,15 @@ void test_evt_flag()
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");
Thread t(osPriorityNormal, THREAD_STACK_SIZE);
mbed_rtos_storage_event_flags_t evtflg_mem;
osEventFlagsAttr_t evtflg_attr;
osEventFlagsId_t evtflg;
EventFlags evtflg;
evtflg_attr.cb_mem = &evtflg_mem;
evtflg_attr.cb_size = sizeof(evtflg_mem);
evtflg = osEventFlagsNew(&evtflg_attr);
TEST_ASSERT_NOT_EQUAL(NULL, evtflg);
t.start(callback(test_evt_flag_thread, &evtflg));
t.start(callback(test_evt_flag_thread, evtflg));
Thread::yield();
ThisThread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingEventFlag, t.get_state());
osEventFlagsSet(evtflg, 0x1);
evtflg.set(0x1);
}
void test_mutex_thread(Mutex *mutex)
@ -633,7 +636,7 @@ void test_mutex()
t.start(callback(test_mutex_thread, &mutex));
Thread::yield();
ThisThread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingMutex, t.get_state());
@ -662,7 +665,7 @@ void test_semaphore()
t.start(callback(test_semaphore_thread, &sem));
Thread::yield();
ThisThread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state());
@ -691,7 +694,7 @@ void test_msg_get()
t.start(callback(test_msg_get_thread, &queue));
Thread::yield();
ThisThread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingMessageGet, t.get_state());
@ -723,7 +726,7 @@ void test_msg_put()
t.start(callback(test_msg_put_thread, &queue));
Thread::yield();
ThisThread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingMessagePut, t.get_state());
queue.get();
@ -773,7 +776,7 @@ void test_thread_prio()
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test");
Thread t(osPriorityNormal, THREAD_STACK_SIZE);
t.start(callback(thread_wait_signal));
t.start(callback(thread_wait_flags));
TEST_ASSERT_EQUAL(osPriorityNormal, t.get_priority());
@ -781,7 +784,7 @@ void test_thread_prio()
TEST_ASSERT_EQUAL(osPriorityHigh, t.get_priority());
t.signal_set(0x1);
t.flags_set(0x1);
t.join();
}
@ -818,12 +821,12 @@ static const case_t cases[] = {
{"Testing thread self terminate", test_self_terminate, DEFAULT_HANDLERS},
{"Testing thread signals: wait", test_thread_signal<0x1, signal_wait>, DEFAULT_HANDLERS},
{"Testing thread signals: timeout", test_thread_signal<0x1, signal_wait_tout>, DEFAULT_HANDLERS},
{"Testing thread signals: multi-bit", test_thread_signal<0x3, signal_wait_multibit>, DEFAULT_HANDLERS},
{"Testing thread signals: multi-bit timeout", test_thread_signal<0x1, signal_wait_multibit_tout>, DEFAULT_HANDLERS},
{"Testing thread signals: signal clear", test_thread_signal_clr, DEFAULT_HANDLERS},
{"Testing thread flags: wait", test_thread_flags_set<0x1, flags_wait>, DEFAULT_HANDLERS},
{"Testing thread flags: timeout", test_thread_flags_set<0x1, flags_wait_tout>, DEFAULT_HANDLERS},
{"Testing thread flags: multi-bit all", test_thread_flags_set<0x3, flags_wait_multibit>, DEFAULT_HANDLERS},
{"Testing thread flags: multi-bit all timeout", test_thread_flags_set<0x1, flags_wait_multibit_tout>, DEFAULT_HANDLERS},
{"Testing thread flags: multi-bit any", test_thread_flags_set<0x1, flags_wait_multibit_any>, DEFAULT_HANDLERS},
{"Testing thread flags: flags clear", test_thread_flags_clear, DEFAULT_HANDLERS},
{"Testing thread stack info", test_thread_stack_info, DEFAULT_HANDLERS},
{"Testing thread wait", test_thread_wait, DEFAULT_HANDLERS},
@ -831,7 +834,7 @@ static const case_t cases[] = {
{"Testing thread states: deleted", test_deleted, DEFAULT_HANDLERS},
{"Testing thread states: wait delay", test_delay, DEFAULT_HANDLERS},
{"Testing thread states: wait signal", test_signal, DEFAULT_HANDLERS},
{"Testing thread states: wait thread flags", test_thread_flags, DEFAULT_HANDLERS},
{"Testing thread states: wait event flag", test_evt_flag, DEFAULT_HANDLERS},
{"Testing thread states: wait mutex", test_mutex, DEFAULT_HANDLERS},
{"Testing thread states: wait semaphore", test_semaphore, DEFAULT_HANDLERS},

View File

@ -188,15 +188,14 @@ int main()
{
int ret = 0;
#if defined(MBEDTLS_PLATFORM_C)
mbedtls_platform_context platform_ctx;
if ((ret = mbedtls_platform_setup(&platform_ctx)) != 0) {
if ((ret = mbedtls_platform_setup(NULL)) != 0) {
mbedtls_printf("Mbed TLS multitest failed! mbedtls_platform_setup returned %d\n", ret);
return 1;
}
#endif
ret = (Harness::run(specification) ? 0 : 1);
#if defined(MBEDTLS_PLATFORM_C)
mbedtls_platform_teardown(&platform_ctx);
mbedtls_platform_teardown(NULL);
#endif
return ret;
}

View File

@ -96,15 +96,14 @@ int main()
{
int ret = 0;
#if defined(MBEDTLS_PLATFORM_C)
mbedtls_platform_context platform_ctx;
if ((ret = mbedtls_platform_setup(&platform_ctx)) != 0) {
if ((ret = mbedtls_platform_setup(NULL)) != 0) {
mbedtls_printf("Mbed TLS selftest failed! mbedtls_platform_setup returned %d\n", ret);
return 1;
}
#endif
ret = (Harness::run(specification) ? 0 : 1);
#if defined(MBEDTLS_PLATFORM_C)
mbedtls_platform_teardown(&platform_ctx);
mbedtls_platform_teardown(NULL);
#endif
return ret;
}

1674
TESTS/netsocket/README.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -56,8 +56,9 @@ void ASYNCHRONOUS_DNS_CACHE()
int delay_ms = (ticker_us - started_us) / 1000;
static int delay_first = delay_ms / 2;
printf("Delays: first: %i, delay_ms: %i\n", delay_first, delay_ms);
// Check that cached accesses are at least twice as fast as the first one
TEST_ASSERT_FALSE(i != 0 && delay_ms > delay_first);
TEST_ASSERT_TRUE(i == 0 || delay_ms <= delay_first);
printf("DNS: query \"%s\" => \"%s\", time %i ms\n",
dns_test_hosts[0], data.addr.get_ip_address(), delay_ms);

View File

@ -59,6 +59,7 @@ extern const char dns_test_hosts_second[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TE
NetworkInterface *get_interface();
void hostbyname_cb(void *data, nsapi_error_t result, SocketAddress *address);
void do_asynchronous_gethostbyname(const char hosts[][DNS_TEST_HOST_LEN], unsigned int op_count, int *exp_ok, int *exp_no_mem, int *exp_dns_failure, int *exp_timeout);
void do_gethostbyname(const char hosts[][DNS_TEST_HOST_LEN], unsigned int op_count, int *exp_ok, int *exp_no_mem, int *exp_dns_failure, int *exp_timeout);
/*
* Test cases
@ -73,5 +74,8 @@ void ASYNCHRONOUS_DNS_EXTERNAL_EVENT_QUEUE();
void ASYNCHRONOUS_DNS_INVALID_HOST();
void ASYNCHRONOUS_DNS_TIMEOUTS();
void ASYNCHRONOUS_DNS_SIMULTANEOUS_REPEAT();
void SYNCHRONOUS_DNS();
void SYNCHRONOUS_DNS_MULTIPLE();
void SYNCHRONOUS_DNS_CACHE();
void SYNCHRONOUS_DNS_INVALID();
#endif

View File

@ -107,6 +107,39 @@ void do_asynchronous_gethostbyname(const char hosts[][DNS_TEST_HOST_LEN], unsign
delete[] data;
}
void do_gethostbyname(const char hosts[][DNS_TEST_HOST_LEN], unsigned int op_count, int *exp_ok, int *exp_no_mem, int *exp_dns_failure, int *exp_timeout)
{
// Verify that there is enough hosts in the host list
TEST_ASSERT(op_count <= MBED_CONF_APP_DNS_TEST_HOSTS_NUM)
// Reset counters
(*exp_ok) = 0;
(*exp_no_mem) = 0;
(*exp_dns_failure) = 0;
(*exp_timeout) = 0;
for (unsigned int i = 0; i < op_count; i++) {
SocketAddress address;
nsapi_error_t err = net->gethostbyname(hosts[i], &address);
TEST_ASSERT(err == NSAPI_ERROR_OK || err == NSAPI_ERROR_NO_MEMORY || err == NSAPI_ERROR_DNS_FAILURE || err == NSAPI_ERROR_TIMEOUT);
if (err == NSAPI_ERROR_OK) {
(*exp_ok)++;
printf("DNS: query \"%s\" => \"%s\"\n",
hosts[i], address.get_ip_address());
} else if (err == NSAPI_ERROR_DNS_FAILURE) {
(*exp_dns_failure)++;
printf("DNS: query \"%s\" => DNS failure\n", hosts[i]);
} else if (err == NSAPI_ERROR_TIMEOUT) {
(*exp_timeout)++;
printf("DNS: query \"%s\" => timeout\n", hosts[i]);
} else if (err == NSAPI_ERROR_NO_MEMORY) {
(*exp_no_mem)++;
printf("DNS: query \"%s\" => no memory\n", hosts[i]);
}
}
}
NetworkInterface *get_interface()
{
return net;
@ -143,6 +176,9 @@ Case cases[] = {
#ifdef MBED_EXTENDED_TESTS
Case("ASYNCHRONOUS_DNS_SIMULTANEOUS_REPEAT", ASYNCHRONOUS_DNS_SIMULTANEOUS_REPEAT),
#endif
Case("SYNCHRONOUS_DNS", SYNCHRONOUS_DNS),
Case("SYNCHRONOUS_DNS_MULTIPLE", SYNCHRONOUS_DNS_MULTIPLE),
Case("SYNCHRONOUS_DNS_INVALID", SYNCHRONOUS_DNS_INVALID),
};
Specification specification(test_setup, cases);

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "dns_tests.h"
using namespace utest::v1;
namespace {
int result_ok;
int result_no_mem;
int result_dns_failure;
int result_exp_timeout;
}
void SYNCHRONOUS_DNS()
{
do_gethostbyname(dns_test_hosts, 1, &result_ok, &result_no_mem, &result_dns_failure, &result_exp_timeout);
TEST_ASSERT(result_ok == 1);
TEST_ASSERT(result_no_mem == 0);
TEST_ASSERT(result_dns_failure == 0);
TEST_ASSERT(result_exp_timeout == 0);
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "dns_tests.h"
using namespace utest::v1;
namespace {
int ticker_us = 0;
}
static void test_dns_query_ticker(void)
{
ticker_us += 100;
}
void SYNCHRONOUS_DNS_CACHE()
{
rtos::Semaphore semaphore;
Ticker ticker;
ticker.attach_us(&test_dns_query_ticker, 100);
for (unsigned int i = 0; i < 5; i++) {
SocketAddress address;
int started_us = ticker_us;
nsapi_error_t err = get_interface()->gethostbyname(dns_test_hosts_second[0], &address);
int delay_ms = (ticker_us - started_us) / 1000;
static int delay_first = delay_ms / 2;
// Check that cached accesses are at least twice as fast as the first one
TEST_ASSERT_TRUE(i == 0 || delay_ms <= delay_first);
printf("DNS: query \"%s\" => \"%s\", time %i ms\n",
dns_test_hosts_second[0], address.get_ip_address(), delay_ms);
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "dns_tests.h"
using namespace utest::v1;
namespace {
int result_ok;
int result_no_mem;
int result_dns_failure;
int result_exp_timeout;
}
void SYNCHRONOUS_DNS_INVALID()
{
//Ensure that there are no addressess in cache
do_gethostbyname(dns_test_hosts_second, MBED_CONF_NSAPI_DNS_CACHE_SIZE, &result_ok, &result_no_mem, &result_dns_failure, &result_exp_timeout);
char dns_test_hosts_new[MBED_CONF_APP_DNS_TEST_HOSTS_NUM][DNS_TEST_HOST_LEN];
memcpy(dns_test_hosts_new, dns_test_hosts, sizeof(dns_test_hosts_new));
int expected_failures = 0;
int expected_successes = 0;
for (int i = 0; i < MBED_CONF_APP_DNS_TEST_HOSTS_NUM; i++) {
if ((i % 2) == 0) {
expected_failures++;
strcat(&(dns_test_hosts_new[i][0]), "_invalid");
} else {
expected_successes++;
}
}
do_gethostbyname(dns_test_hosts_new, MBED_CONF_APP_DNS_TEST_HOSTS_NUM, &result_ok, &result_no_mem, &result_dns_failure, &result_exp_timeout);
TEST_ASSERT(result_ok == expected_successes);
TEST_ASSERT(result_no_mem == 0);
TEST_ASSERT(result_dns_failure == expected_failures);
TEST_ASSERT(result_exp_timeout == 0);
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "dns_tests.h"
using namespace utest::v1;
namespace {
int result_ok;
int result_no_mem;
int result_dns_failure;
int result_exp_timeout;
}
void SYNCHRONOUS_DNS_MULTIPLE()
{
do_gethostbyname(dns_test_hosts, MBED_CONF_APP_DNS_TEST_HOSTS_NUM, &result_ok, &result_no_mem, &result_dns_failure, &result_exp_timeout);
TEST_ASSERT(result_ok == MBED_CONF_APP_DNS_TEST_HOSTS_NUM);
TEST_ASSERT(result_no_mem == 0);
TEST_ASSERT(result_dns_failure == 0);
TEST_ASSERT(result_exp_timeout == 0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

View File

@ -30,8 +30,8 @@ nsapi_error_t tcpsocket_connect_to_discard_srv(TCPSocket &sock);
int split2half_rmng_tcp_test_time(); // [s]
namespace tcp_global {
static const int TESTS_TIMEOUT = 480;
static const int TCP_OS_STACK_SIZE = 1024;
static const int TESTS_TIMEOUT = 960;
static const int TCP_OS_STACK_SIZE = 2048;
static const int RX_BUFF_SIZE = 1220;
static const int TX_BUFF_SIZE = 1220;

View File

@ -29,7 +29,7 @@ static const int SIGNAL_SIGIO1 = 0x1;
static const int SIGNAL_SIGIO2 = 0x2;
static const int SIGIO_TIMEOUT = 5000; //[ms]
Thread thread;
Thread thread(osPriorityNormal, tcp_global::TCP_OS_STACK_SIZE);
volatile bool running = true;
}
@ -50,8 +50,8 @@ static void check_const_len_rand_sequence()
sock.sigio(callback(_sigio_handler1, Thread::gettid()));
static const int BUFF_SIZE = 10;
char rx_buff[BUFF_SIZE] = {0};
char tx_buff[BUFF_SIZE] = {0};
static char rx_buff[BUFF_SIZE] = {0};
static char tx_buff[BUFF_SIZE] = {0};
int bytes2process;
@ -107,8 +107,8 @@ static void check_var_len_rand_sequence()
sock.sigio(callback(_sigio_handler2, Thread::gettid()));
static const int BUFF_SIZE = 1001;
char rx_buff[BUFF_SIZE];
char tx_buff[BUFF_SIZE];
static char rx_buff[BUFF_SIZE];
static char tx_buff[BUFF_SIZE];
static const int pkt_size_diff = 100;
int bytes2process;

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

View File

@ -65,7 +65,7 @@ void test_emac_initialize()
#endif
// Power up the interface and emac driver
network_interface->connect();
TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, network_interface->connect());
worker_loop_link_up_wait();
}

View File

@ -53,7 +53,7 @@ using namespace utest::v1;
utest::v1::status_t test_setup(const size_t number_of_cases)
{
#if !MBED_CONF_APP_ECHO_SERVER
GREENTEA_SETUP(600, "default_auto");
GREENTEA_SETUP(1200, "default_auto");
#endif
return verbose_test_setup_handler(number_of_cases);
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define WIFI 2
#if !defined(MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE) || \
(MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE == WIFI && !defined(MBED_CONF_NSAPI_DEFAULT_WIFI_SSID))
#error [NOT_SUPPORTED] No network configuration found for this target.
#endif
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"
#include "utest/utest_stack_trace.h"
#include "networkinterface_tests.h"
using namespace utest::v1;
// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(480, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("NETWORKINTERFACE_STATUS", NETWORKINTERFACE_STATUS),
Case("NETWORKINTERFACE_STATUS_NONBLOCK", NETWORKINTERFACE_STATUS_NONBLOCK),
Case("NETWORKINTERFACE_STATUS_GET", NETWORKINTERFACE_STATUS_GET),
Case("NETWORKINTERFACE_CONN_DISC_REPEAT", NETWORKINTERFACE_CONN_DISC_REPEAT),
};
Specification specification(test_setup, cases);
int main()
{
return !Harness::run(specification);
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "networkinterface_tests.h"
#include "unity/unity.h"
#include "utest.h"
using namespace utest::v1;
namespace
{
NetworkInterface* net;
const int repeats = 5;
}
void NETWORKINTERFACE_CONN_DISC_REPEAT()
{
net = NetworkInterface::get_default_instance();
for (int i = 0; i < repeats; i++) {
nsapi_error_t err = net->connect();
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err);
err = net->disconnect();
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err);
}
}

View File

@ -0,0 +1,160 @@
/*
* Copyright (c) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "networkinterface_tests.h"
#include "unity/unity.h"
#include "utest.h"
using namespace utest::v1;
namespace
{
NetworkInterface* net;
rtos::Semaphore status_semaphore;
int status_write_counter = 0;
int status_read_counter = 0;
const int repeats = 5;
const int status_buffer_size = 100;
nsapi_connection_status_t current_status = NSAPI_STATUS_ERROR_UNSUPPORTED;
nsapi_connection_status_t statuses[status_buffer_size];
}
void status_cb(nsapi_event_t event, intptr_t value)
{
TEST_ASSERT_EQUAL(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, event);
statuses[status_write_counter] = static_cast<nsapi_connection_status_t>(value);
status_write_counter++;
if (status_write_counter >= status_buffer_size) {
TEST_ASSERT(0);
}
status_semaphore.release();
}
nsapi_connection_status_t wait_status_callback()
{
nsapi_connection_status_t status;
while (true) {
status_semaphore.wait();
status = statuses[status_read_counter];
status_read_counter++;
if (status != current_status) {
current_status = status;
return status;
}
}
}
void NETWORKINTERFACE_STATUS()
{
nsapi_connection_status_t status;
status_write_counter = 0;
status_read_counter = 0;
current_status = NSAPI_STATUS_ERROR_UNSUPPORTED;
net = NetworkInterface::get_default_instance();
net->attach(status_cb);
net->set_blocking(true);
for (int i = 0; i < repeats; i++) {
nsapi_error_t err = net->connect();
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err);
status = wait_status_callback();
TEST_ASSERT_EQUAL(NSAPI_STATUS_CONNECTING, status);
status = wait_status_callback();
if (status == NSAPI_STATUS_LOCAL_UP) {
status = wait_status_callback();
}
TEST_ASSERT_EQUAL(NSAPI_STATUS_GLOBAL_UP, status);
net->disconnect();
status = wait_status_callback();
TEST_ASSERT_EQUAL(NSAPI_STATUS_DISCONNECTED, status);
}
net->attach(NULL);
}
void NETWORKINTERFACE_STATUS_NONBLOCK()
{
nsapi_connection_status_t status;
status_write_counter = 0;
status_read_counter = 0;
current_status = NSAPI_STATUS_ERROR_UNSUPPORTED;
net = NetworkInterface::get_default_instance();
net->attach(status_cb);
net->set_blocking(false);
for (int i = 0; i < repeats; i++) {
nsapi_error_t err = net->connect();
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err);
status = wait_status_callback();
TEST_ASSERT_EQUAL(NSAPI_STATUS_CONNECTING, status);
status = wait_status_callback();
if (status == NSAPI_STATUS_LOCAL_UP) {
status = wait_status_callback();
}
TEST_ASSERT_EQUAL(NSAPI_STATUS_GLOBAL_UP, status);
net->disconnect();
status = wait_status_callback();
TEST_ASSERT_EQUAL(NSAPI_STATUS_DISCONNECTED, status);
}
net->attach(NULL);
net->set_blocking(true);
}
void NETWORKINTERFACE_STATUS_GET()
{
nsapi_connection_status_t status;
net = NetworkInterface::get_default_instance();
net->set_blocking(true);
TEST_ASSERT_EQUAL(NSAPI_STATUS_DISCONNECTED, net->get_connection_status());
for (int i = 0; i < repeats; i++) {
nsapi_error_t err = net->connect();
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, err);
while (net->get_connection_status() != NSAPI_STATUS_GLOBAL_UP) {
wait(0.5);
}
net->disconnect();
TEST_ASSERT_EQUAL(NSAPI_STATUS_DISCONNECTED, net->get_connection_status());
}
net->attach(NULL);
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NETWORKINTERFACE_TESTS_H
#define NETWORKINTERFACE_TESTS_H
/*
* Test cases
*/
void NETWORKINTERFACE_STATUS();
void NETWORKINTERFACE_STATUS_NONBLOCK();
void NETWORKINTERFACE_STATUS_GET();
void NETWORKINTERFACE_CONN_DISC_REPEAT();
#endif //NETWORKINTERFACE_TESTS_H

499
TESTS/nfc/eeprom/main.cpp Normal file
View File

@ -0,0 +1,499 @@
/*
* Copyright (c) 2017, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include <events/mbed_events.h>
#include "NFCEEPROMDriver.h"
#if !MBED_CONF_NFCEEPROM
#error [NOT_SUPPORTED] NFC EEPROM not supported for this target
#endif
using namespace utest::v1;
using namespace mbed::nfc;
/* individual steps that map to specific operations that include parameters */
typedef enum {
START_SESSION = 0x0000,
END_SESSION = 0x0100,
READ_BYTES = 0x0200,
READ_2_BYTES = 0x0201,
READ_2_BYTES_OFFSET_FAIL = 0x0202,
READ_4_BYTES = 0x0203,
READ_4_BYTES_MIXED = 0x0204,
READ_4_BYTES_OFFSET = 0x0205,
READ_4_BYTES_ERASED = 0x0206,
READ_4_BYTES_FAIL = 0x0207,
WRITE_BYTES = 0x0300,
WRITE_2_BYTES = 0x0301,
WRITE_2_BYTES_OFFSET = 0x0302,
WRITE_2_BYTES_OFFSET_FAIL = 0x0303,
WRITE_4_BYTES = 0x0304,
WRITE_4_BYTES_FAIL = 0x0305,
ERASE_BYTES = 0x0400,
ERASE_4_BYTES = 0x0401,
READ_SIZE = 0x0500,
READ_SIZE_2 = 0x0501,
READ_SIZE_4 = 0x0502,
WRITE_SIZE = 0x0600,
WRITE_SIZE_2 = 0x0601,
WRITE_SIZE_4 = 0x0602,
TERMINATE = 0xFF00
} TestCommand_t;
/* We group the command based on their fist byte to simplify step checking.
* Individual conditions of a step are checked in the event so this doesn't
* sacrifice any correctness checking */
const size_t TEST_COMMAND_GROUP_MASK = 0xFF00;
/* test case sequences that index into the array of commands which comprise them */
typedef enum {
SESSION_TEST,
WRITE_READ_TEST,
ERASE_TEST,
WRITE_READ_SIZE_TEST,
TRUNCATE_TEST,
WRITE_TRUNCATE_TEST,
WRITE_WITH_OFFSET_TEST,
WRITE_BEYOND_SIZE_TEST,
SEQUENCE_MAX
} TestSequence_t;
static EventQueue event_queue(/* event count */ 10 * EVENTS_EVENT_SIZE);
static const size_t MAX_STEP = 10;
static const size_t BUFFER_MAX = 10;
/* defines the "script" the test follows, each step is checked and all
* have to execute to completion for a successful run */
static const TestCommand_t SEQUENCES[SEQUENCE_MAX][MAX_STEP] = {
/* SESSION_TEST */
{ START_SESSION, END_SESSION, TERMINATE },
/* WRITE_READ_TEST */
{
START_SESSION, WRITE_SIZE_4, READ_SIZE_4, WRITE_4_BYTES, READ_4_BYTES,
WRITE_2_BYTES, READ_4_BYTES_MIXED, END_SESSION, TERMINATE
},
/* ERASE_TEST */
{
START_SESSION, WRITE_SIZE_4, READ_SIZE_4, WRITE_4_BYTES, READ_4_BYTES,
ERASE_4_BYTES, READ_4_BYTES_ERASED, END_SESSION, TERMINATE
},
/* WRITE_READ_SIZE_TEST */
{
START_SESSION, WRITE_SIZE_2, READ_SIZE_2, WRITE_SIZE_4, READ_SIZE_4,
END_SESSION, TERMINATE
},
/* TRUNCATE_TEST */
{
START_SESSION, WRITE_SIZE_4, READ_SIZE_4, WRITE_4_BYTES, READ_4_BYTES,
WRITE_SIZE_2, READ_SIZE_2, READ_4_BYTES_FAIL, END_SESSION, TERMINATE
},
/* WRITE_TRUNCATE_TEST */
{
START_SESSION, WRITE_SIZE_2, READ_SIZE_2, WRITE_4_BYTES_FAIL, READ_4_BYTES_FAIL,
END_SESSION, TERMINATE
},
/* WRITE_WITH_OFFSET_TEST */
{
START_SESSION, WRITE_SIZE_4, READ_SIZE_4, WRITE_4_BYTES, READ_4_BYTES,
WRITE_2_BYTES_OFFSET, READ_4_BYTES_OFFSET, END_SESSION, TERMINATE
},
/* WRITE_BEYOND_SIZE_TEST */
{
START_SESSION, WRITE_SIZE_2, READ_SIZE_2, WRITE_2_BYTES_OFFSET_FAIL, READ_2_BYTES_OFFSET_FAIL,
WRITE_2_BYTES, READ_2_BYTES, END_SESSION, TERMINATE
}
};
static const uint8_t DATA_4_BYTES[] = { 0x01, 0x02, 0x03, 0x04 };
static const uint8_t DATA_2_BYTES[] = { 0x05, 0x06 };
static const uint8_t DATA_4_BYTES_MIXED[] = { 0x05, 0x06, 0x03, 0x04 };
static const uint8_t DATA_4_BYTES_OFFSET[] = { 0x01, 0x02, 0x05, 0x06 };
static const uint8_t DATA_4_BYTES_ERASED[] = { 0x00, 0x00, 0x00, 0x00 };
class DriverTest : public NFCEEPROMDriver::Delegate {
public:
DriverTest(NFCEEPROMDriver *_driver)
: _operation_data(NULL),
_driver(_driver),
_sequence(SEQUENCE_MAX),
_step(0),
_result_size(0),
_address(0),
_success(true) { };
virtual ~DriverTest() { };
/* Delegate events */
virtual void on_session_started(bool success)
{
if (success != _success) {
TEST_FAIL_MESSAGE("failed to start session");
}
evaluate_step(START_SESSION);
};
virtual void on_session_ended(bool success)
{
if (success != _success) {
TEST_FAIL_MESSAGE("failed to end session");
}
evaluate_step(END_SESSION);
};
virtual void on_bytes_read(size_t count)
{
if (count != _result_size) {
TEST_FAIL_MESSAGE("failed to read bytes");
}
if (memcmp(_buffer, _operation_data, count) != 0) {
TEST_FAIL_MESSAGE("read bytes are different than expected");
}
evaluate_step(READ_BYTES);
};
virtual void on_bytes_written(size_t count)
{
if (count != _result_size) {
TEST_FAIL_MESSAGE("failed to write bytes");
}
evaluate_step(WRITE_BYTES);
};
virtual void on_size_written(bool success)
{
if (success != _success) {
TEST_FAIL_MESSAGE("failed to write size");
}
evaluate_step(WRITE_SIZE);
};
virtual void on_size_read(bool success, size_t size)
{
if (success != _success || size != _result_size) {
TEST_FAIL_MESSAGE("failed to read size");
}
evaluate_step(READ_SIZE);
};
virtual void on_bytes_erased(size_t count)
{
if (count != _result_size) {
TEST_FAIL_MESSAGE("failed to erase bytes");
}
evaluate_step(ERASE_BYTES);
}
/* Sequence running code */
void run_sequence(TestSequence_t sequence)
{
_sequence = sequence;
if (_sequence >= SEQUENCE_MAX) {
TEST_FAIL_MESSAGE("internal test failure - invalid command");
}
execute_next_step();
event_queue.dispatch_forever();
TEST_ASSERT_EQUAL(TERMINATE, SEQUENCES[_sequence][_step]);
}
void execute_next_step()
{
TestCommand_t command = SEQUENCES[_sequence][_step];
/* setup data buffer */
switch (command) {
case READ_2_BYTES:
case READ_2_BYTES_OFFSET_FAIL:
case WRITE_2_BYTES:
case WRITE_2_BYTES_OFFSET:
case WRITE_2_BYTES_OFFSET_FAIL:
_operation_data = DATA_2_BYTES;
break;
case READ_4_BYTES:
case READ_4_BYTES_FAIL:
case WRITE_4_BYTES:
case WRITE_4_BYTES_FAIL:
_operation_data = DATA_4_BYTES;
break;
case READ_4_BYTES_ERASED:
_operation_data = DATA_4_BYTES_ERASED;
break;
case READ_4_BYTES_MIXED:
_operation_data = DATA_4_BYTES_MIXED;
break;
case READ_4_BYTES_OFFSET:
_operation_data = DATA_4_BYTES_OFFSET;
break;
default:
_operation_data = NULL;
}
/* setup result size */
switch (command) {
case READ_2_BYTES:
case READ_4_BYTES_FAIL:
case WRITE_2_BYTES:
case WRITE_4_BYTES_FAIL:
case WRITE_2_BYTES_OFFSET:
case READ_SIZE_2:
_result_size = 2;
break;
case READ_4_BYTES:
case READ_4_BYTES_ERASED:
case READ_4_BYTES_MIXED:
case READ_4_BYTES_OFFSET:
case WRITE_4_BYTES:
case ERASE_4_BYTES:
case READ_SIZE_4:
_result_size = 4;
break;
default:
_result_size = 0;
}
/* setup operation size */
switch (command) {
case READ_2_BYTES:
case READ_2_BYTES_OFFSET_FAIL:
case WRITE_2_BYTES:
case WRITE_2_BYTES_OFFSET:
case WRITE_2_BYTES_OFFSET_FAIL:
case WRITE_SIZE_2:
_operation_size = 2;
break;
case READ_4_BYTES:
case READ_4_BYTES_ERASED:
case READ_4_BYTES_MIXED:
case READ_4_BYTES_OFFSET:
case READ_4_BYTES_FAIL:
case WRITE_4_BYTES:
case WRITE_4_BYTES_FAIL:
case ERASE_4_BYTES:
case READ_SIZE_4:
case WRITE_SIZE_4:
_operation_size = 4;
break;
default:
_operation_size = 0;
}
/* setup offset */
switch (command) {
case READ_2_BYTES_OFFSET_FAIL:
case WRITE_2_BYTES_OFFSET:
case WRITE_2_BYTES_OFFSET_FAIL:
_address = 2;
break;
default:
_address = 0;
}
/* setup command success */
switch (command) {
case READ_2_BYTES_OFFSET_FAIL:
case WRITE_2_BYTES_OFFSET_FAIL:
_success = false;
break;
default:
_success = true;
}
/* call next command */
switch (command & TEST_COMMAND_GROUP_MASK) {
case START_SESSION:
_driver->start_session(true);
break;
case END_SESSION:
_driver->end_session();
break;
case READ_BYTES:
_driver->read_bytes(_address, _buffer, _operation_size);
break;
case WRITE_BYTES:
_driver->write_bytes(_address, _operation_data, _operation_size);
break;
case ERASE_BYTES:
_driver->erase_bytes(_address, 4);
break;
case READ_SIZE:
_driver->read_size();
break;
case WRITE_SIZE:
_driver->write_size(_operation_size);
break;
case TERMINATE:
event_queue.break_dispatch();
break;
default:
TEST_FAIL_MESSAGE("internal test failure - invalid command");
}
}
void evaluate_step(TestCommand_t command_completed)
{
/* check last command succeeded */
TEST_ASSERT_EQUAL(command_completed, SEQUENCES[_sequence][_step]&TEST_COMMAND_GROUP_MASK);
_step++;
if (_step == MAX_STEP) {
TEST_FAIL_MESSAGE("internal test failure - too many steps");
}
execute_next_step();
}
private:
uint8_t _buffer[BUFFER_MAX];
const uint8_t *_operation_data;
NFCEEPROMDriver *_driver;
TestSequence_t _sequence;
size_t _step;
size_t _result_size;
size_t _operation_size;
size_t _address;
bool _success;
};
/* test case running code */
static DriverTest *driver_test;
extern NFCEEPROMDriver *greentea_nfc_EEPROM_driver_get_instance();
utest::v1::status_t test_setup(const Case *const source, const size_t index_of_case)
{
NFCEEPROMDriver *driver = greentea_nfc_EEPROM_driver_get_instance();
driver_test = new DriverTest(driver);
driver->set_event_queue(&event_queue);
driver->set_delegate(driver_test);
driver->reset();
TEST_ASSERT_NOT_EQUAL(0, driver->read_max_size());
return greentea_case_setup_handler(source, index_of_case);
}
void session()
{
driver_test->run_sequence(SESSION_TEST);
}
void write_read()
{
driver_test->run_sequence(WRITE_READ_TEST);
}
void erase_bytes()
{
driver_test->run_sequence(ERASE_TEST);
}
void write_read_size()
{
driver_test->run_sequence(WRITE_READ_SIZE_TEST);
}
void truncate_size()
{
driver_test->run_sequence(TRUNCATE_TEST);
}
void write_bytes_truncated()
{
driver_test->run_sequence(WRITE_TRUNCATE_TEST);
}
void write_with_offset()
{
driver_test->run_sequence(WRITE_WITH_OFFSET_TEST);
}
void write_beyond_size()
{
driver_test->run_sequence(WRITE_BEYOND_SIZE_TEST);
}
utest::v1::status_t test_tear_down(const Case *const source, const size_t passed,
const size_t failed, const failure_t reason)
{
delete driver_test;
return greentea_case_teardown_handler(source, passed, failed, reason);
}
/* test setup */
utest::v1::status_t test_init(const size_t number_of_cases)
{
GREENTEA_SETUP(10, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
// Test cases
Case cases[] = {
Case("NFCEEPROM-SESSION", test_setup, session, test_tear_down),
Case("NFCEEPROM-WRITE-READ", test_setup, write_read, test_tear_down),
Case("NFCEEPROM-ERASE-BYTES", test_setup, erase_bytes, test_tear_down),
Case("NFCEEPROM-WRITE-READ-SIZE", test_setup, write_read_size, test_tear_down),
Case("NFCEEPROM-TRUNCATE-SIZE", test_setup, truncate_size, test_tear_down),
Case("NFCEEPROM-WRITE-BYTES-TRUNCATED", test_setup, write_bytes_truncated, test_tear_down),
Case("NFCEEPROM-WRITE-WITH-OFFSET", test_setup, write_with_offset, test_tear_down),
Case("NFCEEPROM-WRITE-BEYOND-SIZE", test_setup, write_beyond_size, test_tear_down)
};
Specification specification(test_init, cases);
// Entry point into the tests
int main()
{
return !Harness::run(specification);
}

0
TEST_APPS/__init__.py Normal file
View File

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdarg.h>
#include "mbed.h"
#include "mbed-client-cli/ns_cmdline.h"
#ifndef ICETEA_EXAMPLE_ENABLED
#error [NOT_SUPPORTED] Skipping example application.
#endif
/**
* Macros for setting console flow control.
*/
#define CONSOLE_FLOWCONTROL_RTS 1
#define CONSOLE_FLOWCONTROL_CTS 2
#define CONSOLE_FLOWCONTROL_RTSCTS 3
#define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x
#define mbed_console_concat(x) mbed_console_concat_(x)
#define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL)
#define SERIAL_CONSOLE_BAUD_RATE 115200
void cmd_ready_cb(int retcode)
{
cmd_next(retcode);
}
void wrap_printf(const char *f, va_list a)
{
vprintf(f, a);
}
int main()
{
cmd_init(&wrap_printf);
int c;
while ((c = getchar()) != EOF) {
cmd_char_input(c);
}
return 0;
}
FileHandle *mbed::mbed_override_console(int)
{
static UARTSerial console(STDIO_UART_TX, STDIO_UART_RX, SERIAL_CONSOLE_BAUD_RATE);
#if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
console.set_flow_control(SerialBase::RTS, STDIO_UART_RTS, NC);
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
console.set_flow_control(SerialBase::CTS, NC, STDIO_UART_CTS);
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
console.set_flow_control(SerialBase::RTSCTS, STDIO_UART_RTS, STDIO_UART_CTS);
#endif
return &console;
}

View File

@ -0,0 +1,88 @@
# Nanostack MAC test application
You can use this application to test the Nanostack RF driver implementations that follow the [Nanostack RF driver porting instructions](https://os.mbed.com/docs/v5.6/reference/contributing-connectivity.html#porting-new-rf-driver-for-6lowpan-stack). The application has a command-line interface that is used to send commands to Nanostack's MAC layer, for example starting PANs, scanning or sending data. The provided tests do not test performance or stability and only indirectly test RF functionalities.
## Table of contents
* [Prerequisites](#prerequisites)
* [Setting up the application](#setting-up-the-application)
* [Application usage](#application-usage)
* [Interactive mode](#interactive-mode)
* [Automated mode](#automated-mode)
* [Testcases](#testcases)
* [Considerations](#considerations)
## Prerequisites
* [Mbed CLI](https://github.com/ARMmbed/mbed-cli).
* Mbed OS target board with build in radio, OR RF shield with Mbed OS driver
## Setting up the application
### Add your RF driver
When using RF shield, you need to configure it to be a default RF driver and instruct Mbed OS that RF driver is present. For example, configuring Atmel RF driver to provide default driver:
```
"target_overrides": {
"*": {
"target.device_has_add": ["802_15_4_RF_PHY"],
"atmel-rf.provide-default": true
```
### Checking platform support
Check that your choice of platform is supported by your choice of toolchain:
```
mbed compile --supported
```
<span class="notes">**Note:** Targets are often abbreviated from the full model names. In the case of `FRDM-K64F` the target is `K64F`.</span>
## Run tests
You can use this application in interactive or automated mode.
### Interactive mode
To set the application to interactive mode:
1. Build the application.
```
mbed test --compile --icetea -t TOOLCHAIN -m TARGET_PLATFORM -DICETEA_MAC_TESTER_ENABLED --test-config NANOSTACK_MAC_TESTER -n address_read_and_write,send_data,send_data_indirect,send_large_payloads,create_and_join_PAN,ED_scan
```
2. Connect your board and copy the compiled application binary from the `BUILD/tests/TARGET_PLATFORM/TOOLCHAIN/TEST_APPS/device/nanostack_mac_tester/` folder to the board.
3. Wait for the device to flash the binary.
4. Open a serial connection with a program such as PuTTY, screen or minicom. The default baudrate is 115200.
5. Press the reset button on the board. The Arm Mbed logo and trace appears in the terminal window.
If the driver registration and SW MAC creation was successful, the application is ready to receive commands.
To start off, type `help` to list all commands available and furthermore `help <command>` to print detailed information about a specific command.
### Automated mode
```
mbed test --clean --compile --run --icetea -t TOOLCHAIN -m TARGET_PLATFORM -DICETEA_MAC_TESTER_ENABLED --test-config NANOSTACK_MAC_TESTER -n address_read_and_write,send_data,send_data_indirect,send_large_payloads,create_and_join_PAN,ED_scan
```
Many of the provided testcases have a `self.channel` variable in the `setUp()` function for setting the RF channel. The default channel is 11. If you wish to run a test on another channel, you will need to change it manually in TEST_APPS/testcases/nanostack_mac_tester/.
Some testcases also use a secondary channel for transmitting and will use the next higher channel for that purpose. If the given channel is 26, the secondary channel will default to 25.
### Test cases
The automated test set runs the following testcases included in the repository under `TEST_APPS/testcases/nanostack_mac_tester/`.
* Create and join PAN
* Direct data transmission(Transmission between two devices)
* Indirect data transmission(Transmission between two devices with one device acting as intermediary)
* ED scan(Energy Density scanning)
* Address read and write
* Large data transmission
### Considerations
* Devices need to be power cycled if they are unresponsive to test framework commands even after resetting.
* Devices can be enclosed in an RF isolation box to improve the consistency of test results.
* Some boards and radio modules come with a PCB trace antenna, instead of an SMD antenna, and need to be spaced further apart to decrease interference.

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "rtos.h"
#include "sw_mac.h"
#include "ns_hal_init.h"
#define MBED_CMDLINE_MAX_LINE_LENGTH 250
#include "ns_cmdline.h"
#include "mac_commands.h"
#define HEAP_FOR_MAC_TESTER_SIZE 10000
#define RX_BUFFER_SIZE 512
#define ATMEL 1
#define MCR20 2
#define OTHER 3
#define TRACE_GROUP "Main"
#include "mbed-trace/mbed_trace.h"
#include "NanostackRfPhy.h"
#if !DEVICE_802_15_4_PHY
#error [NOT_SUPPORTED] No 802.15.4 RF driver found for this target
#endif
#ifndef ICETEA_MAC_TESTER_ENABLED
#error [NOT_SUPPORTED] Skipping Nanostack MAC tester application.
#endif
extern mac_api_s *mac_interface;
RawSerial pc(USBTX, USBRX);
osThreadId main_thread;
static CircularBuffer<uint8_t, RX_BUFFER_SIZE> rx_buffer;
static uint8_t ns_heap[HEAP_FOR_MAC_TESTER_SIZE];
static void app_heap_error_handler(heap_fail_t event)
{
tr_error("Heap error (%d), app_heap_error_handler()", event);
switch (event) {
case NS_DYN_MEM_NULL_FREE:
case NS_DYN_MEM_DOUBLE_FREE:
case NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID:
case NS_DYN_MEM_POINTER_NOT_VALID:
case NS_DYN_MEM_HEAP_SECTOR_CORRUPTED:
case NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED:
break;
default:
break;
}
while (1);
}
static void rx_interrupt(void)
{
uint8_t c = pc.getc();
rx_buffer.push(c);
if (main_thread != NULL) {
osSignalSet(main_thread, 1);
}
}
static void handle_rx_data(void)
{
bool exit = false;
uint8_t data;
while (1) {
exit = !rx_buffer.pop(data);
if (exit) {
break;
}
cmd_char_input(data);
}
}
static int mac_prepare(void)
{
NanostackRfPhy &rf_phy = NanostackRfPhy::get_default_instance();
int8_t rf_driver_id = rf_phy.rf_register();
uint8_t rf_eui64[8];
if (rf_driver_id < 0) {
tr_error("Failed to register RF driver.");
return -1;
}
rf_phy.get_mac_address(rf_eui64);
mac_description_storage_size_t mac_description;
mac_description.device_decription_table_size = DEVICE_DESCRIPTOR_TABLE_SIZE; /** MAC Device description list size */
mac_description.key_description_table_size = KEY_DESCRIPTOR_TABLE_SIZE; /** MAC Key description list size */
mac_description.key_lookup_size = LOOKUP_DESCRIPTOR_TABLE_SIZE; /** Key description key lookup list size */
mac_description.key_usage_size = USAGE_DESCRIPTOR_TABLE_SIZE; /** Key description key usage list size */
tr_info("Registered RF driver with id: %hhu, EUI64: %s", rf_driver_id, mbed_trace_array(rf_eui64, 8));
mac_interface = ns_sw_mac_create(rf_driver_id, &mac_description);
if (!mac_interface) {
tr_error("Failed to create SW MAC.");
return -2;
}
return mac_interface->mac_initialize(mac_interface, mac_data_confirm_handler,
mac_data_indication_handler, mac_purge_confirm_handler, mac_mlme_confirm_handler,
mac_mlme_indication_handler, rf_driver_id);
}
static void cmd_ready_cb(int retcode)
{
cmd_next(retcode);
}
static void trace_printer(const char *str)
{
printf("%s\n", str);
cmd_output();
fflush(stdout);
}
int main(void)
{
main_thread = osThreadGetId();
pc.baud(MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
pc.attach(rx_interrupt);
ns_hal_init(ns_heap, HEAP_FOR_MAC_TESTER_SIZE, app_heap_error_handler, NULL);
mbed_trace_init();
mbed_trace_print_function_set(trace_printer);
cmd_init(&default_cmd_response_out);
cmd_set_ready_cb(cmd_ready_cb);
mac_commands_init();
if (mac_prepare() != 0) {
return -1;
}
tr_info("Created driver & SW MAC");
while (true) {
osEvent os_event = Thread::signal_wait(1);
if (os_event.status != osEventSignal) {
osThreadYield();
} else {
handle_rx_data();
}
}
return 0;
}

View File

@ -0,0 +1,16 @@
{
"macros": ["MBED_TRACE_LINE_LENGTH=200", "OS_TASKCNT=4", "OS_IDLESTKSIZE=32"],
"target_overrides": {
"*": {
"nanostack.configuration": "lowpan_host",
"platform.stdio-convert-newlines": true,
"platform.stdio-baud-rate": 115200,
"mbed-mesh-api.heap-size": 6000,
"nanostack-hal.event_loop_thread_stack_size": 2000,
"mbed-trace.enable": true,
"nsapi.default-stack": "LWIP",
"target.device_has_add": ["802_15_4_PHY"],
"atmel-rf.provide-default": true
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MAC_COMMANDS_H_
#define MAC_COMMANDS_H_
#include <cstring>
#include <cstdlib>
#include "ns_cmdline.h"
#include "nsdynmemLIB.h"
#include "mbed_trace.h"
#include "mac_api.h"
#include "mlme.h"
#include "mac_mcps.h"
#include "mac_common_defines.h"
#include "mac_filter_api.h"
#include "util.h"
#define LOOKUP_DESCRIPTOR_TABLE_SIZE 2
#define DEVICE_DESCRIPTOR_TABLE_SIZE 2
#define USAGE_DESCRIPTOR_TABLE_SIZE 2
#define KEY_DESCRIPTOR_TABLE_SIZE 2
void mac_commands_init(void);
void mac_data_confirm_handler(const mac_api_t *api, const mcps_data_conf_t *data);
void mac_data_indication_handler(const mac_api_t *api, const mcps_data_ind_t *data);
void mac_purge_confirm_handler(const mac_api_t *api, mcps_purge_conf_t *data);
void mac_mlme_confirm_handler(const mac_api_t *api, mlme_primitive id, const void *data);
void mac_mlme_indication_handler(const mac_api_t *api, mlme_primitive id, const void *data);
int mac_start_command(int argc, char *argv[]);
int mac_scan_command(int argc, char *argv[]);
int mac_data_command(int argc, char *argv[]);
int mac_poll_command(int argc, char *argv[]);
int mac_purge_command(int argc, char *argv[]);
int mac_set_command(int argc, char *argv[]);
int mac_get_command(int argc, char *argv[]);
int mac_reset_command(int argc, char *argv[]);
int mac_address_command(int argc, char *argv[]);
int mac_key_command(int argc, char *argv[]);
int mac_add_neighbour_command(int argc, char *argv[]);
int mac_filter_command(int argc, char *argv[]);
int mac_config_status_command(int argc, char *argv[]);
int mac_find_beacon_command(int argc, char *argv[]);
int mac_wait_command(int argc, char *argv[]);
int mac_analyze_ed_command(int argc, char *argv[]);
int reset_command(int argc, char *argv[]);
int silent_mode_command(int argc, char *argv[]);
#endif

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "util.h"
int string_to_bytes(const char *str, uint8_t *buf, int bytes)
{
int len = strlen(str);
if (len <= (3 * bytes - 1)) {
int i;
for (i = 0; i < bytes; ++i) {
if (i * 3 < len) {
buf[i] = (uint8_t)strtoul(str + i * 3, NULL, 16);
} else {
buf[i] = 0;
}
}
return 0;
}
return -1;
}
const char *mlme_status_string(uint8_t status)
{
switch (status) {
case MLME_SUCCESS: return "MLME_SUCCESS";
case MLME_BUSY_CHAN: return "MLME_BUSY_CHAN";
case MLME_BUSY_RX: return "MLME_BUSY_RX";
case MLME_BUSY_TX: return "MLME_BUSY_TX";
case MLME_FORCE_TRX_OFF: return "MLME_FORCE_TRX_OFF";
case MLME_IDLE: return "MLME_IDLE";
case MLME_RX_ON: return "MLME_RX_ON";
case MLME_TRX_OFF: return "MLME_TRX_OFF";
case MLME_TX_ON: return "MLME_TX_ON";
case MLME_COUNTER_ERROR: return "MLME_COUNTER_ERROR";
case MLME_IMPROPER_KEY_TYPE: return "MLME_IMPROPER_KEY_TYPE";
case MLME_IMPROPER_SECURITY_LEVEL: return "MLME_IMPROPER_SECURITY_LEVEL";
case MLME_UNSUPPORTED_LEGACY: return "MLME_UNSUPPORTED_LEGACY";
case MLME_UNSUPPORTED_SECURITY: return "MLME_UNSUPPORTED_SECURITY";
case MLME_SECURITY_FAIL: return "MLME_SECURITY_FAIL";
case MLME_FRAME_TOO_LONG: return "MLME_FRAME_TOO_LONG";
case MLME_INVALID_HANDLE: return "MLME_INVALID_HANDLE";
case MLME_INVALID_PARAMETER: return "MLME_INVALID_PARAMETER";
case MLME_TX_NO_ACK: return "MLME_TX_NO_ACK";
case MLME_NO_BEACON: return "MLME_NO_BEACON";
case MLME_NO_DATA: return "MLME_NO_DATA";
case MLME_NO_SHORT_ADDRESS: return "MLME_NO_SHORT_ADDRESS";
case MLME_PAN_ID_CONFLICT: return "MLME_PAN_ID_CONFLICT";
case MLME_TRANSACTION_EXPIRED: return "MLME_TRANSACTION_EXPIRED";
case MLME_TRANSACTION_OVERFLOW: return "MLME_TRANSACTION_OVERFLOW";
case MLME_UNAVAILABLE_KEY: return "MLME_UNAVAILABLE_KEY";
case MLME_UNSUPPORTED_ATTRIBUTE: return "MLME_UNSUPPORTED_ATTRIBUTE";
case MLME_INVALID_ADDRESS: return "MLME_INVALID_ADDRESS";
case MLME_INVALID_INDEX: return "MLME_INVALID_INDEX";
case MLME_LIMIT_REACHED: return "MLME_LIMIT_REACHED";
case MLME_READ_ONLY: return "MLME_READ_ONLY";
case MLME_SCAN_IN_PROGRESS: return "MLME_SCAN_IN_PROGRESS";
case MLME_DATA_POLL_NOTIFICATION: return "MLME_DATA_POLL_NOTIFICATION";
default: return NULL;
}
}
int channel_from_mask(uint32_t channel_mask, int index)
{
int expected_index = 0;
for (int i = 0; i < 27; ++i) {
if ((channel_mask >> i) & 1) {
if (expected_index == index) {
return i;
}
++expected_index;
}
}
return -1;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Arm Limited and affiliates.
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -14,15 +14,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef UTIL_H_
#define UTIL_H_
#include "CppUTest/CommandLineTestRunner.h"
#include "CppUTest/TestPlugin.h"
#include "CppUTest/TestRegistry.h"
#include "CppUTestExt/MockSupportPlugin.h"
int main(int ac, char **av)
{
return CommandLineTestRunner::RunAllTests(ac, av);
}
#include <cstdlib>
#include <cstring>
IMPORT_TEST_GROUP(AT_CellularBase);
#include "mbed.h"
#include "mlme.h"
int string_to_bytes(const char *str, uint8_t *buf, int bytes);
const char *mlme_status_string(uint8_t status);
int channel_from_mask(uint32_t channel_mask, int index);
#endif

View File

@ -0,0 +1,158 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "NetworkStack.h"
#include "NetworkInterface.h"
#include "mbed-client-cli/ns_cmdline.h"
#include "mbed-trace/mbed_trace.h"
#include "ip4string.h"
#define WIFI 2
#if !defined(MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE) || \
(MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE == WIFI && !defined(MBED_CONF_NSAPI_DEFAULT_WIFI_SSID))
#error [NOT_SUPPORTED] No network configuration found for this target.
#endif
#include <string.h>
#define TRACE_GROUP "Aifc"
NetworkInterface *net;
NetworkInterface *get_interface(void)
{
return net;
}
int cmd_ifup(int argc, char *argv[]);
int cmd_ifdown(int argc, char *argv[]);
int cmd_ifconfig(int argc, char *argv[]);
const char *MAN_IFCONFIG = " ifup interface up\r\n"\
" ifdown interface down\r\n";
static void ifconfig_print()
{
if (!net) {
cmd_printf("No interface configured\r\n");
return;
}
const char *str = net->get_ip_address();
if (str) {
uint8_t buf[4];
if (stoip4(str, strlen(str), buf)) {
cmd_printf("IPv4 if addr: %s\r\n", str);
} else {
cmd_printf("IPv6 if addr:\r\n [0]: %s\r\n", str);
}
} else {
cmd_printf("No IP address\r\n");
}
str = net->get_mac_address();
if (str) {
cmd_printf("MAC-48: %s\r\n", str);
} else {
cmd_printf("MAC-48: unknown\r\n");
}
}
void cmd_ifconfig_init(void)
{
cmd_add("ifup", cmd_ifup, "ifconfig up", MAN_IFCONFIG);
cmd_add("ifdown", cmd_ifdown, "ifconfig down", MAN_IFCONFIG);
cmd_add("ifconfig", cmd_ifconfig, "ifconfig", MAN_IFCONFIG);
}
int cmd_ifconfig(int argc, char *argv[])
{
ifconfig_print();
return CMDLINE_RETCODE_SUCCESS;
}
int cmd_ifup(int argc, char *argv[])
{
if (!net) {
net = NetworkInterface::get_default_instance();
}
int err = net->connect();
if (err != NSAPI_ERROR_OK) {
return CMDLINE_RETCODE_FAIL;
}
ifconfig_print();
return CMDLINE_RETCODE_SUCCESS;
}
int cmd_ifdown(int argc, char *argv[])
{
if (!net) {
return CMDLINE_RETCODE_FAIL;
}
int err = net->disconnect();
if (err != NSAPI_ERROR_OK) {
return CMDLINE_RETCODE_FAIL;
}
return CMDLINE_RETCODE_SUCCESS;
}
const char *networkstack_error_to_str(int errorcode)
{
switch (errorcode) {
case NSAPI_ERROR_OK:
return "NSAPI_ERROR_OK";
case NSAPI_ERROR_WOULD_BLOCK:
return "NSAPI_ERROR_WOULD_BLOCK";
case NSAPI_ERROR_UNSUPPORTED:
return "NSAPI_ERROR_UNSUPPORTED";
case NSAPI_ERROR_PARAMETER:
return "NSAPI_ERROR_PARAMETER";
case NSAPI_ERROR_NO_CONNECTION:
return "NSAPI_ERROR_NO_CONNECTION";
case NSAPI_ERROR_NO_SOCKET:
return "NSAPI_ERROR_NO_SOCKET";
case NSAPI_ERROR_NO_ADDRESS:
return "NSAPI_ERROR_NO_ADDRESS";
case NSAPI_ERROR_NO_MEMORY:
return "NSAPI_ERROR_NO_MEMORY";
case NSAPI_ERROR_NO_SSID:
return "NSAPI_ERROR_NO_SSID";
case NSAPI_ERROR_DNS_FAILURE:
return "NSAPI_ERROR_DNS_FAILURE";
case NSAPI_ERROR_DHCP_FAILURE:
return "NSAPI_ERROR_DHCP_FAILURE";
case NSAPI_ERROR_AUTH_FAILURE:
return "NSAPI_ERROR_AUTH_FAILURE";
case NSAPI_ERROR_DEVICE_ERROR:
return "NSAPI_ERROR_DEVICE_ERROR";
case NSAPI_ERROR_IN_PROGRESS:
return "NSAPI_ERROR_IN_PROGRESS";
case NSAPI_ERROR_ALREADY:
return "NSAPI_ERROR_ALREADY";
case NSAPI_ERROR_IS_CONNECTED:
return "NSAPI_ERROR_IS_CONNECTED";
case NSAPI_ERROR_CONNECTION_LOST:
return "NSAPI_ERROR_CONNECTION_LOST";
case NSAPI_ERROR_CONNECTION_TIMEOUT:
return "NSAPI_ERROR_CONNECTION_TIMEOUT";
default:
return "unknown error code";
}
}

View File

@ -1,8 +1,6 @@
/*
* Copyright (c) 2013-2016 ARM Limited. All rights reserved.
*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
@ -14,25 +12,23 @@
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* -----------------------------------------------------------------------------
*
* Project: CMSIS-RTOS RTX
* Title: OS Event Observer
*
* -----------------------------------------------------------------------------
*/
#include "rt_OsEventObserver.h"
#ifndef CMD_IFCONFIG_H
#define CMD_IFCONFIG_H
const OsEventObserver *osEventObs;
#include "NetworkInterface.h"
#include "NetworkStack.h"
void osRegisterForOsEvents(const OsEventObserver *observer)
{
static uint8_t has_been_called = 0;
if (has_been_called) {
return;
}
has_been_called = 1;
/** Get a pointer to a network interface instance
*
* Allowed interface types (depend on application configurations):
* cell0, wlan0, eth0, mesh0
*
* @return pointer to the network interface, or NULL if unrecognized or ambiguous
*/
NetworkInterface *get_interface(void);
osEventObs = observer;
}
void cmd_ifconfig_init(void);
const char *networkstack_error_to_str(int errorcode);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CMD_SOCKET_H_
#define CMD_SOCKET_H_
#include "nsapi_types.h"
int handle_nsapi_error(const char *function, nsapi_error_t ret);
int handle_nsapi_size_or_error(const char *function, nsapi_size_or_error_t ret);
void cmd_socket_init(void);
#endif

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdarg.h>
#include "mbed.h"
#include "mbed-client-cli/ns_cmdline.h"
#include "cmd_ifconfig.h"
#include "cmd_socket.h"
/**
* Macros for setting console flow control.
*/
#define CONSOLE_FLOWCONTROL_RTS 1
#define CONSOLE_FLOWCONTROL_CTS 2
#define CONSOLE_FLOWCONTROL_RTSCTS 3
#define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x
#define mbed_console_concat(x) mbed_console_concat_(x)
#define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL)
#define SERIAL_CONSOLE_BAUD_RATE 115200
void cmd_ready_cb(int retcode)
{
cmd_next(retcode);
}
void wrap_printf(const char *f, va_list a)
{
vprintf(f, a);
}
int main()
{
cmd_init(&wrap_printf);
cmd_ifconfig_init();
cmd_socket_init();
int c;
while ((c = getchar()) != EOF) {
cmd_char_input(c);
}
return 0;
}
FileHandle *mbed::mbed_override_console(int)
{
static UARTSerial console(STDIO_UART_TX, STDIO_UART_RX, SERIAL_CONSOLE_BAUD_RATE);
#if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
console.set_flow_control(SerialBase::RTS, STDIO_UART_RTS, NC);
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
console.set_flow_control(SerialBase::CTS, NC, STDIO_UART_CTS);
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
console.set_flow_control(SerialBase::RTSCTS, STDIO_UART_RTS, STDIO_UART_CTS);
#endif
return &console;
}

View File

@ -0,0 +1,22 @@
{
"macros": [
"MEM_ALLOC=malloc",
"MEM_FREE=free",
"MBED_HEAP_STATS_ENABLED=1",
"MBED_MEM_TRACING_ENABLED"
],
"target_overrides": {
"*": {
"target.features_add": ["LWIP", "COMMON_PAL"],
"mbed-trace.enable": 1,
"platform.stdio-baud-rate": 115200,
"platform.stdio-convert-newlines": true,
"platform.stdio-buffered-serial": true,
"platform.stdio-flush-at-exit": true,
"drivers.uart-serial-rxbuf-size": 768
},
"UBLOX_EVK_ODIN_W2" : {
"target.device_has_remove": ["EMAC"]
}
}
}

View File

@ -0,0 +1,242 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "ip6string.h"
#include "strconv.h"
int8_t strtohex(uint8_t *out, const char *str, int8_t max_length)
{
int8_t i = 0;
char *rd = (char *)str;
uint8_t *wr = out;
while (*rd != 0) {
if (i > max_length) {
break;
}
*wr++ = strtoul(rd, &rd, 16);
while (!isxdigit((int)*rd) && *rd != 0) {
rd++; //skip some invalid characters
}
i++;
}
return i;
}
int hexstr_to_bytes_inplace(char *str)
{
int16_t len, i, j;
if (str == NULL) {
return -1;
}
len = strlen(str);
if (len < 2 || (len + 1) % 3 != 0) {
return -1;
}
for (i = 0, j = 0; i < len; i += 3, ++j) {
str[j] = (char)strtol(str + i, 0, 16);
}
return j;
}
// convert hex string (eg. "76 ab ff") to binary array
int string_to_bytes(const char *str, uint8_t *buf, int bytes)
{
int len = strlen(str);
if (len <= (3 * bytes - 1)) {
int i;
for (i = 0; i < bytes; i++) {
if (i * 3 < len) {
buf[i] = (uint8_t)strtoul(str + i * 3, 0, 16);
} else {
buf[i] = 0;
}
}
return 0;
}
return -1;
}
int16_t hextostr(const uint8_t *buf, uint16_t buf_length, char *out, int16_t out_length, char delimiter)
{
int16_t outLeft = out_length;
int16_t arrLeft = buf_length;
const uint8_t *rd = buf;
int retcode = 0;
char *wr = out;
while (arrLeft > 0 && outLeft > 0) {
retcode = snprintf(wr, outLeft, "%02x", *rd);
if (retcode <= 0 || retcode >= outLeft) {
break;
}
outLeft -= retcode;
wr += retcode;
arrLeft --;
rd++;
if (delimiter && arrLeft > 0 && outLeft > 0) {
*wr++ = delimiter;
outLeft--;
*wr = 0;
}
}
return (int16_t)(wr - out);
}
int replace_hexdata(char *str)
{
char *ptr = str;
if (str == NULL) {
return 0;
}
while (*ptr) {
if (ptr[0] == '\\') {
if (ptr[1] == 'n') {
ptr[0] = 0x0a;
memmove(ptr + 1, ptr + 2, strlen(ptr + 2) + 1);
} else if (ptr[1] == 'r') {
ptr[0] = 0x0d;
memmove(ptr + 1, ptr + 2, strlen(ptr + 2) + 1);
} else if (ptr[1] == 'x') {
char *end;
ptr[0] = (char)strtoul(ptr + 2, &end, 16);
memmove(ptr + 1, end, strlen(end) + 1);
} else if (isdigit((int)ptr[1])) {
char *end;
ptr[0] = strtoul(ptr + 1, &end, 10);
memmove(ptr + 1, end, strlen(end) + 1);
}
}
ptr++;
}
return ptr - str;
}
bool is_visible(uint8_t *buf, int len)
{
while (len--) {
if (!isalnum(*buf) && *buf != ' ') {
return false;
}
buf++;
}
return true;
}
char *strdupl(const char *str)
{
if (!str) {
return NULL;
}
char *p = malloc(strlen(str) + 1);
if (!p) {
return p;
}
strcpy(p, str);
return p;
}
int strnlen_(const char *s, int n)
{
char *end = memchr(s, 0, n);
return end ? end - s : n;
}
char *strndupl(const char *s, int n)
{
char *p = NULL;
int len = strnlen_(s, n);
p = malloc(len + 1);
if (!p) {
return p;
}
p[len] = 0;
return memcpy(p, s, len);
}
int strnicmp_(char const *a, char const *b, int n)
{
for (; (n > 0 && *a != 0 && *b != 0) ; a++, b++, n--) {
int d = tolower((int) * a) - tolower((int) * b);
if (d != 0 || !*a) {
return d;
}
}
return 0;
}
/* HELPING PRINT FUNCTIONS for cmd_printf */
static inline uint8_t context_split_mask(uint_fast8_t split_value)
{
return (uint8_t) - (0x100u >> split_value);
}
static uint8_t *bitcopy(uint8_t *restrict dst, const uint8_t *restrict src, uint_fast8_t bits)
{
uint_fast8_t bytes = bits / 8;
bits %= 8;
if (bytes) {
dst = (uint8_t *) memcpy(dst, src, bytes) + bytes;
src += bytes;
}
if (bits) {
uint_fast8_t split_bit = context_split_mask(bits);
*dst = (*src & split_bit) | (*dst & ~ split_bit);
}
return dst;
}
char tmp_print_buffer[128] = {0};
char *print_ipv6(const void *addr_ptr)
{
ip6tos(addr_ptr, tmp_print_buffer);
return tmp_print_buffer;
}
char *print_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len)
{
char *str = tmp_print_buffer;
int retval;
char tmp[40];
uint8_t addr[16] = {0};
if (prefix_len != 0) {
if (prefix == NULL || prefix_len > 128) {
return "<err>";
}
bitcopy(addr, prefix, prefix_len);
}
ip6tos(addr, tmp);
retval = snprintf(str, 128, "%s/%u", tmp, prefix_len);
if (retval <= 0) {
return "";
}
return str;
}
char *print_array(const uint8_t *buf, uint16_t len)
{
int16_t retcode = hextostr(buf, len, tmp_print_buffer, 128, ':');
if (retcode > 0) {
//yeah, something is converted
}
return tmp_print_buffer;
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef STRCONVERSION_H
#define STRCONVERSION_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ns_types.h"
/** Convert hex string to binary array
* e.g.
* char str[] = {30, 31, 32, 33};
* uint8_t buffer[4];
* strtohex( buffer, str, 4 );
*/
int8_t strtohex(uint8_t *out, const char *str, int8_t max_length);
/** Convert space separated hex string (eg. "76 ab ff") to binary array.
*/
int string_to_bytes(const char *str, uint8_t *buf, int bytes);
/** Convert a colon/space separated hex string (eg. "76:ab:ff") to binary
* array (inplace) returning the number of the bytes in the array.
*/
int hexstr_to_bytes_inplace(char *str);
/** Convert hex array to string
*/
int16_t hextostr(const uint8_t *buf, uint16_t buf_length, char *out, int16_t out_length, char delimiter);
/** Replace hex characters from string
* e.g.
* "hello\\n" -> "hello\n"
* "hello\\r" -> "hello\r"
* "val: \\10" -> "val: \x0a" //integer
* "val: \\x10" -> "val: \x10" //hex value
* @param str string that will be replaced
* @return length
*/
int replace_hexdata(char *str);
/**
* check if array contains only visible characters
* = isalpha | isdigit
*/
bool is_visible(uint8_t *buf, int len);
/** Convert ipv6 address to string format
*/
char *print_ipv6(const void *addr_ptr);
/** Convert ipv6 prefix to string format
*/
char *print_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len);
/** Convert binary array to string format and return static results
*/
char *print_array(const uint8_t *buf, uint16_t len);
/** The strdupl() function shall return a pointer to a new string,
* which is a duplicate of the string pointed to by s1. The returned pointer can be passed to free().
* A null pointer is returned if the new string cannot be created.
* strdupl are same than linux strdup, but this way we avoid to duplicate reference in linux
*/
char *strdupl(const char *str);
/** The strdup() function returns a pointer to a new string which is a duplicate of the string.
* Memory for the new string is obtained with malloc(3), and can be freed with free(3).
* The strndup() function is similar, but only copies at most n bytes. If s is longer than n,
* only n bytes are copied, and a terminating null byte ('\0') is added.
*/
char *strndupl(const char *s, int n);
/** strnlen - determine the length of a fixed-size string
* The strnlen() function returns the number of bytes in the string pointed to by s, excluding the terminating null bye ('\0'), but at most maxlen.
* In doing this, strnlen() looks only at the first maxlen bytes at s and never beyond s+maxlen.
* The strnlen() function returns strlen(s), if that is less than maxlen, or maxlen if there is no null byte ('\0')
* among the first maxlen bytes pointed to by s.
*/
int strnlen_(const char *s, int n);
/** strnicmp compares a and b without sensitivity to case.
* All alphabetic characters in the two arguments a and b are converted to lowercase before the comparison.
*/
int strnicmp_(char const *a, char const *b, int n);
#ifdef __cplusplus
}
#endif
#endif

View File

View File

@ -0,0 +1,157 @@
"""
Copyright 2018 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import re
import time
from collections import OrderedDict
from datetime import datetime
from icetea_lib.Plugin.PluginBase import PluginBase
class IpTestParsers(PluginBase):
# constructor
def __init__(self):
super(IpTestParsers, self).__init__()
def get_parsers(self):
return {
'ifconfig': self.__ifconfigParser,
'ifup': self.__ifconfigParser,
'ethup': self.__ifconfigParser,
'dut1': self.__ifconfigParser,
'dut2': self.__ifconfigParser,
'dut3': self.__ifconfigParser,
'dut4': self.__ifconfigParser,
'dut5': self.__ifconfigParser,
'dut6': self.__ifconfigParser,
'socket': self.__mbedossocketParser,
'ticker': self.__ticker_parser
}
# socket command for mbedos
def __mbedossocketParser(self, response):
results = {'socket_id': None,
'data_type': None,
'data': "",
'printed_bytes': None,
'sent_bytes': None,
'received_bytes': None,
'address': None,
'port': None,
'loop_id': None
}
respLines = response.lines
part = None
for line in respLines:
ret = PluginBase.find_one(line, ".*sid: ([0-9]+)")
if ret is not False:
results['socket_id'] = ret
ret = PluginBase.find_one(line, ".*(hex|string) data, printing .* bytes:")
if ret is not False:
results['data_type'] = ret
ret = PluginBase.find_one(line, ".*data, printing (.*) bytes:")
if ret is not False:
part = "data"
ret = PluginBase.find_one(line, "^Printed (.*) bytes$")
if ret is not False:
results['printed_bytes'] = int(ret)
part = None
if part == "data":
ret = PluginBase.find_one(line, "^\d{4}: (.*)$")
if ret is not False:
results['data'] = results['data'] + ret
ret = PluginBase.find_one(line, ".*sent: ([0-9]+) bytes")
if ret is not False:
results['sent_bytes'] = int(ret)
ret = PluginBase.find_one(line, ".*received: ([0-9]+) bytes")
if ret is not False:
results['received_bytes'] = int(ret)
ret = PluginBase.find_one(line, ".*address: ([0-9a-fxA-F:.]+)")
if ret is not False:
results['address'] = ret
ret = PluginBase.find_one(line, ".*port: ([0-9]+)")
if ret is not False:
results['port'] = ret
ret = PluginBase.find_one(line, ".*lid: ([0-9]+)")
if ret is not False:
results['loop_id'] = ret
return results
# response parser for ifup
def __ifconfigParser(self, response):
results = {}
lines = response.traces
part = None
results['address'] = {
'll': '',
'globals': [],
'ipv4': None,
'ipv6': []
}
for line in lines:
# print "ifcfgparser: %s" % line
match = re.search('IPv6 if addr', line)
if match:
part = "address"
match = re.search('IPv4 if addr', line)
if match:
part = "address"
match = re.search('MAC-48\:[\W]{1,}(.*)', line)
if match:
mac48 = match.group(1)
# Validate the MAC-48 syntax as well
match = re.search("([0-9a-fA-F]{2}:??){5}([0-9a-fA-F]{2})", mac48)
if match:
results['MAC'] = mac48
if part == "address":
match = re.search('.*\[(\d)\]:\W([abcdefg\d\:]{5,})', line)
if match:
addr = match.group(2)
if re.search('^fe80\:\:', addr):
results['address']['ll'] = addr
else:
results['address']["globals"].append(addr)
match = re.search('\[(\d)\]:\W([a-fA-F\d\:]{5,})', line)
if match:
results['address']['ipv6'].append(match.group(2))
match = re.search('(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$', line)
if match:
results['address']['ipv4'] = match.group(1)
return results
def __ticker_parser(self, response):
results = {}
respLines = response.lines
for line in respLines:
ret = PluginBase.find_one(line, 'Ticker id: ([0-9]+)')
if ret is not False:
results['ticker_id'] = ret
return results

View File

@ -0,0 +1,19 @@
"""
Copyright 2018 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from ip_test_parsers import IpTestParsers
plugins_to_load = {
"ip_test_parsers": IpTestParsers
}

103
TEST_APPS/readme.md Normal file
View File

@ -0,0 +1,103 @@
## Running Icetea tests located under mbed-os
### Structure
Mbed OS has a folder called `TEST_APPS` that contains everything related to Icetea testing.
There are currently three folders:
- `device` - contains all the different test applications you can flash to your board.
- `icetea_plugins` - contains plugins that are being used by some of the testcases, needed for the test execution.
- `testcases` - contains Icetea testcases written in Python.
The testcases depend on test applications.
### Preparing your work environment
#### Prerequisites
You need Icetea and version 1.8.0 or higher of Mbed CLI installed.
#### Selecting the network interface to use
Depending on the device, there might be a default network interface type defined in `mbed-os/targets/targets.json`, which you can use to locate a default test-config file.
If the default network interface type is not defined or you want to use a different interface than the default, you need to provide a 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 that have their network drivers residing inside `mbed-os` can use generic `test_configs`, such as `HeapBlockDeviceAndEthernetInterface.json` and `HeapBlockDeviceAndWifiInterface.json`. Otherwise, you need to use a device-specific test-config.
### Running the tests
Now that you have selected the interface, you can run the Icetea tests from the `mbed-os` root on your command-line by running the following command:
`mbed test -m <target> -t <toolchain> --icetea`
This command compiles the OS, compiles the test applications, creates a test suite and then starts running the tests.
If you only want to run some specific tests, you can use the `-n` option. You can choose multiple tests by separating them with a comma (`,`):
`mbed test -m <target> -t <toolchain> --icetea -n test1,test2`
#### Running the tests with a specific test-config
Some devices may offer multiple network interfaces to operate with. For example, `UBLOX_EVK_ODIN_W2` offers ethernet and Wi-Fi capabilities.
The tests can be run for either one of those using already existing test-config -files.
To run the tests with the Wi-Fi interface:
`mbed test -m UBLOX_EVK_ODIN_W2 -t <toolchain> --icetea --test-config tools/test_configs/HeapBlockDeviceAndWifiInterface.json`
To run the tests with the ethernet interface:
`mbed test -m UBLOX_EVK_ODIN_W2 -t <toolchain> --icetea --test-config tools/test_configs/HeapBlockDeviceAndEthernetInterface.json`
#### Providing Wi-Fi access point information
If you are using the Wi-Fi interface for running the tests, you need to also provide information about the used access point.
The information can be provided in the used test-config file.
Example of access point information:
```
"target_overrides": {
"*": {
"target.network-default-interface-type": "WIFI",
"nsapi.default-wifi-ssid": "\"ssid\"",
"nsapi.default-wifi-password": "\"password\"",
"nsapi.default-wifi-security": "WPA_WPA2"
}
}
```
### Test results
Icetea prints the results from the test run to the command-line, and the final result looks similar to this:
```
+--------------------------------+---------+-------------+-------------+-----------+----------+
| Testcase | Verdict | Fail Reason | Skip Reason | platforms | duration |
+--------------------------------+---------+-------------+-------------+-----------+----------+
| test_cmdline | pass | | | K64F | 8.555 |
| UDPSOCKET_BIND_PORT | pass | | | K64F | 19.614 |
| TCPSOCKET_BIND_PORT | pass | | | K64F | 15.852 |
| TCPSERVER_ACCEPT | pass | | | K64F | 41.629 |
| TCPSOCKET_ECHOTEST_BURST_SHORT | pass | | | K64F | 19.926 |
+--------------------------------+---------+-------------+-------------+-----------+----------+
+---------------+----------------+
| Summary | |
+---------------+----------------+
| Final Verdict | PASS |
| count | 5 |
| passrate | 100.00 % |
| pass | 5 |
| Duration | 0:01:45.576000 |
+---------------+----------------+
```
You can also find the results from the tests in the `mbed-os/log` folder.
You probably want to add the log folder to your `.mbedignore` file to prevent issues with build commands becoming too long over the time.

View File

@ -0,0 +1,14 @@
Icetea tests
============
This folder contains all the test cases done with Icetea residing in `mbed-os`.
The tests are divided in to subfolders and each subfolder contains a set of testcases.
The subfolder has a description of all the testcases it contains.
Testcases
---------
Current testcases:
- [netsocket](https://github.com/ARMmbed/mbed-os/blob/master/TEST_APPS/testcases/netsocket)
- [example](https://github.com/ARMmbed/mbed-os/blob/master/TEST_APPS/testcases/example)

View File

View File

@ -0,0 +1,24 @@
Example tests
=============
This folder contains example tests for Icetea
The test located under this folder is dependent of the application [exampleapp](https://github.com/ARMmbed/mbed-os/blob/master/TEST_APPS/device/exampleapp)
The exampleapp is disabled by default, to be able to run the test_cmdline with the exampleapp, either remove the preprocessor macro from exampleapp.cpp or add `-DICETEA_EXAMPLE_ENABLED` to the mbed test command
Testcases
---------
### test_cmdline
**Description:**
Send command line commands to target over serial interface.
This test introduces the Icetea testcase structure to the user.
**Test steps:**
Send "echo hello world" to the target.
Target sends "hello world" back to the host machine.
Send help to the target.
Target prints out the command line commands the application supports.
**Expected result:**
The test exits without timeouts.

View File

View File

@ -0,0 +1,50 @@
"""
Copyright 2018 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from icetea_lib.bench import Bench
class Testcase(Bench):
def __init__(self):
Bench.__init__(self,
name="test_cmdline",
title="Smoke test for command line interface",
status="released",
purpose="Verify Command Line Interface",
component=["cmdline"],
type="smoke",
requirements={
"duts": {
'*': {
"count": 1,
"type": "hardware",
"application": {
"name": "TEST_APPS-device-exampleapp"
}
},
"1": {"nick": "dut1"},
}
}
)
def setup(self):
pass
def case(self):
self.command("dut1", "echo hello world")
self.command("dut1", "help")
def teardown(self):
pass

View File

@ -0,0 +1,107 @@
"""
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import threading
import os,sys
from icetea_lib.bench import Bench
class Testcase(Bench):
def __init__(self):
Bench.__init__(self, name = "ED_scan",
title = "ED scan test",
status = "development",
type = "smoke",
subtype = "",
execution = {
"skip": {
"value": False,
"reason": ""
}
},
author = "Valtteri Erkkila",
purpose = "Tests reading the ED values from channels 11-16",
feature = ["MLME-SCAN (ED)"],
component = ["MAC"],
requirements = {
"duts": {
'*': {
"count":3,
"type": "hardware",
"allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW24D", "UBLOX_EVK_ODIN_W2"],
"application": {
"name": "TEST_APPS-device-nanostack_mac_tester"
}
},
"1":{"nick": "First"},
"2":{"nick": "Second"},
"3":{"nick": "Third"}
}}
)
def setUp(self):
self.channel = 11
self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01")
self.command("Second", "addr --64-bit 01:02:03:00:00:00:00:02")
self.command("Third", "addr --64-bit 01:02:03:00:00:00:00:03")
def spam_channel(self, event):
while not event.wait(0.1):
self.lock_th.acquire()
self.command("First", "data --dst_addr 01:02:03:00:00:00:00:03 --msdu {} --msdu_length {} --wait_for_confirm false".format(self.payload, len(self.payload)))
self.command("Third", "data --dst_addr 01:02:03:00:00:00:00:01 --msdu {} --msdu_length {} --wait_for_confirm false".format(self.payload, len(self.payload)))
self.lock_th.release()
def mask_from_channel_list(self, channels):
res = 0
for ch in channels:
res = res | ( 1 << ch)
return hex(res)
def case(self):
self.lock_th = threading.Lock()
self.payload = "01234567890123456789012345678901234567890123456789"
self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel))
self.command("Second", "start --pan_coordinator false --logical_channel {}".format(self.channel))
self.command("Third", "start --pan_coordinator false --logical_channel {}".format(self.channel))
#No reason to print their spamming
self.command("First", "silent-mode on")
self.command("Third", "silent-mode on")
self.stop_event = threading.Event()
self.th = threading.Thread(target=self.spam_channel, args=(self.stop_event,))
self.th.start()
self.stopped = True
channels = range(11,27)
for i in range(0, 3):
self.lock_th.acquire()
self.command("First", "mlme-reset")
self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel))
self.command("Third", "mlme-reset")
self.command("Third", "start --pan_coordinator false --logical_channel {}".format(self.channel))
self.lock_th.release()
self.command("Second", "scan --scan_type 0 --scan_duration 7 --channel_mask {}".format(self.mask_from_channel_list(channels)))
self.command("Second", "analyze-ed --channel {} --above 100".format(self.channel))
def tearDown(self):
self.command("First", "silent-mode off")
self.command("Third", "silent-mode off")
self.stop_event.set()
self.th.join()
del self.th
self.reset_dut()

View File

@ -0,0 +1 @@
#!/usr/bin/env python

View File

@ -0,0 +1,65 @@
"""
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import os,sys
from icetea_lib.bench import Bench
class Testcase(Bench):
def __init__(self):
Bench.__init__(self, name = "address_read_and_write",
title = "MAC address and PAN id read/write test",
status = "development",
type = "smoke",
subtype = "",
execution = {
"skip": {
"value": False,
"reason": ""
}
},
author = "Valtteri Erkkila",
purpose = "Tests reading a MAC address from the driver, and writing to the modifiable MAC address",
feature = ["MLME-SET"],
component = ["MAC"],
requirements = {
"duts": {
'*': {
"count":1,
"type": "hardware",
"allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW24D", "UBLOX_EVK_ODIN_W2"],
"application": {
"name": "TEST_APPS-device-nanostack_mac_tester"
}
},
"1":{"nick": "First"}
}}
)
def setUp(self):
pass
def case(self):
self.command("First", "addr")
self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01")
self.command("First", "addr --16-bit 0xABCD")
#macPANId
self.command("First", "mlme-set --attr 0x50 --value_bytes CD:CD --value_size 2")
self.command("First", "addr")
self.verify_trace(1, "MAC64: 01:02:03:00:00:00:00:01")
def tearDown(self):
self.reset_dut()

View File

@ -0,0 +1,86 @@
"""
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import os,sys
from icetea_lib.bench import Bench
class Testcase(Bench):
def __init__(self):
Bench.__init__(self, name = "create_and_join_PAN",
title = "Create a PAN and have a device join it",
status = "development",
type = "smoke",
subtype = "",
execution = {
"skip": {
"value": False,
"reason": ""
}
},
author = "Valtteri Erkkila",
purpose = "",
feature = ["MLME-START", "MLME-SCAN (active)"],
component = ["MAC"],
requirements = {
"duts": {
'*': {
"count":3,
"type": "hardware",
"allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW24D", "UBLOX_EVK_ODIN_W2"],
"application": {
"name": "TEST_APPS-device-nanostack_mac_tester"
}
},
"1":{"nick": "First"},
"2":{"nick": "Second"},
"3":{"nick": "Third"}
}}
)
def mask_from_channel_list(self, channels):
res = 0
for ch in channels:
res = res | ( 1 << ch)
return hex(res)
def setUp(self):
self.channel = 11
def case(self):
#Beacon payload & length
self.command("First", "mlme-set --attr 0x45 --value_ascii mac-tester --value_size 10")
self.command("First", "mlme-set --attr 0x46 --value_uint8 10 --value_size 1")
self.command("Second", "mlme-set --attr 0x45 --value_ascii second-mac-tester --value_size 17")
self.command("Second", "mlme-set --attr 0x46 --value_uint8 17 --value_size 1")
self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel))
self.command("Second", "start --pan_coordinator true --logical_channel {}".format(int(self.channel)+1))
self.delay(3)
if self.channel == 11:
channels = [11,12]
elif self.channel == 26:
channels = [25,26]
else:
channels = [self.channel, self.channel+1]
self.command("Third", "scan --channel_mask {}".format(self.mask_from_channel_list(channels)))
self.delay(0.2)
self.command("Third", "find-beacon --data mac-tester")
self.command("Third", "find-beacon --data second-mac-tester")
def tearDown(self):
self.reset_dut()

View File

@ -0,0 +1,66 @@
"""
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import os,sys
from icetea_lib.bench import Bench
class Testcase(Bench):
def __init__(self):
Bench.__init__(self, name = "send_data",
title = "Simple data transmission test",
status = "development",
type = "smoke",
subtype = "",
execution = {
"skip": {
"value": False,
"reason": ""
}
},
author = "Valtteri Erkkila",
purpose = "Tests that sending data works",
feature = ["MCPS-DATA"],
component = ["MAC"],
requirements = {
"duts": {
'*': {
"count":2,
"type": "hardware",
"allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW24D", "UBLOX_EVK_ODIN_W2"],
"application": {
"name": "TEST_APPS-device-nanostack_mac_tester"
}
},
"1":{"nick": "First"},
"2":{"nick": "Second"}
}}
)
def setUp(self):
self.channel = 11
self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01")
self.command("Second", "addr --64-bit 01:02:03:00:00:00:00:02")
def case(self):
self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel))
self.command("Second", "start --pan_coordinator false --logical_channel {}".format(self.channel))
self.command("First", "data --dst_addr 01:02:03:00:00:00:00:02 --msdu_length 5 --msdu abcde")
self.command("Second", "data --dst_addr 01:02:03:00:00:00:00:01 --msdu_length 5 --msdu 12345")
def tearDown(self):
self.reset_dut()

View File

@ -0,0 +1,96 @@
"""
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import os,sys
from icetea_lib.bench import Bench
class Testcase(Bench):
def __init__(self):
Bench.__init__(self, name = "send_data_indirect",
title = "Indirect data transmission test",
status = "development",
type = "smoke",
subtype = "",
execution = {
"skip": {
"value": False,
"reason": ""
}
},
author = "Valtteri Erkkila",
purpose = "Tests sending data indirectly, i.e polling the coordinator for data",
feature = ["MCPS-DATA", "MLME-POLL"],
component = ["MAC"],
requirements = {
"duts": {
'*': {
"count":3,
"type": "hardware",
"allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW24D", "UBLOX_EVK_ODIN_W2"],
"application": {
"name": "TEST_APPS-device-nanostack_mac_tester"
}
},
"1":{"nick": "First"},
"2":{"nick": "Second"},
"3":{"nick": "Third"}
}}
)
def setUp(self):
self.channel = 11
self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01")
self.command("Second", "addr --64-bit 01:02:03:00:00:00:00:02")
self.command("Third", "addr --64-bit 01:02:03:00:00:00:00:03")
def case(self):
self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel))
self.command("Second", "start --pan_coordinator false --logical_channel {}".format(self.channel))
self.command("Third", "start --pan_coordinator false --logical_channel {}".format(self.channel))
#macRxOnWhenIdle
self.command("Second", "mlme-set --attr 0x52 --value_uint8 0 --value_size 1")
self.command("Third", "mlme-set --attr 0x52 --value_uint8 0 --value_size 1")
self.command("First", "add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:02 --pan_id 0x1234 --index 0")
self.command("First", "add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:03 --pan_id 0x1234 --index 1")
self.command("Second", "add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:01 --pan_id 0x1234 --index 0")
self.command("Third", "add-neigh --frame_ctr 0 --mac16 0xFFFF --mac64 01:02:03:00:00:00:00:01 --pan_id 0x1234 --index 0")
self.command("Second", "config-status --data_ind abcde")
self.command("Third", "config-status --data_ind 12345")
#Runs into timing issues if extensive printing is enabled
self.command("*", "silent-mode on")
self.command("First", "data --dst_addr 01:02:03:00:00:00:00:02 --msdu_length 5 --msdu abcde --indirect_tx true --wait_for_confirm false")
self.command("Second", "poll --coord_address 01:02:03:00:00:00:00:01")
self.command("First", "data")
self.command("First", "data")
self.command("Second", "poll")
self.command("Second", "poll")
self.command("Second", "config-status --poll 235")
self.command("Second", "poll")
self.command("Second", "config-status --poll 235")
self.command("First", "data --dst_addr 01:02:03:00:00:00:00:03 --msdu 12345")
self.command("Second", "poll")
self.command("Third", "poll --coord_address 01:02:03:00:00:00:00:01")
self.command("*", "silent-mode off")
def tearDown(self):
self.reset_dut()

View File

@ -0,0 +1,79 @@
"""
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import os,sys
from icetea_lib.bench import Bench
class Testcase(Bench):
def __init__(self):
Bench.__init__(self, name = "send_large_payloads",
title = "Data transmission test with large packets",
status = "development",
type = "reliability",
subtype = "",
execution = {
"skip": {
"value": False,
"reason": ""
}
},
author = "Valtteri Erkkila",
purpose = "Repeatedly sends long packets, checking that the payload is correct in each one",
feature = ["MCPS-DATA"],
component = ["MAC"],
requirements = {
"duts": {
'*': {
"count":2,
"type": "hardware",
"allowed_platforms": ["K64F", "K66F", "NUCLEO_F429ZI", "KW24D", "UBLOX_EVK_ODIN_W2"],
"application": {
"name": "TEST_APPS-device-nanostack_mac_tester"
}
},
"1":{"nick": "First"},
"2":{"nick": "Second"}
}}
)
def setUp(self):
self.channel = 11
self.command("First", "addr --64-bit 01:02:03:00:00:00:00:01")
self.command("Second", "addr --64-bit 01:02:03:00:00:00:00:02")
def case(self):
#104 characters, headers are 2+1+2+8+8+2=23 bytes, resulting in a packet size of 127 (max)
large_payload = "0123456789abcdefghjiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZZZZZZZZZ0123456789012345678901234567891234"
self.command("First", "start --pan_coordinator true --logical_channel {}".format(self.channel))
self.command("Second", "start --pan_coordinator false --logical_channel {}".format(self.channel))
self.command("First", "config-status --data_ind {}".format(large_payload))
self.command("Second", "config-status --data_ind {}".format(large_payload))
self.command("First", "data --dst_addr 01:02:03:00:00:00:00:02 --msdu_length {} --msdu {}".format(len(large_payload), large_payload))
self.command("Second", "wait --timeout 500")
self.command("Second", "data --dst_addr 01:02:03:00:00:00:00:01 --msdu_length {} --msdu {}".format(len(large_payload), large_payload))
self.command("First", "wait --timeout 500")
for i in range(0, 25):
self.command("First", "data")
self.command("Second", "wait")
self.command("Second", "data")
self.command("First", "wait")
def tearDown(self):
self.reset_dut()

View File

@ -0,0 +1,65 @@
"""
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import os,sys
# ensure that test/ directory is first choice for imports
test_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
if not test_dir in sys.path:
sys.path.insert(0, test_dir)
from GenericTestcase import Bench
from Error import TestStepFail
class Testcase(Bench):
def __init__(self):
Bench.__init__(self, name = "template", # Name should be the same as the filename
title = "TITLE",
status = "development",
type = "TYPE",
subtype = "",
execution = {
"skip": {
"value": False,
"reason": ""
}
},
author = "Valtteri Erkkila",
purpose = "",
feature = [""],
component = ["MAC"],
requirements = {
"duts": {
'*': {
"count":2, # Count must reflect the amount of specified devices below
"type": "hardware",
"application":{ "name":"generalTestApplication", "version": "1.0"},
"rf_channel": 11
},
"1":{"nick": "First"},
"2":{"nick": "Second"}
}}
)
def setUp(self):
pass
def case(self):
pass
def tearDown(self):
pass
if __name__=='__main__':
sys.exit( Testcase().run() )

View File

@ -0,0 +1,7 @@
Netsocket tests
===============
This folder contains netsocket tests for Icetea
The tests located under this folder are dependent of the application [socket_app](https://github.com/ARMmbed/mbed-os/blob/master/TEST_APPS/device/socket_app)
The test cases under this folder are defined in [Network Socket test plan](https://github.com/ARMmbed/mbed-os/blob/master/TESTS/netsocket/README.md)

View File

@ -0,0 +1,71 @@
"""
Copyright 2018 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from icetea_lib.bench import Bench
from icetea_lib.tools import test_case
class MultipleTestcase(Bench):
def __init__(self, **kwargs):
testcase_args = {
'status': "released",
'component': ["mbed-os", "netsocket"],
'type': "smoke",
'subtype': "socket",
'requirements': {
"duts": {
"*": {
"count": 1,
"type": "hardware",
"application": {"name": "TEST_APPS-device-socket_app"}
},
"1": {"nick": "dut1"},
}
}
}
testcase_args.update(kwargs)
Bench.__init__(self, **testcase_args)
def setup(self):
self.command("dut1", "ifup")
def socket_bind_port(self, socket_type):
response = self.command("dut1", "socket new " + socket_type)
socket_id = int(response.parsed['socket_id'])
self.command("dut1", "socket " + str(socket_id) + " open")
self.command("dut1", "socket " + str(socket_id) + " bind port 1024")
self.command("dut1", "socket " + str(socket_id) + " delete")
def teardown(self):
self.command("dut1", "ifdown")
@test_case(MultipleTestcase,
name="TCPSOCKET_BIND_PORT",
title="tcpsocket open and bind port",
purpose="Verify TCPSocket can be created, opened and port binded")
def test1(self):
self.socket_bind_port("TCPSocket")
@test_case(MultipleTestcase,
name="UDPSOCKET_BIND_PORT",
title="udpsocket open and bind port",
purpose="Verify UDPSocket can be created, opened and port binded")
def test2(self):
self.socket_bind_port("UDPSocket")

View File

@ -0,0 +1,103 @@
"""
Copyright 2018 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import threading
import time
from icetea_lib.TestStepError import TestStepFail
from icetea_lib.bench import Bench
from interface import interfaceUp, interfaceDown
class Testcase(Bench):
def __init__(self):
Bench.__init__(self,
name="TCPSERVER_ACCEPT",
title="TCPSERVER_ACCEPT",
purpose="Test that TCPServer::bind(), TCPServer::listen() and TCPServer::accept() works",
status="released",
component=["mbed-os", "netsocket"],
author="Juha Ylinen <juha.ylinen@arm.com>",
type="smoke",
subtype="socket",
requirements={
"duts": {
'*': { # requirements for all nodes
"count": 2,
"type": "hardware",
"application": {"name": "TEST_APPS-device-socket_app"}
},
"1": {"nick": "dut1"},
"2": {"nick": "dut2"}
}
}
)
def setup(self):
interface = interfaceUp(self, ["dut1"])
self.server_ip = interface["dut1"]["ip"]
interface = interfaceUp(self, ["dut2"])
self.client_ip = interface["dut2"]["ip"]
def clientThread(self):
self.logger.info("Starting")
time.sleep(5) # wait accept from server
self.command("dut2", "socket " + str(self.client_socket_id) + " open")
self.command("dut2", "socket " + str(self.client_socket_id) + " connect " + str(self.server_ip) + " " + str(
self.used_port))
def case(self):
self.used_port = 2000
response = self.command("dut1", "socket new TCPServer")
server_base_socket_id = int(response.parsed['socket_id'])
self.command("dut1", "socket " + str(server_base_socket_id) + " open")
self.command("dut1", "socket " + str(server_base_socket_id) + " bind port " + str(self.used_port))
self.command("dut1", "socket " + str(server_base_socket_id) + " listen")
response = self.command("dut1", "socket new TCPSocket")
server_socket_id = int(response.parsed['socket_id'])
self.command("dut1", "socket " + str(server_socket_id) + " open")
response = self.command("dut2", "socket new TCPSocket")
zero = response.timedelta
self.client_socket_id = int(response.parsed['socket_id'])
# Create a thread which calls client connect()
t = threading.Thread(name='clientThread', target=self.clientThread)
t.start()
wait = 5
response = self.command("dut1", "socket " + str(server_base_socket_id) + " accept " + str(server_socket_id))
response.verify_response_duration(expected=wait, zero=zero, threshold_percent=10, break_in_fail=True)
socket_id = int(response.parsed['socket_id'])
t.join()
self.command("dut1", "socket " + str(socket_id) + " send hello")
response = self.command("dut2", "socket " + str(self.client_socket_id) + " recv 5")
data = response.parsed['data'].replace(":", "")
if data != "hello":
raise TestStepFail("Received data doesn't match the sent data")
self.command("dut1", "socket " + str(server_socket_id) + " delete")
self.command("dut1", "socket " + str(server_base_socket_id) + " delete")
self.command("dut2", "socket " + str(self.client_socket_id) + " delete")
def teardown(self):
interfaceDown(self, ["dut1"])
interfaceDown(self, ["dut2"])

View File

@ -0,0 +1,78 @@
"""
Copyright 2018 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import string
from icetea_lib.Randomize.randomize import Randomize
from icetea_lib.bench import Bench, TestStepFail
class Testcase(Bench):
def __init__(self):
Bench.__init__(self,
name="TCPSOCKET_ECHOTEST_BURST_SHORT",
title="TCPSOCKET_ECHOTEST_BURST_SHORT",
purpose="Verify that TCPSocket can send burst of packets to echo server and read incoming packets",
status="released",
component=["mbed-os", "netsocket"],
author="Juha Ylinen <juha.ylinen@arm.com>",
type="smoke",
subtype="socket",
requirements={
"duts": {
'*': { # requirements for all nodes
"count": 1,
"type": "hardware",
"application": {
"name": "TEST_APPS-device-socket_app"
}
},
"1": {"nick": "dut1"},
}
}
)
def setup(self):
self.command("dut1", "ifup")
def case(self):
response = self.command("dut1", "socket new TCPSocket")
socket_id = int(response.parsed['socket_id'])
self.command("dut1", "socket " + str(socket_id) + " open")
self.command("dut1", "socket " + str(socket_id) + " connect echo.mbedcloudtesting.com 7")
for i in range(2):
sentData = ""
for size in (100, 200, 300, 120, 500):
packet = Randomize.random_string(max_len=size, min_len=size, chars=string.ascii_uppercase)
sentData += packet
response = self.command("dut1", "socket " + str(socket_id) + " send " + str(packet))
response.verify_trace("TCPSocket::send() returned: " + str(size))
received = 0
data = ""
totalSize = 1220
while received < totalSize:
response = self.command("dut1", "socket " + str(socket_id) + " recv " + str(totalSize))
data += response.parsed['data'].replace(":", "")
received += int(response.parsed['received_bytes'])
if data != sentData:
raise TestStepFail("Received data doesn't match the sent data")
self.command("dut1", "socket " + str(socket_id) + " delete")
def teardown(self):
self.command("dut1", "ifdown")

View File

@ -0,0 +1,43 @@
"""
Copyright 2018 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from icetea_lib.TestStepError import TestStepFail
'''
This interface script is intended to be a common library to be used in testcase scripts by testers.
It delegates setUp and tearDown functions with different provided network interface types using setUp() and tearDown() methods.
'''
def interfaceUp(tc, duts):
interfaces = {}
for dut in duts:
interface = {dut: {"ipv4": None, "ipv6": None}}
resp = tc.command("%s" % dut, "ifup")
ip = interface[dut]["ip"] = interface[dut]["ipv4"] = resp.parsed["address"]["ipv4"]
if not ip:
if resp.parsed["address"]["ipv6"]:
ip = interface[dut]["ip"] = interface[dut]["ipv6"] = resp.parsed["address"]["ipv6"][0]
if not ip:
raise TestStepFail("Failed to parse IP address")
interfaces.update(interface)
return interfaces
def interfaceDown(tc, duts):
for dut in duts:
tc.command(dut, "ifdown")

1
UNITTESTS/.mbedignore Normal file
View File

@ -0,0 +1 @@
*

202
UNITTESTS/CMakeLists.txt Normal file
View File

@ -0,0 +1,202 @@
cmake_minimum_required(VERSION 3.0.2)
set(PROJECT_NAME unittests)
set(LIB_NAME MbedOS)
project(${PROJECT_NAME})
# Setup c++ standard
macro(use_cxx14)
if (CMAKE_VERSION VERSION_LESS 3.1)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++98")
endif()
else()
set(CMAKE_CXX_STANDARD 98)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
endmacro()
use_cxx14()
####################
# GTEST
####################
# Download and unpack googletest at configure time
configure_file(googletest-CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
if (result)
message(FATAL_ERROR "CMake failed for google test: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
if (result)
message(FATAL_ERROR "Build failed for google test: ${result}")
endif()
# Prevent overriding the parent project's compiler/linker
# settings on Windows
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
${CMAKE_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)
# The gtest/gtest_main/gmock/gmock_main targets carry header search path
# dependencies automatically when using CMake 2.8.11 or
# later.
target_include_directories(gmock_main SYSTEM BEFORE INTERFACE
"${gtest_SOURCE_DIR}/include"
"${gmock_SOURCE_DIR}/include")
####################
# TESTING
####################
enable_testing()
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${CMAKE_BINARY_DIR}/Testing"
)
####################
# CODE COVERAGE SETUP
####################
if (COVERAGE)
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
message(WARNING "Non-debug build may result misleading code coverage results.")
endif()
# Append coverage compiler flags
set(COVERAGE_COMPILER_FLAGS "-g -O0 --coverage -fprofile-arcs -ftest-coverage")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}")
endif(COVERAGE)
####################
# UNIT TESTS
####################
# Set include dirs.
set(unittest-includes-base
"${PROJECT_SOURCE_DIR}/target_h"
"${PROJECT_SOURCE_DIR}/target_h/events"
"${PROJECT_SOURCE_DIR}/target_h/events/equeue"
"${PROJECT_SOURCE_DIR}/target_h/platform"
"${PROJECT_SOURCE_DIR}/stubs"
"${PROJECT_SOURCE_DIR}/.."
"${PROJECT_SOURCE_DIR}/../features"
"${PROJECT_SOURCE_DIR}/../features/netsocket"
"${PROJECT_SOURCE_DIR}/../platform"
"${PROJECT_SOURCE_DIR}/../drivers"
"${PROJECT_SOURCE_DIR}/../hal"
"${PROJECT_SOURCE_DIR}/../events"
"${PROJECT_SOURCE_DIR}/../events/equeue"
"${PROJECT_SOURCE_DIR}/../rtos"
"${PROJECT_SOURCE_DIR}/../rtos/TARGET_CORTEX"
"${PROJECT_SOURCE_DIR}/../rtos/TARGET_CORTEX/rtx5/Include"
"${PROJECT_SOURCE_DIR}/../cmsis"
"${PROJECT_SOURCE_DIR}/../features/frameworks"
"${PROJECT_SOURCE_DIR}/../features/frameworks/mbed-trace"
"${PROJECT_SOURCE_DIR}/../features/frameworks/nanostack-libservice"
"${PROJECT_SOURCE_DIR}/../features/frameworks/nanostack-libservice/mbed-client-libservice"
"${PROJECT_SOURCE_DIR}/../features/filesystem/fat"
"${PROJECT_SOURCE_DIR}/../features/filesystem/fat/ChaN"
"${PROJECT_SOURCE_DIR}/../features/filesystem/bd"
"${PROJECT_SOURCE_DIR}/../features/filesystem/"
"${PROJECT_SOURCE_DIR}/../features/filesystem/littlefs"
"${PROJECT_SOURCE_DIR}/../features/filesystem/littlefs/littlefs"
"${PROJECT_SOURCE_DIR}/../features/cellular/framework/API"
"${PROJECT_SOURCE_DIR}/../features/cellular/framework/AT"
"${PROJECT_SOURCE_DIR}/../features/cellular/framework"
"${PROJECT_SOURCE_DIR}/../features/cellular/framework/common"
"${PROJECT_SOURCE_DIR}/../features/lorawan"
"${PROJECT_SOURCE_DIR}/../features/lorawan/lorastack"
"${PROJECT_SOURCE_DIR}/../features/lorawan/lorastack/mac"
"${PROJECT_SOURCE_DIR}/../features/lorawan/lorastack/phy"
"${PROJECT_SOURCE_DIR}/../features/lorawan/system"
"${PROJECT_SOURCE_DIR}/../features/mbedtls"
"${PROJECT_SOURCE_DIR}/../features/mbedtls/inc"
)
# Create a list for test suites.
set(TEST_SUITES)
# Get all matched tests.
file(GLOB_RECURSE unittest-file-list
"unittest.cmake"
)
if ("${unittest-file-list}" STREQUAL "")
message(FATAL_ERROR "No tests found. Exiting...")
endif()
# Create unit test targets
foreach(testfile ${unittest-file-list})
####################
# DEFINE TARGETS
####################
# Init file lists.
set(unittest-includes ${unittest-includes-base})
set(unittest-sources)
set(unittest-test-sources)
# Get source files
include("${testfile}")
get_filename_component(TEST_SUITE_DIR ${testfile} DIRECTORY)
file(RELATIVE_PATH
TEST_SUITE_NAME # output
${PROJECT_SOURCE_DIR} # root
${TEST_SUITE_DIR} #abs dirpath
)
string(REGEX REPLACE "/|\\\\" "-" TEST_SUITE_NAME ${TEST_SUITE_NAME})
set(TEST_SUITES ${TEST_SUITES} ${TEST_SUITE_NAME})
set(LIBS_TO_BE_LINKED gmock_main)
# Build directories list
set(BUILD_DIRECTORIES)
if (unittest-sources)
# Create the testable static library.
add_library("${TEST_SUITE_NAME}.${LIB_NAME}" STATIC ${unittest-sources})
target_include_directories("${TEST_SUITE_NAME}.${LIB_NAME}" PRIVATE
${unittest-includes})
set(LIBS_TO_BE_LINKED ${LIBS_TO_BE_LINKED} "${TEST_SUITE_NAME}.${LIB_NAME}")
# Append lib build directory to list
list(APPEND BUILD_DIRECTORIES "./CMakeFiles/${TEST_SUITE_NAME}.${LIB_NAME}.dir")
endif(unittest-sources)
if (unittest-test-sources)
# Create the executable.
add_executable(${TEST_SUITE_NAME} ${unittest-test-sources})
target_include_directories(${TEST_SUITE_NAME} PRIVATE
${unittest-includes})
# Link the executable with the libraries.
target_link_libraries(${TEST_SUITE_NAME} ${LIBS_TO_BE_LINKED})
add_test(NAME "${TEST_SUITE_NAME}" COMMAND ${TEST_SUITE_NAME})
# Append test build directory to list
list(APPEND BUILD_DIRECTORIES "./CMakeFiles/${TEST_SUITE_NAME}.dir")
else()
message(WARNING "No test source files found for ${TEST_SUITE_NAME}.\n")
endif(unittest-test-sources)
endforeach(testfile)

View File

@ -0,0 +1,30 @@
{
"configurations": [
{
"name": "GNU-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "mingw64" ],
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
"environments": [
{
"environment": "mingw64"
}
]
},
{
"name": "GNU-Release",
"generator": "Ninja",
"configurationType": "Release",
"inheritEnvironments": [ "mingw64" ],
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
"environments": [
{
"environment": "mingw64"
}
]
}
]
}

190
UNITTESTS/README.md Normal file
View File

@ -0,0 +1,190 @@
## Unit testing
This document describes how to write and test unit tests for Mbed OS. To prevent and solve problems, please see the [troubleshooting](#troubleshooting) section.
### Introduction
Unit tests test code in small sections on a host machine. Unlike other testing tools, unit testing doesn't require embedded hardware, and it doesn't need to build the full operating system. Because of this, unit testing can result in faster tests than other testing tools. Unit testing takes place in a build environment where we test each C or C++ class or module in isolation. This means we build test suites into separate test binaries and stub all access outside to remove dependencies on any specific embedded hardware or software combination. This allows us to complete the testing using native compilers on the build machine.
### Prerequisites
Please install the following dependencies to use Mbed OS unit testing.
- GNU toolchains.
- GCC 6 or later. We recommend you use MinGW-W64 on Windows, but any Windows port of the above GCC versions works.
- CMake 3.0 or newer.
- Python 2.7.x, 3.5 or newer.
- Pip 10.0 or newer.
- Gcovr 4.1 or newer.
- Mbed CLI 1.8.0 or newer.
Detailed instructions for supported operating systems are below.
#### Installing dependencies on Debian or Ubuntu
1. `sudo apt-get -y install build-essential cmake`
1. Install Python and Pip with:
```
sudo apt-get -y install python python-setuptools
sudo easy_install pip
```
1. Install Gcovr and [Mbed CLI](https://os.mbed.com/docs/latest/tools/arm-mbed-cli.html) with `pip install "gcovr>=4.1" mbed-cli`.
#### Installing dependencies on macOS
1. Install [Homebrew](https://brew.sh/).
1. Install GCC compilers and CMake with: `brew install gcc cmake`.
1. Install Python and Pip:
```
brew install python
sudo easy_install pip
```
1. Install Gcovr and [Mbed CLI](https://os.mbed.com/docs/latest/tools/arm-mbed-cli.html) with `pip install "gcovr>=4.1" mbed-cli`.
#### Installing dependencies on Windows
1. Download and install [MinGW-W64](http://mingw-w64.org/).
1. Download CMake binaries from https://cmake.org/download/, and run the installer.
1. Download Python 2.7 or Python 3 from https://www.python.org/getit/, and run the installer.
1. Add MinGW, CMake and Python into system PATH.
1. Install Gcovr and [Mbed CLI](https://os.mbed.com/docs/latest/tools/arm-mbed-cli.html) with `pip install "gcovr>=4.1" mbed-cli`.
### Test code structure
Unit tests are located in the Mbed OS repository under the `UNITTESTS` folder. We recommend unit test files use an identical directory path to the file under test. This makes it easier to find unit tests for a particular class or a module. For example, if the file under test is `some/example/path/ClassName.cpp`, then all the test files are in the `UNITTESTS/some/example/path/ClassName` directory. Each test suite needs to have its own `unittest.cmake` file for test configuration.
#### Test discovery
Registering unit tests for running is automatic, and the test runner handles registration. However, test files are not automatically assigned to be built. We build unit tests by using a separate build system, which searches for unit tests under the `UNITTESTS` directory.
For the build system to find and build any test suite automatically, you must include a unit test configuration file named `unittest.cmake` for each unit test suite. This configuration file contains all the source files required for the build.
#### Test names
The build system automatically generates names of test suites. The name is constructed by taking a relative file path from the UNITTESTS directory to the test directory and replacing path separators with dashes. For example, the test suite name for `some/example/path/ClassName.cpp` is `some-example-path-ClassName`. Suite names are used when deciding which test suites to run.
### Unit testing with Mbed CLI
Mbed CLI supports unit tests through `mbed test --unittests` command. For information on using Mbed CLI, please see the [CLI documentation in handbook](https://os.mbed.com/docs/latest/tools/arm-mbed-cli.html).
### Writing unit tests
Create two files in the test directory for each test suite:
- Unit test source file (`test_ClassName.cpp`).
- Unit test configuration file (`unittest.cmake`).
List all the files required for the build in the `unittest.cmake` file. We recommend you list the file paths relative to the `UNITTESTS` folder. Use the following variables to list the source files and include paths:
- **unittest-includes** - List of header include paths. You can use this to extend or overwrite default paths listed in CMakeLists.txt.
- **unittest-sources** - List of files under test.
- **unittest-test-sources** - List of test sources and stubs.
With the following steps, you can write a simple unit test. In this example, `rtos/Semaphore.cpp` is a class under test.
1. Create a directory for unit test files in `UNITTESTS/rtos/Semaphore`.
1. Create a test configuration file `UNITTESTS/rtos/Semaphore/unittest.cmake` with the following content:
```
set(unittest-sources
../rtos/Semaphore.cpp
)
set(unittest-test-sources
stubs/mbed_assert.c
rtos/Semaphore/test_Semaphore.cpp
)
```
1. Create a test source file `UNITTESTS/rtos/Semaphore/test_Semaphore.cpp` with the following content:
```
#include "gtest/gtest.h"
#include "rtos/Semaphore.h"
static osStatus_t retval = osOK;
static uint32_t count = 0;
// Test stubs
osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)
{
return retval;
}
osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id)
{
return retval;
}
osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)
{
return retval;
}
uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id)
{
return count;
}
osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr)
{
return (void *)&count; // Just a dymmy reference
}
class TestSemaphore : public testing::Test {
protected:
rtos::Semaphore *sem;
virtual void SetUp()
{
sem = new rtos::Semaphore();
}
virtual void TearDown()
{
delete sem;
}
};
TEST_F(TestSemaphore, constructor)
{
EXPECT_TRUE(sem);
}
```
### Building and running unit tests
Use Mbed CLI to build and run unit tests. For advanced use, you can run CMake and a make program directly.
#### Build tests directly with CMake
1. Create a build directory `mkdir UNITTESTS/build`.
1. Move to the build directory `cd UNITTESTS/build`.
1. Run CMake using a relative path to `UNITTESTS` folder as the argument. So from `UNITTESTS/build` use `cmake ..`:
- Add `-g [generator]` if generating other than Unix Makefiles such in case of MinGW use `-g "MinGW Makefiles"`.
- Add `-DCOVERAGE:True` to add coverage compiler flags.
- See the [CMake manual](https://cmake.org/cmake/help/v3.0/manual/cmake.1.html) for more information.
1. Run a make program (Make, Gmake, Mingw32-make and so on) to build the tests.
#### Run tests directly with CTest
Run a test binary in the build directory to run a unit test suite. To run multiple test suites at once, use CTest test runner. Run CTest with `ctest`. Add `-v` to get results for each test case. See the [CTest manual](https://cmake.org/cmake/help/v3.0/manual/ctest.1.html) for more information.
#### Run tests with GUI test runner
1. Install *gtest-runner* using the [documentation](https://github.com/nholthaus/gtest-runner).
1. Run *gtest-runner*
1. Add test executables into the list.
1. Run them.
### Get code coverage
Use Mbed CLI to generate code coverage reports. For advanced use, you can run Gcovr or any other code coverage tool directly in the build directory.
### Troubleshooting
**Problem:** Generic problems with CMake or with the build process.
* **Solution**: Delete the build directory. Make sure that CMake, g++, gcc and a make program can be found in the path and are correct versions.
**Problem:** Virus protection identifies files generated by CMake as malicious and quarantines the files on Windows.
* **Solution**: Restore the false positive files from the quarantine.

View File

@ -14,8 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "CppUTest/TestHarness.h"
#include "test_at_cellularbase.h"
#include "gtest/gtest.h"
#include "AT_CellularBase.h"
#include "EventQueue.h"
#include "AT_CellularBase.h"
#include "ATHandler_stub.h"
@ -57,26 +58,44 @@ public:
}
};
Test_AT_CellularBase::Test_AT_CellularBase()
{
// AStyle ignored as the definition is not clear due to preprocessor usage
// *INDENT-OFF*
class TestAT_CellularBase : public testing::Test {
protected:
void SetUp()
{
}
void TearDown()
{
}
};
// *INDENT-ON*
TEST_F(TestAT_CellularBase, Create)
{
EventQueue eq;
FileHandle_stub fh;
ATHandler ah(&fh, eq, 100, ",");
AT_CellularBase *unit = new AT_CellularBase(ah);
EXPECT_TRUE(unit != NULL);
delete unit;
}
Test_AT_CellularBase::~Test_AT_CellularBase()
{
}
void Test_AT_CellularBase::test_AT_CellularBase_get_at_handler()
TEST_F(TestAT_CellularBase, test_AT_CellularBase_get_at_handler)
{
EventQueue eq;
FileHandle_stub fh;
ATHandler ah(&fh, eq, 100, ",");
AT_CellularBase at(ah);
CHECK(&ah == &at.get_at_handler());
EXPECT_TRUE(&ah == &at.get_at_handler());
}
void Test_AT_CellularBase::test_AT_CellularBase_get_device_error()
TEST_F(TestAT_CellularBase, test_AT_CellularBase_get_device_error)
{
EventQueue eq;
FileHandle_stub fh;
@ -85,12 +104,12 @@ void Test_AT_CellularBase::test_AT_CellularBase_get_device_error()
ATHandler_stub::device_err_value.errCode = 8;
CHECK_EQUAL(8, at.get_device_error().errCode);
EXPECT_EQ(8, at.get_device_error().errCode);
ATHandler_stub::device_err_value.errCode = 0;
}
void Test_AT_CellularBase::test_AT_CellularBase_set_unsupported_features()
TEST_F(TestAT_CellularBase, test_AT_CellularBase_set_unsupported_features)
{
EventQueue eq;
FileHandle_stub fh;
@ -105,15 +124,14 @@ void Test_AT_CellularBase::test_AT_CellularBase_set_unsupported_features()
at.set_unsupported_features(unsupported_features);
}
void Test_AT_CellularBase::test_AT_CellularBase_is_supported()
TEST_F(TestAT_CellularBase, test_AT_CellularBase_is_supported)
{
EventQueue eq;
FileHandle_stub fh;
ATHandler ah(&fh, eq, 0, ",");
my_base my_at(ah);
CHECK(true == my_at.check_supported());
CHECK(true == my_at.check_supported_not_found());
CHECK(false == my_at.check_not_supported());
EXPECT_TRUE(true == my_at.check_supported());
EXPECT_TRUE(true == my_at.check_supported_not_found());
EXPECT_TRUE(false == my_at.check_not_supported());
}

View File

@ -0,0 +1,28 @@
####################
# UNIT TESTS
####################
# Add test specific include paths
set(unittest-includes ${unittest-includes}
features/cellular/framework/AT/AT_CellularBase
../features/cellular/framework/AT
../features/cellular/framework/common
../features/frameworks/mbed-trace
../features/frameworks/nanostack-libservice/mbed-client-libservice
../features/netsocket
)
# Source files
set(unittest-sources
../features/cellular/framework/AT/AT_CellularBase.cpp
)
# Test files
set(unittest-test-sources
features/cellular/framework/AT/at_cellularbase/at_cellularbasetest.cpp
stubs/mbed_assert_stub.c
stubs/ATHandler_stub.cpp
stubs/EventQueue_stub.cpp
stubs/FileHandle_stub.cpp
)

View File

@ -0,0 +1,277 @@
/*
* Copyright (c) 2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "gtest/gtest.h"
#include "AT_CellularDevice.h"
#include "ATHandler_stub.h"
#include "AT_CellularBase_stub.h"
#include <string.h>
using namespace mbed;
using namespace events;
class TestAT_CellularDevice : public testing::Test {
protected:
void SetUp() {
}
void TearDown() {
}
};
TEST_F(TestAT_CellularDevice, Create)
{
EventQueue que;
AT_CellularDevice dev(que);
CellularDevice *dev2 = new AT_CellularDevice(que);
EXPECT_TRUE(dev2 != NULL);
delete dev2;
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_get_at_handler)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
FileHandle_stub fh2;
FileHandle_stub fh3;
EXPECT_TRUE(dev.open_network(&fh1));
EXPECT_TRUE(dev.open_sms(&fh2));
AT_CellularBase_stub::handler_value = AT_CellularBase_stub::handler_at_constructor_value;
EXPECT_TRUE(dev.open_sim(&fh3));
ATHandler_stub::fh_value = &fh1;
EXPECT_TRUE(dev.open_power(&fh1));
ATHandler_stub::fh_value = NULL;
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_open_network)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
EXPECT_TRUE(!dev.open_network(NULL));
EXPECT_TRUE(dev.open_network(&fh1));
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_open_sms)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
EXPECT_TRUE(!dev.open_sms(NULL));
EXPECT_TRUE(dev.open_sms(&fh1));
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_open_power)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
EXPECT_TRUE(!dev.open_power(NULL));
EXPECT_TRUE(dev.open_power(&fh1));
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_open_sim)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
EXPECT_TRUE(! dev.open_sim(NULL));
EXPECT_TRUE(dev.open_sim(&fh1));
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_open_information)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
EXPECT_TRUE(!dev.open_information(NULL));
EXPECT_TRUE(dev.open_information(&fh1));
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_close_network)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
ATHandler_stub::ref_count = 0;
EXPECT_TRUE(dev.open_network(&fh1));
AT_CellularBase_stub::handler_value = AT_CellularBase_stub::handler_at_constructor_value;
EXPECT_TRUE(ATHandler_stub::ref_count == 1);
dev.close_network();
EXPECT_TRUE(ATHandler_stub::ref_count == kATHandler_destructor_ref_ount);
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_close_sms)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
ATHandler_stub::ref_count = 0;
EXPECT_TRUE(dev.open_sms(&fh1));
AT_CellularBase_stub::handler_value = AT_CellularBase_stub::handler_at_constructor_value;
EXPECT_TRUE(ATHandler_stub::ref_count == 1);
dev.close_sms();
EXPECT_TRUE(ATHandler_stub::ref_count == kATHandler_destructor_ref_ount);
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_close_power)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
ATHandler_stub::ref_count = 0;
EXPECT_TRUE(dev.open_power(&fh1));
AT_CellularBase_stub::handler_value = AT_CellularBase_stub::handler_at_constructor_value;
EXPECT_TRUE(ATHandler_stub::ref_count == 1);
dev.close_power();
EXPECT_TRUE(ATHandler_stub::ref_count == kATHandler_destructor_ref_ount);
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_close_sim)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
ATHandler_stub::ref_count = 0;
int ana = 0;
EXPECT_TRUE(dev.open_sim(&fh1));
AT_CellularBase_stub::handler_value = AT_CellularBase_stub::handler_at_constructor_value;
ana = ATHandler_stub::ref_count;
dev.close_sms(); // this should not affect to refcount as it's not opened
EXPECT_TRUE(ATHandler_stub::ref_count == 1);
ana = ATHandler_stub::ref_count;
dev.close_sim();
EXPECT_TRUE(ATHandler_stub::ref_count == kATHandler_destructor_ref_ount);
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_close_information)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
ATHandler_stub::int_value = 0;
EXPECT_TRUE(dev.open_information(&fh1));
ATHandler_stub::fh_value = NULL;
AT_CellularBase_stub::handler_value = NULL;
dev.close_information();
ATHandler_stub::fh_value = &fh1;
ATHandler at(&fh1, que, 0, ",");
AT_CellularBase_stub::handler_value = &at;
EXPECT_TRUE(dev.open_information(&fh1));
AT_CellularBase_stub::handler_value = AT_CellularBase_stub::handler_at_constructor_value;
dev.close_information();
EXPECT_TRUE(ATHandler_stub::ref_count == 1);
ATHandler_stub::fh_value = NULL;
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_set_timeout)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
ATHandler_stub::timeout = 0;
ATHandler_stub::default_timeout = false;
// no interfaces open so settings timeout should not change anything
dev.set_timeout(5000);
EXPECT_TRUE(ATHandler_stub::timeout == 0);
EXPECT_TRUE(ATHandler_stub::default_timeout == false);
EXPECT_TRUE(dev.open_sim(&fh1));
EXPECT_TRUE(ATHandler_stub::ref_count == 1);
dev.set_timeout(5000);
EXPECT_TRUE(ATHandler_stub::timeout == 5000);
EXPECT_TRUE(ATHandler_stub::default_timeout == true);
dev.close_sim();
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_modem_debug_on)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
ATHandler_stub::debug_on = false;
// no interfaces open so debug toggling should not affect
dev.modem_debug_on(true);
EXPECT_TRUE(ATHandler_stub::debug_on == false);
EXPECT_TRUE(dev.open_sim(&fh1));
EXPECT_TRUE(ATHandler_stub::ref_count == 1);
dev.modem_debug_on(true);
EXPECT_TRUE(ATHandler_stub::debug_on == true);
dev.close_sim();
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_get_stack)
{
EventQueue que;
AT_CellularDevice dev(que);
FileHandle_stub fh1;
NetworkStack *stack = dev.get_stack();
EXPECT_TRUE(stack == NULL);
EXPECT_TRUE(dev.open_network(&fh1));
stack = dev.get_stack();
EXPECT_TRUE(stack == NULL); // Not in PPP so also null but this is got from the network class
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_get_send_delay)
{
EventQueue que;
AT_CellularDevice dev(que);
EXPECT_TRUE(0 == dev.get_send_delay());
}
TEST_F(TestAT_CellularDevice, test_AT_CellularDevice_init_module)
{
EventQueue que;
AT_CellularDevice dev(que);
EXPECT_TRUE(NSAPI_ERROR_OK == dev.init_module(NULL));
}

View File

@ -0,0 +1,36 @@
####################
# UNIT TESTS
####################
# Add test specific include paths
set(unittest-includes ${unittest-includes}
features/cellular/framework/common/util
../features/cellular/framework/common
../features/cellular/framework/AT
../features/frameworks/mbed-client-randlib/mbed-client-randlib
)
# Source files
set(unittest-sources
stubs/randLIB_stub.c
../features/cellular/framework/AT/AT_CellularDevice.cpp
)
# Test files
set(unittest-test-sources
features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp
stubs/AT_CellularNetwork_stub.cpp
stubs/ATHandler_stub.cpp
stubs/AT_CellularSMS_stub.cpp
stubs/AT_CellularSIM_stub.cpp
stubs/AT_CellularPower_stub.cpp
stubs/AT_CellularInformation_stub.cpp
stubs/CellularUtil_stub.cpp
stubs/AT_CellularBase_stub.cpp
stubs/NetworkInterface_stub.cpp
stubs/EventQueue_stub.cpp
stubs/FileHandle_stub.cpp
stubs/mbed_assert_stub.c
stubs/CellularDevice_stub.cpp
)

Some files were not shown because too many files have changed in this diff Show More