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

pull/8352/head
Offir Kochalsky 2018-10-21 08:51:49 +03:00
commit 638951aa86
692 changed files with 50680 additions and 3898 deletions

View File

@ -1,5 +1,6 @@
### Description
<!--
<!--
Required
Add detailed description of what you are reporting.
Good example: https://os.mbed.com/docs/latest/reference/workflow.html
@ -13,19 +14,15 @@
### Issue request type
<!--
<!--
Required
Please add only one X to one of the following types. Do not fill multiple types. (Split the issue otherwise.)
Please note this is not a GitHub task list; indenting the boxes or changing the format to add a '.' or '*' in front
of them changes the meaning incorrectly. The only changes to make are to add a description under the
description heading and to add an 'x' to the correct box.
[X] Question
[ ] Enhancement
[ ] Bug
Please add only one X to one of the following types. Do not fill multiple types (split the issue otherwise.)
Please note this is not a GitHub task list, indenting the boxes or changing the format to add a '.' or '*' in front
of them would change the meaning incorrectly. The only changes to be made are to add a description text under the
description heading and to add a 'x' to the correct box.
-->
[ ] Question
[ ] Enhancement
[ ] Bug
[ ] Question
[ ] Enhancement
[ ] Bug

View File

@ -20,5 +20,7 @@
[ ] Refactor
[ ] Target update
[ ] Functionality change
[ ] Docs update
[ ] Test update
[ ] Breaking change

View File

