mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #291 from ARMmbed/devel_gt_client
[test porting] Merge mbedmicro tests (HAL, RTOS and basic NET) to mbed-os/TESTS
commit
170268f156
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity/unity.h"
|
||||
#include "utest/utest.h"
|
||||
|
||||
namespace {
|
||||
static char buffer[256] = {0};
|
||||
}
|
||||
|
||||
#define CLEAN_BUFFER memset(::buffer, 0x00, sizeof(::buffer))
|
||||
#define NEGATIVE_INTEGERS -32768,-3214,-999,-100,-1,0,-1,-4231,-999,-4123,-32760,-99999
|
||||
#define POSITIVE_INTEGERS 32768,3214,999,100,1,0,1,4231,999,4123,32760,99999
|
||||
#define FLOATS 0.002,0.92430,15.91320,791.77368,6208.2,25719.4952,426815.982588,6429271.046,42468024.93,212006462.910
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
|
||||
void test_case_c_string_i_d() {
|
||||
CLEAN_BUFFER;
|
||||
sprintf(buffer, "%i %d %i %d %i %d %i %d %i %d %i %i", NEGATIVE_INTEGERS);
|
||||
TEST_ASSERT_EQUAL_STRING("-32768 -3214 -999 -100 -1 0 -1 -4231 -999 -4123 -32760 -99999", buffer);
|
||||
}
|
||||
|
||||
void test_case_c_string_u_d() {
|
||||
CLEAN_BUFFER;
|
||||
sprintf(buffer, "%u %d %u %d %u %d %u %d %u %d %u %d", POSITIVE_INTEGERS);
|
||||
TEST_ASSERT_EQUAL_STRING("32768 3214 999 100 1 0 1 4231 999 4123 32760 99999", buffer);
|
||||
}
|
||||
|
||||
void test_case_c_string_x_E() {
|
||||
CLEAN_BUFFER;
|
||||
sprintf(buffer, "%x %X %x %X %x %X %x %X %x %X %x %X", POSITIVE_INTEGERS);
|
||||
TEST_ASSERT_EQUAL_STRING("8000 C8E 3e7 64 1 0 1 1087 3e7 101B 7ff8 1869F", buffer);
|
||||
}
|
||||
|
||||
void test_case_c_string_f_f() {
|
||||
CLEAN_BUFFER;
|
||||
sprintf(buffer, "%f %f %f %f %f %f %f %f %f %f", FLOATS);
|
||||
TEST_ASSERT_EQUAL_STRING("0.002000 0.924300 15.913200 791.773680 6208.200000 25719.495200 426815.982588 6429271.046000 42468024.930000 212006462.910000", buffer);
|
||||
}
|
||||
|
||||
void test_case_c_string_g_g() {
|
||||
CLEAN_BUFFER;
|
||||
sprintf(buffer, "%g %g %g %g %g %g %g %g %g %g", FLOATS);
|
||||
TEST_ASSERT_EQUAL_STRING("0.002 0.9243 15.9132 791.774 6208.2 25719.5 426816 6.42927e+006 4.2468e+007 2.12006e+008", buffer);
|
||||
TEST_ASSERT_EQUAL_STRING("0.002 0.9243 15.9132 791.774 6208.2 25719.5 426816 6.42927e+06 4.2468e+07 2.12006e+08", buffer);
|
||||
}
|
||||
|
||||
void test_case_c_string_e_E() {
|
||||
CLEAN_BUFFER;
|
||||
sprintf(buffer, "%e %E %e %E %e %E %e %E %e %E", FLOATS);
|
||||
TEST_ASSERT_EQUAL_STRING("2.000000e-003 9.243000E-001 1.591320e+001 7.917737E+002 6.208200e+003 2.571950E+004 4.268160e+005 6.429271E+006 4.246802e+007 2.120065E+008", buffer);
|
||||
TEST_ASSERT_EQUAL_STRING("2.000000e-03 9.243000E-01 1.591320e+01 7.917737E+02 6.208200e+03 2.571950E+04 4.268160e+05 6.429271E+06 4.246802e+07 2.120065E+08", buffer);
|
||||
}
|
||||
|
||||
void test_case_c_string_strtok() {
|
||||
CLEAN_BUFFER;
|
||||
char str[] ="- This, a sample string.";
|
||||
char * pch = strtok (str," ,.-");
|
||||
while (pch != NULL) {
|
||||
strcat(buffer, pch);
|
||||
pch = strtok (NULL, " ,.-");
|
||||
}
|
||||
TEST_ASSERT_EQUAL_STRING("Thisasamplestring", buffer);
|
||||
}
|
||||
|
||||
void test_case_c_string_strpbrk() {
|
||||
CLEAN_BUFFER;
|
||||
char str[] = "This is a sample string";
|
||||
char key[] = "aeiou";
|
||||
char *pch = strpbrk(str, key);
|
||||
while (pch != NULL)
|
||||
{
|
||||
char buf[2] = {*pch, '\0'};
|
||||
strcat(buffer, buf);
|
||||
pch = strpbrk(pch + 1,key);
|
||||
}
|
||||
TEST_ASSERT_EQUAL_STRING("iiaaei", buffer);
|
||||
}
|
||||
|
||||
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
|
||||
greentea_case_failure_abort_handler(source, reason);
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("C strings: strtok", test_case_c_string_strtok, greentea_failure_handler),
|
||||
Case("C strings: strpbrk", test_case_c_string_strpbrk, greentea_failure_handler),
|
||||
Case("C strings: %i %d integer formatting", test_case_c_string_i_d, greentea_failure_handler),
|
||||
Case("C strings: %u %d integer formatting", test_case_c_string_u_d, greentea_failure_handler),
|
||||
Case("C strings: %x %E integer formatting", test_case_c_string_x_E, greentea_failure_handler),
|
||||
Case("C strings: %f %f float formatting", test_case_c_string_f_f, greentea_failure_handler),
|
||||
Case("C strings: %e %E float formatting", test_case_c_string_e_E, greentea_failure_handler),
|
||||
Case("C strings: %g %g float formatting", test_case_c_string_g_g, greentea_failure_handler),
|
||||
};
|
||||
|
||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(5, "default_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||
|
||||
int main() {
|
||||
Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
|
||||
// static functions
|
||||
template <typename T>
|
||||
T static_func5(T a0, T a1, T a2, T a3, T a4) { return a0 | a1 | a2 | a3 | a4; }
|
||||
template <typename T>
|
||||
T static_func4(T a0, T a1, T a2, T a3) { return a0 | a1 | a2 | a3; }
|
||||
template <typename T>
|
||||
T static_func3(T a0, T a1, T a2) { return a0 | a1 | a2; }
|
||||
template <typename T>
|
||||
T static_func2(T a0, T a1) { return a0 | a1; }
|
||||
template <typename T>
|
||||
T static_func1(T a0) { return a0; }
|
||||
template <typename T>
|
||||
T static_func0() { return 0; }
|
||||
|
||||
// class functions
|
||||
template <typename T>
|
||||
struct Thing {
|
||||
T t;
|
||||
Thing() : t(0x80) {}
|
||||
|
||||
T member_func5(T a0, T a1, T a2, T a3, T a4) { return t | a0 | a1 | a2 | a3 | a4; }
|
||||
T member_func4(T a0, T a1, T a2, T a3) { return t | a0 | a1 | a2 | a3; }
|
||||
T member_func3(T a0, T a1, T a2) { return t | a0 | a1 | a2; }
|
||||
T member_func2(T a0, T a1) { return t | a0 | a1; }
|
||||
T member_func1(T a0) { return t | a0; }
|
||||
T member_func0() { return t; }
|
||||
};
|
||||
|
||||
// bound functions
|
||||
template <typename T>
|
||||
T bound_func5(Thing<T> *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; }
|
||||
template <typename T>
|
||||
T bound_func4(Thing<T> *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; }
|
||||
template <typename T>
|
||||
T bound_func3(Thing<T> *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; }
|
||||
template <typename T>
|
||||
T bound_func2(Thing<T> *t, T a0, T a1) { return t->t | a0 | a1; }
|
||||
template <typename T>
|
||||
T bound_func1(Thing<T> *t, T a0) { return t->t | a0; }
|
||||
template <typename T>
|
||||
T bound_func0(Thing<T> *t) { return t->t; }
|
||||
|
||||
|
||||
// function call and result verification
|
||||
template <typename T>
|
||||
struct Verifier {
|
||||
static void verify5(Callback<T(T,T,T,T,T)> func) {
|
||||
T result = func(0x01, 0x02, 0x04, 0x08, 0x10);
|
||||
TEST_ASSERT_EQUAL(result, 0x1f);
|
||||
}
|
||||
|
||||
template <typename O, typename M>
|
||||
static void verify5(O *obj, M method) {
|
||||
Callback<T(T,T,T,T,T)> func(obj, method);
|
||||
T result = func(0x01, 0x02, 0x04, 0x08, 0x10);
|
||||
TEST_ASSERT_EQUAL(result, 0x9f);
|
||||
}
|
||||
|
||||
static void verify4(Callback<T(T,T,T,T)> func) {
|
||||
T result = func(0x01, 0x02, 0x04, 0x08);
|
||||
TEST_ASSERT_EQUAL(result, 0x0f);
|
||||
}
|
||||
|
||||
template <typename O, typename M>
|
||||
static void verify4(O *obj, M method) {
|
||||
Callback<T(T,T,T,T)> func(obj, method);
|
||||
T result = func(0x01, 0x02, 0x04, 0x08);
|
||||
TEST_ASSERT_EQUAL(result, 0x8f);
|
||||
}
|
||||
|
||||
static void verify3(Callback<T(T,T,T)> func) {
|
||||
T result = func(0x01, 0x02, 0x04);
|
||||
TEST_ASSERT_EQUAL(result, 0x07);
|
||||
}
|
||||
|
||||
template <typename O, typename M>
|
||||
static void verify3(O *obj, M method) {
|
||||
Callback<T(T,T,T)> func(obj, method);
|
||||
T result = func(0x01, 0x02, 0x04);
|
||||
TEST_ASSERT_EQUAL(result, 0x87);
|
||||
}
|
||||
|
||||
static void verify2(Callback<T(T,T)> func) {
|
||||
T result = func(0x01, 0x02);
|
||||
TEST_ASSERT_EQUAL(result, 0x03);
|
||||
}
|
||||
|
||||
template <typename O, typename M>
|
||||
static void verify2(O *obj, M method) {
|
||||
Callback<T(T,T)> func(obj, method);
|
||||
T result = func(0x01, 0x02);
|
||||
TEST_ASSERT_EQUAL(result, 0x83);
|
||||
}
|
||||
|
||||
static void verify1(Callback<T(T)> func) {
|
||||
T result = func(0x01);
|
||||
TEST_ASSERT_EQUAL(result, 0x01);
|
||||
}
|
||||
|
||||
template <typename O, typename M>
|
||||
static void verify1(O *obj, M method) {
|
||||
Callback<T(T)> func(obj, method);
|
||||
T result = func(0x01);
|
||||
TEST_ASSERT_EQUAL(result, 0x81);
|
||||
}
|
||||
|
||||
static void verify0(Callback<T()> func) {
|
||||
T result = func();
|
||||
TEST_ASSERT_EQUAL(result, 0x00);
|
||||
}
|
||||
|
||||
template <typename O, typename M>
|
||||
static void verify0(O *obj, M method) {
|
||||
Callback<T()> func(obj, method);
|
||||
T result = func();
|
||||
TEST_ASSERT_EQUAL(result, 0x80);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// test dispatch
|
||||
template <typename T>
|
||||
void test_dispatch5() {
|
||||
Thing<T> thing;
|
||||
Verifier<T>::verify5(static_func5<T>);
|
||||
Verifier<T>::verify5(&thing, &Thing<T>::member_func5);
|
||||
Verifier<T>::verify5(&thing, &bound_func5<T>);
|
||||
|
||||
Callback<T(T,T,T,T,T)> callback(static_func5);
|
||||
Verifier<T>::verify5(callback);
|
||||
callback.attach(&thing, &bound_func5<T>);
|
||||
Verifier<T>::verify5(&callback, &Callback<T(T,T,T,T,T)>::call);
|
||||
Verifier<T>::verify5((void*)&callback, &Callback<T(T,T,T,T,T)>::thunk);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_dispatch4() {
|
||||
Thing<T> thing;
|
||||
Verifier<T>::verify4(static_func4<T>);
|
||||
Verifier<T>::verify4(&thing, &Thing<T>::member_func4);
|
||||
Verifier<T>::verify4(&thing, &bound_func4<T>);
|
||||
|
||||
Callback<T(T,T,T,T)> callback(static_func4);
|
||||
Verifier<T>::verify4(callback);
|
||||
callback.attach(&thing, &bound_func4<T>);
|
||||
Verifier<T>::verify4(&callback, &Callback<T(T,T,T,T)>::call);
|
||||
Verifier<T>::verify4((void*)&callback, &Callback<T(T,T,T,T)>::thunk);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_dispatch3() {
|
||||
Thing<T> thing;
|
||||
Verifier<T>::verify3(static_func3<T>);
|
||||
Verifier<T>::verify3(&thing, &Thing<T>::member_func3);
|
||||
Verifier<T>::verify3(&thing, &bound_func3<T>);
|
||||
|
||||
Callback<T(T,T,T)> callback(static_func3);
|
||||
Verifier<T>::verify3(callback);
|
||||
callback.attach(&thing, &bound_func3<T>);
|
||||
Verifier<T>::verify3(&callback, &Callback<T(T,T,T)>::call);
|
||||
Verifier<T>::verify3((void*)&callback, &Callback<T(T,T,T)>::thunk);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_dispatch2() {
|
||||
Thing<T> thing;
|
||||
Verifier<T>::verify2(static_func2<T>);
|
||||
Verifier<T>::verify2(&thing, &Thing<T>::member_func2);
|
||||
Verifier<T>::verify2(&thing, &bound_func2<T>);
|
||||
|
||||
Callback<T(T,T)> callback(static_func2);
|
||||
Verifier<T>::verify2(callback);
|
||||
callback.attach(&thing, &bound_func2<T>);
|
||||
Verifier<T>::verify2(&callback, &Callback<T(T,T)>::call);
|
||||
Verifier<T>::verify2((void*)&callback, &Callback<T(T,T)>::thunk);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_dispatch1() {
|
||||
Thing<T> thing;
|
||||
Verifier<T>::verify1(static_func1<T>);
|
||||
Verifier<T>::verify1(&thing, &Thing<T>::member_func1);
|
||||
Verifier<T>::verify1(&thing, &bound_func1<T>);
|
||||
|
||||
Callback<T(T)> callback(static_func1);
|
||||
Verifier<T>::verify1(callback);
|
||||
callback.attach(&thing, &bound_func1<T>);
|
||||
Verifier<T>::verify1(&callback, &Callback<T(T)>::call);
|
||||
Verifier<T>::verify1((void*)&callback, &Callback<T(T)>::thunk);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_dispatch0() {
|
||||
Thing<T> thing;
|
||||
Verifier<T>::verify0(static_func0<T>);
|
||||
Verifier<T>::verify0(&thing, &Thing<T>::member_func0);
|
||||
Verifier<T>::verify0(&thing, &bound_func0<T>);
|
||||
|
||||
Callback<T()> callback(static_func0);
|
||||
Verifier<T>::verify0(callback);
|
||||
callback.attach(&thing, &bound_func0<T>);
|
||||
Verifier<T>::verify0(&callback, &Callback<T()>::call);
|
||||
Verifier<T>::verify0((void*)&callback, &Callback<T()>::thunk);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_fparg1() {
|
||||
Thing<T> thing;
|
||||
FunctionPointerArg1<T,T> fp(static_func1<T>);
|
||||
Verifier<T>::verify1(fp);
|
||||
Verifier<T>::verify1(fp.get_function());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_fparg0() {
|
||||
Thing<T> thing;
|
||||
FunctionPointerArg1<T,void> fp(static_func0<T>);
|
||||
Verifier<T>::verify0(fp);
|
||||
Verifier<T>::verify0(fp.get_function());
|
||||
}
|
||||
|
||||
|
||||
// Test setup
|
||||
utest::v1::status_t test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(5, "default_auto");
|
||||
return verbose_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("Testing callbacks with 5 ints", test_dispatch5<int>),
|
||||
Case("Testing callbacks with 4 ints", test_dispatch4<int>),
|
||||
Case("Testing callbacks with 3 ints", test_dispatch3<int>),
|
||||
Case("Testing callbacks with 2 ints", test_dispatch2<int>),
|
||||
Case("Testing callbacks with 1 ints", test_dispatch1<int>),
|
||||
Case("Testing callbacks with 0 ints", test_dispatch0<int>),
|
||||
|
||||
Case("Testing callbacks with 5 uchars", test_dispatch5<unsigned char>),
|
||||
Case("Testing callbacks with 4 uchars", test_dispatch4<unsigned char>),
|
||||
Case("Testing callbacks with 3 uchars", test_dispatch3<unsigned char>),
|
||||
Case("Testing callbacks with 2 uchars", test_dispatch2<unsigned char>),
|
||||
Case("Testing callbacks with 1 uchars", test_dispatch1<unsigned char>),
|
||||
Case("Testing callbacks with 0 uchars", test_dispatch0<unsigned char>),
|
||||
|
||||
Case("Testing callbacks with 5 uint64s", test_dispatch5<uint64_t>),
|
||||
Case("Testing callbacks with 4 uint64s", test_dispatch4<uint64_t>),
|
||||
Case("Testing callbacks with 3 uint64s", test_dispatch3<uint64_t>),
|
||||
Case("Testing callbacks with 2 uint64s", test_dispatch2<uint64_t>),
|
||||
Case("Testing callbacks with 1 uint64s", test_dispatch1<uint64_t>),
|
||||
Case("Testing callbacks with 0 uint64s", test_dispatch0<uint64_t>),
|
||||
|
||||
Case("Testing FunctionPointerArg1 compatibility", test_fparg1<int>),
|
||||
Case("Testing FunctionPointer compatibility", test_fparg0<int>),
|
||||
};
|
||||
|
||||
Specification specification(test_setup, cases);
|
||||
|
||||
int main() {
|
||||
return !Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2013-2014 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 "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
|
||||
class DevNull : public Stream {
|
||||
public:
|
||||
DevNull(const char *name = NULL) : Stream(name) {}
|
||||
|
||||
protected:
|
||||
virtual int _getc() {
|
||||
return 0;
|
||||
}
|
||||
virtual int _putc(int c) {
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
DevNull null("null");
|
||||
|
||||
int main() {
|
||||
GREENTEA_SETUP(2, "dev_null_auto");
|
||||
|
||||
printf("MBED: before re-routing stdout to /null\n"); // This shouldn't appear
|
||||
greentea_send_kv("to_stdout", "re-routing stdout to /null");
|
||||
|
||||
if (freopen("/null", "w", stdout)) {
|
||||
// This shouldn't appear on serial
|
||||
// We should use pure printf here to send KV
|
||||
printf("{{to_null;printf redirected to /null}}\n");
|
||||
printf("MBED: this printf is already redirected to /null\n");
|
||||
}
|
||||
GREENTEA_TESTSUITE_RESULT(false);
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity/unity.h"
|
||||
#include "utest/utest.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
// Echo server (echo payload to host)
|
||||
template<int N>
|
||||
void test_case_echo_server_x() {
|
||||
char _key[10] = {};
|
||||
char _value[128] = {};
|
||||
const int echo_count = N;
|
||||
|
||||
// Handshake with host
|
||||
greentea_send_kv("echo_count", echo_count);
|
||||
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
||||
TEST_ASSERT_EQUAL_INT(echo_count, atoi(_value));
|
||||
|
||||
for (int i=0; i < echo_count; ++i) {
|
||||
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
|
||||
greentea_send_kv(_key, _value);
|
||||
}
|
||||
}
|
||||
|
||||
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
|
||||
greentea_case_failure_abort_handler(source, reason);
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("Echo server: x16", test_case_echo_server_x<16>, greentea_failure_handler),
|
||||
Case("Echo server: x32", test_case_echo_server_x<32>, greentea_failure_handler),
|
||||
Case("Echo server: x64", test_case_echo_server_x<64>, greentea_failure_handler),
|
||||
};
|
||||
|
||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(30, "echo");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||
|
||||
int main() {
|
||||
Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <utility> // std::pair
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity/unity.h"
|
||||
#include "utest/utest.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
#define PATTERN_CHECK_VALUE 0xF0F0ADAD
|
||||
|
||||
class CppTestCaseHelperClass {
|
||||
private:
|
||||
const char* name;
|
||||
const unsigned pattern;
|
||||
|
||||
public:
|
||||
CppTestCaseHelperClass(const char* _name) : name(_name), pattern(PATTERN_CHECK_VALUE) {
|
||||
print("init");
|
||||
}
|
||||
|
||||
void print(const char *message) {
|
||||
printf("%s::%s\n", name, message);
|
||||
}
|
||||
|
||||
bool check_init(void) {
|
||||
bool result = (pattern == PATTERN_CHECK_VALUE);
|
||||
print(result ? "check_init: OK" : "check_init: ERROR");
|
||||
return result;
|
||||
}
|
||||
|
||||
void stack_test(void) {
|
||||
print("stack_test");
|
||||
CppTestCaseHelperClass t("Stack");
|
||||
t.hello();
|
||||
}
|
||||
|
||||
void hello(void) {
|
||||
print("hello");
|
||||
}
|
||||
|
||||
~CppTestCaseHelperClass() {
|
||||
print("destroy");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void test_case_basic() {
|
||||
TEST_ASSERT_TRUE(true);
|
||||
TEST_ASSERT_FALSE(false);
|
||||
TEST_ASSERT_EQUAL_STRING("The quick brown fox jumps over the lazy dog",
|
||||
"The quick brown fox jumps over the lazy dog");
|
||||
}
|
||||
|
||||
void test_case_blinky() {
|
||||
static DigitalOut myled(LED1);
|
||||
const int cnt_max = 1024;
|
||||
for (int cnt = 0; cnt < cnt_max; ++cnt) {
|
||||
myled = !myled;
|
||||
}
|
||||
}
|
||||
|
||||
void test_case_cpp_stack() {
|
||||
// Check C++ start-up initialisation
|
||||
CppTestCaseHelperClass s("Static");
|
||||
|
||||
// Global stack object simple test
|
||||
s.stack_test();
|
||||
TEST_ASSERT_TRUE_MESSAGE(s.check_init(), "s.check_init() failed");
|
||||
}
|
||||
|
||||
void test_case_cpp_heap() {
|
||||
// Heap test object simple test
|
||||
CppTestCaseHelperClass *m = new CppTestCaseHelperClass("Heap");
|
||||
m->hello();
|
||||
TEST_ASSERT_TRUE_MESSAGE(m->check_init(), "m->check_init() failed");
|
||||
delete m;
|
||||
}
|
||||
|
||||
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
|
||||
greentea_case_failure_abort_handler(source, reason);
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
// Generic test cases
|
||||
Case cases[] = {
|
||||
Case("Basic", test_case_basic, greentea_failure_handler),
|
||||
Case("Blinky", test_case_blinky, greentea_failure_handler),
|
||||
Case("C++ stack", test_case_cpp_stack, greentea_failure_handler),
|
||||
Case("C++ heap", test_case_cpp_heap, greentea_failure_handler)
|
||||
};
|
||||
|
||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||
|
||||
int main() {
|
||||
Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity/unity.h"
|
||||
#include "utest/utest.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
#define CUSTOM_TIME 1256729737
|
||||
|
||||
void test_case_rtc_strftime() {
|
||||
greentea_send_kv("timestamp", CUSTOM_TIME);
|
||||
|
||||
char buffer[32] = {0};
|
||||
char kv_buff[64] = {0};
|
||||
set_time(CUSTOM_TIME); // Set RTC time to Wed, 28 Oct 2009 11:35:37
|
||||
|
||||
for (int i=0; i<10; ++i) {
|
||||
time_t seconds = time(NULL);
|
||||
sprintf(kv_buff, "[%ld] ", seconds);
|
||||
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S %p", localtime(&seconds));
|
||||
strcat(kv_buff, buffer);
|
||||
greentea_send_kv("rtc", kv_buff);
|
||||
wait(1);
|
||||
}
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("RTC strftime", test_case_rtc_strftime),
|
||||
};
|
||||
|
||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(20, "rtc_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||
|
||||
int main() {
|
||||
Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity/unity.h"
|
||||
#include "utest/utest.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <math.h>
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
#define TABLE_SIZE(TAB) (sizeof(TAB) / sizeof(TAB[0]))
|
||||
|
||||
#define NEGATIVE_INTEGERS -32768,-3214,-999,-100,-1,0,1,4231,999,4123,32760,99999
|
||||
#define POSITIVE_INTEGERS 32768,3214,999,100,1,0,1,4231,999,4123,32760,99999
|
||||
#define FLOATS 0.002,0.92430,15.91320,791.77368,6208.2,25719.4952,426815.982588,6429271.046,42468024.93,212006462.910
|
||||
#define FLOATS_STR "0.002","0.92430","15.91320","791.77368","6208.2","25719.4952","426815.982588","6429271.046","42468024.93","212006462.910"
|
||||
|
||||
|
||||
namespace {
|
||||
int p_integers[] = {POSITIVE_INTEGERS};
|
||||
int n_integers[] = {NEGATIVE_INTEGERS};
|
||||
float floats[] = {FLOATS};
|
||||
|
||||
template <class T, class F>
|
||||
void BubbleSort(T& _array, size_t array_size, F functor) {
|
||||
bool flag = true;
|
||||
size_t numLength = array_size;
|
||||
for(size_t i = 1; (i <= numLength) && flag; i++) {
|
||||
flag = false;
|
||||
for (size_t j = 0; j < (numLength - 1); j++) {
|
||||
if (functor(_array[j+1], _array[j])) {
|
||||
int temp = _array[j];
|
||||
_array[j] = _array[j + 1];
|
||||
_array[j+1] = temp;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct printInt {
|
||||
void operator()(int i) { printf("%d ", i); }
|
||||
};
|
||||
|
||||
struct printFloat {
|
||||
void operator()(float f) { printf("%f ", f); }
|
||||
};
|
||||
|
||||
struct printString {
|
||||
void operator()(const char* s) { printf("%s ", s); }
|
||||
};
|
||||
|
||||
struct greaterAbs {
|
||||
bool operator()(int a, int b) { return abs(a) > abs(b); }
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void test_case_stl_equal() {
|
||||
std::vector<int> v_pints(p_integers, p_integers + TABLE_SIZE(p_integers));
|
||||
TEST_ASSERT_TRUE(std::equal(v_pints.begin(), v_pints.end(), p_integers));
|
||||
}
|
||||
|
||||
void test_case_stl_transform() {
|
||||
const char* floats_str[] = {FLOATS_STR};
|
||||
float floats_transform[TABLE_SIZE(floats_str)] = {0.0};
|
||||
std::transform(floats_str, floats_str + TABLE_SIZE(floats_str), floats_transform, atof);
|
||||
//printf("stl_transform::floats_str: ");
|
||||
//std::for_each(floats_str, floats_str + TABLE_SIZE(floats_str), printString());
|
||||
//printf("stl_transform::floats_transform: ");
|
||||
//std::for_each(floats_transform, floats_transform + TABLE_SIZE(floats_transform), printFloat());
|
||||
//printf("\n");
|
||||
|
||||
TEST_ASSERT_TRUE(std::equal(floats_transform, floats_transform + TABLE_SIZE(floats_transform), floats));
|
||||
}
|
||||
|
||||
void test_case_stl_sort_greater() {
|
||||
std::vector<int> v_nints_1(n_integers, n_integers + TABLE_SIZE(n_integers));
|
||||
std::vector<int> v_nints_2(n_integers, n_integers + TABLE_SIZE(n_integers));
|
||||
|
||||
BubbleSort(v_nints_1, v_nints_1.size(), std::greater<int>());
|
||||
std::sort(v_nints_2.begin(), v_nints_2.end(), std::greater<int>());
|
||||
|
||||
TEST_ASSERT_TRUE(std::equal(v_nints_1.begin(), v_nints_1.end(), v_nints_2.begin()));
|
||||
}
|
||||
|
||||
void test_case_stl_sort_abs() {
|
||||
std::vector<int> v_nints_1(n_integers, n_integers + TABLE_SIZE(n_integers));
|
||||
std::vector<int> v_nints_2(n_integers, n_integers + TABLE_SIZE(n_integers));
|
||||
|
||||
BubbleSort(v_nints_1, v_nints_1.size(), greaterAbs());
|
||||
std::sort(v_nints_2.begin(), v_nints_2.end(), greaterAbs());
|
||||
|
||||
TEST_ASSERT_TRUE(std::equal(v_nints_1.begin(), v_nints_1.end(), v_nints_2.begin()));
|
||||
}
|
||||
|
||||
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
|
||||
greentea_case_failure_abort_handler(source, reason);
|
||||
return STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("STL std::equal", test_case_stl_equal, greentea_failure_handler),
|
||||
Case("STL std::transform", test_case_stl_transform, greentea_failure_handler),
|
||||
Case("STL std::sort greater", test_case_stl_sort_greater, greentea_failure_handler),
|
||||
Case("STL std::sort abs", test_case_stl_sort_abs, greentea_failure_handler)
|
||||
};
|
||||
|
||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(5, "default_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||
|
||||
int main() {
|
||||
Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "utest/utest.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
void send_kv_tick() {
|
||||
static int count = 0;
|
||||
if (count < 10) {
|
||||
greentea_send_kv("tick", count);
|
||||
} else if (count == 10) {
|
||||
Harness::validate_callback();
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
Ticker flipper_1;
|
||||
DigitalOut led1(LED1);
|
||||
|
||||
void flip_1() {
|
||||
static int led1_state = 0;
|
||||
if (led1_state) {
|
||||
led1 = 0; led1_state = 0;
|
||||
} else {
|
||||
led1 = 1; led1_state = 1;
|
||||
}
|
||||
send_kv_tick();
|
||||
}
|
||||
|
||||
Ticker flipper_2;
|
||||
DigitalOut led2(LED2);
|
||||
|
||||
void flip_2() {
|
||||
static int led2_state = 0;
|
||||
if (led2_state) {
|
||||
led2 = 0; led2_state = 0;
|
||||
} else {
|
||||
led2 = 1; led2_state = 1;
|
||||
}
|
||||
}
|
||||
|
||||
control_t test_case_ticker() {
|
||||
led1 = 0;
|
||||
led2 = 0;
|
||||
flipper_1.attach(&flip_1, 1.0);
|
||||
flipper_2.attach(&flip_2, 2.0);
|
||||
return CaseTimeout(15 * 1000);
|
||||
}
|
||||
|
||||
// Test cases
|
||||
Case cases[] = {
|
||||
Case("Timers: 2 x tickers", test_case_ticker),
|
||||
};
|
||||
|
||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(20, "wait_us_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||
|
||||
int main() {
|
||||
Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "utest/utest.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
Ticker tick;
|
||||
DigitalOut led(LED1);
|
||||
|
||||
namespace {
|
||||
const int MS_INTERVALS = 1000;
|
||||
}
|
||||
|
||||
void send_kv_tick() {
|
||||
static int count = 0;
|
||||
if (count < 10) {
|
||||
greentea_send_kv("tick", count);
|
||||
} else if (count == 10) {
|
||||
Harness::validate_callback();
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
void togglePin(void) {
|
||||
static int ticker_count = 0;
|
||||
if (ticker_count >= MS_INTERVALS) {
|
||||
send_kv_tick();
|
||||
ticker_count = 0;
|
||||
led = !led;
|
||||
}
|
||||
ticker_count++;
|
||||
}
|
||||
|
||||
utest::v1::control_t test_case_ticker() {
|
||||
tick.attach_us(togglePin, 1000);
|
||||
return CaseTimeout(15 * 1000);
|
||||
}
|
||||
|
||||
// Test cases
|
||||
Case cases[] = {
|
||||
Case("Timers: 1x ticker", test_case_ticker),
|
||||
};
|
||||
|
||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(20, "wait_us_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||
|
||||
int main() {
|
||||
Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "utest/utest.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
void ticker_callback_1(void);
|
||||
void ticker_callback_2(void);
|
||||
|
||||
DigitalOut led0(LED1);
|
||||
DigitalOut led1(LED2);
|
||||
Ticker ticker;
|
||||
|
||||
void send_kv_tick() {
|
||||
static int count = 0;
|
||||
if (count < 10) {
|
||||
greentea_send_kv("tick", count);
|
||||
} else if (count == 10) {
|
||||
Harness::validate_callback();
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
void ticker_callback_2(void) {
|
||||
ticker.detach();
|
||||
ticker.attach(ticker_callback_1, 1.0);
|
||||
led1 = !led1;
|
||||
send_kv_tick();
|
||||
}
|
||||
|
||||
void ticker_callback_1(void) {
|
||||
ticker.detach();
|
||||
ticker.attach(ticker_callback_2, 1.0);
|
||||
led0 = !led0;
|
||||
send_kv_tick();
|
||||
}
|
||||
|
||||
utest::v1::control_t test_case_ticker() {
|
||||
ticker.attach(ticker_callback_1, 1.0);
|
||||
return CaseTimeout(15 * 1000);
|
||||
}
|
||||
|
||||
// Test cases
|
||||
Case cases[] = {
|
||||
Case("Timers: 2x callbacks", test_case_ticker),
|
||||
};
|
||||
|
||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(20, "wait_us_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||
|
||||
int main() {
|
||||
Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "utest/utest.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
Timeout timer;
|
||||
DigitalOut led(LED1);
|
||||
|
||||
namespace {
|
||||
const int MS_INTERVALS = 1000;
|
||||
}
|
||||
|
||||
void send_kv_tick() {
|
||||
static int count = 0;
|
||||
if (count < 10) {
|
||||
greentea_send_kv("tick", count);
|
||||
} else if (count == 10) {
|
||||
Harness::validate_callback();
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
void toggleOff(void);
|
||||
|
||||
void toggleOn(void) {
|
||||
static int toggle_counter = 0;
|
||||
if (toggle_counter == MS_INTERVALS) {
|
||||
led = !led;
|
||||
send_kv_tick();
|
||||
toggle_counter = 0;
|
||||
}
|
||||
toggle_counter++;
|
||||
timer.attach_us(toggleOff, 500);
|
||||
}
|
||||
|
||||
void toggleOff(void) {
|
||||
timer.attach_us(toggleOn, 500);
|
||||
}
|
||||
|
||||
control_t test_case_ticker() {
|
||||
toggleOn();
|
||||
return CaseTimeout(15 * 1000);
|
||||
}
|
||||
|
||||
// Test cases
|
||||
Case cases[] = {
|
||||
Case("Timers: toggle on/off", test_case_ticker),
|
||||
};
|
||||
|
||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(20, "wait_us_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||
|
||||
int main() {
|
||||
Harness::run(specification);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "utest/utest.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
DigitalOut led(LED1);
|
||||
|
||||
void test_case_ticker() {
|
||||
for (int i=0; i < 10; ++i) {
|
||||
// 10 secs...
|
||||
for (int j = 0; j < 1000; ++j) {
|
||||
// 1000 * 1000us = 1 sec
|
||||
wait_us(1000);
|
||||
}
|
||||
led = !led; // Blink
|
||||
greentea_send_kv("tick", i);
|
||||
}
|
||||
}
|
||||
|
||||
// Test cases
|
||||
Case cases[] = {
|
||||
Case("Timers: wait_us", test_case_ticker),
|
||||
};
|
||||
|
||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(20, "wait_us_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||
|
||||
int main() {
|
||||
Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
#include "toolchain.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
MBED_PACKED(struct) TestAttrPackedStruct1 {
|
||||
char a;
|
||||
int x;
|
||||
};
|
||||
|
||||
typedef MBED_PACKED(struct) {
|
||||
char a;
|
||||
int x;
|
||||
} TestAttrPackedStruct2;
|
||||
|
||||
int testPacked() {
|
||||
int failed = 0;
|
||||
|
||||
if (sizeof(struct TestAttrPackedStruct1) != sizeof(int) + sizeof(char)) {
|
||||
failed++;
|
||||
}
|
||||
|
||||
if (sizeof(TestAttrPackedStruct2) != sizeof(int) + sizeof(char)) {
|
||||
failed++;
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
|
||||
MBED_ALIGN(8) char a;
|
||||
MBED_ALIGN(8) char b;
|
||||
MBED_ALIGN(16) char c;
|
||||
MBED_ALIGN(8) char d;
|
||||
MBED_ALIGN(16) char e;
|
||||
|
||||
int testAlign() {
|
||||
int failed = 0;
|
||||
|
||||
if(((uintptr_t)&a) & 0x7){
|
||||
failed++;
|
||||
}
|
||||
if(((uintptr_t)&b) & 0x7){
|
||||
failed++;
|
||||
}
|
||||
if(((uintptr_t)&c) & 0xf){
|
||||
failed++;
|
||||
}
|
||||
if(((uintptr_t)&d) & 0x7){
|
||||
failed++;
|
||||
}
|
||||
if(((uintptr_t)&e) & 0xf){
|
||||
failed++;
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
|
||||
int testUnused1(MBED_UNUSED int arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testUnused() {
|
||||
return testUnused1(0);
|
||||
}
|
||||
|
||||
|
||||
int testWeak1();
|
||||
int testWeak2();
|
||||
|
||||
MBED_WEAK int testWeak1() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int testWeak2() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testWeak() {
|
||||
return testWeak1() | testWeak2();
|
||||
}
|
||||
|
||||
|
||||
MBED_PURE int testPure1() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testPure() {
|
||||
return testPure1();
|
||||
}
|
||||
|
||||
|
||||
MBED_FORCEINLINE int testForceInline1() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testForceInline() {
|
||||
return testForceInline1();
|
||||
}
|
||||
|
||||
|
||||
MBED_NORETURN int testNoReturn1() {
|
||||
while (1) {}
|
||||
}
|
||||
|
||||
int testNoReturn() {
|
||||
if (0) {
|
||||
testNoReturn1();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int testUnreachable1(int i) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
return 0;
|
||||
}
|
||||
|
||||
MBED_UNREACHABLE;
|
||||
}
|
||||
|
||||
int testUnreachable() {
|
||||
return testUnreachable1(0);
|
||||
}
|
||||
|
||||
|
||||
MBED_DEPRECATED("this message should not be displayed")
|
||||
void testDeprecatedUnused();
|
||||
void testDeprecatedUnused() { }
|
||||
|
||||
MBED_DEPRECATED("this message should be displayed")
|
||||
int testDeprecatedUsed();
|
||||
int testDeprecatedUsed() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testDeprecated() {
|
||||
return testDeprecatedUsed();
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "toolchain.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
|
||||
// Test functions declared as C functions to avoid issues with name mangling
|
||||
extern "C" {
|
||||
int testPacked();
|
||||
int testAlign();
|
||||
int testUnused();
|
||||
int testWeak();
|
||||
int testPure();
|
||||
int testForceInline();
|
||||
int testNoReturn();
|
||||
int testUnreachable();
|
||||
int testDeprecated();
|
||||
}
|
||||
|
||||
|
||||
// Test wrapper and test cases for utest
|
||||
template <int (*F)()>
|
||||
void test_wrapper() {
|
||||
TEST_ASSERT_UNLESS(F());
|
||||
}
|
||||
|
||||
utest::v1::status_t test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(5, "default_auto");
|
||||
return verbose_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("Testing PACKED attribute", test_wrapper<testPacked>),
|
||||
Case("Testing ALIGN attribute", test_wrapper<testAlign>),
|
||||
Case("Testing UNUSED attribute", test_wrapper<testUnused>),
|
||||
Case("Testing WEAK attribute", test_wrapper<testWeak>),
|
||||
Case("Testing PURE attribute", test_wrapper<testPure>),
|
||||
Case("Testing FORCEINLINE attribute", test_wrapper<testForceInline>),
|
||||
Case("Testing NORETURN attribute", test_wrapper<testNoReturn>),
|
||||
Case("Testing UNREACHABLE attribute", test_wrapper<testUnreachable>),
|
||||
Case("Testing DEPRECATED attribute", test_wrapper<testDeprecated>),
|
||||
};
|
||||
|
||||
Specification specification(test_setup, cases);
|
||||
|
||||
int main() {
|
||||
return !Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#include "toolchain.h"
|
||||
|
||||
int testWeak1() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
MBED_WEAK int testWeak2() {
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#include "greentea-client/test_env.h"
|
||||
|
||||
namespace {
|
||||
bool mbed_main_called = false;
|
||||
}
|
||||
|
||||
extern "C" void mbed_main() {
|
||||
printf("MBED: mbed_main() call before main()\r\n");
|
||||
mbed_main_called = true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
GREENTEA_SETUP(5, "default_auto");
|
||||
printf("MBED: main() starts now!\r\n");
|
||||
GREENTEA_TESTSUITE_RESULT(mbed_main_called);
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
#include "greentea-client/test_env.h"
|
||||
|
||||
#define PATTERN_CHECK_VALUE 0xF0F0ADAD
|
||||
|
||||
class Test {
|
||||
|
||||
private:
|
||||
const char* name;
|
||||
const int pattern;
|
||||
|
||||
public:
|
||||
Test(const char* _name) : name(_name), pattern(PATTERN_CHECK_VALUE) {
|
||||
print("init");
|
||||
}
|
||||
|
||||
void print(const char *message) {
|
||||
printf("%s::%s\n", name, message);
|
||||
}
|
||||
|
||||
bool check_init(void) {
|
||||
bool result = (pattern == PATTERN_CHECK_VALUE);
|
||||
print(result ? "check_init: OK" : "check_init: ERROR");
|
||||
return result;
|
||||
}
|
||||
|
||||
void stack_test(void) {
|
||||
print("stack_test");
|
||||
Test t("Stack");
|
||||
t.hello();
|
||||
}
|
||||
|
||||
void hello(void) {
|
||||
print("hello");
|
||||
}
|
||||
|
||||
~Test() {
|
||||
print("destroy");
|
||||
}
|
||||
};
|
||||
|
||||
/* Check C++ startup initialisation */
|
||||
Test s("Static");
|
||||
|
||||
/* EXPECTED OUTPUT:
|
||||
*******************
|
||||
Static::init
|
||||
Static::stack_test
|
||||
Stack::init
|
||||
Stack::hello
|
||||
Stack::destroy
|
||||
Static::check_init: OK
|
||||
Heap::init
|
||||
Heap::hello
|
||||
Heap::destroy
|
||||
*******************/
|
||||
int main (void) {
|
||||
GREENTEA_SETUP(10, "default_auto");
|
||||
|
||||
bool result = true;
|
||||
for (;;)
|
||||
{
|
||||
// Global stack object simple test
|
||||
s.stack_test();
|
||||
if (s.check_init() == false)
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Heap test object simple test
|
||||
Test *m = new Test("Heap");
|
||||
m->hello();
|
||||
|
||||
if (m->check_init() == false)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
delete m;
|
||||
break;
|
||||
}
|
||||
|
||||
GREENTEA_TESTSUITE_RESULT(result);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
#include <utility> // std::pair
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
|
||||
uint32_t test_64(uint64_t ticks) {
|
||||
ticks >>= 3; // divide by 8
|
||||
if (ticks > 0xFFFFFFFF) {
|
||||
ticks /= 3;
|
||||
} else {
|
||||
ticks = (ticks * 0x55555556) >> 32; // divide by 3
|
||||
}
|
||||
return (uint32_t)(0xFFFFFFFF & ticks);
|
||||
}
|
||||
|
||||
const char *result_str(bool result) {
|
||||
return result ? "[OK]" : "[FAIL]";
|
||||
}
|
||||
|
||||
int main() {
|
||||
GREENTEA_SETUP(5, "default_auto");
|
||||
|
||||
bool result = true;
|
||||
|
||||
{ // 0xFFFFFFFF * 8 = 0x7fffffff8
|
||||
std::pair<uint32_t, uint64_t> values = std::make_pair(0x55555555, 0x7FFFFFFF8);
|
||||
uint32_t test_ret = test_64(values.second);
|
||||
bool test_res = values.first == test_ret;
|
||||
result = result && test_res;
|
||||
printf("64bit: 0x7FFFFFFF8: expected 0x%lX got 0x%lX ... %s\r\n", values.first, test_ret, result_str(test_res));
|
||||
}
|
||||
|
||||
{ // 0xFFFFFFFF * 24 = 0x17ffffffe8
|
||||
std::pair<uint32_t, uint64_t> values = std::make_pair(0xFFFFFFFF, 0x17FFFFFFE8);
|
||||
uint32_t test_ret = test_64(values.second);
|
||||
bool test_res = values.first == test_ret;
|
||||
result = result && test_res;
|
||||
printf("64bit: 0x17FFFFFFE8: expected 0x%lX got 0x%lX ... %s\r\n", values.first, test_ret, result_str(test_res));
|
||||
}
|
||||
|
||||
GREENTEA_TESTSUITE_RESULT(result);
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "greentea-client/test_env.h"
|
||||
|
||||
static char *initial_stack_p;
|
||||
static char *initial_heap_p;
|
||||
|
||||
static char line[256];
|
||||
static unsigned int iterations = 0;
|
||||
|
||||
void report_iterations(void) {
|
||||
unsigned int tot = (0x100 * iterations)*2;
|
||||
printf("\nAllocated (%d)Kb in (%u) iterations\n", tot/1024, iterations);
|
||||
#if !defined(TOOLCHAIN_GCC_CR)
|
||||
// EA: This causes a crash when compiling with GCC_CR???
|
||||
printf("%.2f\n", ((float)(tot)/(float)(initial_stack_p - initial_heap_p))*100.);
|
||||
#endif
|
||||
#ifdef TOOLCHAIN_ARM
|
||||
#ifndef __MICROLIB
|
||||
__heapvalid((__heapprt) fprintf, stdout, 1);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void stack_test(char *latest_heap_pointer) {
|
||||
char stack_line[256];
|
||||
iterations++;
|
||||
|
||||
sprintf(stack_line, "\nstack pointer: %p", &stack_line[255]);
|
||||
puts(stack_line);
|
||||
|
||||
char *heap_pointer = (char*)malloc(0x100);
|
||||
|
||||
if (heap_pointer == NULL) {
|
||||
int diff = (&stack_line[255] - latest_heap_pointer);
|
||||
if (diff > 0x200) {
|
||||
sprintf(stack_line, "\n[WARNING] Malloc failed to allocate memory too soon. There are (0x%x) free bytes", diff);
|
||||
report_iterations();
|
||||
puts(stack_line);
|
||||
} else {
|
||||
puts("\n[SUCCESS] Stack/Heap collision detected");
|
||||
report_iterations();
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
heap_pointer += 0x100;
|
||||
sprintf(line, "heap pointer: %p", heap_pointer);
|
||||
puts(line);
|
||||
}
|
||||
|
||||
if ((&stack_line[255]) > heap_pointer) {
|
||||
stack_test(heap_pointer);
|
||||
} else {
|
||||
puts("\n[WARNING] The Stack/Heap collision was not detected");
|
||||
report_iterations();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main (void) {
|
||||
GREENTEA_SETUP(30, "default_auto");
|
||||
|
||||
char c;
|
||||
initial_stack_p = &c;
|
||||
|
||||
initial_heap_p = (char*)malloc(1);
|
||||
if (initial_heap_p == NULL) {
|
||||
printf("Unable to malloc a single byte\n");
|
||||
GREENTEA_TESTSUITE_RESULT(false);
|
||||
}
|
||||
|
||||
printf("Initial stack/heap geometry:\n");
|
||||
printf(" stack pointer:V %p\n", initial_stack_p);
|
||||
printf(" heap pointer :^ %p\n", initial_heap_p);
|
||||
|
||||
initial_heap_p++;
|
||||
stack_test(initial_heap_p);
|
||||
|
||||
GREENTEA_TESTSUITE_RESULT(true);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
host_tests/*
|
|
@ -0,0 +1,198 @@
|
|||
# Copyright 2015 ARM Limited, All rights reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import sys
|
||||
import select
|
||||
import socket
|
||||
import logging
|
||||
from threading import Thread
|
||||
from sys import stdout
|
||||
from SocketServer import BaseRequestHandler, TCPServer
|
||||
from mbed_host_tests import BaseHostTest, event_callback
|
||||
|
||||
|
||||
class TCPEchoClientHandler(BaseRequestHandler):
|
||||
def handle(self):
|
||||
"""
|
||||
Handles a connection. Test starts by client(i.e. mbed) connecting to server.
|
||||
This connection handler receives data and echoes back to the client util
|
||||
{{end}} is received. Then it sits on recv() for client to terminate the
|
||||
connection.
|
||||
|
||||
Note: reason for not echoing data back after receiving {{end}} is that send
|
||||
fails raising a SocketError as client closes connection.
|
||||
"""
|
||||
print ("HOST: TCPEchoClient_Handler: Connection received...")
|
||||
while self.server.isrunning():
|
||||
try:
|
||||
data = self.recv()
|
||||
if not data: break
|
||||
except Exception as e:
|
||||
print ('HOST: TCPEchoClient_Handler recv error: %s' % str(e))
|
||||
break
|
||||
|
||||
print ('HOST: TCPEchoClient_Handler: Rx: \n%s\n' % data)
|
||||
|
||||
try:
|
||||
# echo data back to the client
|
||||
self.send(data)
|
||||
except Exception as e:
|
||||
print ('HOST: TCPEchoClient_Handler send error: %s' % str(e))
|
||||
break
|
||||
print 'Connection finished'
|
||||
|
||||
def recv(self):
|
||||
"""
|
||||
Try to receive until server is shutdown
|
||||
"""
|
||||
while self.server.isrunning():
|
||||
rl, wl, xl = select.select([self.request], [], [], 1)
|
||||
if len(rl):
|
||||
return self.request.recv(1024)
|
||||
|
||||
def send(self, data):
|
||||
"""
|
||||
Try to send until server is shutdown
|
||||
"""
|
||||
while self.server.isrunning():
|
||||
rl, wl, xl = select.select([], [self.request], [], 1)
|
||||
if len(wl):
|
||||
self.request.sendall(data)
|
||||
break
|
||||
|
||||
|
||||
class TCPServerWrapper(TCPServer):
|
||||
"""
|
||||
Wrapper over TCP server to implement server initiated shutdown.
|
||||
Adds a flag:= running that a request handler can check and come out of
|
||||
recv loop when shutdown is called.
|
||||
"""
|
||||
|
||||
def __init__(self, addr, request_handler):
|
||||
# hmm, TCPServer is not sub-classed from object!
|
||||
if issubclass(TCPServer, object):
|
||||
super(TCPServerWrapper, self).__init__(addr, request_handler)
|
||||
else:
|
||||
TCPServer.__init__(self, addr, request_handler)
|
||||
self.running = False
|
||||
|
||||
def serve_forever(self):
|
||||
self.running = True
|
||||
if issubclass(TCPServer, object):
|
||||
super(TCPServerWrapper, self).serve_forever()
|
||||
else:
|
||||
TCPServer.serve_forever(self)
|
||||
|
||||
def shutdown(self):
|
||||
self.running = False
|
||||
if issubclass(TCPServer, object):
|
||||
super(TCPServerWrapper, self).shutdown()
|
||||
else:
|
||||
TCPServer.shutdown(self)
|
||||
|
||||
def isrunning(self):
|
||||
return self.running
|
||||
|
||||
|
||||
class TCPEchoClientTest(BaseHostTest):
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialise test parameters.
|
||||
|
||||
:return:
|
||||
"""
|
||||
BaseHostTest.__init__(self)
|
||||
self.SERVER_IP = None # Will be determined after knowing the target IP
|
||||
self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port
|
||||
self.server = None
|
||||
self.server_thread = None
|
||||
self.target_ip = None
|
||||
|
||||
@staticmethod
|
||||
def find_interface_to_target_addr(target_ip):
|
||||
"""
|
||||
Finds IP address of the interface through which it is connected to the target.
|
||||
|
||||
:return:
|
||||
"""
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.connect((target_ip, 0)) # Target IP, Any port
|
||||
ip = s.getsockname()[0]
|
||||
s.close()
|
||||
return ip
|
||||
|
||||
def setup_tcp_server(self):
|
||||
"""
|
||||
sets up a TCP server for target to connect and send test data.
|
||||
|
||||
:return:
|
||||
"""
|
||||
# !NOTE: There should mechanism to assert in the host test
|
||||
if self.SERVER_IP is None:
|
||||
self.log("setup_tcp_server() called before determining server IP!")
|
||||
self.notify_complete(False)
|
||||
|
||||
# Returning none will suppress host test from printing success code
|
||||
self.server = TCPServerWrapper((self.SERVER_IP, self.SERVER_PORT), TCPEchoClientHandler)
|
||||
ip, port = self.server.server_address
|
||||
self.SERVER_PORT = port
|
||||
self.server.allow_reuse_address = True
|
||||
self.log("HOST: Listening for TCP connections: " + self.SERVER_IP + ":" + str(self.SERVER_PORT))
|
||||
self.server_thread = Thread(target=TCPEchoClientTest.server_thread_func, args=(self,))
|
||||
self.server_thread.start()
|
||||
|
||||
@staticmethod
|
||||
def server_thread_func(this):
|
||||
"""
|
||||
Thread function to run TCP server forever.
|
||||
|
||||
:param this:
|
||||
:return:
|
||||
"""
|
||||
this.server.serve_forever()
|
||||
|
||||
@event_callback("target_ip")
|
||||
def _callback_target_ip(self, key, value, timestamp):
|
||||
"""
|
||||
Callback to handle reception of target's IP address.
|
||||
|
||||
:param key:
|
||||
:param value:
|
||||
:param timestamp:
|
||||
:return:
|
||||
"""
|
||||
self.target_ip = value
|
||||
self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip)
|
||||
self.setup_tcp_server()
|
||||
|
||||
@event_callback("host_ip")
|
||||
def _callback_host_ip(self, key, value, timestamp):
|
||||
"""
|
||||
Callback for request for host IP Addr
|
||||
|
||||
"""
|
||||
self.send_kv("host_ip", self.SERVER_IP)
|
||||
|
||||
@event_callback("host_port")
|
||||
def _callback_host_port(self, key, value, timestamp):
|
||||
"""
|
||||
Callback for request for host port
|
||||
"""
|
||||
self.send_kv("host_port", self.SERVER_PORT)
|
||||
|
||||
def teardown(self):
|
||||
if self.server:
|
||||
self.server.shutdown()
|
||||
self.server_thread.join()
|
|
@ -0,0 +1,125 @@
|
|||
"""
|
||||
mbed SDK
|
||||
Copyright (c) 2011-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import socket
|
||||
from sys import stdout
|
||||
from threading import Thread
|
||||
from SocketServer import BaseRequestHandler, UDPServer
|
||||
from mbed_host_tests import BaseHostTest, event_callback
|
||||
|
||||
|
||||
class UDPEchoClientHandler(BaseRequestHandler):
|
||||
def handle(self):
|
||||
""" UDP packet handler. Echoes data back to sender's address.
|
||||
"""
|
||||
data, sock = self.request
|
||||
print ('HOST: UDPEchoClientHandler: Rx: \n%s\n' % data)
|
||||
sock.sendto(data, self.client_address)
|
||||
|
||||
|
||||
class UDPEchoClientTest(BaseHostTest):
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialise test parameters.
|
||||
|
||||
:return:
|
||||
"""
|
||||
BaseHostTest.__init__(self)
|
||||
self.SERVER_IP = None # Will be determined after knowing the target IP
|
||||
self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port
|
||||
self.server = None
|
||||
self.server_thread = None
|
||||
self.target_ip = None
|
||||
|
||||
@staticmethod
|
||||
def find_interface_to_target_addr(target_ip):
|
||||
"""
|
||||
Finds IP address of the interface through which it is connected to the target.
|
||||
|
||||
:return:
|
||||
"""
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.connect((target_ip, 0)) # Target IP, Any port
|
||||
ip = s.getsockname()[0]
|
||||
s.close()
|
||||
return ip
|
||||
|
||||
def setup_udp_server(self):
|
||||
"""
|
||||
sets up a UDP server for target to connect and send test data.
|
||||
|
||||
:return:
|
||||
"""
|
||||
# !NOTE: There should mechanism to assert in the host test
|
||||
if self.SERVER_IP is None:
|
||||
self.log("setup_udp_server() called before determining server IP!")
|
||||
self.notify_complete(False)
|
||||
|
||||
# Returning none will suppress host test from printing success code
|
||||
self.server = UDPServer((self.SERVER_IP, self.SERVER_PORT), UDPEchoClientHandler)
|
||||
ip, port = self.server.server_address
|
||||
self.SERVER_PORT = port
|
||||
self.server.allow_reuse_address = True
|
||||
self.log("HOST: Listening for UDP packets: " + self.SERVER_IP + ":" + str(self.SERVER_PORT))
|
||||
self.server_thread = Thread(target=UDPEchoClientTest.server_thread_func, args=(self,))
|
||||
self.server_thread.start()
|
||||
|
||||
@staticmethod
|
||||
def server_thread_func(this):
|
||||
"""
|
||||
Thread function to run TCP server forever.
|
||||
|
||||
:param this:
|
||||
:return:
|
||||
"""
|
||||
this.server.serve_forever()
|
||||
|
||||
@event_callback("target_ip")
|
||||
def _callback_target_ip(self, key, value, timestamp):
|
||||
"""
|
||||
Callback to handle reception of target's IP address.
|
||||
|
||||
:param key:
|
||||
:param value:
|
||||
:param timestamp:
|
||||
:return:
|
||||
"""
|
||||
self.target_ip = value
|
||||
self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip)
|
||||
self.setup_udp_server()
|
||||
|
||||
@event_callback("host_ip")
|
||||
def _callback_host_ip(self, key, value, timestamp):
|
||||
"""
|
||||
Callback for request for host IP Addr
|
||||
|
||||
"""
|
||||
self.send_kv("host_ip", self.SERVER_IP)
|
||||
|
||||
@event_callback("host_port")
|
||||
def _callback_host_port(self, key, value, timestamp):
|
||||
"""
|
||||
Callback for request for host port
|
||||
"""
|
||||
self.send_kv("host_port", self.SERVER_PORT)
|
||||
|
||||
def teardown(self):
|
||||
if self.server:
|
||||
self.server.shutdown()
|
||||
self.server_thread.join()
|
|
@ -0,0 +1,61 @@
|
|||
#include "mbed.h"
|
||||
#include "LWIPInterface.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
|
||||
namespace {
|
||||
//const char *HTTP_SERVER_NAME = "utcnist.colorado.edu";
|
||||
const char *HTTP_SERVER_NAME = "pool.ntp.org";
|
||||
const int HTTP_SERVER_PORT = 123;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
|
||||
bool result = false;
|
||||
const time_t TIME1970 = 2208988800L;
|
||||
int ntp_values[12] = {0};
|
||||
|
||||
LWIPInterface eth;
|
||||
//eth.init(); //Use DHCP
|
||||
eth.connect();
|
||||
printf("UDP client IP Address is %s\n", eth.get_ip_address());
|
||||
|
||||
UDPSocket sock;
|
||||
sock.open(ð);
|
||||
|
||||
SocketAddress nist(ð, HTTP_SERVER_NAME, HTTP_SERVER_PORT);
|
||||
|
||||
printf("UDP: NIST server %s address: %s on port %d\r\n", HTTP_SERVER_NAME, nist.get_ip_address(), nist.get_port());
|
||||
|
||||
memset(ntp_values, 0x00, sizeof(ntp_values));
|
||||
ntp_values[0] = '\x1b';
|
||||
|
||||
int ret_send = sock.sendto(nist, (void*)ntp_values, sizeof(ntp_values));
|
||||
printf("UDP: Sent %d Bytes to NTP server \n", ret_send);
|
||||
|
||||
const int n = sock.recvfrom(&nist, (void*)ntp_values, sizeof(ntp_values));
|
||||
|
||||
printf("UDP: Recved from NTP server %d Bytes \n", n);
|
||||
|
||||
if (n > 0 ) {
|
||||
result = true;
|
||||
|
||||
printf("UDP: Values returned by NTP server: \n");
|
||||
for (size_t i=0; i < sizeof(ntp_values) / sizeof(ntp_values[0]); ++i) {
|
||||
printf("\t[%02d] 0x%X", i, ntohl(ntp_values[i]));
|
||||
|
||||
if (i == 10) {
|
||||
time_t timestamp = ntohl(ntp_values[i]) - TIME1970;
|
||||
printf("\tNTP timestamp is %s", ctime(×tamp));
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sock.close();
|
||||
eth.disconnect();
|
||||
GREENTEA_TESTSUITE_RESULT(result);
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
#include "mbed.h"
|
||||
#include "LWIPInterface.h"
|
||||
#include "TCPSocket.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity/unity.h"
|
||||
|
||||
|
||||
#ifndef MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE
|
||||
#define MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE 256
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
char tx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0};
|
||||
char rx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0};
|
||||
const char ASCII_MAX = '~' - ' ';
|
||||
}
|
||||
|
||||
void prep_buffer(char *tx_buffer, size_t tx_size) {
|
||||
for (size_t i=0; i<tx_size; ++i) {
|
||||
tx_buffer[i] = (rand() % ASCII_MAX) + ' ' + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
GREENTEA_SETUP(20, "tcp_echo_client");
|
||||
|
||||
LWIPInterface eth;
|
||||
eth.connect();
|
||||
|
||||
printf("MBED: TCPClient IP address is '%s'\n", eth.get_ip_address());
|
||||
printf("MBED: TCPClient waiting for server IP and port...\n");
|
||||
|
||||
greentea_send_kv("target_ip", eth.get_ip_address());
|
||||
|
||||
bool result = false;
|
||||
|
||||
char recv_key[] = "host_port";
|
||||
char ipbuf[60] = {0};
|
||||
char portbuf[16] = {0};
|
||||
unsigned int port = 0;
|
||||
|
||||
greentea_send_kv("host_ip", " ");
|
||||
greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));
|
||||
|
||||
greentea_send_kv("host_port", " ");
|
||||
greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
|
||||
sscanf(portbuf, "%u", &port);
|
||||
|
||||
printf("MBED: Server IP address received: %s:%d \n", ipbuf, port);
|
||||
|
||||
TCPSocket sock(ð);
|
||||
SocketAddress tcp_addr(ipbuf, port);
|
||||
if (sock.connect(tcp_addr) == 0) {
|
||||
printf("HTTP: Connected to %s:%d\r\n", ipbuf, port);
|
||||
printf("tx_buffer buffer size: %u\r\n", sizeof(tx_buffer));
|
||||
printf("rx_buffer buffer size: %u\r\n", sizeof(rx_buffer));
|
||||
|
||||
prep_buffer(tx_buffer, sizeof(tx_buffer));
|
||||
sock.send(tx_buffer, sizeof(tx_buffer));
|
||||
|
||||
// Server will respond with HTTP GET's success code
|
||||
const int ret = sock.recv(rx_buffer, sizeof(rx_buffer));
|
||||
|
||||
result = !memcmp(tx_buffer, rx_buffer, sizeof(tx_buffer));
|
||||
|
||||
TEST_ASSERT_EQUAL(ret, sizeof(rx_buffer));
|
||||
TEST_ASSERT_EQUAL(true, result);
|
||||
}
|
||||
|
||||
sock.close();
|
||||
eth.disconnect();
|
||||
GREENTEA_TESTSUITE_RESULT(result);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
#include <algorithm>
|
||||
#include "mbed.h"
|
||||
#include "LWIPInterface.h"
|
||||
#include "TCPSocket.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity/unity.h"
|
||||
|
||||
namespace {
|
||||
// Test connection information
|
||||
const char *HTTP_SERVER_NAME = "developer.mbed.org";
|
||||
const char *HTTP_SERVER_FILE_PATH = "/media/uploads/mbed_official/hello.txt";
|
||||
const int HTTP_SERVER_PORT = 80;
|
||||
#if defined(TARGET_VK_RZ_A1H)
|
||||
const int RECV_BUFFER_SIZE = 300;
|
||||
#else
|
||||
const int RECV_BUFFER_SIZE = 512;
|
||||
#endif
|
||||
// Test related data
|
||||
const char *HTTP_OK_STR = "200 OK";
|
||||
const char *HTTP_HELLO_STR = "Hello world!";
|
||||
|
||||
// Test buffers
|
||||
char buffer[RECV_BUFFER_SIZE] = {0};
|
||||
}
|
||||
|
||||
bool find_substring(const char *first, const char *last, const char *s_first, const char *s_last) {
|
||||
const char *f = std::search(first, last, s_first, s_last);
|
||||
return (f != last);
|
||||
}
|
||||
|
||||
int main() {
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
|
||||
bool result = true;
|
||||
LWIPInterface eth;
|
||||
//eth.init(); //Use DHCP
|
||||
eth.connect();
|
||||
printf("TCP client IP Address is %s\r\n", eth.get_ip_address());
|
||||
|
||||
TCPSocket sock(ð);
|
||||
if (sock.connect(HTTP_SERVER_NAME, HTTP_SERVER_PORT) == 0) {
|
||||
printf("HTTP: Connected to %s:%d\r\n", HTTP_SERVER_NAME, HTTP_SERVER_PORT);
|
||||
|
||||
// We are constructing GET command like this:
|
||||
// GET http://developer.mbed.org/media/uploads/mbed_official/hello.txt HTTP/1.0\n\n
|
||||
strcpy(buffer, "GET http://");
|
||||
strcat(buffer, HTTP_SERVER_NAME);
|
||||
strcat(buffer, HTTP_SERVER_FILE_PATH);
|
||||
strcat(buffer, " HTTP/1.0\n\n");
|
||||
// Send GET command
|
||||
sock.send(buffer, strlen(buffer));
|
||||
|
||||
// Server will respond with HTTP GET's success code
|
||||
const int ret = sock.recv(buffer, sizeof(buffer) - 1);
|
||||
buffer[ret] = '\0';
|
||||
|
||||
// Find 200 OK HTTP status in reply
|
||||
bool found_200_ok = find_substring(buffer, buffer + ret, HTTP_OK_STR, HTTP_OK_STR + strlen(HTTP_OK_STR));
|
||||
// Find "Hello World!" string in reply
|
||||
bool found_hello = find_substring(buffer, buffer + ret, HTTP_HELLO_STR, HTTP_HELLO_STR + strlen(HTTP_HELLO_STR));
|
||||
|
||||
TEST_ASSERT_TRUE(found_200_ok);
|
||||
TEST_ASSERT_TRUE(found_hello);
|
||||
|
||||
if (!found_200_ok) result = false;
|
||||
if (!found_hello) result = false;
|
||||
|
||||
printf("HTTP: Received %d chars from server\r\n", ret);
|
||||
printf("HTTP: Received 200 OK status ... %s\r\n", found_200_ok ? "[OK]" : "[FAIL]");
|
||||
printf("HTTP: Received '%s' status ... %s\r\n", HTTP_HELLO_STR, found_hello ? "[OK]" : "[FAIL]");
|
||||
printf("HTTP: Received massage:\r\n\r\n");
|
||||
printf("%s", buffer);
|
||||
}
|
||||
|
||||
sock.close();
|
||||
eth.disconnect();
|
||||
GREENTEA_TESTSUITE_RESULT(result);
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
#include "mbed.h"
|
||||
#include "LWIPInterface.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
|
||||
#ifndef MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE
|
||||
#define MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE 256
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
char tx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE] = {0};
|
||||
char rx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE] = {0};
|
||||
const char ASCII_MAX = '~' - ' ';
|
||||
const int ECHO_LOOPS = 16;
|
||||
}
|
||||
|
||||
void prep_buffer(char *tx_buffer, size_t tx_size) {
|
||||
for (size_t i=0; i<tx_size; ++i) {
|
||||
tx_buffer[i] = (rand() % ASCII_MAX) + ' ' + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
GREENTEA_SETUP(20, "udp_echo_client");
|
||||
|
||||
LWIPInterface eth;
|
||||
eth.connect();
|
||||
printf("UDP client IP Address is %s\n", eth.get_ip_address());
|
||||
|
||||
greentea_send_kv("target_ip", eth.get_ip_address());
|
||||
|
||||
bool result = true;
|
||||
|
||||
char recv_key[] = "host_port";
|
||||
char ipbuf[60] = {0};
|
||||
char portbuf[16] = {0};
|
||||
unsigned int port = 0;
|
||||
|
||||
UDPSocket sock;
|
||||
sock.open(ð);
|
||||
|
||||
greentea_send_kv("host_ip", " ");
|
||||
greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));
|
||||
|
||||
greentea_send_kv("host_port", " ");
|
||||
greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
|
||||
sscanf(portbuf, "%u", &port);
|
||||
|
||||
printf("MBED: UDP Server IP address received: %s:%d \n", ipbuf, port);
|
||||
|
||||
SocketAddress addr(ipbuf, port);
|
||||
|
||||
for (int i=0; i < ECHO_LOOPS; ++i) {
|
||||
prep_buffer(tx_buffer, sizeof(tx_buffer));
|
||||
const int ret = sock.sendto(addr, tx_buffer, sizeof(tx_buffer));
|
||||
printf("[%02d] sent...%d Bytes \n", i, ret);
|
||||
|
||||
const int n = sock.recvfrom(&addr, rx_buffer, sizeof(rx_buffer));
|
||||
printf("[%02d] recv...%d Bytes \n", i, n);
|
||||
|
||||
if (memcmp(rx_buffer, tx_buffer, sizeof(rx_buffer))) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sock.close();
|
||||
eth.disconnect();
|
||||
GREENTEA_TESTSUITE_RESULT(result);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "rtos.h"
|
||||
|
||||
/*
|
||||
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
|
||||
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
|
||||
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
|
||||
*/
|
||||
#if (defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)) && defined(TOOLCHAIN_GCC)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#elif (defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB)) && defined(TOOLCHAIN_GCC)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#else
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE
|
||||
#endif
|
||||
|
||||
DigitalOut led1(LED1);
|
||||
DigitalOut led2(LED2);
|
||||
|
||||
void led2_thread(void const *argument) {
|
||||
static int count = 0;
|
||||
while (true) {
|
||||
led2 = !led2;
|
||||
Thread::wait(1000);
|
||||
greentea_send_kv("tick", count++);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
GREENTEA_SETUP(15, "wait_us_auto");
|
||||
|
||||
Thread thread(led2_thread, NULL, osPriorityNormal, STACK_SIZE);
|
||||
|
||||
while (true) {
|
||||
led1 = !led1;
|
||||
Thread::wait(500);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "rtos.h"
|
||||
|
||||
#define QUEUE_SIZE 5
|
||||
#define THREAD_DELAY 250
|
||||
#define QUEUE_PUT_ISR_VALUE 128
|
||||
#define QUEUE_PUT_THREAD_VALUE 127
|
||||
|
||||
/*
|
||||
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
|
||||
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
|
||||
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
|
||||
*/
|
||||
#if defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#else
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE
|
||||
#endif
|
||||
|
||||
Queue<uint32_t, QUEUE_SIZE> queue;
|
||||
|
||||
DigitalOut myled(LED1);
|
||||
|
||||
void queue_isr() {
|
||||
|
||||
queue.put((uint32_t*)QUEUE_PUT_ISR_VALUE);
|
||||
myled = !myled;
|
||||
}
|
||||
|
||||
void queue_thread(void const *argument) {
|
||||
while (true) {
|
||||
queue.put((uint32_t*)QUEUE_PUT_THREAD_VALUE);
|
||||
Thread::wait(THREAD_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
int main (void) {
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
|
||||
Thread thread(queue_thread, NULL, osPriorityNormal, STACK_SIZE);
|
||||
Ticker ticker;
|
||||
ticker.attach(queue_isr, 1.0);
|
||||
int isr_puts_counter = 0;
|
||||
bool result = true;
|
||||
|
||||
while (true) {
|
||||
osEvent evt = queue.get();
|
||||
if (evt.status != osEventMessage) {
|
||||
printf("QUEUE_GET: Status(0x%02X) ... [FAIL]\r\n", evt.status);
|
||||
result = false;
|
||||
break;
|
||||
} else {
|
||||
printf("QUEUE_GET: Value(%u) ... [OK]\r\n", evt.value.v);
|
||||
if (evt.value.v == QUEUE_PUT_ISR_VALUE) {
|
||||
isr_puts_counter++;
|
||||
}
|
||||
if (isr_puts_counter >= QUEUE_SIZE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GREENTEA_TESTSUITE_RESULT(result);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "rtos.h"
|
||||
|
||||
typedef struct {
|
||||
float voltage; /* AD result of measured voltage */
|
||||
float current; /* AD result of measured current */
|
||||
uint32_t counter; /* A counter value */
|
||||
} mail_t;
|
||||
|
||||
#define CREATE_VOLTAGE(COUNTER) (COUNTER * 0.1) * 33
|
||||
#define CREATE_CURRENT(COUNTER) (COUNTER * 0.1) * 11
|
||||
#define QUEUE_SIZE 16
|
||||
#define QUEUE_PUT_DELAY 100
|
||||
|
||||
/*
|
||||
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
|
||||
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
|
||||
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
|
||||
*/
|
||||
#if (defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)) && defined(TOOLCHAIN_GCC)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_GCC)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#else
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE
|
||||
#endif
|
||||
|
||||
Mail<mail_t, QUEUE_SIZE> mail_box;
|
||||
|
||||
void send_thread (void const *argument) {
|
||||
static uint32_t i = 10;
|
||||
while (true) {
|
||||
i++; // fake data update
|
||||
mail_t *mail = mail_box.alloc();
|
||||
mail->voltage = CREATE_VOLTAGE(i);
|
||||
mail->current = CREATE_CURRENT(i);
|
||||
mail->counter = i;
|
||||
mail_box.put(mail);
|
||||
Thread::wait(QUEUE_PUT_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
int main (void) {
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
|
||||
Thread thread(send_thread, NULL, osPriorityNormal, STACK_SIZE);
|
||||
bool result = true;
|
||||
int result_counter = 0;
|
||||
|
||||
while (true) {
|
||||
osEvent evt = mail_box.get();
|
||||
if (evt.status == osEventMail) {
|
||||
mail_t *mail = (mail_t*)evt.value.p;
|
||||
const float expected_voltage = CREATE_VOLTAGE(mail->counter);
|
||||
const float expected_current = CREATE_CURRENT(mail->counter);
|
||||
// Check using macros if received values correspond to values sent via queue
|
||||
bool expected_values = (expected_voltage == mail->voltage) &&
|
||||
(expected_current == mail->current);
|
||||
result = result && expected_values;
|
||||
const char *result_msg = expected_values ? "OK" : "FAIL";
|
||||
printf("%3d %.2fV %.2fA ... [%s]\r\n", mail->counter,
|
||||
mail->voltage,
|
||||
mail->current,
|
||||
result_msg);
|
||||
mail_box.free(mail);
|
||||
if (result == false || ++result_counter == QUEUE_SIZE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
GREENTEA_TESTSUITE_RESULT(result);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "rtos.h"
|
||||
|
||||
#define THREAD_DELAY 50
|
||||
#define SIGNALS_TO_EMIT 100
|
||||
|
||||
/*
|
||||
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
|
||||
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
|
||||
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
|
||||
*/
|
||||
#if (defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)) && defined(TOOLCHAIN_GCC)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#elif (defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB)) && defined(TOOLCHAIN_GCC)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#elif defined(TARGET_STM32F334R8) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#elif defined(TARGET_STM32F030R8) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#elif defined(TARGET_STM32F070RB) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#elif defined(TARGET_STM32F072RB) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#elif defined(TARGET_STM32F302R8) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#elif defined(TARGET_STM32F303K8) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#else
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE
|
||||
#endif
|
||||
|
||||
void print_char(char c = '*') {
|
||||
printf("%c", c);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
Mutex stdio_mutex;
|
||||
DigitalOut led(LED1);
|
||||
|
||||
volatile int change_counter = 0;
|
||||
volatile bool changing_counter = false;
|
||||
volatile bool mutex_defect = false;
|
||||
|
||||
bool manipulate_protected_zone(const int thread_delay) {
|
||||
bool result = true;
|
||||
|
||||
stdio_mutex.lock(); // LOCK
|
||||
if (changing_counter == true) {
|
||||
// 'e' stands for error. If changing_counter is true access is not exclusively
|
||||
print_char('e');
|
||||
result = false;
|
||||
mutex_defect = true;
|
||||
}
|
||||
changing_counter = true;
|
||||
|
||||
// Some action on protected
|
||||
led = !led;
|
||||
change_counter++;
|
||||
print_char('.');
|
||||
Thread::wait(thread_delay);
|
||||
|
||||
changing_counter = false;
|
||||
stdio_mutex.unlock(); // UNLOCK
|
||||
return result;
|
||||
}
|
||||
|
||||
void test_thread(void const *args) {
|
||||
const int thread_delay = int(args);
|
||||
while (true) {
|
||||
manipulate_protected_zone(thread_delay);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
|
||||
const int t1_delay = THREAD_DELAY * 1;
|
||||
const int t2_delay = THREAD_DELAY * 2;
|
||||
const int t3_delay = THREAD_DELAY * 3;
|
||||
Thread t2(test_thread, (void *)t2_delay, osPriorityNormal, STACK_SIZE);
|
||||
Thread t3(test_thread, (void *)t3_delay, osPriorityNormal, STACK_SIZE);
|
||||
|
||||
while (true) {
|
||||
// Thread 1 action
|
||||
Thread::wait(t1_delay);
|
||||
manipulate_protected_zone(t1_delay);
|
||||
if (change_counter >= SIGNALS_TO_EMIT or mutex_defect == true) {
|
||||
t2.terminate();
|
||||
t3.terminate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
GREENTEA_TESTSUITE_RESULT(!mutex_defect);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "rtos.h"
|
||||
|
||||
typedef struct {
|
||||
float voltage; /* AD result of measured voltage */
|
||||
float current; /* AD result of measured current */
|
||||
uint32_t counter; /* A counter value */
|
||||
} message_t;
|
||||
|
||||
#define CREATE_VOLTAGE(COUNTER) (COUNTER * 0.1) * 33
|
||||
#define CREATE_CURRENT(COUNTER) (COUNTER * 0.1) * 11
|
||||
#define QUEUE_SIZE 16
|
||||
#define QUEUE_PUT_DELAY 100
|
||||
|
||||
/*
|
||||
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
|
||||
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
|
||||
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
|
||||
*/
|
||||
#if (defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)) && defined(TOOLCHAIN_GCC)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_GCC)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#else
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE
|
||||
#endif
|
||||
|
||||
MemoryPool<message_t, QUEUE_SIZE> mpool;
|
||||
Queue<message_t, QUEUE_SIZE> queue;
|
||||
|
||||
/* Send Thread */
|
||||
void send_thread (void const *argument) {
|
||||
static uint32_t i = 10;
|
||||
while (true) {
|
||||
i++; // Fake data update
|
||||
message_t *message = mpool.alloc();
|
||||
message->voltage = CREATE_VOLTAGE(i);
|
||||
message->current = CREATE_CURRENT(i);
|
||||
message->counter = i;
|
||||
queue.put(message);
|
||||
Thread::wait(QUEUE_PUT_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
int main (void) {
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
|
||||
Thread thread(send_thread, NULL, osPriorityNormal, STACK_SIZE);
|
||||
bool result = true;
|
||||
int result_counter = 0;
|
||||
|
||||
while (true) {
|
||||
osEvent evt = queue.get();
|
||||
if (evt.status == osEventMessage) {
|
||||
message_t *message = (message_t*)evt.value.p;
|
||||
const float expected_voltage = CREATE_VOLTAGE(message->counter);
|
||||
const float expected_current = CREATE_CURRENT(message->counter);
|
||||
// Check using macros if received values correspond to values sent via queue
|
||||
bool expected_values = (expected_voltage == message->voltage) &&
|
||||
(expected_current == message->current);
|
||||
result = result && expected_values;
|
||||
const char *result_msg = expected_values ? "OK" : "FAIL";
|
||||
printf("%3d %.2fV %.2fA ... [%s]\r\n", message->counter,
|
||||
message->voltage,
|
||||
message->current,
|
||||
result_msg);
|
||||
mpool.free(message);
|
||||
if (result == false || ++result_counter == QUEUE_SIZE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
GREENTEA_TESTSUITE_RESULT(result);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "rtos.h"
|
||||
|
||||
#define THREAD_DELAY 75
|
||||
#define SEMAPHORE_SLOTS 2
|
||||
#define SEM_CHANGES 100
|
||||
|
||||
/*
|
||||
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
|
||||
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
|
||||
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
|
||||
*/
|
||||
#if (defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)) && defined(TOOLCHAIN_GCC)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/16
|
||||
#elif (defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB)) && defined(TOOLCHAIN_GCC)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/8
|
||||
#elif defined(TARGET_STM32F334R8) && (defined(TOOLCHAIN_GCC) || defined(TOOLCHAIN_IAR))
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#elif defined(TARGET_STM32F103RB) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#elif defined(TARGET_STM32F030R8) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#elif defined(TARGET_STM32F070RB) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#elif defined(TARGET_STM32F072RB) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#elif defined(TARGET_STM32F302R8) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#elif defined(TARGET_STM32F303K8) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#else
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE
|
||||
#endif
|
||||
|
||||
void print_char(char c = '*') {
|
||||
printf("%c", c);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
Semaphore two_slots(SEMAPHORE_SLOTS);
|
||||
|
||||
volatile int change_counter = 0;
|
||||
volatile int sem_counter = 0;
|
||||
volatile bool sem_defect = false;
|
||||
|
||||
void test_thread(void const *delay) {
|
||||
const int thread_delay = int(delay);
|
||||
while (true) {
|
||||
two_slots.wait();
|
||||
sem_counter++;
|
||||
const bool sem_lock_failed = sem_counter > SEMAPHORE_SLOTS;
|
||||
const char msg = sem_lock_failed ? 'e' : sem_counter + '0';
|
||||
print_char(msg);
|
||||
if (sem_lock_failed) {
|
||||
sem_defect = true;
|
||||
}
|
||||
Thread::wait(thread_delay);
|
||||
print_char('.');
|
||||
sem_counter--;
|
||||
change_counter++;
|
||||
two_slots.release();
|
||||
}
|
||||
}
|
||||
|
||||
int main (void) {
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
|
||||
const int t1_delay = THREAD_DELAY * 1;
|
||||
const int t2_delay = THREAD_DELAY * 2;
|
||||
const int t3_delay = THREAD_DELAY * 3;
|
||||
Thread t1(test_thread, (void *)t1_delay, osPriorityNormal, STACK_SIZE);
|
||||
Thread t2(test_thread, (void *)t2_delay, osPriorityNormal, STACK_SIZE);
|
||||
Thread t3(test_thread, (void *)t3_delay, osPriorityNormal, STACK_SIZE);
|
||||
|
||||
while (true) {
|
||||
if (change_counter >= SEM_CHANGES or sem_defect == true) {
|
||||
t1.terminate();
|
||||
t2.terminate();
|
||||
t3.terminate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
GREENTEA_TESTSUITE_RESULT(!sem_defect);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "rtos.h"
|
||||
|
||||
#define SIGNAL_SET_VALUE 0x01
|
||||
const int SIGNALS_TO_EMIT = 100;
|
||||
const int SIGNAL_HANDLE_DELEY = 25;
|
||||
|
||||
/*
|
||||
* The stack size is defined in cmsis_os.h mainly dependent on the underlying toolchain and
|
||||
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
|
||||
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
|
||||
*/
|
||||
#if defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/4
|
||||
#elif (defined(TARGET_STM32F030R8)) && defined(TOOLCHAIN_IAR)
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE/2
|
||||
#else
|
||||
#define STACK_SIZE DEFAULT_STACK_SIZE
|
||||
#endif
|
||||
|
||||
DigitalOut led(LED1);
|
||||
int signal_counter = 0;
|
||||
|
||||
void led_thread(void const *argument) {
|
||||
while (true) {
|
||||
// Signal flags that are reported as event are automatically cleared.
|
||||
Thread::signal_wait(SIGNAL_SET_VALUE);
|
||||
led = !led;
|
||||
signal_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
int main (void) {
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
|
||||
Thread thread(led_thread, NULL, osPriorityNormal, STACK_SIZE);
|
||||
bool result = false;
|
||||
|
||||
printf("Handling %d signals...\r\n", SIGNALS_TO_EMIT);
|
||||
|
||||
while (true) {
|
||||
Thread::wait(2 * SIGNAL_HANDLE_DELEY);
|
||||
thread.signal_set(SIGNAL_SET_VALUE);
|
||||
if (signal_counter == SIGNALS_TO_EMIT) {
|
||||
printf("Handled %d signals\r\n", signal_counter);
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
GREENTEA_TESTSUITE_RESULT(result);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
#include "rtos.h"
|
||||
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
|
||||
// Tasks with different functions to test on threads
|
||||
void increment(const void *var) {
|
||||
(*(int *)var)++;
|
||||
}
|
||||
|
||||
void increment_with_yield(const void *var) {
|
||||
Thread::yield();
|
||||
(*(int *)var)++;
|
||||
}
|
||||
|
||||
void increment_with_wait(const void *var) {
|
||||
Thread::wait(100);
|
||||
(*(int *)var)++;
|
||||
}
|
||||
|
||||
void increment_with_child(const void *var) {
|
||||
Thread child(increment, (void*)var);
|
||||
child.join();
|
||||
}
|
||||
|
||||
void increment_with_murder(const void *var) {
|
||||
Thread child(increment_with_wait, (void*)var);
|
||||
// Kill child before it can increment var
|
||||
child.terminate();
|
||||
(*(int *)var)++;
|
||||
}
|
||||
|
||||
|
||||
// Tests that spawn tasks in different configurations
|
||||
template <void (*F)(const void *)>
|
||||
void test_single_thread() {
|
||||
int var = 0;
|
||||
Thread thread(F, &var);
|
||||
thread.join();
|
||||
TEST_ASSERT_EQUAL(var, 1);
|
||||
}
|
||||
|
||||
template <int N, void (*F)(const void *)>
|
||||
void test_parallel_threads() {
|
||||
int var = 0;
|
||||
Thread *threads[N];
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
threads[i] = new Thread(F, &var);
|
||||
}
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
threads[i]->join();
|
||||
delete threads[i];
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL(var, N);
|
||||
}
|
||||
|
||||
template <int N, void (*F)(const void *)>
|
||||
void test_serial_threads() {
|
||||
int var = 0;
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
Thread thread(F, &var);
|
||||
thread.join();
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL(var, N);
|
||||
}
|
||||
|
||||
|
||||
utest::v1::status_t test_setup(const size_t number_of_cases) {
|
||||
GREENTEA_SETUP(40, "default_auto");
|
||||
return verbose_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
// Test cases
|
||||
Case cases[] = {
|
||||
Case("Testing single thread", test_single_thread<increment>),
|
||||
Case("Testing parallel threads", test_parallel_threads<3, increment>),
|
||||
Case("Testing serial threads", test_serial_threads<10, increment>),
|
||||
|
||||
Case("Testing single thread with yield", test_single_thread<increment_with_yield>),
|
||||
Case("Testing parallel threads with yield", test_parallel_threads<3, increment_with_yield>),
|
||||
Case("Testing serial threads with yield", test_serial_threads<10, increment_with_yield>),
|
||||
|
||||
Case("Testing single thread with wait", test_single_thread<increment_with_wait>),
|
||||
Case("Testing parallel threads with wait", test_parallel_threads<3, increment_with_wait>),
|
||||
Case("Testing serial threads with wait", test_serial_threads<10, increment_with_wait>),
|
||||
|
||||
Case("Testing single thread with child", test_single_thread<increment_with_child>),
|
||||
Case("Testing parallel threads with child", test_parallel_threads<3, increment_with_child>),
|
||||
Case("Testing serial threads with child", test_serial_threads<10, increment_with_child>),
|
||||
|
||||
Case("Testing single thread with murder", test_single_thread<increment_with_murder>),
|
||||
Case("Testing parallel threads with murder", test_parallel_threads<3, increment_with_murder>),
|
||||
Case("Testing serial threads with murder", test_serial_threads<10, increment_with_murder>),
|
||||
};
|
||||
|
||||
Specification specification(test_setup, cases);
|
||||
|
||||
int main() {
|
||||
return !Harness::run(specification);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "rtos.h"
|
||||
|
||||
DigitalOut LEDs[4] = {
|
||||
DigitalOut(LED1), DigitalOut(LED2), DigitalOut(LED3), DigitalOut(LED4)
|
||||
};
|
||||
|
||||
void blink(void const *n) {
|
||||
static int blink_counter = 0;
|
||||
static int count = 0;
|
||||
const int led_id = int(n);
|
||||
LEDs[led_id] = !LEDs[led_id];
|
||||
if (++blink_counter == 75) {
|
||||
greentea_send_kv("tick", count++);
|
||||
blink_counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
GREENTEA_SETUP(15, "wait_us_auto");
|
||||
|
||||
RtosTimer led_1_timer(blink, osTimerPeriodic, (void *)0);
|
||||
RtosTimer led_2_timer(blink, osTimerPeriodic, (void *)1);
|
||||
RtosTimer led_3_timer(blink, osTimerPeriodic, (void *)2);
|
||||
RtosTimer led_4_timer(blink, osTimerPeriodic, (void *)3);
|
||||
|
||||
led_1_timer.start(200);
|
||||
led_2_timer.start(100);
|
||||
led_3_timer.start(50);
|
||||
led_4_timer.start(25);
|
||||
|
||||
Thread::wait(osWaitForever);
|
||||
}
|
Loading…
Reference in New Issue