@ -86,6 +86,7 @@ matrix:
- arm-none-eabi-gcc --version
- python --version
- pip list --verbose
script:
# Run local testing on tools
- PYTHONPATH=. coverage run -a -m pytest tools/test
@ -132,10 +133,10 @@ matrix:
# update status if we succeeded, compare with master if possible
- |
CURR=$(cat astyle-branch.out | grep Formatted | wc -l)
PREV=$(curl https://api.github.com/repos/$TRAVIS_REPO_SLUG/status/master \
PREV=$(curl -u "$MBED_BOT" https://api.github.com/repos/$TRAVIS_REPO_SLUG/status/master \
| jq -re "select(.sha != \"$TRAVIS_COMMIT\")
| .statuses[] | select(.context == \"travis-ci/$NAME\").description
| capture(\", (?<files>[0-9]+) files\").warnings" \
| capture(\", (?<files>[0-9]+) files\").files" \
|| echo 0)
STATUSM="Passed, ${CURR} files"

View File

@ -29,7 +29,7 @@ class RtcResetTest(BaseHostTest):
"""
"""Start of the RTC"""
START_TIME = 50000
START_TIME = 1537789823 # GMT: Monday, 24 September 2018 11:50:23
START_TIME_TOLERANCE = 10
"""Time to delay after sending reset"""
DELAY_TIME = 5.0

View File

@ -38,6 +38,7 @@
using namespace utest::v1;
using namespace mbed;
static LoRaRadio *radio = NULL;
rtos::Semaphore event_sem(0);

View File

@ -79,7 +79,7 @@ void test_multi_ticker(void)
ticker[i].attach_us(callback(increment_multi_counter), MULTI_TICKER_TIME_MS * 1000);
}
Thread::wait(MULTI_TICKER_TIME_MS + extra_wait);
ThisThread::sleep_for(MULTI_TICKER_TIME_MS + extra_wait);
TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter);
for (int i = 0; i < TICKER_COUNT; i++) {
@ -95,7 +95,7 @@ void test_multi_ticker(void)
ticker[i].attach_us(callback(increment_multi_counter), (MULTI_TICKER_TIME_MS + i) * 1000);
}
Thread::wait(MULTI_TICKER_TIME_MS + TICKER_COUNT + extra_wait);
ThisThread::sleep_for(MULTI_TICKER_TIME_MS + TICKER_COUNT + extra_wait);
TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter);
for (int i = 0; i < TICKER_COUNT; i++) {

View File

@ -391,7 +391,7 @@ static void test_case_multithread_malloc_free()
threads[i].start(callback(malloc_free, &threads_continue));
}
Thread::wait(wait_time_us);
ThisThread::sleep_for(wait_time_us);
threads_continue = false;
for (int i = 0; i < NUM_TEST_THREADS; i++) {

View File

@ -39,13 +39,13 @@ class TestClass {
public:
TestClass()
{
Thread::wait(500);
ThisThread::sleep_for(500);
instance_count++;
}
void do_something()
{
Thread::wait(100);
ThisThread::sleep_for(100);
}
~TestClass()
@ -83,7 +83,7 @@ void test_case_func_race()
// Start start first thread
t1.start(cb);
// Start second thread while the first is inside the constructor
Thread::wait(250);
ThisThread::sleep_for(250);
t2.start(cb);
// Wait for the threads to finish
@ -105,7 +105,7 @@ void test_case_class_race()
// Start start first thread
t1.start(cb);
// Start second thread while the first is inside the constructor
Thread::wait(250);
ThisThread::sleep_for(250);
t2.start(cb);
// Wait for the threads to finish

View File

@ -195,7 +195,7 @@ void test_multi_ticker(void)
ticker[i].attach_us(callback(increment_multi_counter), MULTI_TICKER_TIME_MS * 1000);
}
Thread::wait(MULTI_TICKER_TIME_MS + extra_wait);
ThisThread::sleep_for(MULTI_TICKER_TIME_MS + extra_wait);
TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter);
for (int i = 0; i < TICKER_COUNT; i++) {
@ -211,7 +211,7 @@ void test_multi_ticker(void)
ticker[i].attach_us(callback(increment_multi_counter), (MULTI_TICKER_TIME_MS + i) * 1000);
}
Thread::wait(MULTI_TICKER_TIME_MS + TICKER_COUNT + extra_wait);
ThisThread::sleep_for(MULTI_TICKER_TIME_MS + TICKER_COUNT + extra_wait);
TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter);
for (int i = 0; i < TICKER_COUNT; i++) {

View File

@ -177,7 +177,7 @@ void test_multiple(void)
for (size_t i = 0; i < NUM_TIMEOUTS; i++) {
timeouts[i].attach_callback(mbed::callback(cnt_callback, &callback_count), TEST_DELAY_US);
}
Thread::wait(TEST_DELAY_MS + 2);
ThisThread::sleep_for(TEST_DELAY_MS + 2);
TEST_ASSERT_EQUAL(NUM_TIMEOUTS, callback_count);
}

View File

@ -0,0 +1,71 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "mbed.h"
using namespace utest::v1;
/**
* This test is intended to gate devices that do not have enough RAM to run
* Mbed os. Devices passing this test should have enough RAM to run all
* other Mbed OS tests.
*
* If your device does not pass this test, then you should determine the
* cause of high memory usage and fix it. If you cannot free enough memory,
* then you should turn off Mbed OS support for this device.
*/
#define MIN_HEAP_SIZE 2048
#define MIN_DATA_SIZE 2048
volatile uint8_t test_buffer[MIN_DATA_SIZE];
static void minimum_heap_test()
{
void *mem = malloc(MIN_HEAP_SIZE);
TEST_ASSERT_NOT_EQUAL(NULL, mem);
free(mem);
}
static void minimum_data_test()
{
// Use test buffer so it is not optimized away
for (int i = 0; i < MIN_DATA_SIZE; i++) {
test_buffer[i] = i & 0xFF;
}
}
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(30, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("Minimum heap test", minimum_heap_test),
Case("Minimum data test", minimum_data_test),
};
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main() {
Harness::run(specification);
}

View File

@ -25,26 +25,9 @@
#include "greentea-client/test_env.h"
#include "mbed_lp_ticker_wrapper.h"
#include "sleep_test_utils.h"
#include "sleep_api_tests.h"
#define US_PER_S 1000000
/* Flush serial buffer before deep sleep
*
* Since deepsleep() may shut down the UART peripheral, we wait for some time
* to allow for hardware serial buffers to completely flush.
*
* Take NUMAKER_PFM_NUC472 as an example:
* Its UART peripheral has 16-byte Tx FIFO. With baud rate set to 9600, flush
* Tx FIFO would take: 16 * 8 * 1000 / 9600 = 13.3 (ms). So set wait time to
* 20ms here for safe.
*
* This should be replaced with a better function that checks if the
* hardware buffers are empty. However, such an API does not exist now,
* so we'll use the busy_wait_ms() function for now.
*/
#define SERIAL_FLUSH_TIME_MS 20
using namespace utest::v1;
static char info[512] = {0};
@ -67,71 +50,6 @@ static const uint32_t sleep_mode_delta_us = (10 + 4 + 5);
* delta = default 10 ms + worst ticker resolution + extra time for code execution */
static const uint32_t deepsleep_mode_delta_us = (10000 + 125 + 5);
unsigned int ticks_to_us(unsigned int ticks, unsigned int freq)
{
return (unsigned int)((unsigned long long) ticks * US_PER_S / freq);
}
unsigned int us_to_ticks(unsigned int us, unsigned int freq)
{
return (unsigned int)((unsigned long long) us * freq / US_PER_S);
}
unsigned int overflow_protect(unsigned int timestamp, unsigned int ticker_width)
{
unsigned int counter_mask = ((1 << ticker_width) - 1);
return (timestamp & counter_mask);
}
bool compare_timestamps(unsigned int delta_ticks, unsigned int ticker_width, unsigned int expected, unsigned int actual)
{
const unsigned int counter_mask = ((1 << ticker_width) - 1);
const unsigned int lower_bound = ((expected - delta_ticks) & counter_mask);
const unsigned int upper_bound = ((expected + delta_ticks) & counter_mask);
if (lower_bound < upper_bound) {
if (actual >= lower_bound && actual <= upper_bound) {
return true;
} else {
return false;
}
} else {
if ((actual >= lower_bound && actual <= counter_mask) || (actual >= 0 && actual <= upper_bound)) {
return true;
} else {
return false;
}
}
}
void busy_wait_ms(int ms)
{
const ticker_info_t *info = us_ticker_get_info();
uint32_t mask = (1 << info->bits) - 1;
int delay = (int)((uint64_t)ms * info->frequency / 1000);
uint32_t prev = us_ticker_read();
while (delay > 0) {
uint32_t next = us_ticker_read();
delay -= (next - prev) & mask;
prev = next;
}
}
void us_ticker_isr(const ticker_data_t *const ticker_data)
{
us_ticker_clear_interrupt();
}
#ifdef DEVICE_LPTICKER
void lp_ticker_isr(const ticker_data_t *const ticker_data)
{
lp_ticker_clear_interrupt();
}
#endif
/* Test that wake-up time from sleep should be less than 10 us and
* high frequency ticker interrupt can wake-up target from sleep. */
void sleep_usticker_test()

View File

@ -0,0 +1,114 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @addtogroup hal_sleep_test_utils
* @{
*/
#ifndef MBED_SLEEP_TEST_UTILS_H
#define MBED_SLEEP_TEST_UTILS_H
#include "hal/ticker_api.h"
#include "hal/us_ticker_api.h"
#include "hal/lp_ticker_api.h"
/* Flush serial buffer before deep sleep
*
* Since deepsleep() may shut down the UART peripheral, we wait for some time
* to allow for hardware serial buffers to completely flush.
*
* Take NUMAKER_PFM_NUC472 as an example:
* Its UART peripheral has 16-byte Tx FIFO. With baud rate set to 9600, flush
* Tx FIFO would take: 16 * 8 * 1000 / 9600 = 13.3 (ms). So set wait time to
* 20ms here for safe.
*
* This should be replaced with a better function that checks if the
* hardware buffers are empty. However, such an API does not exist now,
* so we'll use the busy_wait_ms() function for now.
*/
#define SERIAL_FLUSH_TIME_MS 20
#define US_PER_S 1000000
unsigned int ticks_to_us(unsigned int ticks, unsigned int freq)
{
return (unsigned int) ((unsigned long long) ticks * US_PER_S / freq);
}
unsigned int us_to_ticks(unsigned int us, unsigned int freq)
{
return (unsigned int) ((unsigned long long) us * freq / US_PER_S);
}
unsigned int overflow_protect(unsigned int timestamp, unsigned int ticker_width)
{
unsigned int counter_mask = ((1 << ticker_width) - 1);
return (timestamp & counter_mask);
}
bool compare_timestamps(unsigned int delta_ticks, unsigned int ticker_width, unsigned int expected, unsigned int actual)
{
const unsigned int counter_mask = ((1 << ticker_width) - 1);
const unsigned int lower_bound = ((expected - delta_ticks) & counter_mask);
const unsigned int upper_bound = ((expected + delta_ticks) & counter_mask);
if (lower_bound < upper_bound) {
if (actual >= lower_bound && actual <= upper_bound) {
return true;
} else {
return false;
}
} else {
if ((actual >= lower_bound && actual <= counter_mask) || (actual >= 0 && actual <= upper_bound)) {
return true;
} else {
return false;
}
}
}
void busy_wait_ms(int ms)
{
const ticker_info_t *info = us_ticker_get_info();
uint32_t mask = (1 << info->bits) - 1;
int delay = (int) ((uint64_t) ms * info->frequency / 1000);
uint32_t prev = us_ticker_read();
while (delay > 0) {
uint32_t next = us_ticker_read();
delay -= (next - prev) & mask;
prev = next;
}
}
void us_ticker_isr(const ticker_data_t * const ticker_data)
{
us_ticker_clear_interrupt();
}
#ifdef DEVICE_LPTICKER
void lp_ticker_isr(const ticker_data_t * const ticker_data)
{
lp_ticker_clear_interrupt();
}
#endif
#endif
/** @}*/

View File

@ -16,46 +16,286 @@
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include <limits.h>
#include "mbed.h"
#include "mbed_lp_ticker_wrapper.h"
#include "../sleep/sleep_test_utils.h"
#include "sleep_manager_api_tests.h"
#if !DEVICE_SLEEP
#error [NOT_SUPPORTED] test not supported
#endif
using namespace utest::v1;
#define SLEEP_DURATION_US 20000ULL
#define DEEP_SLEEP_TEST_CHECK_WAIT_US 2000
#define DEEP_SLEEP_TEST_CHECK_WAIT_DELTA_US 500
void sleep_manager_deepsleep_counter_test()
using utest::v1::Case;
using utest::v1::Specification;
using utest::v1::Harness;
static uint32_t num_test_errors = 0UL;
mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value,
const char *filename, int line_number)
{
bool deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check();
TEST_ASSERT_TRUE(deep_sleep_allowed);
(void) error_status;
(void) error_msg;
(void) error_value;
(void) filename;
(void) line_number;
num_test_errors++;
return MBED_SUCCESS;
}
void test_lock_unlock()
{
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
sleep_manager_lock_deep_sleep();
deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check();
TEST_ASSERT_FALSE(deep_sleep_allowed);
TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep());
sleep_manager_unlock_deep_sleep();
deep_sleep_allowed = sleep_manager_can_deep_sleep_test_check();
TEST_ASSERT_TRUE(deep_sleep_allowed);
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
}
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason)
void test_lone_unlock()
{
greentea_case_failure_abort_handler(source, reason);
return STATUS_CONTINUE;
uint32_t expected_err_count = num_test_errors + 1;
sleep_manager_unlock_deep_sleep();
TEST_ASSERT_EQUAL_UINT32(expected_err_count, num_test_errors);
// Make sure upcoming tests won't be broken.
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
}
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
void test_lock_eq_ushrt_max()
{
GREENTEA_SETUP(20, "default_auto");
return greentea_test_setup_handler(number_of_cases);
uint32_t lock_count = 0;
while (lock_count < USHRT_MAX) {
sleep_manager_lock_deep_sleep();
lock_count++;
TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep());
}
while (lock_count > 1) {
sleep_manager_unlock_deep_sleep();
lock_count--;
TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep());
}
sleep_manager_unlock_deep_sleep();
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
}
void test_lock_gt_ushrt_max()
{
uint32_t lock_count = 0;
while (lock_count < USHRT_MAX) {
sleep_manager_lock_deep_sleep();
lock_count++;
TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep());
}
uint32_t expected_err_count = num_test_errors + 1;
sleep_manager_lock_deep_sleep();
TEST_ASSERT_EQUAL_UINT32(expected_err_count, num_test_errors);
// Make sure upcoming tests won't be broken.
while (lock_count > 0) {
sleep_manager_unlock_deep_sleep();
lock_count--;
}
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
}
#if DEVICE_LPTICKER
#if DEVICE_USTICKER
utest::v1::status_t testcase_setup(const Case * const source, const size_t index_of_case)
{
// Suspend the RTOS kernel scheduler to prevent interference with duration of sleep.
osKernelSuspend();
#if DEVICE_LPTICKER
ticker_suspend(get_lp_ticker_data());
#if (LPTICKER_DELAY_TICKS > 0)
// Suspend the low power ticker wrapper to prevent interference with deep sleep lock.
lp_ticker_wrapper_suspend();
#endif
#endif
ticker_suspend(get_us_ticker_data());
// Make sure HAL tickers are initialized.
us_ticker_init();
#if DEVICE_LPTICKER
lp_ticker_init();
#endif
return utest::v1::greentea_case_setup_handler(source, index_of_case);
}
utest::v1::status_t testcase_teardown(const Case * const source, const size_t passed, const size_t failed,
const utest::v1::failure_t failure)
{
ticker_resume(get_us_ticker_data());
#if DEVICE_LPTICKER
#if (LPTICKER_DELAY_TICKS > 0)
lp_ticker_wrapper_resume();
#endif
ticker_resume(get_lp_ticker_data());
#endif
osKernelResume(0);
return utest::v1::greentea_case_teardown_handler(source, passed, failed, failure);
}
/* This test is based on the fact that the high-speed clocks are turned off
* in deep sleep mode but remain on in the ordinary sleep mode. Low-speed
* clocks stay on for both sleep and deep sleep modes.
*
* The type of sleep that was actually used by sleep_manager_sleep_auto()
* can be detected by comparing times measured by us and lp tickers.
*/
void test_sleep_auto()
{
const ticker_info_t *us_ticker_info = get_us_ticker_data()->interface->get_info();
const unsigned us_ticker_mask = ((1 << us_ticker_info->bits) - 1);
const ticker_irq_handler_type us_ticker_irq_handler_org = set_us_ticker_irq_handler(us_ticker_isr);
const ticker_info_t *lp_ticker_info = get_lp_ticker_data()->interface->get_info();
const unsigned lp_ticker_mask = ((1 << lp_ticker_info->bits) - 1);
const ticker_irq_handler_type lp_ticker_irq_handler_org = set_lp_ticker_irq_handler(lp_ticker_isr);
us_timestamp_t us_ts1, us_ts2, lp_ts1, lp_ts2, us_diff1, us_diff2, lp_diff1, lp_diff2;
sleep_manager_lock_deep_sleep();
uint32_t lp_wakeup_ts_raw = lp_ticker_read() + us_to_ticks(SLEEP_DURATION_US, lp_ticker_info->frequency);
timestamp_t lp_wakeup_ts = overflow_protect(lp_wakeup_ts_raw, lp_ticker_info->bits);
lp_ticker_set_interrupt(lp_wakeup_ts);
us_ts1 = ticks_to_us(us_ticker_read(), us_ticker_info->frequency);
lp_ts1 = ticks_to_us(lp_ticker_read(), lp_ticker_info->frequency);
sleep_manager_sleep_auto();
us_ts2 = ticks_to_us(us_ticker_read(), us_ticker_info->frequency);
us_diff1 = (us_ts1 <= us_ts2) ? (us_ts2 - us_ts1) : (us_ticker_mask - us_ts1 + us_ts2 + 1);
lp_ts2 = ticks_to_us(lp_ticker_read(), lp_ticker_info->frequency);
lp_diff1 = (lp_ts1 <= lp_ts2) ? (lp_ts2 - lp_ts1) : (lp_ticker_mask - lp_ts1 + lp_ts2 + 1);
// Deep sleep locked -- ordinary sleep mode used:
// * us_ticker powered ON,
// * lp_ticker powered ON,
// so both should increment equally.
// Verify us and lp tickers incremented equally, with 10% tolerance.
TEST_ASSERT_UINT64_WITHIN_MESSAGE(
SLEEP_DURATION_US / 10ULL, lp_diff1, us_diff1,
"Deep sleep mode locked, but still used");
sleep_manager_unlock_deep_sleep();
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
// Wait for hardware serial buffers to flush.
busy_wait_ms(SERIAL_FLUSH_TIME_MS);
lp_wakeup_ts_raw = lp_ticker_read() + us_to_ticks(SLEEP_DURATION_US, lp_ticker_info->frequency);
lp_wakeup_ts = overflow_protect(lp_wakeup_ts_raw, lp_ticker_info->bits);
lp_ticker_set_interrupt(lp_wakeup_ts);
us_ts1 = ticks_to_us(us_ticker_read(), us_ticker_info->frequency);
lp_ts1 = ticks_to_us(lp_ticker_read(), lp_ticker_info->frequency);
sleep_manager_sleep_auto();
us_ts2 = ticks_to_us(us_ticker_read(), us_ticker_info->frequency);
us_diff2 = (us_ts1 <= us_ts2) ? (us_ts2 - us_ts1) : (us_ticker_mask - us_ts1 + us_ts2 + 1);
lp_ts2 = ticks_to_us(lp_ticker_read(), lp_ticker_info->frequency);
lp_diff2 = (lp_ts1 <= lp_ts2) ? (lp_ts2 - lp_ts1) : (lp_ticker_mask - lp_ts1 + lp_ts2 + 1);
// Deep sleep unlocked -- deep sleep mode used:
// * us_ticker powered OFF,
// * lp_ticker powered ON.
// The us_ticker increment represents only the code execution time
// and should be much shorter than both:
// 1. current lp_ticker increment,
// 2. previous us_ticker increment (locked sleep test above)
// Verify that the current us_ticker increment:
// 1. is at most 10% of lp_ticker increment
// 2. is at most 10% of previous us_ticker increment.
TEST_ASSERT_MESSAGE(us_diff2 < lp_diff2 / 10ULL, "Deep sleep mode unlocked, but not used");
TEST_ASSERT_MESSAGE(us_diff2 < us_diff1 / 10ULL, "Deep sleep mode unlocked, but not used");
set_us_ticker_irq_handler(us_ticker_irq_handler_org);
set_lp_ticker_irq_handler(lp_ticker_irq_handler_org);
}
#endif
void test_lock_unlock_test_check()
{
// Make sure HAL tickers are initialized.
ticker_read(get_us_ticker_data());
ticker_read(get_lp_ticker_data());
// Use LowPowerTimer instead of Timer to prevent deep sleep lock.
LowPowerTimer lp_timer;
us_timestamp_t exec_time_unlocked, exec_time_locked;
LowPowerTimeout lp_timeout;
// Deep sleep unlocked:
// * sleep_manager_can_deep_sleep() returns true,
// * sleep_manager_can_deep_sleep_test_check() returns true instantly.
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
lp_timer.start();
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep_test_check());
lp_timer.stop();
exec_time_unlocked = lp_timer.read_high_resolution_us();
// Deep sleep locked:
// * sleep_manager_can_deep_sleep() returns false,
// * sleep_manager_can_deep_sleep_test_check() returns false with 2 ms delay.
sleep_manager_lock_deep_sleep();
TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep());
lp_timer.reset();
lp_timer.start();
TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep_test_check());
lp_timer.stop();
exec_time_locked = lp_timer.read_high_resolution_us();
TEST_ASSERT_UINT64_WITHIN(DEEP_SLEEP_TEST_CHECK_WAIT_DELTA_US, DEEP_SLEEP_TEST_CHECK_WAIT_US,
exec_time_locked - exec_time_unlocked);
// Deep sleep unlocked with a 1 ms delay:
// * sleep_manager_can_deep_sleep() returns false,
// * sleep_manager_can_deep_sleep_test_check() returns true with a 1 ms delay,
// * sleep_manager_can_deep_sleep() returns true when checked again.
lp_timer.reset();
lp_timeout.attach_us(mbed::callback(sleep_manager_unlock_deep_sleep_internal),
DEEP_SLEEP_TEST_CHECK_WAIT_US / 2);
lp_timer.start();
TEST_ASSERT_FALSE(sleep_manager_can_deep_sleep());
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep_test_check());
lp_timer.stop();
TEST_ASSERT_UINT64_WITHIN(DEEP_SLEEP_TEST_CHECK_WAIT_DELTA_US, DEEP_SLEEP_TEST_CHECK_WAIT_US / 2,
lp_timer.read_high_resolution_us());
TEST_ASSERT_TRUE(sleep_manager_can_deep_sleep());
}
#endif
utest::v1::status_t testsuite_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(10, "default_auto");
return utest::v1::greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("sleep manager - deep sleep counter", sleep_manager_deepsleep_counter_test, greentea_failure_handler),
Case("deep sleep lock/unlock", test_lock_unlock),
Case("deep sleep unbalanced unlock", test_lone_unlock),
Case("deep sleep locked USHRT_MAX times", test_lock_eq_ushrt_max),
Case("deep sleep locked more than USHRT_MAX times", test_lock_gt_ushrt_max),
#if DEVICE_LPTICKER
#if DEVICE_USTICKER
Case("sleep_auto calls sleep/deep sleep based on lock",
(utest::v1::case_setup_handler_t) testcase_setup,
test_sleep_auto,
(utest::v1::case_teardown_handler_t) testcase_teardown),
#endif
Case("deep sleep lock/unlock test_check", test_lock_unlock_test_check),
#endif
};
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
Specification specification(testsuite_setup, cases);
int main()
{
Harness::run(specification);
return !Harness::run(specification);
}

View File

@ -0,0 +1,102 @@
/* mbed Microcontroller Library
* 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.
*/
/**
* @addtogroup hal_sleep_manager_tests
* @{
*/
#ifndef MBED_HAL_SLEEP_MANAGER_API_TESTS_H
#define MBED_HAL_SLEEP_MANAGER_API_TESTS_H
#if DEVICE_SLEEP
/** Test lock/unlock
*
* Given no prior calls to lock/unlock
* When the deep sleep status is checked
* Then the deep sleep is allowed
*
* When the lock function is called
* Then the deep sleep is not allowed
*
* When the unlock function is called
* Then the deep sleep is allowed again
*/
void test_lock_unlock();
/** Test an unbalanced unlock call
*
* Given the deep sleep has not been locked
* When the deep sleep mode is unlocked
* Then an mbed_error is raised
*/
void test_lone_unlock();
/** Test lock USHRT_MAX times
*
* Given a device with sleep mode support
* When deep sleep mode is locked USHRT_MAX times
* Then the deep sleep mode is locked
*
* When unlock is called repeatedly
* Then deep sleep mode stays locked until the number
* of unlock calls is equal to number of lock calls
*/
void test_lock_eq_ushrt_max();
/** Test lock more than USHRT_MAX times
*
* Given the deep sleep has already been locked USHRT_MAX times
* When the deep sleep mode is locked again
* Then an mbed_error is raised
*/
void test_lock_gt_ushrt_max();
/** Test sleep_auto calls sleep and deep sleep based on lock
*
* Given a device with sleep mode support
* When the deep sleep mode is locked
* Then sleep_auto uses sleep mode
*
* When the deep sleep mode is unlocked
* Then sleep_auto uses deep sleep mode
*/
void test_sleep_auto();
/** Test lock/unlock test_check fun
*
* Given the deep sleep has not been locked
* When the deep sleep status is checked
* Then sleep_manager_can_deep_sleep() returns true
* and sleep_manager_can_deep_sleep_test_check() returns true instantly.
*
* When the deep sleep mode is locked
* Then sleep_manager_can_deep_sleep() returns false
* and sleep_manager_can_deep_sleep_test_check() returns false with 2 ms delay.
*
* When the deep sleep mode is unlocked with a 1 ms delay
* Then sleep_manager_can_deep_sleep() returns false
* and sleep_manager_can_deep_sleep_test_check() returns true with 1 ms delay
* and sleep_manager_can_deep_sleep() returns true when checked again.
*/
void test_lock_unlock_test_check();
#endif
#endif
/** @}*/

View File

@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "mbed.h"
#include "sleep_manager_api_racecondition_tests.h"
#if !DEVICE_SLEEP
#error [NOT_SUPPORTED] test not supported
@ -34,7 +35,7 @@ void sleep_manager_locking_thread_test()
{
for (uint32_t i = 0; i < 100; i++) {
sleep_manager_lock_deep_sleep();
Thread::wait(25);
ThisThread::sleep_for(25);
sleep_manager_unlock_deep_sleep();
}
}
@ -47,7 +48,7 @@ void sleep_manager_multithread_test()
Thread t2(osPriorityNormal, TEST_STACK_SIZE);
t1.start(callback(cb));
Thread::wait(25);
ThisThread::sleep_for(25);
t2.start(callback(cb));
// Wait for the threads to finish
@ -94,8 +95,8 @@ utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
}
Case cases[] = {
Case("sleep manager HAL - locking multithreaded", sleep_manager_multithread_test),
Case("sleep manager HAL - locking IRQ", sleep_manager_irq_test),
Case("deep sleep lock/unlock is thread safe", sleep_manager_multithread_test),
Case("deep sleep lock/unlock is IRQ safe", sleep_manager_irq_test),
};
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

View File

@ -0,0 +1,43 @@
/* mbed Microcontroller Library
* 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.
*/
/**
* @addtogroup hal_sleep_manager_tests
* @{
*/
#ifndef MBED_HAL_SLEEP_MANAGER_API_RACECONDITION_TESTS_H
#define MBED_HAL_SLEEP_MANAGER_API_RACECONDITION_TESTS_H
/** Test lock/unlock is thread safe
*
* Given a device with sleep mode support
* When multiple threads are using the sleep manager API
* Then lock/unlock calls are thread safe
*/
void sleep_manager_multithread_test();
/** Test lock/unlock is IRQ safe
*
* Given a device with sleep mode support
* When the sleep manager API is used from IRQ and the main thread concurrently
* Then lock/unlock calls are IRQ safe
*/
void sleep_manager_irq_test();
#endif
/** @}*/

View File

@ -18,14 +18,13 @@
#include "platform/FileHandle.h"
#define POS_IS_VALID(pos) (pos >= 0 && pos < _end)
#define NEW_POS_IS_VALID(pos) (pos >= 0 && pos < (int32_t)FILE_SIZE)
#define SEEK_POS_IS_VALID(pos) (pos >= 0 && pos <= _end)
#define INVALID_POS (-1)
template<uint32_t FILE_SIZE>
class TestFile : public FileHandle {
class TestFile : public mbed::FileHandle {
public:
TestFile(): _pos(0), _end(0) {}
~TestFile() {}

View File

@ -0,0 +1,75 @@
/* mbed Microcontroller Library
* 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.
*/
#include "greentea-client/test_env.h"
#include "utest/utest.h"
#include "unity/unity.h"
#include "mbed.h"
using utest::v1::Case;
class Loopback : public Stream {
public:
Loopback(const char *name = NULL) : Stream(name) {}
protected:
virtual int _getc()
{
return _c;
}
virtual int _putc(int c)
{
_c = c;
return c;
}
private:
char _c;
};
Loopback loop("loopback");
void test_putc_getc()
{
int ret;
char char_buf[2] = {'a', 'b'};
ret = loop.putc(char_buf[0]);
TEST_ASSERT_EQUAL_INT(char_buf[0], ret);
ret = loop.getc();
TEST_ASSERT_EQUAL_INT(char_buf[0], ret);
ret = loop.putc(char_buf[1]);
TEST_ASSERT_EQUAL_INT(char_buf[1], ret);
ret = loop.getc();
TEST_ASSERT_EQUAL_INT(char_buf[1], ret);
return;
}
utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(10, "default_auto");
return utest::v1::verbose_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("Test putc/getc", test_putc_getc)
};
utest::v1::Specification specification(test_setup, cases);
int main()
{
return !utest::v1::Harness::run(specification);
}

View File

@ -56,7 +56,7 @@ void get_cpu_usage()
uint8_t usage = 100 - ((diff * 100) / (SAMPLE_TIME * 1000));
prev_idle_time = stats.idle_time;
TEST_ASSERT_NOT_EQUAL(0, usage);
Thread::wait(SAMPLE_TIME);
ThisThread::sleep_for(SAMPLE_TIME);
}
}
@ -65,7 +65,7 @@ void test_cpu_info(void)
mbed_stats_cpu_t stats;
// Additional read to make sure timer is initialized
mbed_stats_cpu_get(&stats);
Thread::wait(3);
ThisThread::sleep_for(3);
mbed_stats_cpu_get(&stats);
TEST_ASSERT_NOT_EQUAL(0, stats.uptime);
TEST_ASSERT_NOT_EQUAL(0, stats.idle_time);
@ -83,7 +83,7 @@ void test_cpu_load(void)
// Steadily increase the system load
for (int count = 1; ; count++) {
Thread::wait(LOOP_TIME);
ThisThread::sleep_for(LOOP_TIME);
if (wait_time <= 0) {
break;
}

View File

@ -46,7 +46,7 @@ void increment_with_delay()
{
while (1) {
counter++;
Thread::wait(500);
ThisThread::sleep_for(500);
}
}
@ -111,7 +111,7 @@ void test_case_multi_threads_blocked()
uint32_t ret = ef.set(FLAG_SIGNAL_DEC);
TEST_ASSERT_FALSE(ret & osFlagsError);
Thread::wait(100);
ThisThread::sleep_for(100);
count = mbed_stats_thread_get_each(stats, MAX_THREAD_STATS);
TEST_ASSERT_EQUAL(1, (count - old_count));

View File

@ -48,7 +48,7 @@ static const int test_timeout = 40;
void update_tick_thread(Mutex *mutex)
{
while (true) {
Thread::wait(1);
ThisThread::sleep_for(1);
mutex->lock();
++elapsed_time_ms;
mutex->unlock();
@ -56,7 +56,7 @@ void update_tick_thread(Mutex *mutex)
}
/** Tests is to measure the accuracy of Thread::wait() over a period of time
/** Tests is to measure the accuracy of ThisThread::sleep_for() over a period of time
Given
a thread updating elapsed_time_ms every milli sec
@ -109,7 +109,7 @@ void test(void)
}
Case cases[] = {
Case("Test Thread::wait accuracy", test)
Case("Test ThisThread::sleep_for accuracy", test)
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)

View File

@ -75,7 +75,7 @@ void send_thread(EventFlags *ef)
const uint32_t flag = flags & (1 << i);
if (flag) {
ef->set(flag);
Thread::wait(wait_ms);
ThisThread::sleep_for(wait_ms);
}
}
}
@ -88,7 +88,7 @@ void send_thread_sync(EventFlags *ef)
if (flag) {
sync_sem.wait();
ef->set(flag);
Thread::wait(wait_ms);
ThisThread::sleep_for(wait_ms);
}
}
}

View File

@ -226,7 +226,7 @@ void test_heap_allocation_free(void)
check_and_free_heap(head, max_allocation_size);
// Force a task switch so a stack check is performed
Thread::wait(10);
ThisThread::sleep_for(10);
printf("Total size dynamically allocated: %luB\n", max_allocation_size);
}

View File

@ -62,7 +62,7 @@ void send_thread(Mail<mail_t, QUEUE_SIZE> *m)
mail->thread_id = thread_id;
mail->data = data++;
m->put(mail);
Thread::wait(wait_ms);
ThisThread::sleep_for(wait_ms);
}
}
@ -72,7 +72,7 @@ void receive_thread(Mail<mail_t, queue_size> *m)
int result_counter = 0;
uint32_t data = thread_id * DATA_BASE;
Thread::wait(wait_ms);
ThisThread::sleep_for(wait_ms);
for (uint32_t i = 0; i < queue_size; i++) {
osEvent evt = m->get();
if (evt.status == osEventMail) {
@ -108,7 +108,7 @@ void test_single_thread_order(void)
thread.start(callback(send_thread<THREAD_1_ID, QUEUE_PUT_DELAY_1, QUEUE_SIZE>, &mail_box));
// wait for some mail to be collected
Thread::wait(10);
ThisThread::sleep_for(10);
for (uint32_t i = 0; i < QUEUE_SIZE; i++) {
// mail receive (main thread)
@ -150,7 +150,7 @@ void test_multi_thread_order(void)
thread3.start(callback(send_thread<THREAD_3_ID, QUEUE_PUT_DELAY_3, 4>, &mail_box));
// wait for some mail to be collected
Thread::wait(10);
ThisThread::sleep_for(10);
for (uint32_t i = 0; i < QUEUE_SIZE; i++) {
// mail receive (main thread)
@ -211,7 +211,7 @@ void test_multi_thread_multi_mail_order(void)
mail->data = data[id]++;
mail_box[id].put(mail);
Thread::wait(i * 10);
ThisThread::sleep_for(i * 10);
}
thread1.join();

View File

@ -90,7 +90,7 @@ void test_multithread_allocation(void)
// Give the test time to run
while (test_time--) {
Thread::wait(1000);
ThisThread::sleep_for(1000);
}
// Join and delete all threads

View File

@ -62,7 +62,7 @@ bool manipulate_protected_zone(const int thread_delay)
change_counter++;
core_util_critical_section_exit();
Thread::wait(thread_delay);
ThisThread::sleep_for(thread_delay);
core_util_critical_section_enter();
changing_counter = false;
@ -100,7 +100,7 @@ void test_multiple_threads(void)
while (true) {
// Thread 1 action
Thread::wait(t1_delay);
ThisThread::sleep_for(t1_delay);
manipulate_protected_zone(t1_delay);
core_util_critical_section_enter();

View File

@ -37,7 +37,7 @@ using namespace utest::v1;
template <uint32_t ms>
void thread_put_uint_msg(Queue<uint32_t, 1> *q)
{
Thread::wait(ms);
ThisThread::sleep_for(ms);
osStatus stat = q->put((uint32_t *) TEST_UINT_MSG);
TEST_ASSERT_EQUAL(osOK, stat);
}
@ -45,7 +45,7 @@ void thread_put_uint_msg(Queue<uint32_t, 1> *q)
template <uint32_t ms, uint32_t val>
void thread_get_uint_msg(Queue<uint32_t, 1> *q)
{
Thread::wait(ms);
ThisThread::sleep_for(ms);
osEvent evt = q->get();
TEST_ASSERT_EQUAL(osEventMessage, evt.status);
TEST_ASSERT_EQUAL(val, evt.value.v);

View File

@ -52,7 +52,7 @@ void test_thread(int const *delay)
if (sem_lock_failed) {
sem_defect = true;
}
Thread::wait(thread_delay);
ThisThread::sleep_for(thread_delay);
sem_counter--;
change_counter++;
two_slots.release();
@ -123,7 +123,7 @@ void test_single_thread()
res = t.start(callback(single_thread, &data));
TEST_ASSERT_EQUAL(osOK, res);
Thread::wait(SHORT_WAIT);
ThisThread::sleep_for(SHORT_WAIT);
TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state());
TEST_ASSERT_EQUAL(0, data.data);
@ -131,7 +131,7 @@ void test_single_thread()
res = sem.release();
TEST_ASSERT_EQUAL(osOK, res);
Thread::wait(SHORT_WAIT);
ThisThread::sleep_for(SHORT_WAIT);
TEST_ASSERT_EQUAL(1, data.data);
@ -160,7 +160,7 @@ void test_timeout()
timer.start();
res = t.start(callback(timeout_thread, &sem));
TEST_ASSERT_EQUAL(osOK, res);
Thread::wait(SHORT_WAIT);
ThisThread::sleep_for(SHORT_WAIT);
TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state());

View File

@ -103,7 +103,7 @@ void run_wait_clear(Sync *sync)
{
sync->sem_parent.release();
sync->sem_child.wait();
int32_t ret = Thread::signal_clr(signals);
int32_t ret = ThisThread::flags_clear(signals);
TEST_ASSERT_EQUAL(test_val, ret);
}
@ -114,10 +114,10 @@ void run_double_wait_clear(Sync *sync)
sync->sem_parent.release();
sync->sem_child.wait();
ret = Thread::signal_clr(signals1);
ret = ThisThread::flags_clear(signals1);
TEST_ASSERT_EQUAL(test_val1, ret);
ret = Thread::signal_clr(signals2);
ret = ThisThread::flags_clear(signals2);
TEST_ASSERT_EQUAL(test_val2, ret);
}
@ -128,7 +128,7 @@ void run_loop_wait_clear(Sync *sync)
int32_t signal = 1 << i;
signals |= signal;
sync->sem_child.wait();
int32_t ret = Thread::signal_clr(NO_SIGNALS);
int32_t ret = ThisThread::flags_clear(NO_SIGNALS);
TEST_ASSERT_EQUAL(signals, ret);
sync->sem_parent.release();
}

View File

@ -474,7 +474,7 @@ void test_thread_wait()
Timer timer;
timer.start();
Thread::wait(150);
ThisThread::sleep_for(150);
TEST_ASSERT_UINT32_WITHIN(50000, 150000, timer.read_us());
}
@ -528,7 +528,7 @@ void test_deleted()
void test_delay_thread()
{
Thread::wait(50);
ThisThread::sleep_for(50);
}
/** Testing thread states: wait delay

View File

@ -715,10 +715,9 @@ Call `UDPSocket::sendto()` with invalid parameters.
3. Call `UDPSocket:sendto( "", 0, NULL, 0);`
4. Call `UDPSocket:sendto(NULL, 9, "hello", 5);`
5. Call `UDPSocket:sendto(NULL, 0, "hello", 5);`
6. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 0, "hello", 5);`
7. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 9,NULL, 0);`
8. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 9, "hello", 5);`
9. destroy the socket
6. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 9,NULL, 0);`
7. Call `UDPSocket:sendto("echo.mbedcloudtesting.com", 9, "hello", 5);`
8. destroy the socket
**Expected result:**
@ -990,9 +989,8 @@ Call `TCPSocket::connect()` with invalid parameters.
1. Call `TCPSocket:connect( NULL, 9);`
2. Call `TCPSocket:connect( "", 9);`
3. Call `TCPSocket:connect( "", 0);`
4. Call `TCPSocket:connect( "echo.mbedcloudtesting.com", 0);`
5. Call `TCPSocket:connect( "echo.mbedcloudtesting.com", 9);`
6. destroy the socket
4. Call `TCPSocket:connect( "echo.mbedcloudtesting.com", 9);`
5. destroy the socket
**Expected result:**

View File

@ -32,7 +32,6 @@ void TCPSOCKET_CONNECT_INVALID()
TEST_ASSERT(sock.connect(NULL, 9) < 0);
TEST_ASSERT(sock.connect("", 9) < 0);
TEST_ASSERT(sock.connect("", 0) < 0);
TEST_ASSERT(sock.connect(MBED_CONF_APP_ECHO_SERVER_ADDR, 0) < 0);
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.connect(MBED_CONF_APP_ECHO_SERVER_ADDR, 9));
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());

View File

@ -119,7 +119,7 @@ void TCPSOCKET_ECHOTEST_NONBLOCK()
tcpsocket_connect_to_echo_srv(sock);
sock.set_blocking(false);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
sock.sigio(callback(_sigio_handler, ThisThread::get_id()));
int bytes2send;
int sent;

View File

@ -41,7 +41,7 @@ void TCPSOCKET_ECHOTEST_BURST()
{
TCPSocket sock;
tcpsocket_connect_to_echo_srv(sock);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
sock.sigio(callback(_sigio_handler, ThisThread::get_id()));
// TX buffer to be preserved for comparison
fill_tx_buffer_ascii(tcp_global::tx_buffer, BURST_SIZE);
@ -94,7 +94,7 @@ void TCPSOCKET_ECHOTEST_BURST_NONBLOCK()
TCPSocket sock;
tcpsocket_connect_to_echo_srv(sock);
sock.set_blocking(false);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
sock.sigio(callback(_sigio_handler, ThisThread::get_id()));
// TX buffer to be preserved for comparison
fill_tx_buffer_ascii(tcp_global::tx_buffer, BURST_SIZE);

View File

@ -63,7 +63,7 @@ void TCPSOCKET_ENDPOINT_CLOSE()
TEST_FAIL();
return;
}
sock.sigio(callback(_sigio_handler, Thread::gettid()));
sock.sigio(callback(_sigio_handler, ThisThread::get_id()));
int recvd = 0;
int recvd_total = 0;

View File

@ -170,7 +170,7 @@ void TCPSOCKET_RECV_100K_NONBLOCK()
}
sock.set_blocking(false);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
sock.sigio(callback(_sigio_handler, ThisThread::get_id()));
rcv_n_chk_against_rfc864_pattern_nonblock(sock);

View File

@ -45,7 +45,7 @@ void TCPSOCKET_RECV_TIMEOUT()
TCPSocket sock;
tcpsocket_connect_to_echo_srv(sock);
sock.set_timeout(100);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
sock.sigio(callback(_sigio_handler, ThisThread::get_id()));
int recvd = 0;
int pkt_unrecvd;

View File

@ -47,7 +47,7 @@ static void check_const_len_rand_sequence()
{
TCPSocket sock;
tcpsocket_connect_to_echo_srv(sock);
sock.sigio(callback(_sigio_handler1, Thread::gettid()));
sock.sigio(callback(_sigio_handler1, ThisThread::get_id()));
static const int BUFF_SIZE = 10;
static char rx_buff[BUFF_SIZE] = {0};
@ -104,7 +104,7 @@ static void check_var_len_rand_sequence()
{
TCPSocket sock;
tcpsocket_connect_to_echo_srv(sock);
sock.sigio(callback(_sigio_handler2, Thread::gettid()));
sock.sigio(callback(_sigio_handler2, ThisThread::get_id()));
static const int BUFF_SIZE = 1001;
static char rx_buff[BUFF_SIZE];

View File

@ -127,7 +127,7 @@ void UDPSOCKET_ECHOTEST_NONBLOCK()
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface()));
sock.set_blocking(false);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
sock.sigio(callback(_sigio_handler, ThisThread::get_id()));
int sent;
int s_idx = 0;

View File

@ -78,7 +78,7 @@ void UDPSOCKET_ECHOTEST_BURST()
const int TIMEOUT = 5000; // [ms]
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface()));
sock.set_timeout(TIMEOUT);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
sock.sigio(callback(_sigio_handler, ThisThread::get_id()));
// TX buffers to be preserved for comparison
prepare_tx_buffers();
@ -156,7 +156,7 @@ void UDPSOCKET_ECHOTEST_BURST_NONBLOCK()
UDPSocket sock;
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface()));
sock.set_blocking(false);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
sock.sigio(callback(_sigio_handler, ThisThread::get_id()));
// TX buffers to be preserved for comparison
prepare_tx_buffers();

View File

@ -46,7 +46,7 @@ void UDPSOCKET_RECV_TIMEOUT()
UDPSocket sock;
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(get_interface()));
sock.set_timeout(100);
sock.sigio(callback(_sigio_handler, Thread::gettid()));
sock.sigio(callback(_sigio_handler, ThisThread::get_id()));
int recvd;
Timer timer;

View File

@ -32,7 +32,6 @@ void UDPSOCKET_SENDTO_INVALID()
TEST_ASSERT(sock.sendto(NULL, 9, NULL, 0) < 0);
TEST_ASSERT(sock.sendto("", 9, NULL, 0) < 0);
TEST_ASSERT(sock.sendto("", 0, NULL, 0) < 0);
TEST_ASSERT_EQUAL(5, sock.sendto(MBED_CONF_APP_ECHO_SERVER_ADDR, 0, "hello", 5));
TEST_ASSERT_EQUAL(0, sock.sendto(MBED_CONF_APP_ECHO_SERVER_ADDR, 9, NULL, 0));
TEST_ASSERT_EQUAL(5, sock.sendto(MBED_CONF_APP_ECHO_SERVER_ADDR, 9, "hello", 5));

View File

@ -30,8 +30,12 @@ void wifi_connect(void)
WiFiInterface *wifi = get_interface();
TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->set_credentials(MBED_CONF_APP_WIFI_UNSECURE_SSID, NULL));
TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->connect());
TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->disconnect());
TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->set_credentials(MBED_CONF_APP_WIFI_UNSECURE_SSID, ""));
TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->connect());
TEST_ASSERT_EQUAL_INT(NSAPI_ERROR_OK, wifi->disconnect());
}
#endif // defined(MBED_CONF_APP_WIFI_UNSECURE_SSID)

View File

@ -34,7 +34,8 @@ void wifi_connect_params_channel_fail(void)
return;
}
nsapi_error_t error = wifi->connect(MBED_CONF_APP_WIFI_SECURE_SSID, MBED_CONF_APP_WIFI_PASSWORD, get_security(), MBED_CONF_APP_WIFI_CH_UNSECURE);
uint8_t wrong_channel = 1 + (MBED_CONF_APP_WIFI_CH_SECURE%10);
nsapi_error_t error = wifi->connect(MBED_CONF_APP_WIFI_SECURE_SSID, MBED_CONF_APP_WIFI_PASSWORD, get_security(), wrong_channel);
TEST_ASSERT(error == NSAPI_ERROR_CONNECTION_TIMEOUT || error == NSAPI_ERROR_NO_CONNECTION);
wifi->set_channel(0);

View File

@ -48,25 +48,18 @@ void wifi_scan(void)
const char *ssid = ap[i].get_ssid();
nsapi_security_t security = ap[i].get_security();
int8_t rssi = ap[i].get_rssi();
uint8_t ch = ap[i].get_channel();
TEST_ASSERT_INT8_WITHIN(-10, -100, rssi);
if (strcmp(MBED_CONF_APP_WIFI_SECURE_SSID, ssid) == 0) {
secure_found = true;
TEST_ASSERT_EQUAL_INT(get_security(), security);
if (MBED_CONF_APP_WIFI_CH_SECURE) {
TEST_ASSERT_EQUAL_INT(MBED_CONF_APP_WIFI_CH_SECURE, ch);
}
}
if (strcmp(MBED_CONF_APP_WIFI_UNSECURE_SSID, ssid) == 0) {
unsecure_found = true;
TEST_ASSERT_EQUAL_INT(NSAPI_SECURITY_NONE, security);
if (MBED_CONF_APP_WIFI_CH_UNSECURE) {
TEST_ASSERT_EQUAL_INT(MBED_CONF_APP_WIFI_CH_UNSECURE, ch);
}
}
}
TEST_ASSERT_TRUE(secure_found);
TEST_ASSERT_TRUE(unsecure_found);
// Finding one SSID is enough
TEST_ASSERT_TRUE(secure_found || unsecure_found);
}
#endif // defined(MBED_CONF_APP_WIFI_SECURE_SSID) && defined(MBED_CONF_APP_WIFI_UNSECURE_SSID)

View File

@ -69,5 +69,6 @@ void wifi_set_channel(void)
TEST_ASSERT(error == NSAPI_ERROR_PARAMETER);
}
wifi->set_channel(0);
}

View File

@ -45,7 +45,7 @@
extern mac_api_s *mac_interface;
RawSerial pc(USBTX, USBRX);
osThreadId main_thread;
osThreadId_t main_thread;
static CircularBuffer<uint8_t, RX_BUFFER_SIZE> rx_buffer;
static uint8_t ns_heap[HEAP_FOR_MAC_TESTER_SIZE];
@ -71,7 +71,7 @@ static void rx_interrupt(void)
uint8_t c = pc.getc();
rx_buffer.push(c);
if (main_thread != NULL) {
osSignalSet(main_thread, 1);
osThreadFlagsSet(main_thread, 1);
}
}
@ -132,7 +132,7 @@ static void trace_printer(const char *str)
int main(void)
{
main_thread = osThreadGetId();
main_thread = ThisThread::get_id();
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);
@ -148,12 +148,8 @@ int main(void)
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();
}
ThisThread::flags_wait_any(1);
handle_rx_data();
}
return 0;
}

View File

@ -518,7 +518,7 @@ static void udp_receiver_thread(SInfo *info)
int *packetSizes = info->getPacketSizeArray();
nsapi_size_or_error_t ret = 0;
info->setReceiverThreadId(Thread::gettid());
info->setReceiverThreadId(ThisThread::get_id());
while (i < n) {
ret = static_cast<UDPSocket &>(info->socket()).recvfrom(&addr, info->getReceiveBuffer() + received, info->getDataCount() - received);
@ -531,7 +531,7 @@ static void udp_receiver_thread(SInfo *info)
i++;
info->setRecvTotal(info->getRecvTotal() + ret);
} else if (ret == NSAPI_ERROR_WOULD_BLOCK) {
Thread::signal_wait(SIGNAL_SIGIO);
ThisThread::flags_wait_all(SIGNAL_SIGIO);
} else {
handle_nsapi_size_or_error("Thread: UDPSocket::recvfrom()", ret);
return;
@ -660,7 +660,7 @@ static void tcp_receiver_thread(SInfo *info)
int bufferSize = info->getDataCount();
nsapi_size_or_error_t ret = 0;
info->setReceiverThreadId(Thread::gettid());
info->setReceiverThreadId(ThisThread::get_id());
for (i = 0; i < n; i++) {
received = 0;
@ -673,7 +673,7 @@ static void tcp_receiver_thread(SInfo *info)
received += ret;
info->setRecvTotal(info->getRecvTotal() + ret);
} else if (ret == NSAPI_ERROR_WOULD_BLOCK) {
Thread::signal_wait(SIGNAL_SIGIO);
ThisThread::flags_wait_all(SIGNAL_SIGIO);
} else {
handle_nsapi_size_or_error("Thread: TCPSocket::recv()", ret);
return;
@ -729,7 +729,7 @@ static nsapi_size_or_error_t tcp_send_command_handler(SInfo *info, int argc, cha
void *data;
nsapi_size_or_error_t ret = 0;
info->setSenderThreadId(Thread::gettid());
info->setSenderThreadId(ThisThread::get_id());
if (cmd_parameter_int(argc, argv, "--data_len", &len)) {
data = malloc(len);
@ -809,7 +809,7 @@ static void bg_traffic_thread(SInfo *info)
char sbuffer[data_len + 1] = "dummydata_";
char rbuffer[data_len + 1];
int scount, rtotal = 0;
info->setSenderThreadId(Thread::gettid());
info->setSenderThreadId(ThisThread::get_id());
for (;;) {
if (!info->available()) {

View File

@ -1,6 +1,6 @@
## 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.
This document describes how to write and test unit tests for Arm Mbed OS. To prevent and solve problems, please see the [troubleshooting](#troubleshooting) section.
### Introduction
@ -11,12 +11,12 @@ Unit tests test code in small sections on a host machine. Unlike other testing t
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.
- GCC 6 or later. We recommend you use MinGW-W64 on Windows, but any Windows port of the above GCC versions works. Default compilers can be used on Mac OS instead of GCC to shorten build times, but code coverage results can then differ.
- 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.
- Arm Mbed CLI 1.8.0 or newer.
Detailed instructions for supported operating systems are below.
@ -30,12 +30,13 @@ Detailed instructions for supported operating systems are below.
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`.
1. Install Gcovr and [Mbed CLI](https://os.mbed.com/docs/latest/tools/developing-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 Xcode Command Line Tools with `xcode-select --install`.
1. Install CMake with: `brew install cmake`.
1. Install Python and Pip:
```
@ -43,7 +44,8 @@ Detailed instructions for supported operating systems are below.
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`.
1. Install Gcovr and [Mbed CLI](https://os.mbed.com/docs/latest/tools/developing-arm-mbed-cli.html) with `pip install "gcovr>=4.1" mbed-cli`.
1. (Optional) Install GCC with `brew install gcc`.
#### Installing dependencies on Windows
@ -51,7 +53,7 @@ Detailed instructions for supported operating systems are below.
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`.
1. Install Gcovr and [Mbed CLI](https://os.mbed.com/docs/latest/tools/developing-arm-mbed-cli.html) with `pip install "gcovr>=4.1" mbed-cli`.
### Test code structure
@ -69,7 +71,7 @@ The build system automatically generates names of test suites. The name is const
### 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).
Mbed CLI supports unit tests through `mbed test --unittests` command. For information on using Mbed CLI, please see the [CLI documentation](https://os.mbed.com/docs/latest/tools/developing-arm-mbed-cli.html).
### Writing unit tests
@ -154,7 +156,7 @@ TEST_F(TestSemaphore, constructor)
### 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.
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
@ -162,9 +164,11 @@ Use Mbed CLI to build and run unit tests. For advanced use, you can run CMake an
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.
- Add `-DCMAKE_MAKE_PROGRAM=<value>`, `-DCMAKE_CXX_COMPILER=<value>` and `-DCMAKE_C_COMPILER=<value>` to use a specific Make program and compilers.
- Add `-DCMAKE_BUILD_TYPE=Debug` to build a debug build.
- 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.
1. Run a Make program to build the tests.
#### Run tests directly with CTest
@ -177,14 +181,27 @@ Run a test binary in the build directory to run a unit test suite. To run multip
1. Add test executables into the list.
1. Run them.
### Debugging
1. Use Mbed CLI to build a debug build. For advanced use, run CMake directly with `-DCMAKE_BUILD_TYPE=Debug`, and then run a Make program.
1. Run GDB with a test executable as an argument to debug unit tests.
### 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.
Use Mbed CLI to generate code coverage reports. For advanced use, follow these steps:
1. Run CMake with both `-DCMAKE_BUILD_TYPE=Debug` and `-DCOVERAGE=True`.
1. Run a Make program to build the tests.
1. Run the tests.
1. 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.
* **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.
**Problem:** CMake compiler check fails on Mac OS Mojave when using GCC-8.
* **Solution**: Make sure gnm (binutils) is not installed. Uninstall binutils with `brew uninstall binutils`.

View File

@ -434,7 +434,7 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_set_registration)
EXPECT_TRUE(NSAPI_ERROR_OK == cn.set_registration("12345"));
}
TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_registration_status)
TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_registration_params)
{
EventQueue que;
FileHandle_stub fh1;
@ -443,33 +443,86 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_registration_status)
AT_CellularNetwork cn(at);
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK;
ATHandler_stub::int_value = 3;
CellularNetwork::RegistrationStatus stat = CellularNetwork::NotRegistered;
EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_status(CellularNetwork::C_EREG, stat));
EXPECT_TRUE(stat == CellularNetwork::RegistrationDenied);
stat = CellularNetwork::NotRegistered;
EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_status(CellularNetwork::C_GREG, stat));
EXPECT_TRUE(stat == CellularNetwork::RegistrationDenied);
CellularNetwork::registration_params_t reg_params;
CellularNetwork::registration_params_t reg_params_check;
EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(CellularNetwork::C_EREG, reg_params));
EXPECT_TRUE(reg_params._status == CellularNetwork::RegistrationDenied);
EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_EGPRS);
EXPECT_TRUE(reg_params._cell_id == -1);
ATHandler_stub::read_string_index = 4;
ATHandler_stub::read_string_table[3] = "00C3";
ATHandler_stub::read_string_table[2] = "1234FFC1";//== cellid and in dec: 305463233
ATHandler_stub::read_string_table[1] = "00100100";
ATHandler_stub::read_string_table[0] = "01000111";
EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(CellularNetwork::C_EREG, reg_params));
EXPECT_TRUE(reg_params._cell_id == 305463233);
EXPECT_TRUE(reg_params._active_time == 240);
EXPECT_TRUE(reg_params._periodic_tau == 70 * 60 *60);
ATHandler_stub::read_string_index = kRead_string_table_size;
ATHandler_stub::read_string_value = NULL;
ATHandler_stub::ssize_value = 0;
// Check get_registration_params without specifying the registration type
EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(reg_params_check));
EXPECT_TRUE(reg_params_check._status == CellularNetwork::RegistrationDenied);
EXPECT_TRUE(reg_params_check._act == CellularNetwork::RAT_EGPRS);
EXPECT_TRUE(reg_params_check._cell_id == 305463233);
EXPECT_TRUE(reg_params_check._active_time == 240);
EXPECT_TRUE(reg_params_check._periodic_tau == 70 * 60 *60);
reg_params._status = CellularNetwork::NotRegistered;
reg_params._act = CellularNetwork::RAT_GSM;
reg_params._cell_id = 1;
EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(CellularNetwork::C_GREG, reg_params));
EXPECT_TRUE(reg_params._status == CellularNetwork::RegistrationDenied);
EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_EGPRS);
EXPECT_TRUE(reg_params._cell_id == -1);
my_AT_CN nw(at);
stat = CellularNetwork::NotRegistered;
EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == nw.get_registration_status(CellularNetwork::C_GREG, stat));
EXPECT_TRUE(stat == CellularNetwork::NotRegistered);
EXPECT_TRUE(NSAPI_ERROR_OK == nw.get_registration_status(CellularNetwork::C_EREG, stat));
EXPECT_TRUE(stat == CellularNetwork::RegistrationDenied);
reg_params._status = CellularNetwork::NotRegistered;
reg_params._act = CellularNetwork::RAT_GSM;
EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == nw.get_registration_params(CellularNetwork::C_GREG, reg_params));
EXPECT_TRUE(reg_params._status == CellularNetwork::NotRegistered);
EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_GSM);
EXPECT_TRUE(NSAPI_ERROR_OK == nw.get_registration_params(CellularNetwork::C_EREG, reg_params));
EXPECT_TRUE(reg_params._status == CellularNetwork::RegistrationDenied);
EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_EGPRS);
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_DEVICE_ERROR;
stat = CellularNetwork::NotRegistered;
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_status(CellularNetwork::C_EREG, stat));
EXPECT_TRUE(stat == -1);
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_status(CellularNetwork::C_GREG, stat));
EXPECT_TRUE(stat == -1);
reg_params._status = CellularNetwork::NotRegistered;
reg_params._act = CellularNetwork::RAT_GSM;
reg_params._cell_id = 1;
reg_params._active_time = 2;
reg_params._periodic_tau = 3;
stat = CellularNetwork::NotRegistered;
EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == nw.get_registration_status(CellularNetwork::C_GREG, stat));
EXPECT_TRUE(stat == CellularNetwork::NotRegistered);
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == nw.get_registration_status(CellularNetwork::C_EREG, stat));
EXPECT_TRUE(stat == -1);
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_params(CellularNetwork::C_EREG, reg_params));
EXPECT_TRUE(reg_params._status == CellularNetwork::StatusNotAvailable);
EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_UNKNOWN);
EXPECT_TRUE(reg_params._cell_id == -1 && reg_params._active_time == -1 && reg_params._periodic_tau == -1);
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == cn.get_registration_params(CellularNetwork::C_GREG, reg_params));
EXPECT_TRUE(reg_params._status == CellularNetwork::StatusNotAvailable);
EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_UNKNOWN);
EXPECT_TRUE(reg_params._cell_id == -1);
reg_params._status = CellularNetwork::SearchingNetwork;
reg_params._act = CellularNetwork::RAT_GSM;
reg_params._cell_id = 1;
reg_params._active_time = 2;
reg_params._periodic_tau = 3;
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == nw.get_registration_params(CellularNetwork::C_EREG, reg_params));
EXPECT_TRUE(reg_params._status == CellularNetwork::StatusNotAvailable);
EXPECT_TRUE(reg_params._act == CellularNetwork::RAT_UNKNOWN);
EXPECT_TRUE(reg_params._cell_id == -1 && reg_params._active_time == -1 && reg_params._periodic_tau == -1);
// Check get_registration_params without specifying the registration type
EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_params(reg_params_check));
EXPECT_TRUE(reg_params_check._status == CellularNetwork::StatusNotAvailable);
EXPECT_TRUE(reg_params_check._act == CellularNetwork::RAT_UNKNOWN);
EXPECT_TRUE(reg_params_check._cell_id == -1 && reg_params_check._active_time == -1 && reg_params_check._periodic_tau == -1);
}
TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_network_registering_mode)
@ -762,19 +815,6 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_set_access_technology)
EXPECT_TRUE(NSAPI_ERROR_OK == my_cn.set_access_technology(CellularNetwork::RAT_GSM_COMPACT));
}
TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_access_technology)
{
EventQueue que;
FileHandle_stub fh1;
ATHandler at(&fh1, que, 0, ",");
AT_CellularNetwork cn(at);
CellularNetwork::RadioAccessTechnology rat;
EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_access_technology(rat));
EXPECT_TRUE(CellularNetwork::RAT_UNKNOWN == rat);
}
TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_scan_plmn)
{
EventQueue que;
@ -989,34 +1029,6 @@ TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_signal_quality)
EXPECT_TRUE(rs == 1 && ber == 1);
}
TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_cell_id)
{
EventQueue que;
FileHandle_stub fh1;
ATHandler at(&fh1, que, 0, ",");
AT_CellularNetwork cn(at);
int id = 0;
EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_cell_id(id));
EXPECT_TRUE(id == -1);
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_DEVICE_ERROR;
EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_cell_id(id));
EXPECT_TRUE(id == -1);
ATHandler_stub::read_string_index = 2;
ATHandler_stub::read_string_table[1] = (char *)"00C3";
ATHandler_stub::read_string_table[0] = (char *)"1234FFC1"; //== cellid and in dec: 305463233
ATHandler_stub::int_value = 1;
// Get registration status to modify cell_id
CellularNetwork::RegistrationType type;
CellularNetwork::RegistrationStatus status;
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_OK;
EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_registration_status(CellularNetwork::C_EREG, status));
EXPECT_TRUE(NSAPI_ERROR_OK == cn.get_cell_id(id));
EXPECT_TRUE(id == 305463233);
}
TEST_F(TestAT_CellularNetwork, test_AT_CellularNetwork_get_3gpp_error)
{
EventQueue que;

View File

@ -175,13 +175,13 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_get_ip_address)
ATHandler at(&fh1, que, 0, ",");
MyStack st(at, 0, IPV6_STACK);
EXPECT_TRUE(0 == strlen(st.get_ip_address()));
EXPECT_EQ(strlen(st.get_ip_address()), 0);
char table[] = "1.2.3.4.5.65.7.8.9.10.11\0";
ATHandler_stub::ssize_value = -1;
ATHandler_stub::bool_value = true;
ATHandler_stub::read_string_value = table;
EXPECT_TRUE(NULL == st.get_ip_address());
EXPECT_TRUE(st.get_ip_address() == NULL);
ATHandler_stub::ssize_value = strlen(table);
ATHandler_stub::bool_value = true;
@ -197,18 +197,18 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_open)
MyStack st(at, 0, IPV6_STACK);
st.bool_value = false;
EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == st.socket_open(NULL, NSAPI_TCP));
EXPECT_EQ(st.socket_open(NULL, NSAPI_TCP), NSAPI_ERROR_UNSUPPORTED);
st.bool_value = true;
st.max_sock_value = 0;
nsapi_socket_t sock = &st.socket;
EXPECT_TRUE(NSAPI_ERROR_NO_SOCKET == st.socket_open(&sock, NSAPI_TCP));
EXPECT_EQ(st.socket_open(&sock, NSAPI_TCP), NSAPI_ERROR_NO_SOCKET);
MyStack st2(at, 0, IPV6_STACK);
st2.bool_value = true;
st2.max_sock_value = 1;
sock = &st2.socket;
EXPECT_TRUE(NSAPI_ERROR_OK == st2.socket_open(&sock, NSAPI_TCP));
EXPECT_EQ(st2.socket_open(&sock, NSAPI_TCP), NSAPI_ERROR_OK);
}
TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_close)
@ -218,21 +218,21 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_close)
ATHandler at(&fh1, que, 0, ",");
MyStack st(at, 0, IPV6_STACK);
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_close(&st.socket));
EXPECT_EQ(st.socket_close(&st.socket), NSAPI_ERROR_DEVICE_ERROR);
nsapi_socket_t sock = &st.socket;
st.bool_value = true;
st.max_sock_value = 1;
EXPECT_TRUE(NSAPI_ERROR_OK == st.socket_open(&sock, NSAPI_TCP));
EXPECT_EQ(st.socket_open(&sock, NSAPI_TCP), NSAPI_ERROR_OK);
st.max_sock_value = 0;
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_close(sock));
EXPECT_EQ(st.socket_close(sock), NSAPI_ERROR_DEVICE_ERROR);
MyStack st2(at, 0, IPV6_STACK);
st2.max_sock_value = 1;
st2.bool_value = true;
sock = &st2.socket;
EXPECT_TRUE(NSAPI_ERROR_OK == st2.socket_open(&sock, NSAPI_TCP));
EXPECT_TRUE(NSAPI_ERROR_OK == st2.socket_close(sock));
EXPECT_EQ(st2.socket_open(&sock, NSAPI_TCP), NSAPI_ERROR_OK);
EXPECT_EQ(st2.socket_close(sock), NSAPI_ERROR_OK);
}
TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_bind)
@ -244,9 +244,9 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_bind)
MyStack st(at, 0, IPV6_STACK);
SocketAddress addr;
ATHandler_stub::nsapi_error_value = NSAPI_ERROR_ALREADY;
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_bind(NULL, addr));
EXPECT_EQ(st.socket_bind(NULL, addr), NSAPI_ERROR_DEVICE_ERROR);
EXPECT_TRUE(NSAPI_ERROR_ALREADY == st.socket_bind(&st.socket, addr));
EXPECT_EQ(st.socket_bind(&st.socket, addr), NSAPI_ERROR_ALREADY);
}
TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_listen)
@ -256,7 +256,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_listen)
ATHandler at(&fh1, que, 0, ",");
MyStack st(at, 0, IPV6_STACK);
EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == st.socket_listen(&st.socket, 4));
EXPECT_EQ(st.socket_listen(&st.socket, 4), NSAPI_ERROR_UNSUPPORTED);
}
TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_connect)
@ -267,9 +267,9 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_connect)
MyStack st(at, 0, IPV6_STACK);
SocketAddress addr;
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_connect(NULL, addr));
EXPECT_EQ(st.socket_connect(NULL, addr), NSAPI_ERROR_DEVICE_ERROR);
EXPECT_TRUE(NSAPI_ERROR_OK == st.socket_connect(&st.socket, addr));
EXPECT_EQ(st.socket_connect(&st.socket, addr), NSAPI_ERROR_OK);
}
TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_accept)
@ -280,7 +280,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_accept)
MyStack st(at, 0, IPV6_STACK);
nsapi_socket_t sock = &st.socket;
EXPECT_TRUE(NSAPI_ERROR_UNSUPPORTED == st.socket_accept(NULL, &sock));
EXPECT_EQ(st.socket_accept(NULL, &sock), NSAPI_ERROR_UNSUPPORTED);
}
TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_send)
@ -290,9 +290,9 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_send)
ATHandler at(&fh1, que, 0, ",");
MyStack st(at, 0, IPV6_STACK);
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_send(NULL, "addr", 4));
EXPECT_EQ(st.socket_send(NULL, "addr", 4), NSAPI_ERROR_DEVICE_ERROR);
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_send(&st.socket, "addr", 4));
EXPECT_EQ(st.socket_send(&st.socket, "addr", 4), NSAPI_ERROR_DEVICE_ERROR);
SocketAddress addr;
st.max_sock_value = 1;
@ -300,7 +300,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_send)
nsapi_socket_t sock = &st.socket;
st.socket_open(&sock, NSAPI_TCP);
st.socket_connect(sock, addr);
EXPECT_TRUE(NSAPI_ERROR_OK == st.socket_send(sock, "addr", 4));
EXPECT_EQ(st.socket_send(sock, "addr", 4), NSAPI_ERROR_OK);
}
TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_sendto)
@ -312,7 +312,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_sendto)
MyStack st(at, 0, IPV6_STACK);
SocketAddress addr;
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_sendto(NULL, addr, "addr", 4));
EXPECT_EQ(st.socket_sendto(NULL, addr, "addr", 4), NSAPI_ERROR_DEVICE_ERROR);
st.max_sock_value = 1;
st.bool_value = true;
@ -320,10 +320,10 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_sendto)
st.socket_open(&sock, NSAPI_TCP);
st.socket_connect(sock, addr);
st.create_error = NSAPI_ERROR_CONNECTION_LOST;
EXPECT_TRUE(NSAPI_ERROR_CONNECTION_LOST == st.socket_sendto(sock, addr, "addr", 4));
EXPECT_EQ(st.socket_sendto(sock, addr, "addr", 4), NSAPI_ERROR_CONNECTION_LOST);
st.create_error = NSAPI_ERROR_OK;
EXPECT_TRUE(NSAPI_ERROR_OK == st.socket_sendto(sock, addr, "addr", 4));
EXPECT_EQ(st.socket_sendto(sock, addr, "addr", 4), NSAPI_ERROR_OK);
}
TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recv)
@ -334,7 +334,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recv)
MyStack st(at, 0, IPV6_STACK);
char table[4];
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_recv(NULL, table, 4));
EXPECT_EQ(st.socket_recv(NULL, table, 4), NSAPI_ERROR_DEVICE_ERROR);
}
TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recvfrom)
@ -345,7 +345,7 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recvfrom)
MyStack st(at, 0, IPV6_STACK);
char table[4];
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == st.socket_recvfrom(NULL, NULL, table, 4));
EXPECT_EQ(st.socket_recvfrom(NULL, NULL, table, 4), NSAPI_ERROR_DEVICE_ERROR);
SocketAddress addr;
st.max_sock_value = 1;
@ -354,10 +354,10 @@ TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_recvfrom)
st.socket_open(&sock, NSAPI_TCP);
st.socket_connect(sock, addr);
st.create_error = NSAPI_ERROR_CONNECTION_LOST;
EXPECT_TRUE(NSAPI_ERROR_CONNECTION_LOST == st.socket_recvfrom(sock, &addr, table, 4));
EXPECT_EQ(st.socket_recvfrom(sock, &addr, table, 4), NSAPI_ERROR_CONNECTION_LOST);
st.create_error = NSAPI_ERROR_OK;
EXPECT_TRUE(NSAPI_ERROR_OK == st.socket_recvfrom(sock, &addr, table, 4));
EXPECT_EQ(st.socket_recvfrom(sock, &addr, table, 4), NSAPI_ERROR_OK);
}
TEST_F(TestAT_CellularStack, test_AT_CellularStack_socket_attach)

View File

@ -579,7 +579,7 @@ TEST_F(TestATHandler, test_ATHandler_read_string)
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == at.get_last_error());
at.clear_error();
// Device error because empty buffer and attempt to fill_buffer by consume_char('\"')
EXPECT_TRUE(-1 == at.read_string(buf1, 1));
EXPECT_TRUE(0 == at.read_string(buf1, 1));
// *** 1 BYTE ***
at.clear_error();
@ -599,7 +599,7 @@ TEST_F(TestATHandler, test_ATHandler_read_string)
// *** CRLF ***
at.clear_error();
char table3[] = "\r\ns\r\n\0";
char table3[] = "\r\n,s\r\n\0";
at.flush();
filehandle_stub_table = table3;
filehandle_stub_table_pos = 0;
@ -670,13 +670,9 @@ TEST_F(TestATHandler, test_ATHandler_read_string)
at.resp_start();
// TO read 1 byte from: "s"OK\r\n -> read "
at.read_bytes(buf5, 1);
// TO read max 1 byte from: s"OK\r\n -> read s
// TO read max 1 byte from: s"OK\r\n -> read s + read to stop_tag(OKCRLF)
EXPECT_TRUE(1 == at.read_string(buf4, 1 + 1/*for NULL*/));
// *** Consume " and run into OKCRLF ***
// TO read max 1 byte from: "OK\r\n -> consume " and find stop tag OKCRLF
EXPECT_TRUE(0 == at.read_string(buf4, 1 + 1/*for NULL*/));
// *** Try to read after stop tag was found ***
// stop tag found do not read further
EXPECT_TRUE(-1 == at.read_string(buf4, 1 + 1/*for NULL*/));
@ -706,7 +702,7 @@ TEST_F(TestATHandler, test_ATHandler_read_string)
mbed_poll_stub::revents_value = POLLIN;
mbed_poll_stub::int_value = 1;
at.resp_start("s");
// TO read from buffer having only " -> consume " -> trying to read when nothing in buffer
// TO read from buffer having only " -> trying to find delimiter or stop_tag(OKCRLF)
EXPECT_TRUE(-1 == at.read_string(buf4, 5));
EXPECT_TRUE(NSAPI_ERROR_DEVICE_ERROR == at.get_last_error());
@ -739,6 +735,21 @@ TEST_F(TestATHandler, test_ATHandler_read_string)
// TO read from
EXPECT_TRUE(6 == at.read_string(buf9, 6 + 1/*for NULL*/));
at.clear_error();
char table11[] = "\"1016\",\"39AB\",9\r\n\0";
mbed_poll_stub::int_value = 0;
at.flush();
filehandle_stub_table = table11;
filehandle_stub_table_pos = 0;
mbed_poll_stub::revents_value = POLLIN;
mbed_poll_stub::int_value = 1;
at.resp_start();
EXPECT_TRUE(4 == at.read_string(buf4, 4 + 1/*for NULL*/));
EXPECT_TRUE(!strncmp(buf4, "1016", 4));
EXPECT_TRUE(4 == at.read_string(buf4, 4 + 1/*for NULL*/));
EXPECT_TRUE(!strncmp(buf4, "39AB", 4));
EXPECT_TRUE(9 == at.read_int());
// *** CRLF part of the string ***
at.clear_error();
char table10[] = "\"s\"\r\nOK\r\n\0";

View File

@ -30,7 +30,7 @@ set(unittest-test-sources
stubs/Timer_stub.cpp
stubs/equeue_stub.c
stubs/Kernel_stub.cpp
stubs/Thread_stub.cpp
stubs/ThisThread_stub.cpp
stubs/randLIB_stub.cpp
)

View File

@ -35,6 +35,23 @@ protected:
};
// *INDENT-ON*
TEST_F(Testutil, test_util_binary_str_to_uint)
{
char binary_str[]="011001011101101000";
uint32_t value = binary_str_to_uint(binary_str, strlen(binary_str) + 1);
EXPECT_TRUE(value == 104296);
value = binary_str_to_uint(binary_str, strlen(binary_str));
EXPECT_TRUE(value == 104296);
value = binary_str_to_uint(binary_str, strlen(binary_str) - 1);
EXPECT_TRUE(value == 52148);
value = binary_str_to_uint(binary_str, strlen(binary_str) - 3);
EXPECT_TRUE(value == 13037);
value = binary_str_to_uint(binary_str + 5, strlen(binary_str) - 5);
EXPECT_TRUE(value == 5992);
EXPECT_TRUE(0 == binary_str_to_uint(NULL, 5));
EXPECT_TRUE(0 == binary_str_to_uint(binary_str, 0));
}
TEST_F(Testutil, test_util_uint_to_binary_string)
{
char str[33];

View File

@ -40,6 +40,7 @@ protected:
virtual void SetUp()
{
object = new LoRaMac();
LoRaWANTimer_stub::time_value = 1;
}
virtual void TearDown()
@ -64,7 +65,9 @@ TEST_F(Test_LoRaMac, initialize)
object->bind_phy(phy);
lorawan_connect_t conn;
memset(&conn, 0, sizeof(conn));
uint8_t key[16];
memset(key, 0, sizeof(key));
conn.connection_u.otaa.app_key = key;
conn.connection_u.otaa.app_eui = key;
conn.connection_u.otaa.dev_eui = key;
@ -119,6 +122,7 @@ TEST_F(Test_LoRaMac, remove_single_channel)
TEST_F(Test_LoRaMac, multicast_channel_link)
{
multicast_params_t p;
memset(&p, 0, sizeof(p));
EXPECT_EQ(LORAWAN_STATUS_PARAMETER_INVALID, object->multicast_channel_link(NULL));
@ -132,6 +136,7 @@ TEST_F(Test_LoRaMac, multicast_channel_link)
TEST_F(Test_LoRaMac, multicast_channel_unlink)
{
multicast_params_t p;
memset(&p, 0, sizeof(p));
EXPECT_EQ(LORAWAN_STATUS_PARAMETER_INVALID, object->multicast_channel_unlink(NULL));
@ -145,7 +150,9 @@ TEST_F(Test_LoRaMac, multicast_channel_unlink)
TEST_F(Test_LoRaMac, send)
{
loramac_mhdr_t mac_hdr;
memset(&mac_hdr, 0, sizeof(mac_hdr));
uint8_t buf[15];
memset(buf, 0, sizeof(buf));
mac_hdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP;
object->send(&mac_hdr, 1, buf, 15);
}
@ -183,6 +190,7 @@ TEST_F(Test_LoRaMac, reset_ongoing_tx)
TEST_F(Test_LoRaMac, prepare_ongoing_tx)
{
uint8_t buf[16];
memset(buf, 0, sizeof(buf));
object->prepare_ongoing_tx(1, buf, 16, 1, 0);
}
@ -214,6 +222,7 @@ TEST_F(Test_LoRaMac, setup_link_check_request)
TEST_F(Test_LoRaMac, prepare_join)
{
lorawan_connect_t conn;
memset(&conn, 0, sizeof(conn));
object->prepare_join(&conn, false);
my_phy phy;
@ -293,7 +302,9 @@ TEST_F(Test_LoRaMac, join)
EXPECT_EQ(LORAWAN_STATUS_OK, object->join(false));
lorawan_connect_t conn;
memset(&conn, 0, sizeof(conn));
uint8_t key[16];
memset(key, 0, sizeof(key));
conn.connection_u.otaa.app_key = key;
conn.connection_u.otaa.app_eui = key;
conn.connection_u.otaa.dev_eui = key;
@ -312,6 +323,7 @@ TEST_F(Test_LoRaMac, on_radio_tx_done)
TEST_F(Test_LoRaMac, on_radio_rx_done)
{
uint8_t buf[16];
memset(buf, 0, sizeof(buf));
object->on_radio_rx_done(buf, 16, 0, 0);
}
@ -330,7 +342,9 @@ TEST_F(Test_LoRaMac, continue_joining_process)
my_phy phy;
object->bind_phy(phy);
lorawan_connect_t conn;
memset(&conn, 0, sizeof(conn));
uint8_t key[16];
memset(key, 0, sizeof(key));
conn.connection_u.otaa.app_key = key;
conn.connection_u.otaa.app_eui = key;
conn.connection_u.otaa.dev_eui = key;
@ -369,6 +383,7 @@ TEST_F(Test_LoRaMac, get_mlme_indication)
TEST_F(Test_LoRaMac, post_process_mcps_req)
{
uint8_t data[16];
memset(data, 0, sizeof(data));
LoRaPHY_stub::bool_counter = 0;
LoRaPHY_stub::bool_table[0] = true;
@ -527,13 +542,15 @@ TEST_F(Test_LoRaMac, get_backoff_timer_event_id)
TEST_F(Test_LoRaMac, clear_tx_pipe)
{
EXPECT_EQ(LORAWAN_STATUS_OK, object->clear_tx_pipe()); //timer id == 0
EXPECT_EQ(LORAWAN_STATUS_NO_OP, object->clear_tx_pipe()); //timer id == 0
my_phy phy;
object->bind_phy(phy);
lorawan_connect_t conn;
memset(&conn, 0, sizeof(conn));
uint8_t key[16];
memset(key, 0, sizeof(key));
conn.connection_u.otaa.app_key = key;
conn.connection_u.otaa.app_eui = key;
conn.connection_u.otaa.dev_eui = key;
@ -543,6 +560,12 @@ TEST_F(Test_LoRaMac, clear_tx_pipe)
EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize(NULL, my_cb));
EventQueue_stub::int_value = 0;
EXPECT_EQ(LORAWAN_STATUS_BUSY, object->clear_tx_pipe());
loramac_mhdr_t machdr;
machdr.bits.mtype = MCPS_UNCONFIRMED;
uint8_t buf[1];
buf[0] = 'T';
LoRaPHY_stub::lorawan_status_value = LORAWAN_STATUS_DUTYCYCLE_RESTRICTED;
EXPECT_TRUE(LORAWAN_STATUS_OK == object->send(&machdr, 15, buf, 1));
EventQueue_stub::int_value = 1;
EXPECT_EQ(LORAWAN_STATUS_OK, object->clear_tx_pipe());
@ -558,3 +581,12 @@ TEST_F(Test_LoRaMac, get_current_slot)
object->get_current_slot();
}
TEST_F(Test_LoRaMac, get_QOS_level)
{
EXPECT_EQ(0, object->get_QOS_level());
}
TEST_F(Test_LoRaMac, get_prev_QOS_level)
{
EXPECT_EQ(1, object->get_prev_QOS_level());
}

View File

@ -60,6 +60,8 @@ TEST_F(Test_LoRaMacChannelPlan, constructor)
TEST_F(Test_LoRaMacChannelPlan, set_plan)
{
lorawan_channelplan_t plan;
memset(&plan, 0, sizeof(plan));
memset(&LoRaPHY_stub::bool_table, 0, sizeof(LoRaPHY_stub::bool_table));
LoRaPHY_stub::bool_counter = 0;
LoRaPHY_stub::bool_table[0] = false;
EXPECT_TRUE(object->set_plan(plan) == LORAWAN_STATUS_SERVICE_UNKNOWN);
@ -74,6 +76,9 @@ TEST_F(Test_LoRaMacChannelPlan, set_plan)
LoRaPHY_stub::bool_table[0] = true;
LoRaPHY_stub::uint8_value = 10;
LoRaPHY_stub::lorawan_status_value = LORAWAN_STATUS_PARAMETER_INVALID;
loramac_channel_t chan;
memset(&chan, 0, sizeof(chan));
plan.channels = &chan;
EXPECT_TRUE(object->set_plan(plan) == LORAWAN_STATUS_PARAMETER_INVALID);
LoRaPHY_stub::bool_counter = 0;

View File

@ -100,6 +100,7 @@ protected:
virtual void SetUp()
{
object = new my_LoRaPHY();
memset(&object->get_phy_params(), 0, sizeof(object->get_phy_params()));
}
virtual void TearDown()
@ -167,8 +168,17 @@ TEST_F(Test_LoRaPHY, calculate_backoff)
{
channel_params_t p[1];
p[0].band = 0;
p[0].dr_range.fields.min = DR_0;
p[0].dr_range.fields.max = DR_5;
object->get_phy_params().channels.channel_list = p;
band_t b[1];
b[0].duty_cycle = 0;
b[0].higher_band_freq = 8689000;
b[0].lower_band_freq = 8687000;
b[0].max_tx_pwr = 20;
b[0].last_join_tx_time = 0;
b[0].last_tx_time = 0;
b[0].off_time = 0;
object->get_phy_params().bands.table = b;
object->calculate_backoff(false, false, false, 0, 10, 12);
@ -180,6 +190,7 @@ TEST_F(Test_LoRaPHY, calculate_backoff)
TEST_F(Test_LoRaPHY, mask_bit_test)
{
uint16_t buf;
buf = 0x08;
EXPECT_TRUE(!object->mask_bit_test(&buf, 0));
}
@ -197,51 +208,58 @@ TEST_F(Test_LoRaPHY, mask_bit_clear)
TEST_F(Test_LoRaPHY, request_new_channel)
{
band_t b;
object->get_phy_params().bands.size = 1;
b.higher_band_freq = 8689000;
b.lower_band_freq = 8678000;
b.duty_cycle = 0;
b.last_join_tx_time = 0;
b.last_tx_time = 0;
b.max_tx_pwr = 20;
b.off_time = 0;
object->get_phy_params().bands.table = &b;
channel_params_t p;
EXPECT_TRUE(0 == object->request_new_channel(1, &p));
p.frequency = 0;
//First 3 channels are set to be default
p.band = 0;
p.dr_range.fields.min = DR_0;
p.dr_range.fields.max = DR_5;
p.frequency = 8687000;
p.rx1_frequency = 0;
uint16_t dflt_msk = 0x07;
object->get_phy_params().channels.default_mask = &dflt_msk;
object->get_phy_params().channels.channel_list = &p;
object->get_phy_params().custom_channelplans_supported = true;
uint16_t list;
object->get_phy_params().channels.default_mask = &list;
channel_params_t pp;
object->get_phy_params().channels.channel_list = &pp;
EXPECT_TRUE(0 == object->request_new_channel(1, &p));
//Default
p.frequency = 2;
EXPECT_TRUE(0 == object->request_new_channel(1, &p));
//Default channel, PARAMETER invalid
EXPECT_TRUE(0 == object->request_new_channel(0, &p));
//Freq & DR invalid
object->get_phy_params().max_channel_cnt = 2;
EXPECT_TRUE(0 == object->request_new_channel(1, &p));
p.frequency = 12345;
p.dr_range.fields.max = 12;
object->get_phy_params().max_channel_cnt = 16;
object->get_phy_params().min_tx_datarate = DR_0;
object->get_phy_params().max_tx_datarate = DR_5;
// Frequency and DR are invalid - LORAWAN_STATUS_FREQ_AND_DR_INVALID
EXPECT_TRUE(0 == object->request_new_channel(0, &p));
//Freq invalid
pp.frequency = 0;
object->get_phy_params().default_max_datarate = 1;
object->get_phy_params().max_tx_datarate = 8;
p.dr_range.fields.max = 2;
p.dr_range.fields.min = 0;
p.frequency = 12345;
p.dr_range.fields.max = DR_5;
object->get_phy_params().default_channel_cnt = 3;
EXPECT_TRUE(2 == object->request_new_channel(0, &p));
//DR invalid
pp.frequency = 2;
p.band = 0;
object->get_phy_params().bands.size = 1;
band_t b;
object->get_phy_params().bands.table = &b;
b.higher_band_freq = 5;
b.lower_band_freq = 1;
p.frequency = 8687000;
p.dr_range.fields.max = 12;
p.dr_range.fields.min = 1;
EXPECT_TRUE(1 == object->request_new_channel(0, &p));
//STATUS_OK
p.dr_range.fields.max = 2;
uint16_t list2[16];
p.dr_range.fields.min = 0;
object->get_phy_params().channels.mask = list2;
p.dr_range.fields.max = DR_5;
p.dr_range.fields.min = DR_0;
uint16_t ch_msk = 0x08;
object->get_phy_params().channels.mask = &ch_msk;
EXPECT_TRUE(3 == object->request_new_channel(0, &p));
}
@ -272,19 +290,27 @@ TEST_F(Test_LoRaPHY, restore_default_channels)
TEST_F(Test_LoRaPHY, apply_cf_list)
{
uint8_t list[16];
memset(list, 0, 16);
object->apply_cf_list(list, 0);
object->get_phy_params().cflist_supported = true;
object->apply_cf_list(list, 0);
object->get_phy_params().default_channel_cnt = 2;
object->get_phy_params().default_channel_cnt = 1;
object->get_phy_params().cflist_channel_cnt = 0;
object->get_phy_params().max_channel_cnt = 3;
uint16_t mask[8];
channel_params_t p[8];
object->get_phy_params().channels.default_mask = mask;
object->get_phy_params().channels.mask = mask;
uint16_t def_mask = 0x01;
channel_params_t p[16];
memset(p, 0, 16);
//one default channel
p[0].band = 0;
p[0].dr_range.fields.min = DR_0;
p[0].dr_range.fields.min = DR_5;
p[0].frequency = 8687000;
object->get_phy_params().channels.default_mask = &def_mask;
object->get_phy_params().channels.mask = &def_mask;
object->get_phy_params().channels.channel_list = p;
object->apply_cf_list(list, 16);
@ -325,6 +351,7 @@ TEST_F(Test_LoRaPHY, rx_config)
uint8_t list2;
object->get_phy_params().payloads_with_repeater.table = &list2;
rx_config_params_t p;
memset(&p, 0, sizeof(rx_config_params_t));
p.datarate = 0;
p.rx_slot = RX_SLOT_WIN_1;
channel_params_t pp[1];
@ -345,11 +372,22 @@ TEST_F(Test_LoRaPHY, rx_config)
TEST_F(Test_LoRaPHY, compute_rx_win_params)
{
uint32_t list[1];
list[0] = 0;
list[0] = 125000;
object->get_phy_params().bandwidths.table = list;
uint8_t list2;
uint8_t list2[1];
list2[0]= 12;
object->get_phy_params().datarates.table = &list2;
channel_params_t ch_lst[16];
memset(ch_lst, 0, sizeof(channel_params_t)*16);
ch_lst[0].band = 0;
ch_lst[0].dr_range.fields.min = DR_0;
ch_lst[0].dr_range.fields.max = DR_5;
ch_lst[0].frequency = 8687000;
object->get_phy_params().channels.channel_list = ch_lst;
object->get_phy_params().channels.channel_list_size = 16;
rx_config_params_t p;
memset(&p, 0, sizeof(rx_config_params_t));
p.frequency = 8687000;
object->compute_rx_win_params(0, 0, 0, &p);
p.datarate = 0;
@ -368,20 +406,25 @@ TEST_F(Test_LoRaPHY, compute_rx_win_params)
TEST_F(Test_LoRaPHY, tx_config)
{
band_t b;
memset(&b, 0, sizeof(band_t));
object->get_phy_params().bands.table = &b;
channel_params_t pp;
memset(&pp, 0, sizeof(channel_params_t));
pp.band=0;
object->get_phy_params().channels.channel_list = &pp;
uint32_t list = 0;
uint32_t list[1];
list[0] = 125000;
object->get_phy_params().bandwidths.table = &list;
uint8_t list2;
uint8_t list2[1];
list2[0] = 12;
object->get_phy_params().datarates.table = &list2;
my_radio radio;
object->set_radio_instance(radio);
tx_config_params_t p;
memset(&p, 0, sizeof(tx_config_params_t));
p.channel=0;
int8_t i;
lorawan_time_t t;
int8_t i = 20;
lorawan_time_t t = 36;
object->tx_config(&p, &i, &t);
p.datarate = 8;
@ -392,7 +435,9 @@ TEST_F(Test_LoRaPHY, tx_config)
TEST_F(Test_LoRaPHY, link_ADR_request)
{
adr_req_params_t p;
memset(&p, 0, sizeof(adr_req_params_t));
uint8_t b[100];
memset(b, 0, 100);
p.payload = b;
b[0] = 0x03;
b[1] = 1;
@ -411,16 +456,17 @@ TEST_F(Test_LoRaPHY, link_ADR_request)
b[14] = 0;
b[15] = 0;
p.payload_size = 16;
int8_t i, j;
uint8_t k, l;
uint8_t t[5];
int8_t i = 0, j = 0;
uint8_t k = 0, l = 0;
uint8_t t[5] = {12, 11, 10, 9, 8};
t[0] = 0;
object->get_phy_params().datarates.size = 1;
object->get_phy_params().datarates.size = 5;
object->get_phy_params().datarates.table = t;
//Test without ADR payload does not make sense here.
object->get_phy_params().max_channel_cnt = 2;
channel_params_t li[4];
object->get_phy_params().max_channel_cnt = 16;
channel_params_t li[16];
memset(li, 0, sizeof(channel_params_t)*16);
object->get_phy_params().channels.channel_list = li;
li[0].frequency = 0;
li[1].frequency = 5;
@ -430,7 +476,7 @@ TEST_F(Test_LoRaPHY, link_ADR_request)
//verify adr with p.adr_enabled = false
EXPECT_TRUE(0 == object->link_ADR_request(&p, &i, &j, &k, &l));
p.current_nb_rep = 0;
p.current_nb_trans = 0;
EXPECT_TRUE(0 == object->link_ADR_request(&p, &i, &j, &k, &l));
p.adr_enabled = true;
@ -484,9 +530,19 @@ TEST_F(Test_LoRaPHY, link_ADR_request)
TEST_F(Test_LoRaPHY, accept_rx_param_setup_req)
{
my_radio radio;
radio.bool_value = true;
object->set_radio_instance(radio);
rx_param_setup_req_t req;
EXPECT_TRUE(0 == object->accept_rx_param_setup_req(&req));
req.datarate = DR_0;
req.dr_offset = 0;
req.frequency = 8678000;
band_t band[1];
memset(band, 0, sizeof(band_t));
band[0].higher_band_freq = 8688000;
band[0].lower_band_freq = 8666000;
object->get_phy_params().bands.size = 1;
object->get_phy_params().bands.table = band;
EXPECT_TRUE(0x07 == object->accept_rx_param_setup_req(&req));
}
TEST_F(Test_LoRaPHY, accept_tx_param_setup_req)
@ -504,8 +560,14 @@ TEST_F(Test_LoRaPHY, dl_channel_request)
object->get_phy_params().dl_channel_req_supported = true;
object->get_phy_params().bands.size = 1;
band_t t[1];
memset(t, 0, sizeof(band_t));
t[0].higher_band_freq = 8688000;
t[0].lower_band_freq = 8668000;
object->get_phy_params().bands.size = 1;
object->get_phy_params().bands.table = t;
channel_params_t p[4];
channel_params_t p[16];
memset(p, 0, sizeof(channel_params_t) * 16);
object->get_phy_params().channels.channel_list_size = 16;
object->get_phy_params().channels.channel_list = p;
p[0].frequency = 0;
@ -533,16 +595,24 @@ TEST_F(Test_LoRaPHY, get_alternate_DR)
TEST_F(Test_LoRaPHY, set_next_channel)
{
channel_selection_params_t p;
uint8_t ch;
lorawan_time_t t1;
lorawan_time_t t2;
memset(&p, 0, sizeof(channel_selection_params_t));
band_t band[1];
memset(band, 0, sizeof(band_t));
band[0].higher_band_freq = 8687000;
object->get_phy_params().bands.size = 1;
object->get_phy_params().bands.table = band;
uint8_t ch = 5;
lorawan_time_t t1 = 16;
lorawan_time_t t2 = 32;
p.aggregate_timeoff = 10000;
EXPECT_TRUE(LORAWAN_STATUS_DUTYCYCLE_RESTRICTED == object->set_next_channel(&p, &ch, &t1, &t2));
uint16_t list[16];
uint16_t list[129];
memset(list, 0, sizeof(list));
list[4] = 1;
memcpy(list, "\0", 16);
list[128] = 1;
object->get_phy_params().channels.mask = list;
object->get_phy_params().channels.default_mask = list;
object->get_phy_params().channels.mask_size = 1;
p.aggregate_timeoff = 10000;
EXPECT_TRUE(LORAWAN_STATUS_DUTYCYCLE_RESTRICTED == object->set_next_channel(&p, &ch, &t1, &t2));
@ -553,11 +623,18 @@ TEST_F(Test_LoRaPHY, set_next_channel)
p.joined = false;
p.dc_enabled = false;
band_t b[4];
ch = 5;
t1 = 16;
t2 = 32;
memset(b, 0, sizeof(band_t)*4);
object->get_phy_params().bands.size = 2;
object->get_phy_params().bands.table = &b;
b[0].off_time = 0;
b[1].off_time = 9999999;
memset(list, 0, 129);
list[4] = 0;
object->get_phy_params().channels.mask = list;
object->get_phy_params().channels.default_mask = list;
object->get_phy_params().channels.mask_size = 128;
p.current_datarate = DR_1;
object->get_phy_params().max_channel_cnt = 4;
@ -595,6 +672,8 @@ TEST_F(Test_LoRaPHY, add_channel)
object->get_phy_params().channels.mask = list;
object->get_phy_params().channels.default_mask = list;
channel_params_t p;
p.band = 0;
p.frequency = 0;
EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->add_channel(&p, 0));
object->get_phy_params().custom_channelplans_supported = true;
@ -634,6 +713,7 @@ TEST_F(Test_LoRaPHY, set_tx_cont_mode)
pp.band=0;
object->get_phy_params().channels.channel_list = &pp;
band_t b;
b.max_tx_pwr = 10;
object->get_phy_params().bands.table = &b;
my_radio radio;
object->set_radio_instance(radio);
@ -641,6 +721,9 @@ TEST_F(Test_LoRaPHY, set_tx_cont_mode)
cw_mode_params_t p;
p.max_eirp = 0;
p.channel=0;
p.tx_power = -1;
p.datarate = 0;
p.antenna_gain = 1;
object->set_tx_cont_mode(&p);
p.max_eirp = 1;

View File

@ -107,6 +107,7 @@ TEST_F(Test_LoRaPHYAU915, constructor)
TEST_F(Test_LoRaPHYAU915, rx_config)
{
rx_config_params_t p;
memset(&p, 0, sizeof(p));
radio.uint8_value = 1;
EXPECT_TRUE(!object->rx_config(&p));
@ -122,7 +123,8 @@ TEST_F(Test_LoRaPHYAU915, rx_config)
TEST_F(Test_LoRaPHYAU915, tx_config)
{
tx_config_params_t p;
int8_t tx;
memset(&p, 0, sizeof(p));
int8_t tx = 0;
lorawan_time_t time;
p.tx_power = 9;
EXPECT_TRUE(object->tx_config(&p, &tx, &time));
@ -131,10 +133,11 @@ TEST_F(Test_LoRaPHYAU915, tx_config)
TEST_F(Test_LoRaPHYAU915, link_ADR_request)
{
adr_req_params_t params;
int8_t dr_out;
int8_t tx_power_out;
uint8_t nb_rep_out;
uint8_t nb_bytes_parsed;
memset(&params, 0, sizeof(params));
int8_t dr_out = 0;
int8_t tx_power_out = 0;
uint8_t nb_rep_out = 0;
uint8_t nb_bytes_parsed = 0;
LoRaPHY_stub::uint8_value = 1;
LoRaPHY_stub::ch_mask_value = 6;
@ -159,6 +162,7 @@ TEST_F(Test_LoRaPHYAU915, link_ADR_request)
TEST_F(Test_LoRaPHYAU915, accept_rx_param_setup_req)
{
rx_param_setup_req_t p;
memset(&p, 0, sizeof(p));
radio.bool_value = false;
EXPECT_TRUE(0 == object->accept_rx_param_setup_req(&p));

View File

@ -109,9 +109,11 @@ TEST_F(Test_LoRaPHYCN470, constructor)
TEST_F(Test_LoRaPHYCN470, set_next_channel)
{
channel_selection_params_t params;
uint8_t channel;
lorawan_time_t time;
lorawan_time_t timeoff;
memset(&params, 0, sizeof(params));
uint8_t channel = 0;
lorawan_time_t time = 0;
lorawan_time_t timeoff = 0;
params.current_datarate = 4;
params.aggregate_timeoff = 0;
@ -130,6 +132,7 @@ TEST_F(Test_LoRaPHYCN470, set_next_channel)
TEST_F(Test_LoRaPHYCN470, rx_config)
{
rx_config_params_t p;
memset(&p, 0, sizeof(p));
radio.uint8_value = 1;
EXPECT_TRUE(!object->rx_config(&p));
@ -145,8 +148,8 @@ TEST_F(Test_LoRaPHYCN470, rx_config)
TEST_F(Test_LoRaPHYCN470, tx_config)
{
tx_config_params_t p;
int8_t tx;
lorawan_time_t time;
int8_t tx = 0;
lorawan_time_t time = 0;
p.tx_power = 9;
EXPECT_TRUE(object->tx_config(&p, &tx, &time));
}
@ -154,10 +157,11 @@ TEST_F(Test_LoRaPHYCN470, tx_config)
TEST_F(Test_LoRaPHYCN470, link_ADR_request)
{
adr_req_params_t params;
int8_t dr_out;
int8_t tx_power_out;
uint8_t nb_rep_out;
uint8_t nb_bytes_parsed;
memset(&params, 0, sizeof(params));
int8_t dr_out = 0;
int8_t tx_power_out = 0;
uint8_t nb_rep_out = 0;
uint8_t nb_bytes_parsed = 0;
LoRaPHY_stub::uint8_value = 1;
LoRaPHY_stub::ch_mask_value = 6;
@ -182,6 +186,8 @@ TEST_F(Test_LoRaPHYCN470, link_ADR_request)
TEST_F(Test_LoRaPHYCN470, accept_rx_param_setup_req)
{
rx_param_setup_req_t p;
memset(&p, 0, sizeof(p));
radio.bool_value = false;
EXPECT_TRUE(0 == object->accept_rx_param_setup_req(&p));
radio.bool_value = true;

View File

@ -117,8 +117,9 @@ TEST_F(Test_LoRaPHYKR920, verify_frequency_for_band)
TEST_F(Test_LoRaPHYKR920, tx_config)
{
tx_config_params_t tx_config;
memset(&tx_config, 0, sizeof(tx_config));
int8_t tx_power = 0;
lorawan_time_t time;
lorawan_time_t time = 0;
tx_config.tx_power = 9;
EXPECT_TRUE(true == object->tx_config(&tx_config, &tx_power, &time));
@ -127,6 +128,7 @@ TEST_F(Test_LoRaPHYKR920, tx_config)
TEST_F(Test_LoRaPHYKR920, set_next_channel)
{
channel_selection_params_t next_channel;
memset(&next_channel, 0, sizeof(next_channel));
lorawan_time_t backoff_time = 0;
lorawan_time_t time = 0;
uint8_t ch = 1;
@ -150,6 +152,7 @@ TEST_F(Test_LoRaPHYKR920, set_next_channel)
TEST_F(Test_LoRaPHYKR920, set_tx_cont_mode)
{
cw_mode_params_t params;
memset(&params, 0, sizeof(params));
params.tx_power = 9;
object->set_tx_cont_mode(&params, 0);
}

View File

@ -111,6 +111,7 @@ TEST_F(Test_LoRaPHYUS915, restore_default_channels)
TEST_F(Test_LoRaPHYUS915, rx_config)
{
rx_config_params_t p;
memset(&p, 0, sizeof(p));
radio.uint8_value = 1;
EXPECT_TRUE(!object->rx_config(&p));
@ -126,18 +127,20 @@ TEST_F(Test_LoRaPHYUS915, rx_config)
TEST_F(Test_LoRaPHYUS915, tx_config)
{
tx_config_params_t p;
int8_t tx;
lorawan_time_t time;
memset(&p, 0, sizeof(p));
int8_t tx = 0;
lorawan_time_t time = 0;
EXPECT_TRUE(object->tx_config(&p, &tx, &time));
}
TEST_F(Test_LoRaPHYUS915, link_ADR_request)
{
adr_req_params_t params;
int8_t dr_out;
int8_t tx_power_out;
uint8_t nb_rep_out;
uint8_t nb_bytes_parsed;
memset(&params, 0, sizeof(params));
int8_t dr_out = 0;
int8_t tx_power_out = 0;
uint8_t nb_rep_out = 0;
uint8_t nb_bytes_parsed = 0;
EXPECT_TRUE(0 == object->link_ADR_request(&params, &dr_out, &tx_power_out, &nb_rep_out, &nb_bytes_parsed));
@ -164,6 +167,8 @@ TEST_F(Test_LoRaPHYUS915, link_ADR_request)
TEST_F(Test_LoRaPHYUS915, accept_rx_param_setup_req)
{
rx_param_setup_req_t p;
memset(&p, 0, sizeof(p));
radio.bool_value = false;
EXPECT_TRUE(0 == object->accept_rx_param_setup_req(&p));
radio.bool_value = true;
@ -188,9 +193,10 @@ TEST_F(Test_LoRaPHYUS915, get_alternate_DR)
TEST_F(Test_LoRaPHYUS915, set_next_channel)
{
channel_selection_params_t params;
uint8_t channel;
lorawan_time_t time;
lorawan_time_t timeoff;
memset(&params, 0, sizeof(params));
uint8_t channel = 0;
lorawan_time_t time = 0;
lorawan_time_t timeoff = 0;
params.current_datarate = 4;
params.aggregate_timeoff = 0;
@ -228,6 +234,7 @@ TEST_F(Test_LoRaPHYUS915, apply_DR_offset)
TEST_F(Test_LoRaPHYUS915, set_tx_cont_mode)
{
cw_mode_params_t p;
memset(&p, 0, sizeof(p));
object->set_tx_cont_mode(&p, 0);
p.datarate = 4;

View File

@ -201,7 +201,7 @@ TEST_F(Test_LoRaWANInterface, add_app_callbacks)
TEST_F(Test_LoRaWANInterface, set_device_class)
{
object->set_device_class(CLASS_A);
EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_device_class(CLASS_A));
}
TEST_F(Test_LoRaWANInterface, get_tx_metadata)

View File

@ -350,6 +350,9 @@ TEST_F(Test_LoRaWANStack, handle_tx)
cb.events = events_cb;
cb.link_check_resp = lc_resp;
cb.battery_level = batt_lvl;
struct equeue_event ptr;
equeue_stub.void_ptr = &ptr;
equeue_stub.call_cb_immediately = true;
EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_lora_callbacks(&cb));
EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_link_check_request());
@ -394,6 +397,10 @@ TEST_F(Test_LoRaWANStack, handle_rx)
LoRaMac_stub::status_value = LORAWAN_STATUS_OK;
EXPECT_TRUE(LORAWAN_STATUS_NO_ACTIVE_SESSIONS == object->handle_rx(NULL, 0, port, flags, false));
struct equeue_event ptr;
equeue_stub.void_ptr = &ptr;
equeue_stub.call_cb_immediately = true;
lorawan_connect_t conn;
conn.connect_type = LORAWAN_CONNECTION_ABP;
EXPECT_TRUE(LORAWAN_STATUS_OK == object->connect(conn));
@ -410,14 +417,13 @@ TEST_F(Test_LoRaWANStack, handle_rx)
my_LoRaPHY phy;
object->bind_phy_and_radio_driver(radio, phy);
struct equeue_event ptr;
equeue_stub.void_ptr = &ptr;
equeue_stub.call_cb_immediately = true;
loramac_mcps_confirm_t conf;
conf.status = LORAMAC_EVENT_INFO_STATUS_OK;
LoRaMac_stub::mcps_conf_ptr = &conf;
radio._ev->tx_done();
loramac_mcps_indication_t ind;
ind.status = LORAMAC_EVENT_INFO_STATUS_OK;
LoRaMac_stub::mcps_ind_ptr = &ind;
loramac_mlme_confirm_t mlme;
@ -429,7 +435,7 @@ TEST_F(Test_LoRaWANStack, handle_rx)
conf.req_type = MCPS_PROPRIETARY;
ind.pending = true;
LoRaMac_stub::dev_class_value = CLASS_C;
LoRaMac_stub::dev_class_value = CLASS_A;
loramac_mlme_indication_t mlme_ind;
mlme_ind.pending = false;
@ -546,16 +552,12 @@ TEST_F(Test_LoRaWANStack, set_device_class)
EXPECT_TRUE(LORAWAN_STATUS_UNSUPPORTED == object->set_device_class(CLASS_B));
EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_device_class(CLASS_A));
//Visit callback
if (LoRaMac_stub::_ack_expiry_handler_for_class_c) {
LoRaMac_stub::_ack_expiry_handler_for_class_c.call();
}
}
TEST_F(Test_LoRaWANStack, acquire_tx_metadata)
{
lorawan_tx_metadata data;
memset(&data, 0, sizeof(data));
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->acquire_tx_metadata(data));
EventQueue queue;
@ -574,15 +576,21 @@ TEST_F(Test_LoRaWANStack, acquire_tx_metadata)
equeue_stub.void_ptr = &ptr;
equeue_stub.call_cb_immediately = true;
loramac_mcps_confirm_t conf;
memset(&conf, 0, sizeof(conf));
conf.status = LORAMAC_EVENT_INFO_STATUS_OK;
LoRaMac_stub::mcps_conf_ptr = &conf;
radio._ev->tx_done();
LoRaMac_stub::slot_value = RX_SLOT_WIN_2;
radio._ev->rx_timeout();
EXPECT_TRUE(LORAWAN_STATUS_OK == object->acquire_tx_metadata(data));
}
TEST_F(Test_LoRaWANStack, acquire_rx_metadata)
{
lorawan_rx_metadata data;
memset(&data, 0, sizeof(data));
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->acquire_rx_metadata(data));
EventQueue queue;
@ -601,13 +609,18 @@ TEST_F(Test_LoRaWANStack, acquire_rx_metadata)
equeue_stub.void_ptr = &ptr;
equeue_stub.call_cb_immediately = true;
loramac_mcps_confirm_t conf;
memset(&conf, 0, sizeof(conf));
conf.status = LORAMAC_EVENT_INFO_STATUS_OK;
LoRaMac_stub::mcps_conf_ptr = &conf;
radio._ev->tx_done();
loramac_mcps_indication_t ind;
memset(&ind, 0, sizeof(ind));
ind.status = LORAMAC_EVENT_INFO_STATUS_OK;
LoRaMac_stub::mcps_ind_ptr = &ind;
loramac_mlme_confirm_t mlme;
mlme.status = LORAMAC_EVENT_INFO_STATUS_OK;
LoRaMac_stub::mlme_conf_ptr = &mlme;
mlme.pending = true;
mlme.req_type = MLME_JOIN;
@ -631,6 +644,7 @@ TEST_F(Test_LoRaWANStack, acquire_rx_metadata)
EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_lora_callbacks(&cb));
mlme.req_type = MLME_LINK_CHECK;
mlme.status = LORAMAC_EVENT_INFO_STATUS_OK;
LoRaMac_stub::bool_true_counter = true;
radio._ev->rx_done(NULL, 0, 0, 0);
EXPECT_TRUE(LORAWAN_STATUS_OK == object->acquire_rx_metadata(data));
@ -658,7 +672,7 @@ TEST_F(Test_LoRaWANStack, stop_sending)
EventQueue queue;
EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue));
LoRaMac_stub::status_value = LORAWAN_STATUS_DEVICE_OFF;
LoRaMac_stub::status_value = LORAWAN_STATUS_BUSY;
EXPECT_TRUE(LORAWAN_STATUS_BUSY == object->stop_sending());
LoRaMac_stub::status_value = LORAWAN_STATUS_OK;
@ -809,10 +823,12 @@ TEST_F(Test_LoRaWANStack, process_reception)
equeue_stub.void_ptr = &ptr;
equeue_stub.call_cb_immediately = true;
loramac_mcps_confirm_t conf;
memset(&conf, 0, sizeof(&conf));
LoRaMac_stub::mcps_conf_ptr = &conf;
radio._ev->tx_done();
loramac_mcps_indication_t ind;
memset(&ind, 0, sizeof(ind));
LoRaMac_stub::mcps_ind_ptr = &ind;
loramac_mlme_confirm_t mlme;
@ -851,7 +867,7 @@ TEST_F(Test_LoRaWANStack, process_reception)
conf.req_type = MCPS_UNCONFIRMED;
LoRaMac_stub::dev_class_value = CLASS_A;
LoRaMac_stub::bool_value = true;
LoRaMac_stub::bool_true_counter++;
mlme_ind.pending = true;
mlme_ind.indication_type = MLME_SCHEDULE_UPLINK;
conf.status = LORAMAC_EVENT_INFO_STATUS_ERROR;

View File

@ -0,0 +1,287 @@
/*
* 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 "gmock/gmock.h"
#include "features/netsocket/EthernetInterface.h"
#include <iostream>
class MockEMAC : public EMAC {
public:
MOCK_METHOD0(power_up, bool());
MOCK_METHOD0(power_down, void());
MOCK_CONST_METHOD0(get_mtu_size, uint32_t());
MOCK_CONST_METHOD0(get_align_preference, uint32_t());
MOCK_CONST_METHOD2(get_ifname, void(char *name, uint8_t size));
MOCK_CONST_METHOD0(get_hwaddr_size, uint8_t());
MOCK_CONST_METHOD1(get_hwaddr, bool(uint8_t *addr));
MOCK_METHOD1(set_hwaddr, void(const uint8_t *));
MOCK_METHOD1(link_out, bool(emac_mem_buf_t *buf));
MOCK_METHOD1(set_link_input_cb, void(emac_link_input_cb_t input_cb));
MOCK_METHOD1(set_link_state_cb, void(emac_link_state_change_cb_t state_cb));
MOCK_METHOD1(add_multicast_group, void(const uint8_t *address));
MOCK_METHOD1(remove_multicast_group, void(const uint8_t *address));
MOCK_METHOD1(set_all_multicast, void(bool all));
MOCK_METHOD1(set_memory_manager, void(EMACMemoryManager &mem_mngr));
static MockEMAC &get_instance()
{
static MockEMAC emacMock1;
return emacMock1;
}
};
MBED_WEAK EMAC &EMAC::get_default_instance()
{
return MockEMAC::get_instance();
}
class EmacNetworkStackMock : public OnboardNetworkStack {
public:
MOCK_METHOD3(gethostbyname, nsapi_error_t(const char *host, SocketAddress *address, nsapi_version_t version));
MOCK_METHOD1(add_dns_server, nsapi_error_t(const SocketAddress &address));
MOCK_METHOD2(call_in, nsapi_error_t(int delay, mbed::Callback<void()> func));
MOCK_METHOD2(socket_open, nsapi_error_t(nsapi_socket_t *handle, nsapi_protocol_t proto));
MOCK_METHOD1(socket_close, nsapi_error_t(nsapi_socket_t handle));
MOCK_METHOD2(socket_bind, nsapi_error_t(nsapi_socket_t handle, const SocketAddress &address));
MOCK_METHOD2(socket_listen, nsapi_error_t(nsapi_socket_t handle, int backlog));
MOCK_METHOD2(socket_connect, nsapi_error_t(nsapi_socket_t handle, const SocketAddress &address));
MOCK_METHOD3(socket_accept, nsapi_error_t(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address));
MOCK_METHOD3(socket_send, nsapi_error_t(nsapi_socket_t handle, const void *data, nsapi_size_t size));
MOCK_METHOD3(socket_recv, nsapi_error_t(nsapi_socket_t handle, void *data, nsapi_size_t size));
MOCK_METHOD4(socket_sendto, nsapi_error_t(nsapi_socket_t handle, const SocketAddress &address, const void *data, nsapi_size_t size));
MOCK_METHOD4(socket_recvfrom, nsapi_error_t(nsapi_socket_t handle, SocketAddress *address, void *data, nsapi_size_t size));
MOCK_METHOD5(setsockopt, nsapi_error_t(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen));
MOCK_METHOD5(getsockopt, nsapi_error_t(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned *optlen));
MOCK_METHOD3(socket_attach, void(nsapi_socket_t handle, void (*callback)(void *), void *data));
MOCK_METHOD3(add_ethernet_interface, nsapi_error_t(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out));
static EmacNetworkStackMock &get_instance()
{
static EmacNetworkStackMock stackMock1;
return stackMock1;
}
class InterfaceMock : public OnboardNetworkStack::Interface {
public:
static InterfaceMock &get_instance()
{
static InterfaceMock test_interface;
return test_interface;
}
MOCK_METHOD6(bringup, nsapi_error_t(bool dhcp, const char *ip,
const char *netmask, const char *gw,
nsapi_ip_stack_t stack,
bool blocking
));
MOCK_METHOD0(bringdown, nsapi_error_t());
MOCK_METHOD1(attach, void(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb));
MOCK_CONST_METHOD0(get_connection_status, nsapi_connection_status_t());
MOCK_METHOD2(get_mac_address, char *(char *buf, nsapi_size_t buflen));
MOCK_METHOD2(get_ip_address, char *(char *buf, nsapi_size_t buflen));
MOCK_METHOD2(get_netmask, char *(char *buf, nsapi_size_t buflen));
MOCK_METHOD2(get_gateway, char *(char *buf, nsapi_size_t buflen));
};
};
OnboardNetworkStack &OnboardNetworkStack::get_default_instance()
{
return EmacNetworkStackMock::get_instance();
}
// Implementaion in in NetworkInterfaceDefaults.cpp
MBED_WEAK EthInterface *EthInterface::get_default_instance()
{
return get_target_default_instance();
}
using ::testing::_;
using ::testing::Return;
using ::testing::ReturnArg;
using ::testing::SaveArg;
using ::testing::SaveArgPointee;
using ::testing::SetArrayArgument;
using ::testing::SetArgPointee;
using ::testing::SetArgReferee;
class TestEthernetInterface: public testing::Test {
protected:
EthernetInterface *iface;
EmacNetworkStackMock *stackMock;
MockEMAC *emacMock;
EmacNetworkStackMock::InterfaceMock *netStackIface;
virtual void SetUp()
{
stackMock = &EmacNetworkStackMock::get_instance();
emacMock = &MockEMAC::get_instance();
netStackIface = &EmacNetworkStackMock::InterfaceMock::get_instance();
iface = new EthernetInterface(MockEMAC::get_instance(), EmacNetworkStackMock::get_instance());
}
virtual void TearDown()
{
// Do not delete the mocks pointers, as they point to statically allocated singletons.
delete iface;
}
/* Enclose the heavily-used connection procedure to improve code redability */
void doConnect(bool dhcp = true, bool blocking = true)
{
EXPECT_CALL(*stackMock, add_ethernet_interface(testing::Ref(*emacMock), true, _))
.Times(1)
.WillOnce(DoAll(SetArgPointee<2>(netStackIface), Return(NSAPI_ERROR_OK)));
EXPECT_CALL(*netStackIface, attach(_))
.Times(1)
.RetiresOnSaturation();;
EXPECT_CALL(*netStackIface, bringup(dhcp, NULL, NULL, NULL, DEFAULT_STACK, blocking))
.Times(1)
.WillOnce(Return(NSAPI_ERROR_OK));
EXPECT_EQ(NSAPI_ERROR_OK, iface->connect());
}
static void cb(nsapi_event_t ev, intptr_t ptr)
{
}
};
TEST_F(TestEthernetInterface, constructor_default)
{
EXPECT_TRUE(iface);
}
TEST_F(TestEthernetInterface, constructor_getter)
{
EthInterface *eth = EthInterface::get_default_instance();
}
TEST_F(TestEthernetInterface, connect)
{
doConnect();
}
TEST_F(TestEthernetInterface, connect_failure)
{
EXPECT_CALL(*stackMock, add_ethernet_interface(testing::Ref(*emacMock), true, _))
.Times(1)
.WillOnce(DoAll(SetArgPointee<2>(netStackIface), Return(NSAPI_ERROR_NO_MEMORY)));
EXPECT_EQ(NSAPI_ERROR_NO_MEMORY, iface->connect());
}
TEST_F(TestEthernetInterface, disconnect_without_connecting)
{
EXPECT_EQ(NSAPI_ERROR_NO_CONNECTION, iface->disconnect());
}
TEST_F(TestEthernetInterface, disconnect)
{
doConnect();
EXPECT_CALL(*netStackIface, bringdown())
.Times(1)
.WillOnce(Return(NSAPI_ERROR_OK));
EXPECT_EQ(NSAPI_ERROR_OK, iface->disconnect());
}
TEST_F(TestEthernetInterface, set_network)
{
char ipAddress[NSAPI_IPv4_SIZE] = "127.0.0.1";
char netmask[NSAPI_IPv4_SIZE] = "255.255.0.0";
char gateway[NSAPI_IPv4_SIZE] = "127.0.0.2";
const char *ipAddressArg;
const char *netmaskArg;
const char *gatewayArg;
EXPECT_EQ(0, iface->get_ip_address());
EXPECT_EQ(0, iface->get_netmask());
EXPECT_EQ(0, iface->get_gateway());
// Set the network data
EXPECT_EQ(NSAPI_ERROR_OK, iface->set_network(ipAddress, netmask, gateway));
// Now the bringup should have different arguments. We can't use doConnect method.
EXPECT_CALL(*stackMock, add_ethernet_interface(testing::Ref(*emacMock), true, _))
.Times(1)
.WillOnce(DoAll(SetArgPointee<2>(netStackIface), Return(NSAPI_ERROR_OK)));
EXPECT_CALL(*netStackIface, attach(_))
.Times(1)
.RetiresOnSaturation();
// Do not put the expected char * arguments, as they are pointers and would not match
EXPECT_CALL(*netStackIface, bringup(false, _, _, _, DEFAULT_STACK, true))
.Times(1)
.WillOnce(DoAll(SaveArg<1>(&ipAddressArg),
SaveArg<2>(&netmaskArg),
SaveArg<3>(&gatewayArg),
Return(NSAPI_ERROR_OK)));
EXPECT_EQ(NSAPI_ERROR_OK, iface->connect());
// Check the contents of the stored pointer arguments.
EXPECT_TRUE(0 == strcmp(ipAddress, ipAddressArg));
EXPECT_TRUE(0 == strcmp(netmask, netmaskArg));
EXPECT_TRUE(0 == strcmp(gateway, gatewayArg));
// Testing the getters makes sense now.
EXPECT_CALL(*netStackIface, get_ip_address(_, _))
.Times(1)
.WillOnce(DoAll(SetArgPointee<0>(*ipAddress), Return(ipAddress)));
EXPECT_EQ(std::string(ipAddress), std::string(iface->get_ip_address()));
EXPECT_CALL(*netStackIface, get_netmask(_, _))
.Times(1)
.WillOnce(DoAll(SetArgPointee<0>(*netmask), Return(netmask)));
EXPECT_EQ(std::string(netmask), std::string(iface->get_netmask()));
EXPECT_CALL(*netStackIface, get_gateway(_, _))
.Times(1)
.WillOnce(DoAll(SetArgPointee<0>(*gateway), Return(gateway)));
EXPECT_EQ(std::string(gateway), std::string(iface->get_gateway()));
}
TEST_F(TestEthernetInterface, get_connection_status)
{
EXPECT_EQ(NSAPI_STATUS_DISCONNECTED, iface->get_connection_status());
doConnect();
EXPECT_CALL(*netStackIface, get_connection_status())
.Times(1)
.WillOnce(Return(NSAPI_STATUS_LOCAL_UP));
EXPECT_EQ(NSAPI_STATUS_LOCAL_UP, iface->get_connection_status());
}
TEST_F(TestEthernetInterface, attach)
{
doConnect();
EXPECT_CALL(*netStackIface, attach(_)) // TODO: check that the correct function is passed.
.Times(1);
iface->attach(cb);
}
TEST_F(TestEthernetInterface, set_dhcp)
{
EXPECT_EQ(NSAPI_ERROR_OK, iface->set_dhcp(false));
doConnect(false, true);
}
TEST_F(TestEthernetInterface, set_blocking)
{
EXPECT_EQ(NSAPI_ERROR_OK, iface->set_blocking(false));
doConnect(true, false);
}

View File

@ -0,0 +1,33 @@
####################
# UNIT TESTS
####################
# Unit test suite name
set(TEST_SUITE_NAME "features_netsocket_EthernetInterface")
# Source files
set(unittest-sources
../features/netsocket/SocketAddress.cpp
../features/netsocket/EthernetInterface.cpp
../features/netsocket/EMACInterface.cpp
../features/netsocket/NetworkInterface.cpp
../features/netsocket/NetworkStack.cpp
../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c
../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c
)
# Test files
set(unittest-test-sources
features/netsocket/EthernetInterface/test_EthernetInterface.cpp
stubs/Mutex_stub.cpp
stubs/mbed_assert_stub.c
stubs/equeue_stub.c
stubs/EventQueue_stub.cpp
stubs/mbed_shared_queues_stub.cpp
stubs/nsapi_dns_stub.cpp
stubs/EventFlags_stub.cpp
stubs/stoip4_stub.c
stubs/ip4tos_stub.c
stubs/NetworkStack_stub.cpp
)

View File

@ -58,12 +58,30 @@ public:
}
// Testing functions
void add_reader (void) { _readers++;}
void rem_reader (void) { _readers--;}
void add_writer (void) { _writers++;}
void rem_writer (void) { _writers--;}
void add_pending (void) { _pending++;}
void rem_pending (void) { _pending--;}
void add_reader(void)
{
_readers++;
}
void rem_reader(void)
{
_readers--;
}
void add_writer(void)
{
_writers++;
}
void rem_writer(void)
{
_writers--;
}
void add_pending(void)
{
_pending++;
}
void rem_pending(void)
{
_pending--;
}
protected:
virtual nsapi_protocol_t get_proto()
@ -204,6 +222,7 @@ TEST_F(TestInternetSocket, getsockopt)
TEST_F(TestInternetSocket, sigio)
{
callback_is_called = false;
socket->open((NetworkStack *)&stack);
socket->sigio(mbed::callback(my_callback));
socket->close(); // Trigger event;
EXPECT_EQ(callback_is_called, true);

View File

@ -72,27 +72,27 @@ class NetworkStackChild : public NetworkStack {
return NSAPI_ERROR_OK;
}
virtual nsapi_error_t socket_accept(nsapi_socket_t server,
nsapi_socket_t *handle, SocketAddress *address = 0)
nsapi_socket_t *handle, SocketAddress *address = 0)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_size_or_error_t socket_send(nsapi_socket_t handle,
const void *data, nsapi_size_t size)
const void *data, nsapi_size_t size)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_size_or_error_t socket_recv(nsapi_socket_t handle,
void *data, nsapi_size_t size)
void *data, nsapi_size_t size)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_size_or_error_t socket_sendto(nsapi_socket_t handle, const SocketAddress &address,
const void *data, nsapi_size_t size)
const void *data, nsapi_size_t size)
{
return NSAPI_ERROR_OK;
}
virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address,
void *buffer, nsapi_size_t size)
void *buffer, nsapi_size_t size)
{
return NSAPI_ERROR_OK;
}
@ -125,8 +125,7 @@ protected:
virtual void TearDown()
{
delete stack;
if (mbed::mbed_shared_queue_stub)
{
if (mbed::mbed_shared_queue_stub) {
delete mbed::mbed_shared_queue_stub;
mbed::mbed_shared_queue_stub = 0;
}
@ -145,7 +144,7 @@ TEST_F(TestNetworkStack, constructor)
TEST_F(TestNetworkStack, get_ip_address_default)
{
EXPECT_EQ(stack->NetworkStack::get_ip_address(), (char*)NULL);
EXPECT_EQ(stack->NetworkStack::get_ip_address(), (char *)NULL);
}
/* gethostbyname */
@ -231,11 +230,11 @@ TEST_F(TestNetworkStack, gethostbyname_async_empty_host)
TEST_F(TestNetworkStack, getstackopt)
{
EXPECT_EQ(stack->getstackopt(0,0,0,0), NSAPI_ERROR_UNSUPPORTED);
EXPECT_EQ(stack->getstackopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED);
}
TEST_F(TestNetworkStack, setstackopt)
{
EXPECT_EQ(stack->setstackopt(0,0,0,0), NSAPI_ERROR_UNSUPPORTED);
EXPECT_EQ(stack->setstackopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED);
}

View File

@ -0,0 +1,166 @@
/*
* 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 "features/netsocket/SocketAddress.h"
#include <iostream>
class TestSocketAddress: public testing::Test {
protected:
SocketAddress *address;
virtual void SetUp()
{
address = new SocketAddress;
}
virtual void TearDown()
{
delete address;
}
void isEqual(SocketAddress addr1, SocketAddress addr2)
{
EXPECT_EQ(std::string(addr1.get_ip_address()), std::string(addr2.get_ip_address()));
EXPECT_EQ(addr1.get_addr().version, addr2.get_addr().version);
EXPECT_TRUE(0 == memcmp(addr1.get_addr().bytes, addr2.get_addr().bytes, NSAPI_IPv4_BYTES));
EXPECT_TRUE(0 == memcmp(addr1.get_ip_bytes(), addr2.get_ip_bytes(), NSAPI_IP_BYTES));
EXPECT_EQ(addr1.get_ip_version(), addr2.get_ip_version());
EXPECT_EQ(addr1.get_port(), addr2.get_port());
}
};
TEST_F(TestSocketAddress, constructor_default)
{
EXPECT_TRUE(address);
EXPECT_EQ(NULL, address->get_ip_address());
EXPECT_EQ(0, address->get_port());
EXPECT_EQ(NSAPI_UNSPEC, address->get_ip_version());
}
TEST_F(TestSocketAddress, constructor_address_ip4)
{
SocketAddress addr("127.0.0.1", 80);
EXPECT_EQ(std::string("127.0.0.1"), std::string(addr.get_ip_address()));
EXPECT_EQ(80, addr.get_port());
EXPECT_EQ(NSAPI_IPv4, addr.get_ip_version());
}
TEST_F(TestSocketAddress, constructor_address_ip6)
{
SocketAddress addr("1234:5678:9abc:def0:1234:5678::def0", 80);
EXPECT_EQ(80, addr.get_port());
EXPECT_EQ(NSAPI_IPv6, addr.get_ip_version());
// Note that a missing zero is added between two neighbouring colons
EXPECT_EQ(std::string("1234:5678:9abc:def0:1234:5678:0:def0"), std::string(addr.get_ip_address()));
}
TEST_F(TestSocketAddress, constructor_address_ip6_invalid)
{
SocketAddress addr("zzzz:yyyy:xxxx:def0:1234:5678:9abc:def0", 80);
EXPECT_EQ(80, addr.get_port());
EXPECT_EQ(NSAPI_UNSPEC, addr.get_ip_version());
EXPECT_EQ(NULL, addr.get_ip_address());
}
TEST_F(TestSocketAddress, constructor_address_bytes_ip4)
{
uint8_t addrBytes[NSAPI_IP_BYTES] = {127, 0, 0, 2};
SocketAddress addr(addrBytes, NSAPI_IPv4, 80);
EXPECT_EQ(std::string("127.0.0.2"), std::string(addr.get_ip_address()));
EXPECT_EQ(80, addr.get_port());
EXPECT_EQ(NSAPI_IPv4, addr.get_ip_version());
EXPECT_TRUE(0 == memcmp(addrBytes, static_cast<const uint8_t *>(addr.get_ip_bytes()), sizeof(addrBytes)));
}
TEST_F(TestSocketAddress, constructor_address_bytes_ip6)
{
uint8_t addrBytes[NSAPI_IP_BYTES] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
SocketAddress addr(addrBytes, NSAPI_IPv6, 80);
// the leading zeroes are removed
EXPECT_EQ(std::string("1:203:405:607:809:a0b:c0d:e0f"), std::string(addr.get_ip_address()));
EXPECT_EQ(80, addr.get_port());
EXPECT_EQ(NSAPI_IPv6, addr.get_ip_version());
EXPECT_TRUE(0 == memcmp(addrBytes, static_cast<const uint8_t *>(addr.get_ip_bytes()), NSAPI_IP_BYTES));
}
TEST_F(TestSocketAddress, constructor_copy)
{
SocketAddress addr(*address);
EXPECT_EQ(address->get_ip_address(), addr.get_ip_address());
EXPECT_EQ(address->get_port(), addr.get_port());
EXPECT_EQ(address->get_ip_version(), addr.get_ip_version());
}
TEST_F(TestSocketAddress, assignment_and_equality_operator_ip4)
{
SocketAddress addr;
address->set_ip_address("127.0.0.2");
address->set_port(81);
// First verify assignment operator (including return value) using equality operator.
EXPECT_EQ((addr = *address), *address);
// Then check inequality operator
EXPECT_FALSE(addr != *address);
// Now proceed to check that the equality operator really works.
isEqual(addr, *address);
}
TEST_F(TestSocketAddress, assignment_and_equality_operator_ip6)
{
SocketAddress addr;
address->set_ip_address("0:0:0:0:0:ffff:7f00:1");
address->set_port(81);
// First verify assignment operator (including return value) using equality operator.
EXPECT_EQ((addr = *address), *address);
// Then check inequality operator
EXPECT_FALSE(addr != *address);
// Now proceed to check that the equality operator really works.
isEqual(addr, *address);
}
TEST_F(TestSocketAddress, equality_null_check)
{
address->set_ip_address("127.0.0.2");
EXPECT_NE(*address, static_cast<SocketAddress>(NULL));
}
TEST_F(TestSocketAddress, equality_wrong_version)
{
SocketAddress addr4("127.0.0.1", 80);
SocketAddress addr6("0:0:0:0:0:ffff:7f00:1", 80); // This is converted 127.0.0.1
EXPECT_NE(addr4, addr6); // But they should still be inequal.
}
TEST_F(TestSocketAddress, bool_operator_false)
{
EXPECT_FALSE(*address ? true : false);
}
TEST_F(TestSocketAddress, bool_operator_ip4_true)
{
SocketAddress addr("127.0.0.1", 80);
EXPECT_TRUE(addr ? true : false);
}
TEST_F(TestSocketAddress, bool_operator_ip6_true)
{
SocketAddress addr("1234:5678:9abc:def0:1234:5678:9abc:def0", 80);
EXPECT_TRUE(addr ? true : false);
}

View File

@ -0,0 +1,27 @@
####################
# UNIT TESTS
####################
# Unit test suite name
set(TEST_SUITE_NAME "features_netsocket_SocketAddress")
# We want to get rid of ip6string.h fake include to use the real definitions.
list(REMOVE_ITEM unittest-includes "${PROJECT_SOURCE_DIR}/target_h")
# Source files
set(unittest-sources
../features/netsocket/SocketAddress.cpp
../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c
../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c
# Adding real ip6-related features, to test the relevant functions fully.
../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c
../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c
../features/frameworks/nanostack-libservice/source/libBits/common_functions.c
)
# Test files
set(unittest-test-sources
features/netsocket/SocketAddress/test_SocketAddress.cpp
)

View File

@ -54,7 +54,7 @@ TEST_F(TestTCPServer, constructor)
TEST_F(TestTCPServer, constructor_parameters)
{
TCPServer serverParam = TCPServer(dynamic_cast<NetworkStack*>(&stack));
TCPServer serverParam = TCPServer(dynamic_cast<NetworkStack *>(&stack));
const SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(serverParam.connect(a), NSAPI_ERROR_OK);
}

View File

@ -62,7 +62,7 @@ TEST_F(TestTCPSocket, constructor)
TEST_F(TestTCPSocket, constructor_parameters)
{
TCPSocket socketParam = TCPSocket(dynamic_cast<NetworkStack*>(&stack));
TCPSocket socketParam = TCPSocket(dynamic_cast<NetworkStack *>(&stack));
const SocketAddress a("127.0.0.1", 1024);
EXPECT_EQ(socketParam.connect(a), NSAPI_ERROR_OK);
}
@ -200,7 +200,7 @@ TEST_F(TestTCPSocket, recv_all_data)
TEST_F(TestTCPSocket, recv_less_than_expected)
{
socket->open((NetworkStack *)&stack);
unsigned int lessThanDataSize = dataSize -1;
unsigned int lessThanDataSize = dataSize - 1;
stack.return_values.push_back(lessThanDataSize);
EXPECT_EQ(socket->recv(dataBuf, dataSize), lessThanDataSize);
}
@ -262,7 +262,7 @@ TEST_F(TestTCPSocket, accept_no_open)
{
nsapi_error_t error;
stack.return_value = NSAPI_ERROR_OK;
EXPECT_EQ(socket->accept(&error), static_cast<TCPSocket*>(NULL));
EXPECT_EQ(socket->accept(&error), static_cast<TCPSocket *>(NULL));
EXPECT_EQ(error, NSAPI_ERROR_NO_SOCKET);
}
@ -271,7 +271,7 @@ TEST_F(TestTCPSocket, accept)
nsapi_error_t error;
stack.return_value = NSAPI_ERROR_OK;
socket->open((NetworkStack *)&stack);
EXPECT_NE(socket->accept(&error), static_cast<TCPSocket*>(NULL));
EXPECT_NE(socket->accept(&error), static_cast<TCPSocket *>(NULL));
EXPECT_EQ(error, NSAPI_ERROR_OK);
}
@ -282,6 +282,6 @@ TEST_F(TestTCPSocket, accept_would_block)
stack.return_value = NSAPI_ERROR_WOULD_BLOCK;
eventFlagsStubNextRetval.push_back(0);
eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
EXPECT_EQ(socket->accept(&error), static_cast<TCPSocket*>(NULL));
EXPECT_EQ(socket->accept(&error), static_cast<TCPSocket *>(NULL));
EXPECT_EQ(error, NSAPI_ERROR_WOULD_BLOCK);
}

View File

@ -79,7 +79,7 @@ TEST_F(TestUDPSocket, sendto_addr_port)
TEST_F(TestUDPSocket, connect)
{
stack.return_value = NSAPI_ERROR_OK;
const nsapi_addr_t addr = {NSAPI_IPv4, {127,0,0,1} };
const nsapi_addr_t addr = {NSAPI_IPv4, {127, 0, 0, 1} };
const SocketAddress a(addr, 1024);
socket->open((NetworkStack *)&stack);
@ -93,7 +93,7 @@ TEST_F(TestUDPSocket, connect)
TEST_F(TestUDPSocket, sendto_timeout)
{
const nsapi_addr_t saddr = {NSAPI_IPv4, {127,0,0,1} };
const nsapi_addr_t saddr = {NSAPI_IPv4, {127, 0, 0, 1} };
const SocketAddress addr(saddr, 1024);
socket->open((NetworkStack *)&stack);
@ -127,8 +127,8 @@ TEST_F(TestUDPSocket, recv)
TEST_F(TestUDPSocket, recv_address_filtering)
{
socket->open((NetworkStack *)&stack);
const nsapi_addr_t addr1 = {NSAPI_IPv4, {127,0,0,1} };
const nsapi_addr_t addr2 = {NSAPI_IPv4, {127,0,0,2} };
const nsapi_addr_t addr1 = {NSAPI_IPv4, {127, 0, 0, 1} };
const nsapi_addr_t addr2 = {NSAPI_IPv4, {127, 0, 0, 2} };
SocketAddress a1(addr1, 1024);
SocketAddress a2(addr2, 1024);

View File

@ -0,0 +1,66 @@
/*
* 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 "features/netsocket/WiFiAccessPoint.h"
#include <cstring>
class TestWiFiAccessPoint : public testing::Test {
protected:
WiFiAccessPoint *ap;
virtual void SetUp()
{
ap = new WiFiAccessPoint;
}
virtual void TearDown()
{
delete ap;
}
};
TEST_F(TestWiFiAccessPoint, constructor)
{
EXPECT_TRUE(ap);
}
TEST_F(TestWiFiAccessPoint, getters_default)
{
// ssid and bssid return pointers to uninitialized memory - impossible to set expectations.
EXPECT_EQ(0, ap->get_channel());
EXPECT_EQ(0, ap->get_rssi());
EXPECT_EQ(NSAPI_SECURITY_NONE, ap->get_security());
}
TEST_F(TestWiFiAccessPoint, set_data)
{
nsapi_wifi_ap_t testAp = {
"mySSID67890123456789012345678901",
{0xd8, 0xc7, 0xc8, 0xcc, 0x43, 0x24},
NSAPI_SECURITY_WPA2,
0x64,
0x02,
};
WiFiAccessPoint *ap1 = new WiFiAccessPoint(testAp);
EXPECT_EQ(std::string(testAp.ssid), std::string(ap1->get_ssid()));
EXPECT_TRUE(0 == std::memcmp(testAp.bssid, ap1->get_bssid(), sizeof(testAp.bssid)));
EXPECT_EQ(testAp.channel, ap1->get_channel());
EXPECT_EQ(testAp.rssi, ap1->get_rssi());
EXPECT_EQ(testAp.security, ap1->get_security());
}

View File

@ -0,0 +1,12 @@
####################
# UNIT TESTS
####################
set(unittest-sources
../features/netsocket/WiFiAccessPoint.cpp
)
set(unittest-test-sources
features/netsocket/WiFiAccessPoint/test_WiFiAccessPoint.cpp
)

View File

@ -36,7 +36,7 @@ int ATHandler_stub::timeout = 0;
bool ATHandler_stub::default_timeout = 0;
bool ATHandler_stub::debug_on = 0;
ssize_t ATHandler_stub::ssize_value = 0;
char *ATHandler_stub::read_string_value = NULL;
const char *ATHandler_stub::read_string_value = NULL;
size_t ATHandler_stub::size_value = 0;
size_t ATHandler_stub::return_given_size = false;
bool ATHandler_stub::bool_value = false;
@ -51,7 +51,7 @@ int ATHandler_stub::int_valid_count_table[kRead_int_table_size];
int ATHandler_stub::int_count = kRead_int_table_size;
int ATHandler_stub::read_string_index = kRead_string_table_size;
char *ATHandler_stub::read_string_table[kRead_string_table_size];
const char *ATHandler_stub::read_string_table[kRead_string_table_size];
int ATHandler_stub::resp_stop_success_count = kResp_stop_count_default;
ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char *output_delimiter, uint16_t send_delay) :
@ -176,7 +176,7 @@ ssize_t ATHandler::read_string(char *buf, size_t size, bool read_even_stop_tag)
ATHandler_stub::read_string_index--;
if (ATHandler_stub::read_string_index >= 0) {
char *tmp = ATHandler_stub::read_string_table[ATHandler_stub::read_string_index];
const char *tmp = ATHandler_stub::read_string_table[ATHandler_stub::read_string_index];
ssize_t len = strlen(tmp);
memcpy(buf, tmp, len + 1);
return len;

View File

@ -41,7 +41,7 @@ extern int timeout;
extern bool default_timeout;
extern bool debug_on;
extern ssize_t ssize_value;
extern char *read_string_value;
extern const char *read_string_value;
extern size_t size_value;
extern size_t return_given_size;
extern bool bool_value;
@ -52,7 +52,7 @@ extern mbed::FileHandle_stub *fh_value;
extern mbed::device_err_t device_err_value;
extern mbed::Callback<void()> callback;
extern bool call_immediately;
extern char *read_string_table[kRead_string_table_size];
extern const char *read_string_table[kRead_string_table_size];
extern int read_string_index;
extern int int_valid_count_table[kRead_int_table_size];
extern int int_count;

View File

@ -111,12 +111,12 @@ nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn)
return NSAPI_ERROR_OK;
}
nsapi_error_t AT_CellularNetwork::get_registration_status(RegistrationType type, RegistrationStatus &status)
nsapi_error_t AT_CellularNetwork::get_registration_params(RegistrationType type, registration_params_t &reg_params)
{
return NSAPI_ERROR_OK;
}
nsapi_error_t AT_CellularNetwork::get_cell_id(int &cell_id)
nsapi_error_t AT_CellularNetwork::get_registration_params(registration_params_t &reg_params)
{
return NSAPI_ERROR_OK;
}
@ -186,12 +186,6 @@ nsapi_error_t AT_CellularNetwork::set_access_technology(RadioAccessTechnology op
return NSAPI_ERROR_OK;
}
nsapi_error_t AT_CellularNetwork::get_access_technology(RadioAccessTechnology &rat)
{
rat = RAT_CATM1;
return NSAPI_ERROR_OK;
}
nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount)
{
return NSAPI_ERROR_OK;

View File

@ -26,6 +26,7 @@ int LoRaMac_stub::bool_false_counter = 0;
int LoRaMac_stub::bool_true_counter = 0;
bool LoRaMac_stub::bool_value = false;
int LoRaMac_stub::int_value = 0;
uint8_t LoRaMac_stub::uint8_value = 1;
rx_slot_t LoRaMac_stub::slot_value = RX_SLOT_WIN_1;
lorawan_status_t LoRaMac_stub::status_value = LORAWAN_STATUS_OK;
loramac_mcps_confirm_t *LoRaMac_stub::mcps_conf_ptr = NULL;
@ -33,10 +34,8 @@ loramac_mcps_indication_t *LoRaMac_stub::mcps_ind_ptr = NULL;
loramac_mlme_confirm_t *LoRaMac_stub::mlme_conf_ptr = NULL;
loramac_mlme_indication_t *LoRaMac_stub::mlme_ind_ptr = NULL;
device_class_t LoRaMac_stub::dev_class_value = CLASS_A;
mbed::Callback<void(void)> LoRaMac_stub::_ack_expiry_handler_for_class_c = NULL;
mbed::Callback<void(void)> LoRaMac_stub::_scheduling_failure_handler = NULL;
LoRaMac::LoRaMac()
: _lora_time(),
_lora_phy(NULL),
@ -334,9 +333,8 @@ device_class_t LoRaMac::get_device_class() const
}
void LoRaMac::set_device_class(const device_class_t &device_class,
mbed::Callback<void(void)>ack_expiry_handler)
mbed::Callback<void(void)>rx2_would_be_closure_handler)
{
LoRaMac_stub::_ack_expiry_handler_for_class_c = ack_expiry_handler;
}
void LoRaMac::setup_link_check_request()
@ -456,3 +454,13 @@ lorawan_status_t LoRaMac::multicast_channel_unlink(multicast_params_t *channel_p
void LoRaMac::bind_phy(LoRaPHY &phy)
{
}
uint8_t LoRaMac::get_QOS_level(void)
{
return LoRaMac_stub::uint8_value;
}
uint8_t LoRaMac::get_prev_QOS_level(void)
{
return LoRaMac_stub::uint8_value;
}

View File

@ -28,6 +28,7 @@ extern bool bool_value;
extern int bool_false_counter;
extern int bool_true_counter;
extern int int_value;
extern uint8_t uint8_value;
extern rx_slot_t slot_value;
extern lorawan_status_t status_value;
extern loramac_mcps_confirm_t *mcps_conf_ptr;
@ -35,6 +36,5 @@ extern loramac_mcps_indication_t *mcps_ind_ptr;
extern loramac_mlme_confirm_t *mlme_conf_ptr;
extern loramac_mlme_indication_t *mlme_ind_ptr;
extern device_class_t dev_class_value;
extern mbed::Callback<void(void)> _ack_expiry_handler_for_class_c;
extern mbed::Callback<void(void)> _scheduling_failure_handler;
}

View File

@ -387,6 +387,7 @@ lorawan_status_t LoRaPHY::set_next_channel(channel_selection_params_t *params,
uint8_t *channel, lorawan_time_t *time,
lorawan_time_t *aggregate_timeoff)
{
*time = 100;
return LoRaPHY_stub::lorawan_status_value;
}

View File

@ -186,8 +186,14 @@ void LoRaWANStack::process_transmission(void)
{
}
void LoRaWANStack::handle_ack_expiry_for_class_c(void)
void post_process_tx_with_reception(void)
{
}
void post_process_tx_no_reception(void)
{
}
void LoRaWANStack::handle_scheduling_failure(void)
@ -295,4 +301,3 @@ void LoRaWANStack::process_idle_state(lorawan_status_t &op_status)
void LoRaWANStack::process_uninitialized_state(lorawan_status_t &op_status)
{
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) , 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 "rtos/ThisThread.h"
namespace rtos {
void ThisThread::sleep_until(uint64_t millisec)
{
}
}

26
UNITTESTS/target_h/rtos.h Normal file
View File

@ -0,0 +1,26 @@
/*
* 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.
*/
#ifndef RTOS_H
#define RTOS_H
typedef enum {
osTimerOnce = 0, ///< One-shot timer.
osTimerPeriodic = 1 ///< Repeating timer.
} os_timer_type;
#endif /* RTOS_H */

View File

@ -1,8 +1,8 @@
/******************************************************************************
* @file mpu_armv7.h
* @brief CMSIS MPU API for Armv7-M MPU
* @version V5.0.4
* @date 10. January 2018
* @version V5.0.5
* @date 06. September 2018
******************************************************************************/
/*
* Copyright (c) 2017-2018 Arm Limited. All rights reserved.
@ -86,10 +86,10 @@
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
*/
#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \
((((TypeExtField ) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
(((IsShareable ) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
(((IsCacheable ) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
(((IsBufferable ) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk))
((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
(((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
(((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
(((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk))
/**
* MPU Region Attribute and Size Register Value
@ -100,11 +100,14 @@
* \param SubRegionDisable Sub-region disable field.
* \param Size Region size of the region to be configured, for example 4K, 8K.
*/
#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \
((((DisableExec ) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
(((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
(((AccessAttributes) ) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk)))
#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \
((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
(((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
(((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \
(((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \
(((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \
(((MPU_RASR_ENABLE_Msk))))
/**
* MPU Region Attribute and Size Register Value
*

View File

@ -20,7 +20,7 @@
#include "at24mac.h"
#include "PinNames.h"
#if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI
#if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI && DEVICE_I2C
#include "NanostackRfPhy.h"

View File

@ -15,7 +15,7 @@
*/
#include <string.h>
#if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI
#if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI && DEVICE_I2C
#include "platform/arm_hal_interrupt.h"
#include "nanostack/platform/arm_hal_phy.h"
@ -297,17 +297,17 @@ static void rf_if_unlock(void)
#ifdef MBED_CONF_RTOS_PRESENT
static void rf_if_cca_timer_signal(void)
{
rf->irq_thread.signal_set(SIG_TIMER_CCA);
rf->irq_thread.flags_set(SIG_TIMER_CCA);
}
static void rf_if_cal_timer_signal(void)
{
rf->irq_thread.signal_set(SIG_TIMER_CAL);
rf->irq_thread.flags_set(SIG_TIMER_CAL);
}
static void rf_if_ack_timer_signal(void)
{
rf->irq_thread.signal_set(SIG_TIMER_ACK);
rf->irq_thread.flags_set(SIG_TIMER_ACK);
}
#endif
@ -1040,7 +1040,7 @@ static void rf_if_disable_irq(void)
#ifdef MBED_CONF_RTOS_PRESENT
static void rf_if_interrupt_handler(void)
{
rf->irq_thread.signal_set(SIG_RADIO);
rf->irq_thread.flags_set(SIG_RADIO);
}
// Started during construction of rf, so variable
@ -1048,21 +1048,18 @@ static void rf_if_interrupt_handler(void)
void RFBits::rf_if_irq_task(void)
{
for (;;) {
osEvent event = irq_thread.signal_wait(0);
if (event.status != osEventSignal) {
continue;
}
uint32_t flags = ThisThread::flags_wait_any(SIG_ALL);
rf_if_lock();
if (event.value.signals & SIG_RADIO) {
if (flags & SIG_RADIO) {
rf_if_irq_task_process_irq();
}
if (event.value.signals & SIG_TIMER_ACK) {
if (flags & SIG_TIMER_ACK) {
rf_ack_wait_timer_interrupt();
}
if (event.value.signals & SIG_TIMER_CCA) {
if (flags & SIG_TIMER_CCA) {
rf_cca_timer_interrupt();
}
if (event.value.signals & SIG_TIMER_CAL) {
if (flags & SIG_TIMER_CAL) {
rf_calibration_timer_interrupt();
}
rf_if_unlock();

View File

@ -15,6 +15,8 @@
*/
#include "at24mac.h"
#if DEVICE_I2C
/* Device addressing */
#define AT24MAC_EEPROM_ADDRESS (0x0A<<4)
#define AT24MAC_RW_PROTECT_ADDRESS (0x06<<4)
@ -29,30 +31,9 @@
#define EUI64_LEN 8
#define EUI48_LEN 6
AT24Mac::I2CReset::I2CReset(PinName sda, PinName scl)
{
mbed::DigitalInOut pin_sda(sda, PIN_OUTPUT, PullUp, 1);
mbed::DigitalInOut pin_scl(scl, PIN_OUTPUT, PullUp, 0);
//generate 9 clocks for worst-case scenario
for (int i = 0; i < 10; ++i) {
pin_scl = 1;
wait_us(5);
pin_scl = 0;
wait_us(5);
}
//generate a STOP condition
pin_sda = 0;
wait_us(5);
pin_scl = 1;
wait_us(5);
pin_sda = 1;
wait_us(5);
}
using namespace mbed;
/*I2C needs to be reset before constructing the I2C object (in case I2C is stuck)
because they use the same pins, therefore i2c_reset has to be before _i2c
in the initializer list*/
AT24Mac::AT24Mac(PinName sda, PinName scl) : i2c_reset(sda, scl), _i2c(sda, scl)
AT24Mac::AT24Mac(PinName sda, PinName scl) : _i2c(sda , scl)
{
// Do nothing
}
@ -80,3 +61,5 @@ int AT24Mac::read_eui48(void *buf)
return -1; //No ACK
return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char*)buf, EUI48_LEN);
}
#endif /* DEVICE_I2C */

View File

@ -17,6 +17,9 @@
#define AT24MAC_H
#include "PinNames.h"
#if DEVICE_I2C
#include "I2C.h"
#include "drivers/DigitalInOut.h"
#include "platform/mbed_wait_api.h"
@ -59,16 +62,8 @@ public:
int read_eui48(void *buf);
private:
/*
* Dummy class to allow us to reset I2C before the I2C constructor is called in
* the initializer list of AT24Mac's constructor
*/
class I2CReset {
public:
I2CReset(PinName sda, PinName scl);
};
I2CReset i2c_reset;
mbed::I2C _i2c;
};
#endif /* DEVICE_I2C */
#endif /* AT24MAC_H */

View File

@ -44,7 +44,7 @@
#if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI
#include "platform/arm_hal_interrupt.h"
#include "platform/mbed_critical.h"
/*****************************************************************************
* PRIVATE VARIABLES *
@ -524,7 +524,7 @@ void MCR20Drv_IRQ_Disable
void
)
{
platform_enter_critical();
core_util_critical_section_enter();
if( mPhyIrqDisableCnt == 0 )
{
@ -533,7 +533,7 @@ void
mPhyIrqDisableCnt++;
platform_exit_critical();
core_util_critical_section_exit();
}
/*---------------------------------------------------------------------------
@ -547,7 +547,7 @@ void MCR20Drv_IRQ_Enable
void
)
{
platform_enter_critical();
core_util_critical_section_enter();
if( mPhyIrqDisableCnt )
{
@ -559,7 +559,7 @@ void
}
}
platform_exit_critical();
core_util_critical_section_exit();
}
/*---------------------------------------------------------------------------

View File

@ -1093,19 +1093,16 @@ static void rf_init_phy_mode(void)
*/
static void PHY_InterruptHandler(void)
{
/* Disable and clear transceiver(IRQ_B) interrupt */
MCR20Drv_IRQ_Disable();
irq_thread->signal_set(1);
irq_thread->flags_set(1);
}
static void PHY_InterruptThread(void)
{
for (;;) {
osEvent event = irq_thread->signal_wait(0);
if (event.status != osEventSignal) {
continue;
}
ThisThread::flags_wait_all(1);
handle_interrupt();
MCR20Drv_IRQ_Enable();
}
}
@ -1113,8 +1110,6 @@ static void handle_interrupt(void)
{
uint8_t xcvseqCopy;
//MCR20Drv_IRQ_Clear();
/* Read transceiver interrupt status and control registers */
mStatusAndControlRegs[IRQSTS1] =
MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[IRQSTS2], 7);
@ -1158,7 +1153,6 @@ static void handle_interrupt(void)
MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 5);
rf_ack_wait_timer_interrupt();
MCR20Drv_IRQ_Enable();
return;
}
}
@ -1182,7 +1176,6 @@ static void handle_interrupt(void)
{
rf_receive();
}
MCR20Drv_IRQ_Enable();
return;
}
@ -1205,12 +1198,10 @@ static void handle_interrupt(void)
break;
}
MCR20Drv_IRQ_Enable();
return;
}
/* Other IRQ. Clear XCVR interrupt flags */
MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3);
MCR20Drv_IRQ_Enable();
}
/*

View File

@ -36,14 +36,8 @@
#define DEBUG_PRINTF(...)
#endif
FlashIAPBlockDevice::FlashIAPBlockDevice()
: _flash(), _base(0), _size(0), _is_initialized(false), _init_ref_count(0)
{
DEBUG_PRINTF("FlashIAPBlockDevice: %" PRIX32 " %" PRIX32 "\r\n", address, size);
}
FlashIAPBlockDevice::FlashIAPBlockDevice(uint32_t address, uint32_t)
: _flash(), _base(0), _size(0), _is_initialized(false), _init_ref_count(0)
FlashIAPBlockDevice::FlashIAPBlockDevice(uint32_t address, uint32_t size)
: _flash(), _base(address), _size(size), _is_initialized(false), _init_ref_count(0)
{
}
@ -70,11 +64,27 @@ int FlashIAPBlockDevice::init()
int ret = _flash.init();
if (ret) {
core_util_atomic_decr_u32(&_init_ref_count, 1);
return ret;
}
_base = _flash.get_flash_start();
_size = _flash.get_flash_size();
if (_size + _base > _flash.get_flash_size() + _flash.get_flash_start()) {
core_util_atomic_decr_u32(&_init_ref_count, 1);
return BD_ERROR_DEVICE_ERROR;
}
if (_base < _flash.get_flash_start()) {
core_util_atomic_decr_u32(&_init_ref_count, 1);
return BD_ERROR_DEVICE_ERROR;
}
if (!_base) {
_base = _flash.get_flash_start();
}
if (!_size) {
_size = _flash.get_flash_size() - (_base - _flash.get_flash_start());
}
_is_initialized = true;
return ret;

View File

@ -28,12 +28,15 @@
*/
class FlashIAPBlockDevice : public BlockDevice {
public:
/** Creates a FlashIAPBlockDevice **/
FlashIAPBlockDevice();
MBED_DEPRECATED("Please use default constructor instead")
FlashIAPBlockDevice(uint32_t address, uint32_t size = 0);
/** Creates a FlashIAPBlockDevice
*
* @param address Physical address where the block device start
* @param size The block device size
*/
FlashIAPBlockDevice(uint32_t address = MBED_CONF_FLASHIAP_BLOCK_DEVICE_BASE_ADDRESS,
uint32_t size = MBED_CONF_FLASHIAP_BLOCK_DEVICE_SIZE);
virtual ~FlashIAPBlockDevice();
/** Initialize a block device

View File

@ -680,7 +680,7 @@ control_t fslittle_fopen_test_05(const size_t call_count)
}
static const char fslittle_fopen_ascii_illegal_buf_g[] = "\"<EFBFBD>'*+,./:;<=>?[\\]|";
static const char fslittle_fopen_ascii_illegal_buf_g[] = "\"?'*+,./:;<=>?[\\]|";
/** @brief test to call fopen() with filename that in includes
* illegal characters

View File

@ -0,0 +1,19 @@
{
"name": "flashiap-block-device",
"config": {
"base-address": {
"help": "Base address for the block device on the external flash.",
"value": "0xFFFFFFFF"
},
"size": {
"help": "Memory allocated for block device.",
"value": "0"
}
},
"target_overrides": {
"REALTEK_RTL8195AM": {
"base-address": "0x1C0000",
"size": "0x40000"
}
}
}

View File

@ -0,0 +1,344 @@
/* mbed Microcontroller Library
* 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.
*/
#include "SPIFReducedBlockDevice.h"
#include "mbed_wait_api.h"
// Read/write/erase sizes
#define SPIF_READ_SIZE 1
#define SPIF_PROG_SIZE 1
#define SPIF_SE_SIZE 4096
#define SPIF_TIMEOUT 10000
// Debug available
#define SPIF_DEBUG 0
// Legacy SFDP Instruction Table.
enum ops {
SPIF_NOP = 0x00, // No operation
SPIF_READ = 0x03, // Read data
SPIF_PROG = 0x02, // Program data
SPIF_SE = 0x20, // 4KB Sector Erase
SPIF_CE = 0xc7, // Chip Erase
SPIF_SFDP = 0x5a, // Read SFDP
SPIF_WREN = 0x06, // Write Enable
SPIF_WRDI = 0x04, // Write Disable
SPIF_RDSR = 0x05, // Read Status Register
SPIF_RDID = 0x9f, // Read Manufacturer and JDEC Device ID
};
// Status register from RDSR
// [---------| wel | wip ]
// [- 6 -| 1 | 1 ]
#define SPIF_WEL 0x2
#define SPIF_WIP 0x1
SPIFReducedBlockDevice::SPIFReducedBlockDevice(
PinName mosi, PinName miso, PinName sclk, PinName cs, int freq)
: _spi(mosi, miso, sclk), _cs(cs), _size(0)
{
_cs = 1;
_spi.frequency(freq);
}
int SPIFReducedBlockDevice::init()
{
// Check for vendor specific hacks, these should move into more general
// handling when possible. RDID is not used to verify a device is attached.
uint8_t id[3];
_cmdread(SPIF_RDID, 0, 3, 0x0, id);
switch (id[0]) {
case 0xbf:
// SST devices come preset with block protection
// enabled for some regions, issue gbpu instruction to clear
_wren();
_cmdwrite(0x98, 0, 0, 0x0, NULL);
break;
}
// Check that device is doing ok
int err = _sync();
if (err) {
return BD_ERROR_DEVICE_ERROR;
}
// Check JEDEC serial flash discoverable parameters for device
// specific info
uint8_t header[16];
_cmdread(SPIF_SFDP, 4, 16, 0x0, header);
// Verify SFDP signature for sanity
// Also check that major/minor version is acceptable
if (!(memcmp(&header[0], "SFDP", 4) == 0 && header[5] == 1)) {
return BD_ERROR_DEVICE_ERROR;
}
// The SFDP spec indicates the standard table is always at offset 0
// in the parameter headers, we check just to be safe
if (!(header[8] == 0 && header[10] == 1)) {
return BD_ERROR_DEVICE_ERROR;
}
// Parameter table pointer, spi commands are BE, SFDP is LE,
// also sfdp command expects extra read wait byte
// header 12-14 3 bytes building the parameter table address
uint32_t table_addr = (
(header[14] << 24) |
(header[13] << 16) |
(header[12] << 8 ));
uint8_t table[8];
_cmdread(SPIF_SFDP, 4, 8, table_addr, table);
// Check erase size, currently only supports 4kbytes
if ((table[0] & 0x3) != 0x1 || table[1] != SPIF_SE) {
// First byte of table, bits 0 and 1 = 0x1 indicating 4 KB Erase is supported
// Second Byte of table = Sector Erase Command (0x20)
return BD_ERROR_DEVICE_ERROR;
}
// Check address size, currently only supports 3byte addresses
if ((table[2] & 0x4) != 0 || (table[7] & 0x80) != 0) {
return BD_ERROR_DEVICE_ERROR;
}
// Get device density, stored as size in bits - 1
uint32_t density = (
(table[7] << 24) |
(table[6] << 16) |
(table[5] << 8 ) |
(table[4] << 0 ));
// Table bytes 5-8 : Bits 0|30 indicate Flash Density (size) in bits (divide by 8 for Bytes)
_size = (density / 8) + 1;
return 0;
}
int SPIFReducedBlockDevice::deinit()
{
// Latch write disable just to keep noise
// from changing the device
_cmdwrite(SPIF_WRDI, 0, 0, 0x0, NULL);
return 0;
}
void SPIFReducedBlockDevice::_cmdread(
uint8_t op, uint32_t addrc, uint32_t retc,
uint32_t addr, uint8_t *rets)
{
_cs = 0;
_spi.write(op);
for (uint32_t i = 0; i < addrc; i++) {
_spi.write(0xff & (addr >> 8 * (addrc - 1 - i)));
}
for (uint32_t i = 0; i < retc; i++) {
rets[i] = _spi.write(0);
}
_cs = 1;
if (SPIF_DEBUG) {
printf("spif <- %02x", op);
for (uint32_t i = 0; i < addrc; i++) {
if (i < addrc) {
printf("%02lx", 0xff & (addr >> 8 * (addrc - 1 - i)));
} else {
printf(" ");
}
}
printf(" ");
for (uint32_t i = 0; i < 16 && i < retc; i++) {
printf("%02x", rets[i]);
}
if (retc > 16) {
printf("...");
}
printf("\n");
}
}
void SPIFReducedBlockDevice::_cmdwrite(
uint8_t op, uint32_t addrc, uint32_t argc,
uint32_t addr, const uint8_t *args)
{
_cs = 0;
_spi.write(op);
for (uint32_t i = 0; i < addrc; i++) {
_spi.write(0xff & (addr >> 8 * (addrc - 1 - i)));
}
for (uint32_t i = 0; i < argc; i++) {
_spi.write(args[i]);
}
_cs = 1;
if (SPIF_DEBUG) {
printf("spif -> %02x", op);
for (uint32_t i = 0; i < addrc; i++) {
if (i < addrc) {
printf("%02lx", 0xff & (addr >> 8 * (addrc - 1 - i)));
} else {
printf(" ");
}
}
printf(" ");
for (uint32_t i = 0; i < 16 && i < argc; i++) {
printf("%02x", args[i]);
}
if (argc > 16) {
printf("...");
}
printf("\n");
}
}
int SPIFReducedBlockDevice::_sync()
{
for (int i = 0; i < SPIF_TIMEOUT; i++) {
// Read status register until write not-in-progress
uint8_t status;
_cmdread(SPIF_RDSR, 0, 1, 0x0, &status);
// Check WIP bit
if (!(status & SPIF_WIP)) {
return 0;
}
wait_ms(1);
}
return BD_ERROR_DEVICE_ERROR;
}
int SPIFReducedBlockDevice::_wren()
{
_cmdwrite(SPIF_WREN, 0, 0, 0x0, NULL);
for (int i = 0; i < SPIF_TIMEOUT; i++) {
// Read status register until write latch is enabled
uint8_t status;
_cmdread(SPIF_RDSR, 0, 1, 0x0, &status);
// Check WEL bit
if (status & SPIF_WEL) {
return 0;
}
wait_ms(1);
}
return BD_ERROR_DEVICE_ERROR;
}
int SPIFReducedBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
{
// Check the address and size fit onto the chip.
MBED_ASSERT(is_valid_read(addr, size));
_cmdread(SPIF_READ, 3, size, addr, static_cast<uint8_t *>(buffer));
return 0;
}
int SPIFReducedBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
{
// Check the address and size fit onto the chip.
MBED_ASSERT(is_valid_program(addr, size));
while (size > 0) {
int err = _wren();
if (err) {
return err;
}
// Write up to 256 bytes a page
uint32_t off = addr % 256;
uint32_t chunk = (off + size < 256) ? size : (256 - off);
_cmdwrite(SPIF_PROG, 3, chunk, addr, static_cast<const uint8_t *>(buffer));
buffer = static_cast<const uint8_t *>(buffer) + chunk;
addr += chunk;
size -= chunk;
wait_ms(1);
err = _sync();
if (err) {
return err;
}
}
return 0;
}
int SPIFReducedBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
// Check the address and size fit onto the chip.
MBED_ASSERT(is_valid_erase(addr, size));
while (size > 0) {
int err = _wren();
if (err) {
return err;
}
// Erase 4kbyte sectors
uint32_t chunk = 4096;
_cmdwrite(SPIF_SE, 3, 0, addr, NULL);
addr += chunk;
size -= chunk;
err = _sync();
if (err) {
return err;
}
}
return 0;
}
bd_size_t SPIFReducedBlockDevice::get_read_size() const
{
return SPIF_READ_SIZE;
}
bd_size_t SPIFReducedBlockDevice::get_program_size() const
{
return SPIF_PROG_SIZE;
}
bd_size_t SPIFReducedBlockDevice::get_erase_size() const
{
return SPIF_SE_SIZE;
}
bd_size_t SPIFReducedBlockDevice::get_erase_size(bd_addr_t addr) const
{
return SPIF_SE_SIZE;
}
int SPIFReducedBlockDevice::get_erase_value() const
{
return 0xFF;
}
bd_size_t SPIFReducedBlockDevice::size() const
{
return _size;
}

View File

@ -0,0 +1,174 @@
/* mbed Microcontroller Library
* 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.
*/
#ifndef MBED_RSPIF_BLOCK_DEVICE_H
#define MBED_RSPIF_BLOCK_DEVICE_H
#include "SPI.h"
#include "DigitalOut.h"
#include "BlockDevice.h"
/** Reduced BlockDevice for SPI based flash devices
* *Should only be used by Boot Loader*
*
* @code
* // Here's an example using the SPI flash device on K82F
* #include "mbed.h"
* #include "SPIFReducedBlockDevice.h"
*
* // Create flash device on SPI bus with PTE5 as chip select
* SPIFReducedBlockDevice rspif(PTE2, PTE4, PTE1, PTE5);
*
* int main() {
* printf("reduced spif test\n");
*
* // Initialize the Reduced SPI flash device and print the memory layout
* rspif.init();
* printf("rspif size: %llu\n", rspif.size());
* printf("rspif read size: %llu\n", rspif.get_read_size());
* printf("rspif program size: %llu\n", rspif.get_program_size());
* printf("rspif erase size: %llu\n", rspif.get_erase_size());
*
* // Write "Hello World!" to the first block
* char *buffer = (char*)malloc(rspif.get_erase_size());
* sprintf(buffer, "Hello World!\n");
* rspif.erase(0, rspif.get_erase_size());
* rspif.program(buffer, 0, rspif.get_erase_size());
*
* // Read back what was stored
* rspif.read(buffer, 0, rspif.get_erase_size());
* printf("%s", buffer);
*
* // Deinitialize the device
* rspif.deinit();
* }
* @endcode
*/
class SPIFReducedBlockDevice : public BlockDevice {
public:
/** Creates a SPIFReducedBlockDevice on a SPI bus specified by pins
*
* @param mosi SPI master out, slave in pin
* @param miso SPI master in, slave out pin
* @param sclk SPI clock pin
* @param csel SPI chip select pin
* @param freq Clock speed of the SPI bus (defaults to 40MHz)
*/
SPIFReducedBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName csel, int freq = 40000000);
/** Initialize a block device
*
* @return 0 on success or a negative error code on failure
*/
virtual int init();
/** Deinitialize a block device
*
* @return 0 on success or a negative error code on failure
*/
virtual int deinit();
/** Read blocks from a block device
*
* @param buffer Buffer to write blocks to
* @param addr Address of block to begin reading from
* @param size Size to read in bytes, must be a multiple of read block size
* @return 0 on success, negative error code on failure
*/
virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
/** Program blocks to a block device
*
* The blocks must have been erased prior to being programmed
*
* @param buffer Buffer of data to write to blocks
* @param addr Address of block to begin writing to
* @param size Size to write in bytes, must be a multiple of program block size
* @return 0 on success, negative error code on failure
*/
virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
/** Erase blocks on a block device
*
* The state of an erased block is undefined until it has been programmed
*
* @param addr Address of block to begin erasing
* @param size Size to erase in bytes, must be a multiple of erase block size
* @return 0 on success, negative error code on failure
*/
virtual int erase(bd_addr_t addr, bd_size_t size);
/** Get the size of a readable block
*
* @return Size of a readable block in bytes
*/
virtual bd_size_t get_read_size() const;
/** Get the size of a programable block
*
* @return Size of a programable block in bytes
* @note Must be a multiple of the read size
*/
virtual bd_size_t get_program_size() const;
/** Get the size of a eraseable block
*
* @return Size of a eraseable block in bytes
* @note Must be a multiple of the program size
*/
virtual bd_size_t get_erase_size() const;
/** Get the size of a eraseable block
*
* @param addr Address of block to query erase size
* @return Size of a eraseable block in bytes
* @note Must be a multiple of the program size
*/
virtual bd_size_t get_erase_size(bd_addr_t addr) const;
/** Get the value of storage byte after it was erased
*
* If get_erase_value returns a non-negative byte value, the underlying
* storage is set to that value when erased, and storage containing
* that value can be programmed without another erase.
*
* @return The value of storage when erased, or -1 if you can't
* rely on the value of erased storage
*/
virtual int get_erase_value() const;
/** Get the total size of the underlying device
*
* @return Size of the underlying device in bytes
*/
virtual bd_size_t size() const;
private:
// Master side hardware
mbed::SPI _spi;
mbed::DigitalOut _cs;
// Device configuration discovered through sfdp
bd_size_t _size;
// Internal functions
int _wren();
int _sync();
void _cmdread(uint8_t op, uint32_t addrc, uint32_t retc,
uint32_t addr, uint8_t *rets);
void _cmdwrite(uint8_t op, uint32_t addrc, uint32_t argc,
uint32_t addr, const uint8_t *args);
};
#endif

View File

@ -0,0 +1,66 @@
{
"name": "rspif-driver",
"config": {
"SPI_MOSI": "NC",
"SPI_MISO": "NC",
"SPI_CLK": "NC",
"SPI_CS": "NC",
"SPI_FREQ": "40000000"
},
"target_overrides": {
"K82F": {
"SPI_MOSI": "PTE2",
"SPI_MISO": "PTE4",
"SPI_CLK": "PTE1",
"SPI_CS": "PTE5"
},
"LPC54114": {
"SPI_MOSI": "P0_20",
"SPI_MISO": "P0_18",
"SPI_CLK": "P0_19",
"SPI_CS": "P1_2"
},
"NRF52840_DK": {
"SPI_MOSI": "p20",
"SPI_MISO": "p21",
"SPI_CLK": "p19",
"SPI_CS": "p17"
},
"HEXIWEAR": {
"SPI_MOSI": "PTD6",
"SPI_MISO": "PTD7",
"SPI_CLK": "PTD5",
"SPI_CS": "PTD4"
},
"MTB_UBLOX_ODIN_W2": {
"SPI_MOSI": "PE_14",
"SPI_MISO": "PE_13",
"SPI_CLK": "PE_12",
"SPI_CS": "PE_11"
},
"MTB_ADV_WISE_1530": {
"SPI_MOSI": "PC_3",
"SPI_MISO": "PC_2",
"SPI_CLK": "PB_13",
"SPI_CS": "PC_12"
},
"MTB_MXCHIP_EMW3166": {
"SPI_MOSI": "PB_15",
"SPI_MISO": "PB_14",
"SPI_CLK": "PB_13",
"SPI_CS": "PA_10"
},
"MTB_USI_WM_BN_BM_22": {
"SPI_MOSI": "PC_3",
"SPI_MISO": "PC_2",
"SPI_CLK": "PB_13",
"SPI_CS": "PA_6"
},
"MTB_ADV_WISE_1570": {
"SPI_MOSI": "PA_7",
"SPI_MISO": "PA_6",
"SPI_CLK": "PA_5",
"SPI_CS": "PB_12"
}
}
}

View File

@ -461,7 +461,7 @@ bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr)
bd_size_t SPIFBlockDevice::size() const
{
if (!_is_initialized) {
return SPIF_BD_ERROR_DEVICE_ERROR;
return 0;
}
return _device_size_bytes;

View File

@ -18,6 +18,7 @@
#include "utest.h"
#include "SPIFBlockDevice.h"
#include "mbed_trace.h"
#include "rtos/Thread.h"
#include <stdlib.h>
using namespace utest::v1;

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