mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #5954 from ARMmbed/release-candidate
Release candidate for mbed-os-5.7.4pull/6195/merge mbed-os-5.7.4
commit
caeaa49d68
10
.travis.yml
10
.travis.yml
|
@ -127,6 +127,7 @@ matrix:
|
|||
before_script:
|
||||
# Setup and patch littlefs-fuse
|
||||
- git clone https://github.com/geky/littlefs-fuse littlefs_fuse
|
||||
- git -C littlefs_fuse checkout 3f1ed6e37799e49e3710830dc6abb926d5503cf2
|
||||
- echo '*' > littlefs_fuse/.mbedignore
|
||||
- rm -rf littlefs_fuse/littlefs/*
|
||||
- cp -r $(git ls-tree --name-only HEAD $LITTLEFS/littlefs/) littlefs_fuse/littlefs
|
||||
|
@ -142,11 +143,10 @@ matrix:
|
|||
# Run local littlefs tests
|
||||
- CFLAGS="-Wno-format" make -C$LITTLEFS/littlefs test QUIET=1
|
||||
# Run local littlefs tests with set of variations
|
||||
- CFLAGS="-Wno-format -DLFS_READ_SIZE=64 -DLFS_PROG_SIZE=64" make -C$LITTLEFS/littlefs test QUIET=1
|
||||
- CFLAGS="-Wno-format -DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" make -C$LITTLEFS/littlefs test QUIET=1
|
||||
- CFLAGS="-Wno-format -DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" make -C$LITTLEFS/littlefs test QUIET=1
|
||||
- CFLAGS="-Wno-format -DLFS_BLOCK_COUNT=1023" make -C$LITTLEFS/littlefs test QUIET=1
|
||||
- CFLAGS="-Wno-format -DLFS_LOOKAHEAD=2048" make -C$LITTLEFS/littlefs test QUIET=1
|
||||
- CFLAGS="-Wno-format -DLFS_READ_SIZE=64 -DLFS_PROG_SIZE=64" make -C$LITTLEFS/littlefs test QUIET=1
|
||||
- CFLAGS="-Wno-format -DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" make -C$LITTLEFS/littlefs test QUIET=1
|
||||
- CFLAGS="-Wno-format -DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" make -C$LITTLEFS/littlefs test QUIET=1
|
||||
- CFLAGS="-Wno-format -DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048" make -C$LITTLEFS/littlefs test QUIET=1
|
||||
# Self-hosting littlefs fuzz test with littlefs-fuse
|
||||
- make -Clittlefs_fuse
|
||||
- littlefs_fuse/lfs --format /dev/loop0
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
|
||||
* Copyright (c) 2017, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
@ -16,41 +16,480 @@
|
|||
*/
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity/unity.h"
|
||||
#include "utest/utest.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
#include "rtos.h"
|
||||
#include "rtc_api.h"
|
||||
|
||||
#if !DEVICE_RTC
|
||||
#error [NOT_SUPPORTED] test not supported
|
||||
#endif
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
#define CUSTOM_TIME 1256729737
|
||||
/* On some boards RTC counter can not be
|
||||
* Initialised with 0 value in such case
|
||||
* drivers sets RTC counter to 1. */
|
||||
#define CUSTOM_TIME_0 1
|
||||
#define CUSTOM_TIME_1 1256729737
|
||||
#define CUSTOM_TIME_2 2147483637
|
||||
|
||||
void test_case_rtc_strftime() {
|
||||
greentea_send_kv("timestamp", CUSTOM_TIME);
|
||||
#define DELAY_10_SEC 10
|
||||
#define MS_PER_SEC 1000
|
||||
#define RTC_DELTA 1
|
||||
|
||||
char buffer[32] = {0};
|
||||
char kv_buff[64] = {0};
|
||||
set_time(CUSTOM_TIME); // Set RTC time to Wed, 28 Oct 2009 11:35:37
|
||||
static volatile int rtc_enabled_ret;
|
||||
static volatile time_t rtc_time_val;
|
||||
static volatile bool rtc_read_called;
|
||||
static volatile bool rtc_write_called;
|
||||
static volatile bool rtc_init_called;
|
||||
static volatile bool rtc_isenabled_called;
|
||||
|
||||
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);
|
||||
}
|
||||
/* Stub of RTC read function. */
|
||||
static time_t read_rtc_stub(void)
|
||||
{
|
||||
rtc_read_called = true;
|
||||
|
||||
return rtc_time_val;
|
||||
}
|
||||
|
||||
/* Stub of RTC write function. */
|
||||
static void write_rtc_stub(time_t t)
|
||||
{
|
||||
rtc_write_called = true;
|
||||
|
||||
rtc_time_val = t;
|
||||
}
|
||||
|
||||
/* Stub of RTC init function. */
|
||||
static void init_rtc_stub(void)
|
||||
{
|
||||
rtc_init_called = true;
|
||||
}
|
||||
|
||||
/* Stub of RTC isenabled function. */
|
||||
static int isenabled_rtc_stub(void)
|
||||
{
|
||||
rtc_isenabled_called = true;
|
||||
|
||||
return rtc_enabled_ret;
|
||||
}
|
||||
|
||||
/* This test verifies if attach_rtc provides availability to
|
||||
* connect specific RTC driver functions.
|
||||
*
|
||||
* This is unit test to verify if correct functions are used
|
||||
* to support RTC.
|
||||
*
|
||||
* Given specific RTC driver functions have been attached (stubs).
|
||||
* When set_time/time functions are called.
|
||||
* Then set_time/time functions use attached RTC functions.
|
||||
*/
|
||||
void test_attach_RTC_stub_funtions()
|
||||
{
|
||||
time_t seconds = 0;
|
||||
|
||||
/* Attache RTC read/write/init/isenabled stubs. */
|
||||
attach_rtc(read_rtc_stub, write_rtc_stub, init_rtc_stub, isenabled_rtc_stub);
|
||||
|
||||
/* Init stub variables/set to unexpected. */
|
||||
rtc_write_called = false;
|
||||
rtc_init_called = false;
|
||||
|
||||
/* Call set_time() function. We expect that init and write RTC stubs
|
||||
* will be executed.
|
||||
*/
|
||||
set_time(CUSTOM_TIME_1);
|
||||
|
||||
/* Verify results. */
|
||||
TEST_ASSERT_EQUAL(true, rtc_write_called);
|
||||
TEST_ASSERT_EQUAL(true, rtc_init_called);
|
||||
|
||||
/* Init stub variables/set to unexpected. */
|
||||
rtc_time_val = CUSTOM_TIME_1;
|
||||
rtc_enabled_ret = true;
|
||||
rtc_isenabled_called = false;
|
||||
rtc_read_called = false;
|
||||
|
||||
/* Call time() function. We expect that isenabled and read RTC stubs
|
||||
* are be executed.
|
||||
*/
|
||||
time(NULL);
|
||||
|
||||
/* Verify results. */
|
||||
TEST_ASSERT_EQUAL(true, rtc_isenabled_called);
|
||||
TEST_ASSERT_EQUAL(true, rtc_read_called);
|
||||
|
||||
/* This part of the test can be executed only on RTC devices. */
|
||||
|
||||
/* Restore env. */
|
||||
attach_rtc(rtc_read, rtc_write, rtc_init, rtc_isenabled);
|
||||
|
||||
/* Set to unexpected. */
|
||||
rtc_write_called = false;
|
||||
rtc_init_called = false;
|
||||
rtc_isenabled_called = false;
|
||||
rtc_init_called = false;
|
||||
|
||||
/* Set time. */
|
||||
set_time(CUSTOM_TIME_1);
|
||||
|
||||
/* Get time. */
|
||||
seconds = time(NULL);
|
||||
|
||||
/* Stub RTC functions should not be called now. */
|
||||
TEST_ASSERT_EQUAL(false, rtc_isenabled_called);
|
||||
TEST_ASSERT_EQUAL(false, rtc_init_called);
|
||||
TEST_ASSERT_EQUAL(false, rtc_write_called);
|
||||
TEST_ASSERT_EQUAL(false, rtc_init_called);
|
||||
|
||||
/* Check if time has been successfully set and retrieved. */
|
||||
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, seconds);
|
||||
}
|
||||
|
||||
/* This test verifies if attach_rtc provides availability to
|
||||
* connect specific RTC driver functions.
|
||||
*
|
||||
* This is unit test to verify if correct functions are used
|
||||
* to support RTC.
|
||||
*
|
||||
* Given specific RTC driver functions have been attached (original).
|
||||
* When set_time/time functions are called.
|
||||
* Then set_time/time functions use attached RTC functions.
|
||||
*/
|
||||
void test_attach_RTC_org_funtions()
|
||||
{
|
||||
time_t seconds = 0;
|
||||
|
||||
/* Attache original driver functions. */
|
||||
attach_rtc(rtc_read, rtc_write, rtc_init, rtc_isenabled);
|
||||
|
||||
/* Set to unexpected. */
|
||||
rtc_write_called = false;
|
||||
rtc_init_called = false;
|
||||
rtc_isenabled_called = false;
|
||||
rtc_init_called = false;
|
||||
|
||||
/* Set time. */
|
||||
set_time(CUSTOM_TIME_1);
|
||||
|
||||
/* Get time. */
|
||||
seconds = time(NULL);
|
||||
|
||||
/* Stub RTC functions should not be called now. */
|
||||
TEST_ASSERT_EQUAL(false, rtc_isenabled_called);
|
||||
TEST_ASSERT_EQUAL(false, rtc_init_called);
|
||||
TEST_ASSERT_EQUAL(false, rtc_write_called);
|
||||
TEST_ASSERT_EQUAL(false, rtc_init_called);
|
||||
|
||||
/* Check if time has been successfully set and retrieved. */
|
||||
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, seconds);
|
||||
}
|
||||
|
||||
/* This test verifies if time() function returns
|
||||
* current time when all RTC functions are
|
||||
* defined and RTC is enabled.
|
||||
*
|
||||
* Note: Stubs are used instead of original RTC functions.
|
||||
*
|
||||
* Given environment has RTC functions defined and RTC is enabled.
|
||||
* When time() functions is called.
|
||||
* Then current time is returned.
|
||||
*/
|
||||
void test_time_RTC_func_defined_RTC_is_enabled()
|
||||
{
|
||||
time_t seconds = 0;
|
||||
|
||||
/* Attache RTC read/write/init/isenabled stubs. */
|
||||
attach_rtc(read_rtc_stub, write_rtc_stub, init_rtc_stub, isenabled_rtc_stub);
|
||||
|
||||
/* Simulate that RTC is enabled. */
|
||||
rtc_enabled_ret = true;
|
||||
|
||||
/* Simulate current time. */
|
||||
rtc_time_val = CUSTOM_TIME_1;
|
||||
|
||||
/* Try to get current time. */
|
||||
seconds = time(NULL);
|
||||
|
||||
/* Check if expected value has been returned. */
|
||||
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, seconds);
|
||||
}
|
||||
|
||||
/* This test verifies if time() function resets time
|
||||
* when RTC functions are defined and RTC is disabled.
|
||||
*
|
||||
* Note: Stubs are used instead of original RTC functions.
|
||||
*
|
||||
* Given environment has RTC functions defined and RTC is disabled.
|
||||
* When time() functions is called.
|
||||
* Then function result is 0.
|
||||
*/
|
||||
void test_time_RTC_func_defined_RTC_is_disabled()
|
||||
{
|
||||
time_t seconds = 0;
|
||||
|
||||
/* Attache RTC read/write/init/isenabled stubs. */
|
||||
attach_rtc(read_rtc_stub, write_rtc_stub, init_rtc_stub, isenabled_rtc_stub);
|
||||
|
||||
/* Simulate that RTC is disabled. */
|
||||
rtc_enabled_ret = false;
|
||||
|
||||
/* Simulate current time. */
|
||||
rtc_time_val = CUSTOM_TIME_1;
|
||||
|
||||
/* Try to get current time. */
|
||||
seconds = time(NULL);
|
||||
|
||||
/* Check if expected value has been returned. */
|
||||
TEST_ASSERT_EQUAL(0, seconds);
|
||||
}
|
||||
|
||||
/* This test verifies if time() function can be successfully
|
||||
* executed when isenabled RTC function is undefined.
|
||||
*
|
||||
* Note: Stubs are used instead of original RTC functions.
|
||||
*
|
||||
* Given environment has isenabled RTC function undefined.
|
||||
* When time() functions is called.
|
||||
* Then current time is returned.
|
||||
*/
|
||||
void test_time_isenabled_RTC_func_undefined()
|
||||
{
|
||||
time_t seconds = 0;
|
||||
|
||||
/* Attache RTC read/write/init stubs. */
|
||||
attach_rtc(read_rtc_stub, write_rtc_stub, init_rtc_stub, NULL);
|
||||
|
||||
/* Simulate current time. */
|
||||
rtc_time_val = CUSTOM_TIME_1;
|
||||
|
||||
/* Try to get current time. */
|
||||
seconds = time(NULL);
|
||||
|
||||
/* Check if expected value has been returned. */
|
||||
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, seconds);
|
||||
}
|
||||
|
||||
/* This test verifies if time() function returns -1 if
|
||||
* read RTC function is undefined.
|
||||
*
|
||||
* Note: Stubs are used instead of original RTC functions.
|
||||
*
|
||||
* Given environment has read RTC function undefined.
|
||||
* When time() functions is called.
|
||||
* Then -1 is returned.
|
||||
*/
|
||||
void test_time_read_RTC_func_undefined()
|
||||
{
|
||||
time_t seconds = 0;
|
||||
|
||||
/* Attache RTC write/init/isenabled stubs. */
|
||||
attach_rtc(NULL, write_rtc_stub, init_rtc_stub, isenabled_rtc_stub);
|
||||
|
||||
/* Simulate current time. */
|
||||
rtc_time_val = CUSTOM_TIME_1;
|
||||
|
||||
/* Try to get current time. */
|
||||
seconds = time(NULL);
|
||||
|
||||
/* Check if expected value has been returned. */
|
||||
TEST_ASSERT_EQUAL((time_t)-1, seconds);
|
||||
}
|
||||
|
||||
/* This test verifies if time() function stores
|
||||
* the result in given time buffer (if specified).
|
||||
*
|
||||
* Note: Stubs are used instead original RTC functions.
|
||||
* Other test cases calls time() routine with
|
||||
* undefined time buffer.
|
||||
*
|
||||
* Given environment has all RTC function defined, RTC is enabled and time buffer is passed to time() function.
|
||||
* When time() functions is called.
|
||||
* Then current time is stored in the specified buffer.
|
||||
*/
|
||||
void test_time_called_with_param()
|
||||
{
|
||||
time_t seconds = 0;
|
||||
time_t buffer = 0;
|
||||
|
||||
/* Attache RTC read/write/init/isenabled stubs. */
|
||||
attach_rtc(read_rtc_stub, write_rtc_stub, init_rtc_stub, isenabled_rtc_stub);
|
||||
|
||||
/* Simulate that RTC is enabled. */
|
||||
rtc_enabled_ret = true;
|
||||
|
||||
/* Simulate current time. */
|
||||
rtc_time_val = CUSTOM_TIME_1;
|
||||
|
||||
/* Try to get current time. */
|
||||
seconds = time(&buffer);
|
||||
|
||||
/* Check if expected value has been returned. */
|
||||
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, seconds);
|
||||
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, buffer);
|
||||
}
|
||||
|
||||
/* This test verifies if set_time() function inits the RTC
|
||||
* and writes current time if RTC functions are defined.
|
||||
*
|
||||
* Note: Stubs are used instead of original RTC functions.
|
||||
*
|
||||
* Given environment has RTC functions defined.
|
||||
* When set_time() functions is called.
|
||||
* Then function initialises RTC and sets RTC time.
|
||||
*/
|
||||
void test_set_time_RTC_func_defined()
|
||||
{
|
||||
/* Attache RTC read/write/init/isenabled stubs. */
|
||||
attach_rtc(read_rtc_stub, write_rtc_stub, init_rtc_stub, isenabled_rtc_stub);
|
||||
|
||||
/* Set to unexpected. */
|
||||
rtc_time_val = 123;
|
||||
rtc_init_called = false;
|
||||
|
||||
/* Set current time. */
|
||||
rtc_time_val = 123;
|
||||
|
||||
/* Set new RTC time. */
|
||||
set_time(CUSTOM_TIME_1);
|
||||
|
||||
/* Check if RTC init has been performed and RTC time has been updated. */
|
||||
TEST_ASSERT_EQUAL(true, rtc_init_called);
|
||||
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, time(NULL));
|
||||
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, rtc_time_val);
|
||||
}
|
||||
|
||||
/* This test verifies if set_time() function can be
|
||||
* successfully executed when init RTC function is undefined.
|
||||
*
|
||||
* Note: Stubs are used instead of original RTC functions.
|
||||
*
|
||||
* Given environment has init RTC function undefined.
|
||||
* When set_time() functions is called.
|
||||
* Then function sets RTC time.
|
||||
*/
|
||||
void test_set_time_init_RTC_func_undefined()
|
||||
{
|
||||
/* Attache RTC read/write/isenabled stubs. */
|
||||
attach_rtc(read_rtc_stub, write_rtc_stub, NULL, isenabled_rtc_stub);
|
||||
|
||||
/* Set to unexpected. */
|
||||
rtc_time_val = 123;
|
||||
|
||||
/* Set new RTC time. */
|
||||
set_time(CUSTOM_TIME_1);
|
||||
|
||||
/* Check if RTC time has been updated. */
|
||||
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, time(NULL));
|
||||
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, rtc_time_val);
|
||||
}
|
||||
|
||||
/* This test verifies if set_time() function can be
|
||||
* successfully executed when write RTC function is undefined.
|
||||
*
|
||||
* Note: Stubs are used instead original RTC functions.
|
||||
*
|
||||
* Given environemt has write RTC function undefined.
|
||||
* When set_time() function is called.
|
||||
* Then function inits RTC and does not modify RTC time.
|
||||
*/
|
||||
void test_set_time_write_RTC_func_undefined()
|
||||
{
|
||||
/* Attache RTC read/write/init/isenabled stubs. */
|
||||
attach_rtc(read_rtc_stub, NULL, init_rtc_stub, isenabled_rtc_stub);
|
||||
|
||||
/* Set to unexpected. */
|
||||
rtc_time_val = 123;
|
||||
rtc_init_called = false;
|
||||
|
||||
/* Set new RTC time. */
|
||||
set_time(CUSTOM_TIME_1);
|
||||
|
||||
/* Check if RTC has been initialized and RTC time has not been updated. */
|
||||
TEST_ASSERT_EQUAL(true, rtc_init_called);
|
||||
TEST_ASSERT_EQUAL(123, time(NULL));
|
||||
TEST_ASSERT_EQUAL(123, rtc_time_val);
|
||||
}
|
||||
|
||||
/* This test verifies if RTC time can be successfully set.
|
||||
*
|
||||
* Note: Original RTC functions are used in this test.
|
||||
*
|
||||
* Given environment has RTC available.
|
||||
* When set_time() functions is called.
|
||||
* Then RTC time is retrieved.
|
||||
*/
|
||||
template<uint32_t timeValue>
|
||||
void test_functional_set()
|
||||
{
|
||||
/* Set original RTC functions. */
|
||||
attach_rtc(rtc_read, rtc_write, rtc_init, rtc_isenabled);
|
||||
|
||||
/* Set new RTC time. */
|
||||
set_time(timeValue);
|
||||
|
||||
/* Get current time and verify that new value has been set. */
|
||||
TEST_ASSERT_EQUAL(timeValue, time(NULL));
|
||||
}
|
||||
|
||||
/* This test verifies if RTC counts seconds.
|
||||
*
|
||||
* Note: Original RTC functions are used in this test.
|
||||
*
|
||||
* Given RTC has time set.
|
||||
* When some time has passed (seconds).
|
||||
* Then RTC time is updated.
|
||||
*/
|
||||
void test_functional_count()
|
||||
{
|
||||
time_t seconds = 0;
|
||||
|
||||
/* Set original RTC functions. */
|
||||
attach_rtc(rtc_read, rtc_write, rtc_init, rtc_isenabled);
|
||||
|
||||
/* Set new RTC time. */
|
||||
set_time(CUSTOM_TIME_2);
|
||||
|
||||
/* Wait 10 sec. */
|
||||
wait_ms(DELAY_10_SEC * MS_PER_SEC);
|
||||
|
||||
/* Get time. */
|
||||
seconds = time(NULL);
|
||||
|
||||
/* Verify that RTC counts seconds. */
|
||||
TEST_ASSERT_UINT_WITHIN(RTC_DELTA, (unsigned int)seconds, CUSTOM_TIME_2 + DELAY_10_SEC);
|
||||
}
|
||||
|
||||
utest::v1::status_t test_setup(const size_t number_of_cases)
|
||||
{
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
return verbose_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("RTC strftime", test_case_rtc_strftime),
|
||||
Case("Unit Test: attach stub RTC functions.", test_attach_RTC_stub_funtions),
|
||||
Case("Unit Test: attach original RTC functions.", test_attach_RTC_org_funtions),
|
||||
|
||||
Case("Unit Test: time() - RTC functions are defined, RTC is enabled.", test_time_RTC_func_defined_RTC_is_enabled),
|
||||
Case("Unit Test: time() - RTC functions are defined, RTC is disabled.", test_time_RTC_func_defined_RTC_is_disabled),
|
||||
Case("Unit Test: time() - isenabled RTC function is undefined.", test_time_isenabled_RTC_func_undefined),
|
||||
Case("Unit Test: time() - read RTC function is undefined.", test_time_read_RTC_func_undefined),
|
||||
Case("Unit Test: time() - result is stored in given buffer.", test_time_called_with_param),
|
||||
|
||||
Case("Unit Test: set_time() - RTC functions are defined.", test_set_time_RTC_func_defined),
|
||||
Case("Unit Test: set_time() - init RTC function is undefined.", test_set_time_init_RTC_func_undefined),
|
||||
Case("Unit Test: set_time() - write RTC function is undefined.", test_set_time_write_RTC_func_undefined),
|
||||
|
||||
Case("Functional Test: set time - CUSTOM_TIME_0.", test_functional_set<CUSTOM_TIME_0>),
|
||||
Case("Functional Test: set time - CUSTOM_TIME_1.", test_functional_set<CUSTOM_TIME_1>),
|
||||
Case("Functional Test: set time - CUSTOM_TIME_2.", test_functional_set<CUSTOM_TIME_2>),
|
||||
|
||||
Case("Functional Test: RTC counts seconds.", test_functional_count),
|
||||
};
|
||||
|
||||
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);
|
||||
Specification specification(test_setup, cases);
|
||||
|
||||
int main() {
|
||||
Harness::run(specification);
|
||||
return !Harness::run(specification);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
using namespace utest::v1;
|
||||
|
||||
#define TEST_CYCLES 1000000
|
||||
#define ALLOWED_DRIFT_PPM 1000 //0.1%
|
||||
#define ALLOWED_DRIFT_PPM 5000 //0.5%
|
||||
|
||||
/*
|
||||
return values to be checked are documented at:
|
||||
|
|
|
@ -28,13 +28,13 @@
|
|||
|
||||
using namespace utest::v1;
|
||||
|
||||
#ifndef MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE
|
||||
#define MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE 256
|
||||
#ifndef MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE
|
||||
#define MBED_CONF_APP_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};
|
||||
char tx_buffer[MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0};
|
||||
char rx_buffer[MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0};
|
||||
}
|
||||
|
||||
void prep_buffer(char *tx_buffer, size_t tx_size) {
|
||||
|
@ -44,7 +44,7 @@ void prep_buffer(char *tx_buffer, size_t tx_size) {
|
|||
}
|
||||
|
||||
void test_tcp_echo() {
|
||||
|
||||
int n = 0;
|
||||
NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION;
|
||||
int err = MBED_CONF_APP_CONNECT_STATEMENT;
|
||||
|
||||
|
@ -86,7 +86,12 @@ void test_tcp_echo() {
|
|||
|
||||
prep_buffer(tx_buffer, sizeof(tx_buffer));
|
||||
#if defined(MBED_CONF_APP_TCP_ECHO_PREFIX)
|
||||
sock.recv(rx_buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX));
|
||||
n = sock.recv(rx_buffer, sizeof(MBED_CONF_APP_TCP_ECHO_PREFIX));
|
||||
if (n >= 0) {
|
||||
printf("recv-ed prefix: %d bytes - %.*s \n", n, n, rx_buffer);
|
||||
} else {
|
||||
printf("Network error in receiving prefix: %d\n", n);
|
||||
}
|
||||
#endif /* MBED_CONF_APP_TCP_ECHO_PREFIX */
|
||||
const int ret = sock.send(tx_buffer, sizeof(tx_buffer));
|
||||
if (ret >= 0) {
|
||||
|
@ -95,7 +100,7 @@ void test_tcp_echo() {
|
|||
printf("Network error %d\n", ret);
|
||||
}
|
||||
|
||||
int n = sock.recv(rx_buffer, sizeof(rx_buffer));
|
||||
n = sock.recv(rx_buffer, sizeof(rx_buffer));
|
||||
if (n >= 0) {
|
||||
printf("recv %d bytes - %.*s \n", n, n, rx_buffer);
|
||||
} else {
|
||||
|
|
|
@ -76,9 +76,15 @@ void test_tcp_hello_world() {
|
|||
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';
|
||||
int ret = 0;
|
||||
int bytes_recvd = 0;
|
||||
|
||||
do {
|
||||
ret += bytes_recvd;
|
||||
bytes_recvd = sock.recv(buffer+ret, sizeof(buffer) - 1 - ret);
|
||||
}while(bytes_recvd > 0);
|
||||
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
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <new>
|
||||
#include "EventQueue.h"
|
||||
#include "ble/BLEInstanceBase.h"
|
||||
#include "BLE/ble.h"
|
||||
#include "ble/BLE.h"
|
||||
|
||||
namespace ble {
|
||||
namespace pal {
|
||||
|
|
|
@ -210,6 +210,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
|
|||
bool has_variable_len,
|
||||
const uint8_t *userDescriptionDescriptorValuePtr,
|
||||
uint16_t userDescriptionDescriptorValueLen,
|
||||
const uint8_t *presentationFormatDescriptorValuePtr,
|
||||
uint16_t presentationFormatDescriptorValueLen,
|
||||
bool readAuthorization,
|
||||
bool writeAuthorization,
|
||||
ble_gatts_char_handles_t *p_char_handle)
|
||||
|
@ -238,6 +240,11 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
|
|||
char_md.char_user_desc_max_size = userDescriptionDescriptorValueLen;
|
||||
char_md.char_user_desc_size = userDescriptionDescriptorValueLen;
|
||||
}
|
||||
if ((presentationFormatDescriptorValueLen > 0) && (presentationFormatDescriptorValuePtr != NULL)) {
|
||||
ASSERT_TRUE( sizeof(ble_gatts_char_pf_t) == sizeof(GattCharacteristic::PresentationFormat_t), ERROR_INVALID_PARAM );
|
||||
ASSERT_TRUE( presentationFormatDescriptorValueLen == sizeof(GattCharacteristic::PresentationFormat_t), ERROR_INVALID_PARAM );
|
||||
char_md.p_char_pf = const_cast<ble_gatts_char_pf_t *>(reinterpret_cast<const ble_gatts_char_pf_t *>(presentationFormatDescriptorValuePtr));
|
||||
}
|
||||
|
||||
/* Attribute declaration */
|
||||
ble_gatts_attr_md_t attr_md = {0};
|
||||
|
|
|
@ -52,6 +52,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
|
|||
bool has_variable_len,
|
||||
const uint8_t *userDescriptionDescriptorValuePtr,
|
||||
uint16_t userDescriptionDescriptorValueLen,
|
||||
const uint8_t *presentationFormatDescriptorValuePtr,
|
||||
uint16_t presentationFormatDescriptorValueLen,
|
||||
bool readAuthorization,
|
||||
bool writeAuthorization,
|
||||
ble_gatts_char_handles_t *p_char_handle);
|
||||
|
|
|
@ -131,6 +131,7 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
|
|||
}
|
||||
GattCharacteristic *p_char = service.getCharacteristic(i);
|
||||
GattAttribute *p_description_descriptor = NULL;
|
||||
GattAttribute *p_presentation_format_descriptor = NULL;
|
||||
|
||||
/* Skip any incompletely defined, read-only characteristics. */
|
||||
if ((p_char->getValueAttribute().getValuePtr() == NULL) &&
|
||||
|
@ -141,11 +142,13 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
|
|||
|
||||
nordicUUID = custom_convert_to_nordic_uuid(p_char->getValueAttribute().getUUID());
|
||||
|
||||
/* The user-description descriptor is a special case which needs to be
|
||||
* handled at the time of adding the characteristic. The following block
|
||||
* is meant to discover its presence. */
|
||||
/* The user-description and presentation-format descriptors are special cases
|
||||
* that need to be handled at the time of adding each characteristic. The
|
||||
* following block is meant to discover their presence. */
|
||||
const uint8_t *userDescriptionDescriptorValuePtr = NULL;
|
||||
uint16_t userDescriptionDescriptorValueLen = 0;
|
||||
const uint8_t *presentationFormatDescriptorValuePtr = NULL;
|
||||
uint16_t presentationFormatDescriptorValueLen = 0;
|
||||
for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) {
|
||||
GattAttribute *p_desc = p_char->getDescriptor(j);
|
||||
if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) {
|
||||
|
@ -153,6 +156,11 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
|
|||
userDescriptionDescriptorValuePtr = p_desc->getValuePtr();
|
||||
userDescriptionDescriptorValueLen = p_desc->getLength();
|
||||
}
|
||||
if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_PRESENTATION_FORMAT) {
|
||||
p_presentation_format_descriptor = p_desc;
|
||||
presentationFormatDescriptorValuePtr = p_desc->getValuePtr();
|
||||
presentationFormatDescriptorValueLen = p_desc->getLength();
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_TRUE ( ERROR_NONE ==
|
||||
|
@ -166,6 +174,8 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
|
|||
p_char->getValueAttribute().hasVariableLength(),
|
||||
userDescriptionDescriptorValuePtr,
|
||||
userDescriptionDescriptorValueLen,
|
||||
presentationFormatDescriptorValuePtr,
|
||||
presentationFormatDescriptorValueLen,
|
||||
p_char->isReadAuthorizationEnabled(),
|
||||
p_char->isWriteAuthorizationEnabled(),
|
||||
&nrfCharacteristicHandles[characteristicCount]),
|
||||
|
@ -179,6 +189,10 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
|
|||
nrfCharacteristicHandles[characteristicCount].user_desc_handle
|
||||
);
|
||||
}
|
||||
if (p_presentation_format_descriptor) {
|
||||
// The handle is not available from the SoftDevice
|
||||
p_presentation_format_descriptor->setHandle(GattAttribute::INVALID_HANDLE);
|
||||
}
|
||||
characteristicCount++;
|
||||
|
||||
/* Add optional descriptors if any */
|
||||
|
@ -188,8 +202,10 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
|
|||
}
|
||||
|
||||
GattAttribute *p_desc = p_char->getDescriptor(j);
|
||||
/* skip the user-description-descriptor here; this has already been handled when adding the characteristic (above). */
|
||||
if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) {
|
||||
/* skip the user-description or presentation-format descriptor here;
|
||||
* they have already been handled when adding the characteristic (above). */
|
||||
if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC
|
||||
|| p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_PRESENTATION_FORMAT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
# Change Log
|
||||
|
||||
## [v4.1.1](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.1.1)
|
||||
**Closed issues:**
|
||||
- IOTCLT-2203 mbed-coap does not handle PUT or POST if they indicate a smaller block size preference (fixed regression)
|
||||
|
||||
-[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.1.0...v4.1.1)
|
||||
|
||||
## [v4.1.0](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.1.0)
|
||||
|
||||
-[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.0.10...v4.1.0)
|
||||
|
||||
**New feature:**
|
||||
- New API to disable automatic GET(BLOCK2) request sending.
|
||||
|
||||
**Closed issues:**
|
||||
- IOTCLT-2203 mbed-coap does not handle PUT or POST if they indicate a smaller block size preference
|
||||
|
||||
## [v4.0.10](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.0.10)
|
||||
|
||||
-[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.0.9...v4.0.10)
|
||||
|
|
|
@ -213,6 +213,29 @@ extern void sn_coap_protocol_block_remove(struct coap_s *handle, sn_nsdl_addr_s
|
|||
*/
|
||||
extern int8_t sn_coap_protocol_delete_retransmission(struct coap_s *handle, uint16_t msg_id);
|
||||
|
||||
/**
|
||||
* \fn int8_t sn_coap_convert_block_size(uint16_t block_size)
|
||||
*
|
||||
* \brief Utility function to convert block size.
|
||||
*
|
||||
* \param block_size Block size to convert.
|
||||
*
|
||||
* \return Value of range 0 - 6
|
||||
*/
|
||||
extern int8_t sn_coap_convert_block_size(uint16_t block_size);
|
||||
|
||||
/**
|
||||
* \fn int8_t sn_coap_protocol_handle_block2_response_internally(struct coap_s *handle, uint8_t handle_response)
|
||||
*
|
||||
* \brief This function change the state whether CoAP library sends the block 2 response automatically or not.
|
||||
*
|
||||
* \param *handle Pointer to CoAP library handle
|
||||
* \param handle_response 1 if CoAP library handles the response sending otherwise 0.
|
||||
*
|
||||
* \return 0 = success, -1 = failure
|
||||
*/
|
||||
extern int8_t sn_coap_protocol_handle_block2_response_internally(struct coap_s *handle, uint8_t handle_response);
|
||||
|
||||
#endif /* SN_COAP_PROTOCOL_H_ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "mbed-coap",
|
||||
"version": "4.0.10",
|
||||
"version": "4.1.1",
|
||||
"description": "COAP library",
|
||||
"keywords": [
|
||||
"coap",
|
||||
|
|
|
@ -229,6 +229,7 @@ struct coap_s {
|
|||
uint8_t sn_coap_resending_count;
|
||||
uint8_t sn_coap_resending_intervall;
|
||||
uint8_t sn_coap_duplication_buffer_size;
|
||||
uint8_t sn_coap_internal_block2_resp_handling; /* If this is set then coap itself sends a next GET request automatically */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -63,18 +63,22 @@ sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
|
||||
if (msg_code == COAP_MSG_CODE_REQUEST_GET) {
|
||||
// Blockwise message response is new GET
|
||||
coap_res_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
|
||||
coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
|
||||
/* msg_id needs to be set by the caller in this case */
|
||||
}
|
||||
else if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
|
||||
coap_res_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
|
||||
coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
|
||||
coap_res_ptr->msg_id = coap_packet_ptr->msg_id;
|
||||
}
|
||||
|
||||
else if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE) {
|
||||
coap_res_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE;
|
||||
coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
|
||||
/* msg_id needs to be set by the caller in this case */
|
||||
}
|
||||
|
||||
else {
|
||||
handle->sn_coap_protocol_free( coap_res_ptr );
|
||||
return NULL;
|
||||
|
|
|
@ -64,7 +64,6 @@ static void sn_coap_protocol_linked_list_blockwise_payload_remo
|
|||
static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr);
|
||||
static void sn_coap_protocol_linked_list_blockwise_remove_old_data(struct coap_s *handle);
|
||||
static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr, void *param);
|
||||
static int8_t sn_coap_convert_block_size(uint16_t block_size);
|
||||
static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, sn_coap_hdr_s *source_header_ptr);
|
||||
#endif
|
||||
#if ENABLE_RESENDINGS
|
||||
|
@ -182,10 +181,10 @@ struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), vo
|
|||
/* If pointer = 0, then re-sending does not return error when failed */
|
||||
handle->sn_coap_rx_callback = used_rx_callback_ptr;
|
||||
|
||||
|
||||
// Handles internally all GET req responses
|
||||
handle->sn_coap_internal_block2_resp_handling = true;
|
||||
|
||||
#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */
|
||||
|
||||
/* * * * Create Linked list for storing active resending messages * * * */
|
||||
ns_list_init(&handle->linked_list_resent_msgs);
|
||||
handle->sn_coap_resending_queue_msgs = SN_COAP_RESENDING_QUEUE_SIZE_MSGS;
|
||||
|
@ -220,6 +219,16 @@ struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), vo
|
|||
return handle;
|
||||
}
|
||||
|
||||
int8_t sn_coap_protocol_handle_block2_response_internally(struct coap_s *handle, uint8_t build_response)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle->sn_coap_internal_block2_resp_handling = build_response;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size)
|
||||
{
|
||||
(void) handle;
|
||||
|
@ -1730,17 +1739,9 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Response with COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE if the payload size is more than we can handle
|
||||
|
||||
uint32_t max_size = SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE;
|
||||
if (!blocks_in_order) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE!");
|
||||
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE;
|
||||
} else if (received_coap_msg_ptr->options_list_ptr->size1 > max_size) {
|
||||
// Include maximum size that stack can handle into response
|
||||
tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE!");
|
||||
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr->size1 = max_size;
|
||||
} else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) {
|
||||
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
|
||||
} else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) {
|
||||
|
@ -1751,14 +1752,31 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
|
|||
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_DELETED;
|
||||
}
|
||||
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = received_coap_msg_ptr->options_list_ptr->block1;
|
||||
src_coap_blockwise_ack_msg_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
|
||||
// Response with COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE if the payload size is more than we can handle
|
||||
if (received_coap_msg_ptr->options_list_ptr->size1 > SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE) {
|
||||
// Include maximum size that stack can handle into response
|
||||
tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE!");
|
||||
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
|
||||
}
|
||||
else {
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = received_coap_msg_ptr->options_list_ptr->block1;
|
||||
src_coap_blockwise_ack_msg_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
|
||||
|
||||
/* Check block size */
|
||||
block_temp = (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 & 0x07);
|
||||
if (block_temp > sn_coap_convert_block_size(handle->sn_coap_block_data_size)) {
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 &= 0xFFFFF8;
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size);
|
||||
/* Check block size */
|
||||
block_temp = (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 & 0x07);
|
||||
uint16_t block_size = 1u << (block_temp + 4);
|
||||
if (block_size > handle->sn_coap_block_data_size) {
|
||||
// Include maximum size that stack can handle into response
|
||||
tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE!");
|
||||
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr->size1 = handle->sn_coap_block_data_size;
|
||||
sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle);
|
||||
}
|
||||
|
||||
if (block_temp > sn_coap_convert_block_size(handle->sn_coap_block_data_size)) {
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 &= 0xFFFFF8;
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size);
|
||||
}
|
||||
}
|
||||
|
||||
src_coap_blockwise_ack_msg_ptr->msg_id = received_coap_msg_ptr->msg_id;
|
||||
|
@ -1832,178 +1850,204 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
|
|||
else {
|
||||
//This is response to request we made
|
||||
if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) {
|
||||
uint32_t block_number = 0;
|
||||
if (handle->sn_coap_internal_block2_resp_handling) {
|
||||
uint32_t block_number = 0;
|
||||
|
||||
/* Store blockwise payload to Linked list */
|
||||
//todo: add block number to stored values - just to make sure all packets are in order
|
||||
sn_coap_protocol_linked_list_blockwise_payload_store(handle,
|
||||
src_addr_ptr,
|
||||
received_coap_msg_ptr->payload_len,
|
||||
received_coap_msg_ptr->payload_ptr,
|
||||
received_coap_msg_ptr->options_list_ptr->block1 >> 4);
|
||||
/* Store blockwise payload to Linked list */
|
||||
//todo: add block number to stored values - just to make sure all packets are in order
|
||||
sn_coap_protocol_linked_list_blockwise_payload_store(handle,
|
||||
src_addr_ptr,
|
||||
received_coap_msg_ptr->payload_len,
|
||||
received_coap_msg_ptr->payload_ptr,
|
||||
received_coap_msg_ptr->options_list_ptr->block2 >> 4);
|
||||
/* If not last block (more value is set) */
|
||||
if (received_coap_msg_ptr->options_list_ptr->block2 & 0x08) {
|
||||
coap_blockwise_msg_s *previous_blockwise_msg_ptr = NULL;
|
||||
//build and send ack
|
||||
received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING;
|
||||
|
||||
/* If not last block (more value is set) */
|
||||
if (received_coap_msg_ptr->options_list_ptr->block2 & 0x08) {
|
||||
coap_blockwise_msg_s *previous_blockwise_msg_ptr = NULL;
|
||||
//build and send ack
|
||||
received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING;
|
||||
|
||||
ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) {
|
||||
if (received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) {
|
||||
previous_blockwise_msg_ptr = msg;
|
||||
break;
|
||||
ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) {
|
||||
if (received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) {
|
||||
previous_blockwise_msg_ptr = msg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!previous_blockwise_msg_ptr || !previous_blockwise_msg_ptr->coap_msg_ptr) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) previous message null!");
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
src_coap_blockwise_ack_msg_ptr = sn_coap_parser_alloc_message(handle);
|
||||
if (src_coap_blockwise_ack_msg_ptr == NULL) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate message!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ns_list_remove(&handle->linked_list_blockwise_sent_msgs, previous_blockwise_msg_ptr);
|
||||
if( previous_blockwise_msg_ptr->coap_msg_ptr ){
|
||||
if(previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr){
|
||||
handle->sn_coap_protocol_free(previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr);
|
||||
previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr = 0;
|
||||
if (!previous_blockwise_msg_ptr || !previous_blockwise_msg_ptr->coap_msg_ptr) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) previous message null!");
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
|
||||
return 0;
|
||||
}
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, previous_blockwise_msg_ptr->coap_msg_ptr);
|
||||
previous_blockwise_msg_ptr->coap_msg_ptr = 0;
|
||||
}
|
||||
handle->sn_coap_protocol_free(previous_blockwise_msg_ptr);
|
||||
previous_blockwise_msg_ptr = 0;
|
||||
|
||||
/* * * Then build CoAP Acknowledgement message * * */
|
||||
src_coap_blockwise_ack_msg_ptr = sn_coap_parser_alloc_message(handle);
|
||||
if (src_coap_blockwise_ack_msg_ptr == NULL) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate message!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate options!");
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr = 0;
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
|
||||
return NULL;
|
||||
}
|
||||
/* * * Then build CoAP Acknowledgement message * * */
|
||||
|
||||
src_coap_blockwise_ack_msg_ptr->msg_id = message_id++;
|
||||
if (message_id == 0) {
|
||||
message_id = 1;
|
||||
}
|
||||
if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate options!");
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr = 0;
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Update block option */
|
||||
block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07;
|
||||
src_coap_blockwise_ack_msg_ptr->msg_id = message_id++;
|
||||
if (message_id == 0) {
|
||||
message_id = 1;
|
||||
}
|
||||
|
||||
block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4;
|
||||
block_number ++;
|
||||
/* Update block option */
|
||||
block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07;
|
||||
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = (block_number << 4) | block_temp;
|
||||
block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4;
|
||||
block_number ++;
|
||||
|
||||
/* Then get needed memory count for Packet data */
|
||||
dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr ,handle->sn_coap_block_data_size);
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = (block_number << 4) | block_temp;
|
||||
|
||||
/* Then allocate memory for Packet data */
|
||||
dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem);
|
||||
|
||||
if (dst_ack_packet_data_ptr == NULL) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate packet!");
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr = 0;
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
|
||||
return NULL;
|
||||
}
|
||||
memset(dst_ack_packet_data_ptr, 0, dst_packed_data_needed_mem);
|
||||
/* Set BLOCK2 (subsequent) GET msg code and copy uri path from previous msg*/
|
||||
if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CONTENT) {
|
||||
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_REQUEST_GET;
|
||||
if (previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_ptr) {
|
||||
src_coap_blockwise_ack_msg_ptr->uri_path_len = previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len;
|
||||
src_coap_blockwise_ack_msg_ptr->uri_path_ptr = handle->sn_coap_protocol_malloc(previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len);
|
||||
if (!src_coap_blockwise_ack_msg_ptr->uri_path_ptr) {
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
|
||||
tr_error("sn_coap_handle_blockwise_message - failed to allocate for uri path ptr!");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(src_coap_blockwise_ack_msg_ptr->uri_path_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len);
|
||||
}
|
||||
if (previous_blockwise_msg_ptr->coap_msg_ptr->token_ptr) {
|
||||
src_coap_blockwise_ack_msg_ptr->token_len = previous_blockwise_msg_ptr->coap_msg_ptr->token_len;
|
||||
src_coap_blockwise_ack_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(previous_blockwise_msg_ptr->coap_msg_ptr->token_len);
|
||||
if (!src_coap_blockwise_ack_msg_ptr->token_ptr) {
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
|
||||
tr_error("sn_coap_handle_blockwise_message - failed to allocate for token ptr!");
|
||||
return NULL;
|
||||
}
|
||||
memcpy(src_coap_blockwise_ack_msg_ptr->token_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->token_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->token_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* * * Then build Acknowledgement message to Packed data * * */
|
||||
if ((sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size)) < 0) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) builder failed!");
|
||||
ns_list_remove(&handle->linked_list_blockwise_sent_msgs, previous_blockwise_msg_ptr);
|
||||
if (previous_blockwise_msg_ptr->coap_msg_ptr) {
|
||||
if (previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr) {
|
||||
handle->sn_coap_protocol_free(previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr);
|
||||
previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr = 0;
|
||||
}
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, previous_blockwise_msg_ptr->coap_msg_ptr);
|
||||
previous_blockwise_msg_ptr->coap_msg_ptr = 0;
|
||||
}
|
||||
handle->sn_coap_protocol_free(previous_blockwise_msg_ptr);
|
||||
previous_blockwise_msg_ptr = 0;
|
||||
|
||||
/* Then get needed memory count for Packet data */
|
||||
dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr ,handle->sn_coap_block_data_size);
|
||||
|
||||
/* Then allocate memory for Packet data */
|
||||
dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem);
|
||||
|
||||
if (dst_ack_packet_data_ptr == NULL) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate packet!");
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr = 0;
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
|
||||
return NULL;
|
||||
}
|
||||
memset(dst_ack_packet_data_ptr, 0, dst_packed_data_needed_mem);
|
||||
|
||||
/* * * Then build Acknowledgement message to Packed data * * */
|
||||
if ((sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size)) < 0) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) builder failed!");
|
||||
handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
|
||||
dst_ack_packet_data_ptr = 0;
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr = 0;
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* * * Save to linked list * * */
|
||||
coap_blockwise_msg_s *stored_blockwise_msg_ptr;
|
||||
|
||||
stored_blockwise_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_msg_s));
|
||||
if (!stored_blockwise_msg_ptr) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate blockwise message!");
|
||||
handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
|
||||
dst_ack_packet_data_ptr = 0;
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr = 0;
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
|
||||
return 0;
|
||||
}
|
||||
memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s));
|
||||
|
||||
stored_blockwise_msg_ptr->timestamp = handle->system_time;
|
||||
|
||||
stored_blockwise_msg_ptr->coap_msg_ptr = src_coap_blockwise_ack_msg_ptr;
|
||||
stored_blockwise_msg_ptr->coap = handle;
|
||||
ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr);
|
||||
|
||||
/* * * Then release memory of CoAP Acknowledgement message * * */
|
||||
handle->sn_coap_tx_callback(dst_ack_packet_data_ptr,
|
||||
dst_packed_data_needed_mem, src_addr_ptr, param);
|
||||
|
||||
#if ENABLE_RESENDINGS
|
||||
uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0);
|
||||
sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr,
|
||||
dst_packed_data_needed_mem,
|
||||
dst_ack_packet_data_ptr,
|
||||
resend_time, param);
|
||||
#endif
|
||||
handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
|
||||
dst_ack_packet_data_ptr = 0;
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr = 0;
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* * * Save to linked list * * */
|
||||
coap_blockwise_msg_s *stored_blockwise_msg_ptr;
|
||||
//Last block received
|
||||
else {
|
||||
/* * * This is the last block when whole Blockwise payload from received * * */
|
||||
/* * * blockwise messages is gathered and returned to User * * */
|
||||
|
||||
stored_blockwise_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_msg_s));
|
||||
if (!stored_blockwise_msg_ptr) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate blockwise message!");
|
||||
handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
|
||||
dst_ack_packet_data_ptr = 0;
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
|
||||
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
|
||||
src_coap_blockwise_ack_msg_ptr = 0;
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
|
||||
return 0;
|
||||
/* Store last Blockwise payload to Linked list */
|
||||
uint16_t payload_len = 0;
|
||||
uint8_t *payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len);
|
||||
uint16_t whole_payload_len = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr);
|
||||
uint8_t *temp_whole_payload_ptr = NULL;
|
||||
|
||||
temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len);
|
||||
if (!temp_whole_payload_ptr) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate whole payload!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
received_coap_msg_ptr->payload_ptr = temp_whole_payload_ptr;
|
||||
received_coap_msg_ptr->payload_len = whole_payload_len;
|
||||
|
||||
/* Copy stored Blockwise payloads to returned whole Blockwise payload pointer */
|
||||
while (payload_ptr != NULL) {
|
||||
memcpy(temp_whole_payload_ptr, payload_ptr, payload_len);
|
||||
|
||||
temp_whole_payload_ptr += payload_len;
|
||||
|
||||
sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle);
|
||||
payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len);
|
||||
}
|
||||
received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED;
|
||||
|
||||
//todo: remove previous msg from list
|
||||
}
|
||||
memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s));
|
||||
|
||||
stored_blockwise_msg_ptr->timestamp = handle->system_time;
|
||||
|
||||
stored_blockwise_msg_ptr->coap_msg_ptr = src_coap_blockwise_ack_msg_ptr;
|
||||
stored_blockwise_msg_ptr->coap = handle;
|
||||
ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr);
|
||||
|
||||
/* * * Then release memory of CoAP Acknowledgement message * * */
|
||||
handle->sn_coap_tx_callback(dst_ack_packet_data_ptr,
|
||||
dst_packed_data_needed_mem, src_addr_ptr, param);
|
||||
|
||||
#if ENABLE_RESENDINGS
|
||||
uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0);
|
||||
sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr,
|
||||
dst_packed_data_needed_mem,
|
||||
dst_ack_packet_data_ptr,
|
||||
resend_time, param);
|
||||
#endif
|
||||
handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
|
||||
dst_ack_packet_data_ptr = 0;
|
||||
}
|
||||
|
||||
//Last block received
|
||||
else {
|
||||
/* * * This is the last block when whole Blockwise payload from received * * */
|
||||
/* * * blockwise messages is gathered and returned to User * * */
|
||||
|
||||
/* Store last Blockwise payload to Linked list */
|
||||
uint16_t payload_len = 0;
|
||||
uint8_t *payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len);
|
||||
uint16_t whole_payload_len = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr);
|
||||
uint8_t *temp_whole_payload_ptr = NULL;
|
||||
|
||||
temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len);
|
||||
if (!temp_whole_payload_ptr) {
|
||||
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate whole payload!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
received_coap_msg_ptr->payload_ptr = temp_whole_payload_ptr;
|
||||
received_coap_msg_ptr->payload_len = whole_payload_len;
|
||||
|
||||
/* Copy stored Blockwise payloads to returned whole Blockwise payload pointer */
|
||||
while (payload_ptr != NULL) {
|
||||
memcpy(temp_whole_payload_ptr, payload_ptr, payload_len);
|
||||
|
||||
temp_whole_payload_ptr += payload_len;
|
||||
|
||||
sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle);
|
||||
payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len);
|
||||
}
|
||||
received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED;
|
||||
|
||||
//todo: remove previous msg from list
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Now we send data to request
|
||||
|
@ -2108,7 +2152,7 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
|
|||
return received_coap_msg_ptr;
|
||||
}
|
||||
|
||||
static int8_t sn_coap_convert_block_size(uint16_t block_size)
|
||||
int8_t sn_coap_convert_block_size(uint16_t block_size)
|
||||
{
|
||||
if (block_size == 16) {
|
||||
return 0;
|
||||
|
|
|
@ -23,4 +23,11 @@
|
|||
|
||||
#define MEM_SIZE (1600 * 16)
|
||||
|
||||
#define MEMP_NUM_TCP_SEG 32
|
||||
#define TCP_MSS 1460
|
||||
#define PBUF_POOL_SIZE 16
|
||||
#define TCP_SND_BUF (8 * TCP_MSS)
|
||||
#define TCP_WND (TCP_MSS * 8)
|
||||
#define PBUF_POOL_BUFSIZE 1600
|
||||
|
||||
#endif
|
|
@ -5,11 +5,73 @@
|
|||
#include "mbed_interface.h"
|
||||
#include "ethernet_api.h"
|
||||
#include "ethernetext_api.h"
|
||||
#include "platform/mbed_toolchain.h"
|
||||
|
||||
#define RECV_TASK_PRI (osPriorityNormal)
|
||||
#define PHY_TASK_PRI (osPriorityNormal)
|
||||
#define PHY_TASK_WAIT (200)
|
||||
|
||||
WEAK int ethernetext_init(ethernet_cfg_t *p_ethcfg)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
WEAK void ethernetext_start_stop(int32_t mode)
|
||||
{
|
||||
}
|
||||
|
||||
WEAK int ethernetext_chk_link_mode(void)
|
||||
{
|
||||
return NEGO_FAIL;
|
||||
}
|
||||
|
||||
WEAK void ethernetext_set_link_mode(int32_t link)
|
||||
{
|
||||
}
|
||||
|
||||
WEAK int ethernet_init(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
WEAK void ethernet_free(void)
|
||||
{
|
||||
}
|
||||
|
||||
WEAK int ethernet_write(const char *data, int size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
WEAK int ethernet_send(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
WEAK int ethernet_receive(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
WEAK int ethernet_read(char *data, int size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
WEAK void ethernet_address(char *mac)
|
||||
{
|
||||
}
|
||||
|
||||
WEAK int ethernet_link(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
WEAK void ethernet_set_link(int speed, int duplex)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* memory */
|
||||
static sys_sem_t recv_ready_sem; /* receive ready semaphore */
|
||||
|
||||
|
@ -195,8 +257,8 @@ err_t eth_arch_enetif_init(struct netif *netif)
|
|||
sys_sem_new(&recv_ready_sem, 0);
|
||||
|
||||
/* task */
|
||||
sys_thread_new("rza1_emac_rx_thread", rza1_recv_task, netif, DEFAULT_THREAD_STACKSIZE, RECV_TASK_PRI);
|
||||
sys_thread_new("rza1_emac_phy_thread", rza1_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_TASK_PRI);
|
||||
sys_thread_new("rza1_recv_task", rza1_recv_task, netif, DEFAULT_THREAD_STACKSIZE, RECV_TASK_PRI);
|
||||
sys_thread_new("rza1_phy_task", rza1_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_TASK_PRI);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LWIPOPTS_CONF_H
|
||||
#define LWIPOPTS_CONF_H
|
||||
|
||||
#define LWIP_TRANSPORT_ETHERNET 1
|
||||
|
||||
#define MEM_SIZE (1600 * 16)
|
||||
|
||||
#endif
|
|
@ -1,210 +0,0 @@
|
|||
#include "lwip/opt.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/ethip6.h"
|
||||
#include "mbed_interface.h"
|
||||
#include "ethernet_api.h"
|
||||
#include "ethernetext_api.h"
|
||||
|
||||
#define RECV_TASK_PRI (osPriorityNormal)
|
||||
#define PHY_TASK_PRI (osPriorityNormal)
|
||||
#define PHY_TASK_WAIT (200)
|
||||
|
||||
/* memory */
|
||||
static sys_sem_t recv_ready_sem; /* receive ready semaphore */
|
||||
|
||||
/* function */
|
||||
static void rza1_recv_task(void *arg);
|
||||
static void rza1_phy_task(void *arg);
|
||||
#if LWIP_IPV4
|
||||
static err_t rza1_etharp_output_ipv4(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr);
|
||||
#endif
|
||||
#if LWIP_IPV6
|
||||
static err_t rza1_etharp_output_ipv6(struct netif *netif, struct pbuf *q, const ip6_addr_t *ipaddr);
|
||||
#endif
|
||||
static err_t rza1_low_level_output(struct netif *netif, struct pbuf *p);
|
||||
static void rza1_recv_callback(void);
|
||||
|
||||
static void rza1_recv_task(void *arg) {
|
||||
struct netif *netif = (struct netif*)arg;
|
||||
u16_t recv_size;
|
||||
struct pbuf *p;
|
||||
int cnt;
|
||||
|
||||
while (1) {
|
||||
sys_arch_sem_wait(&recv_ready_sem, 0);
|
||||
for (cnt = 0; cnt < 16; cnt++) {
|
||||
recv_size = ethernet_receive();
|
||||
if (recv_size != 0) {
|
||||
p = pbuf_alloc(PBUF_RAW, recv_size, PBUF_RAM);
|
||||
if (p != NULL) {
|
||||
(void)ethernet_read((char *)p->payload, p->len);
|
||||
/* full packet send to tcpip_thread to process */
|
||||
if (netif->input(p, netif) != ERR_OK) {
|
||||
/* Free buffer */
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rza1_phy_task(void *arg) {
|
||||
struct netif *netif = (struct netif*)arg;
|
||||
s32_t connect_sts = 0; /* 0: disconnect, 1:connect */
|
||||
s32_t link_sts;
|
||||
s32_t link_mode_new = NEGO_FAIL;
|
||||
s32_t link_mode_old = NEGO_FAIL;
|
||||
|
||||
while (1) {
|
||||
link_sts = ethernet_link();
|
||||
if (link_sts == 1) {
|
||||
link_mode_new = ethernetext_chk_link_mode();
|
||||
if (link_mode_new != link_mode_old) {
|
||||
if (connect_sts == 1) {
|
||||
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
|
||||
}
|
||||
if (link_mode_new != NEGO_FAIL) {
|
||||
ethernetext_set_link_mode(link_mode_new);
|
||||
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1);
|
||||
connect_sts = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (connect_sts != 0) {
|
||||
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
|
||||
link_mode_new = NEGO_FAIL;
|
||||
connect_sts = 0;
|
||||
}
|
||||
}
|
||||
link_mode_old = link_mode_new;
|
||||
osDelay(PHY_TASK_WAIT);
|
||||
}
|
||||
}
|
||||
|
||||
#if LWIP_IPV4
|
||||
static err_t rza1_etharp_output_ipv4(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) {
|
||||
/* Only send packet is link is up */
|
||||
if (netif->flags & NETIF_FLAG_LINK_UP) {
|
||||
return etharp_output(netif, q, ipaddr);
|
||||
}
|
||||
|
||||
return ERR_CONN;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LWIP_IPV6
|
||||
static err_t rza1_etharp_output_ipv6(struct netif *netif, struct pbuf *q, const ip6_addr_t *ipaddr) {
|
||||
/* Only send packet is link is up */
|
||||
if (netif->flags & NETIF_FLAG_LINK_UP) {
|
||||
return ethip6_output(netif, q, ipaddr);
|
||||
}
|
||||
|
||||
return ERR_CONN;
|
||||
}
|
||||
#endif
|
||||
|
||||
static err_t rza1_low_level_output(struct netif *netif, struct pbuf *p) {
|
||||
struct pbuf *q;
|
||||
s32_t cnt;
|
||||
err_t err = ERR_MEM;
|
||||
s32_t write_size = 0;
|
||||
|
||||
if ((p->payload != NULL) && (p->len != 0)) {
|
||||
/* If the first data can't be written, transmit descriptor is full. */
|
||||
for (cnt = 0; cnt < 100; cnt++) {
|
||||
write_size = ethernet_write((char *)p->payload, p->len);
|
||||
if (write_size != 0) {
|
||||
break;
|
||||
}
|
||||
osDelay(1);
|
||||
}
|
||||
if (write_size != 0) {
|
||||
for (q = p->next; q != NULL; q = q->next) {
|
||||
(void)ethernet_write((char *)q->payload, q->len);
|
||||
}
|
||||
if (ethernet_send() == 1) {
|
||||
err = ERR_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void rza1_recv_callback(void) {
|
||||
sys_sem_signal(&recv_ready_sem);
|
||||
}
|
||||
|
||||
err_t eth_arch_enetif_init(struct netif *netif)
|
||||
{
|
||||
ethernet_cfg_t ethcfg;
|
||||
|
||||
/* set MAC hardware address */
|
||||
#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
|
||||
netif->hwaddr[0] = MBED_MAC_ADDR_0;
|
||||
netif->hwaddr[1] = MBED_MAC_ADDR_1;
|
||||
netif->hwaddr[2] = MBED_MAC_ADDR_2;
|
||||
netif->hwaddr[3] = MBED_MAC_ADDR_3;
|
||||
netif->hwaddr[4] = MBED_MAC_ADDR_4;
|
||||
netif->hwaddr[5] = MBED_MAC_ADDR_5;
|
||||
#else
|
||||
mbed_mac_address((char *)netif->hwaddr);
|
||||
#endif
|
||||
netif->hwaddr_len = ETH_HWADDR_LEN;
|
||||
|
||||
/* maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
|
||||
/* device capabilities */
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET;
|
||||
#ifdef LWIP_IGMP
|
||||
netif->flags |= NETIF_FLAG_IGMP;
|
||||
#endif
|
||||
#if LWIP_IPV6_MLD
|
||||
netif->flags |= NETIF_FLAG_MLD6;
|
||||
#endif
|
||||
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
/* Initialize interface hostname */
|
||||
netif->hostname = "lwiprza1";
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
|
||||
netif->name[0] = 'e';
|
||||
netif->name[1] = 'n';
|
||||
|
||||
#if LWIP_IPV4
|
||||
netif->output = rza1_etharp_output_ipv4;
|
||||
#endif
|
||||
#if LWIP_IPV6
|
||||
netif->output_ip6 = rza1_etharp_output_ipv6;
|
||||
#endif
|
||||
|
||||
netif->linkoutput = rza1_low_level_output;
|
||||
|
||||
/* Initialize the hardware */
|
||||
ethcfg.int_priority = 6;
|
||||
ethcfg.recv_cb = &rza1_recv_callback;
|
||||
ethcfg.ether_mac = (char *)netif->hwaddr;
|
||||
ethernetext_init(ðcfg);
|
||||
|
||||
/* semaphore */
|
||||
sys_sem_new(&recv_ready_sem, 0);
|
||||
|
||||
/* task */
|
||||
sys_thread_new("rza1_emac_rx_thread", rza1_recv_task, netif, DEFAULT_THREAD_STACKSIZE, RECV_TASK_PRI);
|
||||
sys_thread_new("rza1_emac_phy_thread", rza1_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_TASK_PRI);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void eth_arch_enable_interrupts(void) {
|
||||
ethernetext_start_stop(1);
|
||||
}
|
||||
|
||||
void eth_arch_disable_interrupts(void) {
|
||||
ethernetext_start_stop(0);
|
||||
}
|
|
@ -196,7 +196,9 @@ DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
|
|||
{
|
||||
debug_if(FFS_DBG, "disk_read(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv);
|
||||
DWORD ssize = disk_get_sector_size(pdrv);
|
||||
int err = _ffs[pdrv]->read(buff, sector*ssize, count*ssize);
|
||||
bd_addr_t addr = (bd_addr_t)sector*ssize;
|
||||
bd_size_t size = (bd_size_t)count*ssize;
|
||||
int err = _ffs[pdrv]->read(buff, addr, size);
|
||||
return err ? RES_PARERR : RES_OK;
|
||||
}
|
||||
|
||||
|
@ -204,12 +206,14 @@ DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
|
|||
{
|
||||
debug_if(FFS_DBG, "disk_write(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv);
|
||||
DWORD ssize = disk_get_sector_size(pdrv);
|
||||
int err = _ffs[pdrv]->erase(sector*ssize, count*ssize);
|
||||
bd_addr_t addr = (bd_addr_t)sector*ssize;
|
||||
bd_size_t size = (bd_size_t)count*ssize;
|
||||
int err = _ffs[pdrv]->erase(addr, size);
|
||||
if (err) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
err = _ffs[pdrv]->program(buff, sector*ssize, count*ssize);
|
||||
err = _ffs[pdrv]->program(buff, addr, size);
|
||||
if (err) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
@ -250,7 +254,9 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
|
|||
} else {
|
||||
DWORD *sectors = (DWORD*)buff;
|
||||
DWORD ssize = disk_get_sector_size(pdrv);
|
||||
int err = _ffs[pdrv]->trim(sectors[0]*ssize, (sectors[1]-sectors[0]+1)*ssize);
|
||||
bd_addr_t addr = (bd_addr_t)sectors[0]*ssize;
|
||||
bd_size_t size = (bd_size_t)(sectors[1]-sectors[0]+1)*ssize;
|
||||
int err = _ffs[pdrv]->trim(addr, size);
|
||||
return err ? RES_PARERR : RES_OK;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,19 +85,19 @@ static int lfs_totype(int type)
|
|||
static int lfs_bd_read(const struct lfs_config *c, lfs_block_t block,
|
||||
lfs_off_t off, void *buffer, lfs_size_t size) {
|
||||
BlockDevice *bd = (BlockDevice *)c->context;
|
||||
return bd->read(buffer, block*c->block_size + off, size);
|
||||
return bd->read(buffer, (bd_addr_t)block*c->block_size + off, size);
|
||||
}
|
||||
|
||||
static int lfs_bd_prog(const struct lfs_config *c, lfs_block_t block,
|
||||
lfs_off_t off, const void *buffer, lfs_size_t size) {
|
||||
BlockDevice *bd = (BlockDevice *)c->context;
|
||||
return bd->program(buffer, block*c->block_size + off, size);
|
||||
return bd->program(buffer, (bd_addr_t)block*c->block_size + off, size);
|
||||
}
|
||||
|
||||
static int lfs_bd_erase(const struct lfs_config *c, lfs_block_t block)
|
||||
{
|
||||
BlockDevice *bd = (BlockDevice *)c->context;
|
||||
return bd->erase(block*c->block_size, c->block_size);
|
||||
return bd->erase((bd_addr_t)block*c->block_size, c->block_size);
|
||||
}
|
||||
|
||||
static int lfs_bd_sync(const struct lfs_config *c)
|
||||
|
|
|
@ -12,10 +12,9 @@ script:
|
|||
- make test QUIET=1
|
||||
|
||||
# run tests with a few different configurations
|
||||
- CFLAGS="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" make test QUIET=1
|
||||
- CFLAGS="-DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" make test QUIET=1
|
||||
- CFLAGS="-DLFS_BLOCK_COUNT=1023" make test QUIET=1
|
||||
- CFLAGS="-DLFS_LOOKAHEAD=2048" make test QUIET=1
|
||||
- CFLAGS="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" make test QUIET=1
|
||||
- CFLAGS="-DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" make test QUIET=1
|
||||
- CFLAGS="-DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048" make test QUIET=1
|
||||
|
||||
# self-host with littlefs-fuse for fuzz test
|
||||
- make -C littlefs-fuse
|
||||
|
|
|
@ -1261,6 +1261,9 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
|||
file->pos = 0;
|
||||
|
||||
if (flags & LFS_O_TRUNC) {
|
||||
if (file->size != 0) {
|
||||
file->flags |= LFS_F_DIRTY;
|
||||
}
|
||||
file->head = 0xffffffff;
|
||||
file->size = 0;
|
||||
}
|
||||
|
@ -2039,9 +2042,9 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||
return err;
|
||||
}
|
||||
|
||||
// setup free lookahead
|
||||
lfs->free.begin = -lfs->cfg->lookahead;
|
||||
lfs->free.off = lfs->cfg->lookahead;
|
||||
// setup free lookahead, rewind so first allocation triggers a scan
|
||||
lfs->free.begin = -lfs_min(lfs->cfg->lookahead, lfs->cfg->block_count);
|
||||
lfs->free.off = -lfs->free.begin;
|
||||
lfs->free.end = lfs->free.begin + lfs->free.off + lfs->cfg->block_count;
|
||||
|
||||
// load superblock
|
||||
|
|
|
@ -34,7 +34,8 @@ tests/test.py << TEST
|
|||
lfs_size_t chunk = 31;
|
||||
srand(0);
|
||||
lfs_mount(&lfs, &cfg) => 0;
|
||||
lfs_file_open(&lfs, &file[0], "$2", LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
||||
lfs_file_open(&lfs, &file[0], "$2",
|
||||
${3:-LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC}) => 0;
|
||||
for (lfs_size_t i = 0; i < size; i += chunk) {
|
||||
chunk = (chunk < size - i) ? chunk : size - i;
|
||||
for (lfs_size_t b = 0; b < chunk; b++) {
|
||||
|
@ -53,7 +54,10 @@ tests/test.py << TEST
|
|||
lfs_size_t chunk = 29;
|
||||
srand(0);
|
||||
lfs_mount(&lfs, &cfg) => 0;
|
||||
lfs_file_open(&lfs, &file[0], "$2", LFS_O_RDONLY) => 0;
|
||||
lfs_stat(&lfs, "$2", &info) => 0;
|
||||
info.type => LFS_TYPE_REG;
|
||||
info.size => size;
|
||||
lfs_file_open(&lfs, &file[0], "$2", ${3:-LFS_O_RDONLY}) => 0;
|
||||
for (lfs_size_t i = 0; i < size; i += chunk) {
|
||||
chunk = (chunk < size - i) ? chunk : size - i;
|
||||
lfs_file_read(&lfs, &file[0], buffer, chunk) => chunk;
|
||||
|
@ -78,10 +82,27 @@ echo "--- Large file test ---"
|
|||
w_test $LARGESIZE largeavacado
|
||||
r_test $LARGESIZE largeavacado
|
||||
|
||||
echo "--- Zero file test ---"
|
||||
w_test 0 noavacado
|
||||
r_test 0 noavacado
|
||||
|
||||
echo "--- Truncate small test ---"
|
||||
w_test $SMALLSIZE mediumavacado
|
||||
r_test $SMALLSIZE mediumavacado
|
||||
w_test $MEDIUMSIZE mediumavacado
|
||||
r_test $MEDIUMSIZE mediumavacado
|
||||
|
||||
echo "--- Truncate zero test ---"
|
||||
w_test $SMALLSIZE noavacado
|
||||
r_test $SMALLSIZE noavacado
|
||||
w_test 0 noavacado
|
||||
r_test 0 noavacado
|
||||
|
||||
echo "--- Non-overlap check ---"
|
||||
r_test $SMALLSIZE smallavacado
|
||||
r_test $MEDIUMSIZE mediumavacado
|
||||
r_test $LARGESIZE largeavacado
|
||||
r_test 0 noavacado
|
||||
|
||||
echo "--- Dir check ---"
|
||||
tests/test.py << TEST
|
||||
|
@ -105,6 +126,10 @@ tests/test.py << TEST
|
|||
strcmp(info.name, "largeavacado") => 0;
|
||||
info.type => LFS_TYPE_REG;
|
||||
info.size => $LARGESIZE;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "noavacado") => 0;
|
||||
info.type => LFS_TYPE_REG;
|
||||
info.size => 0;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 0;
|
||||
lfs_dir_close(&lfs, &dir[0]) => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
|
|
@ -48,10 +48,7 @@ override CFLAGS += -I$(EVENTLOOP_DIR)/nanostack-event-loop/
|
|||
COAPSERVICE_DIR := ../coap-service
|
||||
override CFLAGS += -I$(COAPSERVICE_DIR)/coap-service/
|
||||
override CFLAGS += -I$(COAPSERVICE_DIR)/source/include/
|
||||
|
||||
ifeq (Linux,$(shell uname))
|
||||
override CFLAGS += -DHAVE_DEBUG
|
||||
endif
|
||||
|
||||
LIB = libcoap-service.a
|
||||
|
||||
|
|
|
@ -46,13 +46,16 @@ static void own_free(void *ptr)
|
|||
|
||||
static NS_LIST_DEFINE(request_list, coap_transaction_t, link);
|
||||
|
||||
static coap_transaction_t *transaction_find_client_by_token(uint8_t token[4])
|
||||
static coap_transaction_t *transaction_find_client_by_token(uint8_t *token, uint8_t token_len, const uint8_t address[static 16], uint16_t port)
|
||||
{
|
||||
(void) address;
|
||||
(void) port;
|
||||
coap_transaction_t *this = NULL;
|
||||
|
||||
ns_list_foreach(coap_transaction_t, cur_ptr, &request_list) {
|
||||
if (memcmp(cur_ptr->token,token,4) == 0 && cur_ptr->client_request) {
|
||||
if ((cur_ptr->token_len == token_len) && (memcmp(cur_ptr->token, token, token_len) == 0) && cur_ptr->client_request) {
|
||||
this = cur_ptr;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
@ -147,12 +150,13 @@ static int8_t coap_rx_function(sn_coap_hdr_s *resp_ptr, sn_nsdl_addr_s *address_
|
|||
coap_transaction_t *this = NULL;
|
||||
(void)address_ptr;
|
||||
(void)param;
|
||||
|
||||
tr_warn("transaction was not handled %d", resp_ptr->msg_id);
|
||||
if (!resp_ptr) {
|
||||
return -1;
|
||||
}
|
||||
if( resp_ptr->token_ptr ){
|
||||
this = transaction_find_client_by_token(resp_ptr->token_ptr);
|
||||
if(resp_ptr->token_ptr){
|
||||
this = transaction_find_client_by_token(resp_ptr->token_ptr, resp_ptr->token_len, address_ptr->addr_ptr, address_ptr->port);
|
||||
}
|
||||
if (!this) {
|
||||
return 0;
|
||||
|
@ -278,6 +282,7 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
|
|||
memcpy(transaction_ptr->remote_address, source_addr_ptr, 16);
|
||||
if (coap_message->token_len) {
|
||||
memcpy(transaction_ptr->token, coap_message->token_ptr, coap_message->token_len);
|
||||
transaction_ptr->token_len = coap_message->token_len;
|
||||
}
|
||||
transaction_ptr->remote_port = port;
|
||||
if (cb(socket_id, coap_message, transaction_ptr) < 0) {
|
||||
|
@ -292,7 +297,7 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
|
|||
} else {
|
||||
coap_transaction_t *this = NULL;
|
||||
if (coap_message->token_ptr) {
|
||||
this = transaction_find_client_by_token(coap_message->token_ptr);
|
||||
this = transaction_find_client_by_token(coap_message->token_ptr, coap_message->token_len, source_addr_ptr, port);
|
||||
}
|
||||
if (!this) {
|
||||
tr_error("client transaction not found");
|
||||
|
@ -352,8 +357,9 @@ uint16_t coap_message_handler_request_send(coap_msg_handler_t *handle, int8_t se
|
|||
|
||||
do{
|
||||
randLIB_get_n_bytes_random(token,4);
|
||||
}while(transaction_find_client_by_token(token));
|
||||
}while(transaction_find_client_by_token(token, 4, destination_addr, destination_port));
|
||||
memcpy(transaction_ptr->token,token,4);
|
||||
transaction_ptr->token_len = 4;
|
||||
request.token_ptr = transaction_ptr->token;
|
||||
request.token_len = 4;
|
||||
|
||||
|
@ -464,7 +470,7 @@ int8_t coap_message_handler_response_send_by_msg_id(coap_msg_handler_t *handle,
|
|||
response.payload_len = payload_len;
|
||||
response.payload_ptr = (uint8_t *) payload_ptr; // Cast away const and trust that nsdl doesn't modify...
|
||||
response.content_format = content_type;
|
||||
response.token_len = 4;
|
||||
response.token_len = transaction_ptr->token_len;
|
||||
response.token_ptr = transaction_ptr->token;
|
||||
response.msg_code = message_code;
|
||||
if (transaction_ptr->req_msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
|
||||
|
|
|
@ -50,18 +50,19 @@ typedef struct coap_msg_handler_s {
|
|||
typedef struct coap_transaction {
|
||||
uint8_t remote_address[16];
|
||||
uint8_t local_address[16];
|
||||
uint8_t token[4];
|
||||
uint8_t token[8];
|
||||
uint32_t create_time;
|
||||
uint8_t *data_ptr;
|
||||
coap_message_handler_response_recv *resp_cb;
|
||||
uint16_t remote_port;
|
||||
uint16_t msg_id;
|
||||
uint16_t data_len;
|
||||
int8_t service_id;
|
||||
uint8_t options;
|
||||
uint8_t *data_ptr;
|
||||
uint8_t token_len;
|
||||
sn_coap_msg_type_e req_msg_type;
|
||||
bool client_request: 1;
|
||||
|
||||
coap_message_handler_response_recv *resp_cb;
|
||||
ns_list_link_t link;
|
||||
} coap_transaction_t;
|
||||
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
# mbed mesh API
|
||||
|
||||
ARM mbed mesh API allows the client to use the IPv6 mesh network.
|
||||
|
||||
The client can use the `LoWPANNDInterface` or `ThreadInterface` object for connecting to the mesh network and when successfully connected, the client can create a socket by using the [mbed C++ socket API](https://developer.mbed.org/teams/NetworkSocketAPI/code/NetworkSocketAPI/docs/tip/) to start communication with a remote peer.
|
||||
|
||||
For ethernet `NanostackEthernetInterface` is provided.
|
||||
|
||||
## Supported mesh networking modes
|
||||
|
||||
Currently, 6LoWPAN-ND (neighbour discovery) and Thread bootstrap modes are supported.
|
||||
|
||||
## Module Configuration
|
||||
|
||||
This module supports static configuration via **mbed configuration system** by using the `mbed_app.json` file. The application needs to create the configuration file if it wants to use other than default settings.
|
||||
|
||||
An example of the configuration file:
|
||||
|
||||
```
|
||||
{
|
||||
"target_overrides": {
|
||||
"*": {
|
||||
"target.features_add": ["IPV6"],
|
||||
"mbed-mesh-api.6lowpan-nd-channel": 12,
|
||||
"mbed-mesh-api.6lowpan-nd-channel-mask": "(1<<12)",
|
||||
"mbed-mesh-api.heap-size": 10000
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configurable parameters in section mbed-mesh-api
|
||||
|
||||
| Parameter name | Value | Description |
|
||||
| --------------- | ------------- | ----------- |
|
||||
| heap-size | number [0-0xfffe] | Nanostack's internal heap size |
|
||||
| use-malloc-for-heap | `false` or `true` | Use `malloc()` for reserving the internal heap. Default: `false` |
|
||||
|
||||
### Thread related configuration parameters
|
||||
|
||||
| Parameter name | Value | Description |
|
||||
| --------------- | ------------- | ----------- |
|
||||
| thread-pskd | string [6-255 chars] | Human-scaled commissioning credentials. |
|
||||
| thread-use-static-link-config | boolean | True: Use the below link config, False: Use commissioning, ignore the below link config. |
|
||||
| thread-device-type | enum from mesh_device_type_t | Supported device operating modes: MESH_DEVICE_TYPE_THREAD_ROUTER, MESH_DEVICE_TYPE_THREAD_SLEEPY_END_DEVICE, MESH_DEVICE_TYPE_THREAD_MINIMAL_END_DEVICE |
|
||||
| thread-config-channel-mask | number [0-0x07fff800] | Channel mask, 0x07fff800 scans all channels. |
|
||||
| thread-config-channel-page | number [0, 2]| Channel page, 0 for 2,4 GHz and 2 for sub-GHz radios. |
|
||||
| thread-config-channel | number [0-27] | RF channel to use. |
|
||||
| thread-config-panid | number [0-0xFFFF] | Network identifier. |
|
||||
| thread-config-network-name | string [1-16] |
|
||||
| thread-config-commissioning-dataset-timestamp | [0-0xFFFFFFFFFFFFFFFF] | [48 bit timestamp seconds]-[15 bit timestamp ticks]-[U bit] |
|
||||
|thread-config-extended-panid | byte array [8] | Extended PAN ID |
|
||||
| thread-master-key | byte array [16]| Network master key. |
|
||||
| thread-config-ml-prefix | byte array [8] | Mesh local prefix. |
|
||||
| thread-config-pskc | byte array [16] | Pre-Shared Key for the Commissioner. |
|
||||
| thread-security-policy | number [0-0xFF] | Commissioning security policy bits |
|
||||
|
||||
### 6LoWPAN related configuration parameters
|
||||
|
||||
| Parameter name | Type | Description |
|
||||
| --------------- | ---------| ----------- |
|
||||
| 6lowpan-nd-channel-mask | number [0-0x07fff800] | Channel mask, bit-mask of channels to use |
|
||||
| 6lowpan-nd-channel-page | number [0, 2] | 0 for 2,4 GHz and 2 for sub-GHz radios |
|
||||
| 6lowpan-nd-channel | number [0-27] | RF channel to use when `channel_mask` is not defined |
|
||||
| 6lowpan-nd-panid-filter | number [0-0xffff] | Beacon PAN ID filter, 0xffff means no filtering |
|
||||
| 6lowpan-nd-security-mode | "NONE" or "PSK" | To use either no security, or Pre shared network key |
|
||||
| 6lowpan-nd-psk-key-id | number | PSK key id when PSK is enabled |
|
||||
| 6lowpan-nd-psk-key | byte array [16] | Pre shared network key |
|
||||
| 6lowpan-nd-sec-level | number [1-7] | Network security level. Use default `5` |
|
||||
| 6lowpan-nd-device-type | "NET_6LOWPAN_ROUTER" or "NET_6LOWPAN_HOST" | Device mode. Router is routing packets from other device, creating a mesh network. |
|
||||
|
||||
## Usage notes
|
||||
|
||||
This module should not be used directly by the applications. The applications should use the `LoWPANNDInterface`, `ThreadInterface` or `NanostackEthernetInterface` directly.
|
||||
|
||||
When using Ethernet interface, there is no configuration options available. It is using dynamic mode to learn the IPv6 prefix from the network. No static configuration is supported.
|
||||
|
||||
### Network connection states
|
||||
|
||||
After the initialization, the network state is `MESH_DISCONNECTED`. After a successful connection, the state changes to `MESH_CONNECTED` and when disconnected from the network the state is changed back to `MESH_DISCONNECTED`.
|
||||
|
||||
In case of connection errors, the state is changed to some of the connection error states. In an error state, there is no need to make a `disconnect` request and the client is allowed to attempt connecting again.
|
||||
|
||||
## Getting started
|
||||
|
||||
See the example application [mbed-os-example-mesh-minimal](https://github.com/ARMmbed/mbed-os-example-mesh-minimal) for usage.
|
||||
|
||||
## Usage example for 6LoWPAN ND mode
|
||||
|
||||
Create a network interface and driver objects.
|
||||
|
||||
```
|
||||
LoWPANNDInterface mesh;
|
||||
NanostackRfPhyNcs36510 rf_phy;
|
||||
```
|
||||
|
||||
Initialize interface with given PHY driver.
|
||||
|
||||
```
|
||||
mesh.initialize(&rf_phy);
|
||||
```
|
||||
|
||||
Then connect to network:
|
||||
|
||||
```
|
||||
if (mesh.connect()) {
|
||||
printf("Connection failed!\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("connected. IP = %s\r\n", mesh.get_ip_address());
|
||||
```
|
||||
|
||||
## Usage example for 6LoWPAN Thread mode
|
||||
|
||||
Basically the same as for ND, but the network interface uses different class:
|
||||
|
||||
```
|
||||
ThreadInterface mesh;
|
||||
mesh.connect();
|
||||
```
|
||||
|
||||
## Usage example with Ethernet
|
||||
|
||||
API is still the same, you just need to provide a driver that implements `NanostackEthernetPhy` API.
|
||||
|
||||
```
|
||||
NanostackEthernetInterface eth;
|
||||
NanostackEthernetPhyK64F phy;
|
||||
|
||||
int main() {
|
||||
eth.initialize(&phy);
|
||||
|
||||
if (eth.connect()) {
|
||||
printf("Connection failed!\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("connected. IP = %s\r\n", eth.get_ip_address());
|
||||
}
|
||||
```
|
|
@ -128,6 +128,20 @@ static void convert_ns_addr_to_mbed(SocketAddress *s_addr, const ns_address_t *n
|
|||
s_addr->set_ip_bytes(ns_addr->address, NSAPI_IPv6);
|
||||
}
|
||||
|
||||
static int8_t find_interface_by_address(const uint8_t target_addr[16])
|
||||
{
|
||||
for (int if_id = 1; if_id <= 127; if_id++) {
|
||||
int i = 0;
|
||||
uint8_t if_addr[16];
|
||||
while (arm_net_address_list_get_next(if_id, &i, if_addr) == 0) {
|
||||
if (memcmp(target_addr, if_addr, 16) == 0) {
|
||||
return if_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void* NanostackSocket::operator new(std::size_t sz) {
|
||||
return MALLOC(sz);
|
||||
}
|
||||
|
@ -693,17 +707,50 @@ nsapi_error_t NanostackInterface::setsockopt(void *handle, int level, int optnam
|
|||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
|
||||
nsapi_error_t ret;
|
||||
|
||||
NanostackLockGuard lock;
|
||||
|
||||
if (::socket_setsockopt(socket->socket_id, level, optname, optval, optlen) == 0) {
|
||||
ret = NSAPI_ERROR_OK;
|
||||
} else {
|
||||
ret = NSAPI_ERROR_PARAMETER;
|
||||
ns_ipv6_mreq_t ns_mreq;
|
||||
|
||||
if (level == NSAPI_SOCKET) {
|
||||
switch (optname) {
|
||||
case NSAPI_ADD_MEMBERSHIP:
|
||||
case NSAPI_DROP_MEMBERSHIP: {
|
||||
if (optlen != sizeof(nsapi_ip_mreq_t)) {
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
const nsapi_ip_mreq_t *imr = static_cast<const nsapi_ip_mreq_t *>(optval);
|
||||
|
||||
/* Check address types are IPv6, or unspecified for interface */
|
||||
if (imr->imr_multiaddr.version != NSAPI_IPv6 ||
|
||||
(imr->imr_interface.version != NSAPI_UNSPEC && imr->imr_interface.version != NSAPI_IPv6)) {
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
/* Convert all parameters to Nanostack native, and proceed with setsockopt */
|
||||
memcpy(ns_mreq.ipv6mr_multiaddr, imr->imr_multiaddr.bytes, 16);
|
||||
if (imr->imr_interface.version == NSAPI_UNSPEC || memcmp(imr->imr_interface.bytes, ns_in6addr_any, 16) == 0) {
|
||||
ns_mreq.ipv6mr_interface = 0;
|
||||
} else {
|
||||
// If this fails, Nanostack will itself fault the invalid -1 interface ID
|
||||
ns_mreq.ipv6mr_interface = find_interface_by_address(imr->imr_interface.bytes);
|
||||
}
|
||||
|
||||
level = SOCKET_IPPROTO_IPV6;
|
||||
optname = optname == NSAPI_ADD_MEMBERSHIP ? SOCKET_IPV6_JOIN_GROUP : SOCKET_IPV6_LEAVE_GROUP;
|
||||
optval = &ns_mreq;
|
||||
optlen = sizeof ns_mreq;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (::socket_setsockopt(socket->socket_id, level, optname, optval, optlen) == 0) {
|
||||
return NSAPI_ERROR_OK;
|
||||
} else {
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t NanostackInterface::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
|
||||
|
|
|
@ -111,7 +111,9 @@ public:
|
|||
* @param data Destination buffer for data received from the host
|
||||
* @param size Size of the buffer in bytes
|
||||
* @return Number of received bytes on success, negative error
|
||||
* code on failure
|
||||
* code on failure. If no data is available to be received
|
||||
* and the peer has performed an orderly shutdown,
|
||||
* recv() returns 0.
|
||||
*/
|
||||
nsapi_size_or_error_t recv(void *data, nsapi_size_t size);
|
||||
|
||||
|
|
|
@ -94,17 +94,18 @@ public:
|
|||
nsapi_size_or_error_t sendto(const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size);
|
||||
|
||||
/** Receive a packet over a UDP socket
|
||||
/** Receive a datagram over a UDP socket
|
||||
*
|
||||
* Receives data and stores the source address in address if address
|
||||
* is not NULL. Returns the number of bytes received into the buffer.
|
||||
* Receives a datagram and stores the source address in address if address
|
||||
* is not NULL. Returns the number of bytes written into the buffer. If the
|
||||
* datagram is larger than the buffer, the excess data is silently discarded.
|
||||
*
|
||||
* By default, recvfrom blocks until data is sent. If socket is set to
|
||||
* non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
|
||||
* immediately.
|
||||
* By default, recvfrom blocks until a datagram is received. If socket is set to
|
||||
* non-blocking or times out with no datagram, NSAPI_ERROR_WOULD_BLOCK
|
||||
* is returned.
|
||||
*
|
||||
* @param address Destination for the source address or NULL
|
||||
* @param data Destination buffer for data received from the host
|
||||
* @param data Destination buffer for datagram received from the host
|
||||
* @param size Size of the buffer in bytes
|
||||
* @return Number of received bytes on success, negative error
|
||||
* code on failure
|
||||
|
|
|
@ -56,6 +56,8 @@ USBAudio::USBAudio(uint32_t frequency_in, uint8_t channel_nb_in, uint32_t freque
|
|||
|
||||
volume = 0;
|
||||
|
||||
_build_configurationDesc();
|
||||
|
||||
// connect the device
|
||||
USBDevice::connect();
|
||||
}
|
||||
|
@ -377,8 +379,8 @@ void USBAudio::USBCallback_requestCompleted(uint8_t * buf, uint32_t length) {
|
|||
FEATURE_UNIT_DESCRIPTOR_LENGTH + \
|
||||
2*OUTPUT_TERMINAL_DESCRIPTOR_LENGTH)
|
||||
|
||||
uint8_t * USBAudio::configurationDesc() {
|
||||
static uint8_t configDescriptor[] = {
|
||||
void USBAudio::_build_configurationDesc() {
|
||||
uint8_t configDescriptorTemp[] = {
|
||||
// Configuration 1
|
||||
CONFIGURATION_DESCRIPTOR_LENGTH, // bLength
|
||||
CONFIGURATION_DESCRIPTOR, // bDescriptorType
|
||||
|
@ -615,15 +617,19 @@ uint8_t * USBAudio::configurationDesc() {
|
|||
0x00, // bLockDelayUnits
|
||||
LSB(0x0000), // wLockDelay
|
||||
MSB(0x0000), // wLockDelay
|
||||
|
||||
// Terminator
|
||||
0 // bLength
|
||||
};
|
||||
|
||||
MBED_ASSERT(sizeof(configDescriptorTemp) == sizeof(configDescriptor));
|
||||
memcpy(configDescriptor, configDescriptorTemp, sizeof(configDescriptor));
|
||||
}
|
||||
|
||||
const uint8_t * USBAudio::configurationDesc() {
|
||||
|
||||
return configDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBAudio::stringIinterfaceDesc() {
|
||||
static uint8_t stringIinterfaceDescriptor[] = {
|
||||
const uint8_t * USBAudio::stringIinterfaceDesc() {
|
||||
static const uint8_t stringIinterfaceDescriptor[] = {
|
||||
0x0c, //bLength
|
||||
STRING_DESCRIPTOR, //bDescriptorType 0x03
|
||||
'A',0,'u',0,'d',0,'i',0,'o',0 //bString iInterface - Audio
|
||||
|
@ -631,8 +637,8 @@ uint8_t * USBAudio::stringIinterfaceDesc() {
|
|||
return stringIinterfaceDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBAudio::stringIproductDesc() {
|
||||
static uint8_t stringIproductDescriptor[] = {
|
||||
const uint8_t * USBAudio::stringIproductDesc() {
|
||||
static const uint8_t stringIproductDescriptor[] = {
|
||||
0x16, //bLength
|
||||
STRING_DESCRIPTOR, //bDescriptorType 0x03
|
||||
'M',0,'b',0,'e',0,'d',0,' ',0,'A',0,'u',0,'d',0,'i',0,'o',0 //bString iProduct - Mbed Audio
|
||||
|
|
|
@ -152,7 +152,7 @@ public:
|
|||
*
|
||||
*/
|
||||
void attach(void(*fptr)(void)) {
|
||||
updateVol.attach(fptr);
|
||||
updateVol = Callback<void()>(fptr);
|
||||
}
|
||||
/** attach a handler to Tx Done
|
||||
*
|
||||
|
@ -160,7 +160,7 @@ public:
|
|||
*
|
||||
*/
|
||||
void attachTx(void(*fptr)(void)) {
|
||||
txDone.attach(fptr);
|
||||
txDone = Callback<void()>(fptr);
|
||||
}
|
||||
/** attach a handler to Rx Done
|
||||
*
|
||||
|
@ -168,7 +168,7 @@ public:
|
|||
*
|
||||
*/
|
||||
void attachRx(void(*fptr)(void)) {
|
||||
rxDone.attach(fptr);
|
||||
rxDone = Callback<void()>(fptr);
|
||||
}
|
||||
|
||||
/** Attach a nonstatic void/void member function to update the volume
|
||||
|
@ -179,15 +179,52 @@ public:
|
|||
*/
|
||||
template<typename T>
|
||||
void attach(T *tptr, void(T::*mptr)(void)) {
|
||||
updateVol.attach(tptr, mptr);
|
||||
updateVol = Callback<void()>(tptr, mptr);
|
||||
}
|
||||
/** Attach a nonstatic void/void member function to Tx Done
|
||||
*
|
||||
* @param tptr Object pointer
|
||||
* @param mptr Member function pointer
|
||||
*
|
||||
*/
|
||||
template<typename T>
|
||||
void attachTx(T *tptr, void(T::*mptr)(void)) {
|
||||
txDone.attach(tptr, mptr);
|
||||
txDone = Callback<void()>(tptr, mptr);
|
||||
}
|
||||
/** Attach a nonstatic void/void member function to Rx Done
|
||||
*
|
||||
* @param tptr Object pointer
|
||||
* @param mptr Member function pointer
|
||||
*
|
||||
*/
|
||||
template<typename T>
|
||||
void attachRx(T *tptr, void(T::*mptr)(void)) {
|
||||
rxDone.attach(tptr, mptr);
|
||||
rxDone = Callback<void()>(tptr, mptr);
|
||||
}
|
||||
|
||||
/** Attach a Callback to update the volume
|
||||
*
|
||||
* @param cb Callback to attach
|
||||
*
|
||||
*/
|
||||
void attach(Callback<void()> &cb) {
|
||||
updateVol = cb;
|
||||
}
|
||||
/** attach a Callback to Tx Done
|
||||
*
|
||||
* @param cb Callback to attach
|
||||
*
|
||||
*/
|
||||
void attachTx(Callback<void()> &cb) {
|
||||
txDone = cb;
|
||||
}
|
||||
/** attach a Callback to Rx Done
|
||||
*
|
||||
* @param cb Callback to attach
|
||||
*
|
||||
*/
|
||||
void attachRx(Callback<void()> &cb) {
|
||||
rxDone = cb;
|
||||
}
|
||||
|
||||
|
||||
|
@ -216,21 +253,21 @@ protected:
|
|||
*
|
||||
* @returns pointer to the string product descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIproductDesc();
|
||||
virtual const uint8_t * stringIproductDesc();
|
||||
|
||||
/*
|
||||
* Get string interface descriptor
|
||||
*
|
||||
* @returns pointer to the string interface descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIinterfaceDesc();
|
||||
virtual const uint8_t * stringIinterfaceDesc();
|
||||
|
||||
/*
|
||||
* Get configuration descriptor
|
||||
*
|
||||
* @returns pointer to the configuration descriptor
|
||||
*/
|
||||
virtual uint8_t * configurationDesc();
|
||||
virtual const uint8_t * configurationDesc();
|
||||
|
||||
/*
|
||||
* Called by USBDevice layer. Set interface/alternate of the device.
|
||||
|
@ -270,6 +307,20 @@ protected:
|
|||
|
||||
private:
|
||||
|
||||
/*
|
||||
* Call to rebuild the configuration descriptor
|
||||
*
|
||||
* This function should be called on creation or when any
|
||||
* value that is part of the configuration descriptor
|
||||
* changes.
|
||||
* @note This function uses ~200 bytes of stack so
|
||||
* make sure your stack is big enough for it.
|
||||
*/
|
||||
void _build_configurationDesc();
|
||||
|
||||
// configuration descriptor
|
||||
uint8_t configDescriptor[183];
|
||||
|
||||
// stream available ?
|
||||
volatile bool available;
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ bool USBDevice::requestGetDescriptor(void)
|
|||
printf("device descr\r\n");
|
||||
#endif
|
||||
transfer.remaining = DEVICE_DESCRIPTOR_LENGTH;
|
||||
transfer.ptr = deviceDesc();
|
||||
transfer.ptr = (uint8_t*)deviceDesc();
|
||||
transfer.direction = DEVICE_TO_HOST;
|
||||
success = true;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ bool USBDevice::requestGetDescriptor(void)
|
|||
transfer.remaining = configurationDesc()[2] \
|
||||
| (configurationDesc()[3] << 8);
|
||||
|
||||
transfer.ptr = configurationDesc();
|
||||
transfer.ptr = (uint8_t*)configurationDesc();
|
||||
transfer.direction = DEVICE_TO_HOST;
|
||||
success = true;
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ bool USBDevice::requestGetDescriptor(void)
|
|||
printf("1\r\n");
|
||||
#endif
|
||||
transfer.remaining = stringLangidDesc()[0];
|
||||
transfer.ptr = stringLangidDesc();
|
||||
transfer.ptr = (uint8_t*)stringLangidDesc();
|
||||
transfer.direction = DEVICE_TO_HOST;
|
||||
success = true;
|
||||
break;
|
||||
|
@ -103,7 +103,7 @@ bool USBDevice::requestGetDescriptor(void)
|
|||
printf("2\r\n");
|
||||
#endif
|
||||
transfer.remaining = stringImanufacturerDesc()[0];
|
||||
transfer.ptr = stringImanufacturerDesc();
|
||||
transfer.ptr = (uint8_t*)stringImanufacturerDesc();
|
||||
transfer.direction = DEVICE_TO_HOST;
|
||||
success = true;
|
||||
break;
|
||||
|
@ -112,7 +112,7 @@ bool USBDevice::requestGetDescriptor(void)
|
|||
printf("3\r\n");
|
||||
#endif
|
||||
transfer.remaining = stringIproductDesc()[0];
|
||||
transfer.ptr = stringIproductDesc();
|
||||
transfer.ptr = (uint8_t*)stringIproductDesc();
|
||||
transfer.direction = DEVICE_TO_HOST;
|
||||
success = true;
|
||||
break;
|
||||
|
@ -121,7 +121,7 @@ bool USBDevice::requestGetDescriptor(void)
|
|||
printf("4\r\n");
|
||||
#endif
|
||||
transfer.remaining = stringIserialDesc()[0];
|
||||
transfer.ptr = stringIserialDesc();
|
||||
transfer.ptr = (uint8_t*)stringIserialDesc();
|
||||
transfer.direction = DEVICE_TO_HOST;
|
||||
success = true;
|
||||
break;
|
||||
|
@ -130,7 +130,7 @@ bool USBDevice::requestGetDescriptor(void)
|
|||
printf("5\r\n");
|
||||
#endif
|
||||
transfer.remaining = stringIConfigurationDesc()[0];
|
||||
transfer.ptr = stringIConfigurationDesc();
|
||||
transfer.ptr = (uint8_t*)stringIConfigurationDesc();
|
||||
transfer.direction = DEVICE_TO_HOST;
|
||||
success = true;
|
||||
break;
|
||||
|
@ -139,7 +139,7 @@ bool USBDevice::requestGetDescriptor(void)
|
|||
printf("6\r\n");
|
||||
#endif
|
||||
transfer.remaining = stringIinterfaceDesc()[0];
|
||||
transfer.ptr = stringIinterfaceDesc();
|
||||
transfer.ptr = (uint8_t*)stringIinterfaceDesc();
|
||||
transfer.direction = DEVICE_TO_HOST;
|
||||
success = true;
|
||||
break;
|
||||
|
@ -187,27 +187,8 @@ bool USBDevice::controlOut(void)
|
|||
/* Check we should be transferring data OUT */
|
||||
if (transfer.direction != HOST_TO_DEVICE)
|
||||
{
|
||||
#if defined(TARGET_KL25Z) | defined(TARGET_KL43Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D5M) | defined(TARGET_K64F) | defined(TARGET_K22F) | defined(TARGET_TEENSY3_1)
|
||||
/*
|
||||
* We seem to have a pending device-to-host transfer. The host must have
|
||||
* sent a new control request without waiting for us to finish processing
|
||||
* the previous one. This appears to happen when we're connected to certain
|
||||
* USB 3.0 host chip set. Do a zeor-length send to tell the host we're not
|
||||
* ready for the new request - that'll make it resend - and then just
|
||||
* pretend we were successful here so that the pending transfer can finish.
|
||||
*/
|
||||
uint8_t buf[1] = { 0 };
|
||||
EP0write(buf, 0);
|
||||
|
||||
/* execute our pending ttransfer */
|
||||
controlIn();
|
||||
|
||||
/* indicate success */
|
||||
return true;
|
||||
#else
|
||||
/* for other platforms, count on the HAL to handle this case */
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Read from endpoint */
|
||||
|
@ -790,7 +771,7 @@ uint8_t * USBDevice::findDescriptor(uint8_t descriptorType)
|
|||
}
|
||||
|
||||
/* Start at first descriptor after the configuration descriptor */
|
||||
ptr = &(configurationDesc()[CONFIGURATION_DESCRIPTOR_LENGTH]);
|
||||
ptr = &(((uint8_t*)configurationDesc())[CONFIGURATION_DESCRIPTOR_LENGTH]);
|
||||
|
||||
do {
|
||||
if (ptr[1] /* bDescriptorType */ == descriptorType)
|
||||
|
@ -926,8 +907,8 @@ bool USBDevice::readEP_NB(uint8_t endpoint, uint8_t * buffer, uint32_t * size, u
|
|||
|
||||
|
||||
|
||||
uint8_t * USBDevice::deviceDesc() {
|
||||
static uint8_t deviceDescriptor[] = {
|
||||
const uint8_t * USBDevice::deviceDesc() {
|
||||
uint8_t deviceDescriptorTemp[] = {
|
||||
DEVICE_DESCRIPTOR_LENGTH, /* bLength */
|
||||
DEVICE_DESCRIPTOR, /* bDescriptorType */
|
||||
LSB(USB_VERSION_2_0), /* bcdUSB (LSB) */
|
||||
|
@ -947,20 +928,22 @@ uint8_t * USBDevice::deviceDesc() {
|
|||
STRING_OFFSET_ISERIAL, /* iSerialNumber */
|
||||
0x01 /* bNumConfigurations */
|
||||
};
|
||||
MBED_ASSERT(sizeof(deviceDescriptorTemp) == sizeof(deviceDescriptor));
|
||||
memcpy(deviceDescriptor, deviceDescriptorTemp, sizeof(deviceDescriptor));
|
||||
return deviceDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBDevice::stringLangidDesc() {
|
||||
static uint8_t stringLangidDescriptor[] = {
|
||||
const uint8_t * USBDevice::stringLangidDesc() {
|
||||
static const uint8_t stringLangidDescriptor[] = {
|
||||
0x04, /*bLength*/
|
||||
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
|
||||
0x09,0x04, /*bString Lang ID - 0x0409 - English*/
|
||||
};
|
||||
return stringLangidDescriptor;
|
||||
return (uint8_t *)stringLangidDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBDevice::stringImanufacturerDesc() {
|
||||
static uint8_t stringImanufacturerDescriptor[] = {
|
||||
const uint8_t * USBDevice::stringImanufacturerDesc() {
|
||||
static const uint8_t stringImanufacturerDescriptor[] = {
|
||||
0x12, /*bLength*/
|
||||
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
|
||||
'm',0,'b',0,'e',0,'d',0,'.',0,'o',0,'r',0,'g',0, /*bString iManufacturer - mbed.org*/
|
||||
|
@ -968,8 +951,8 @@ uint8_t * USBDevice::stringImanufacturerDesc() {
|
|||
return stringImanufacturerDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBDevice::stringIserialDesc() {
|
||||
static uint8_t stringIserialDescriptor[] = {
|
||||
const uint8_t * USBDevice::stringIserialDesc() {
|
||||
static const uint8_t stringIserialDescriptor[] = {
|
||||
0x16, /*bLength*/
|
||||
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
|
||||
'0',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0, /*bString iSerial - 0123456789*/
|
||||
|
@ -977,8 +960,8 @@ uint8_t * USBDevice::stringIserialDesc() {
|
|||
return stringIserialDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBDevice::stringIConfigurationDesc() {
|
||||
static uint8_t stringIconfigurationDescriptor[] = {
|
||||
const uint8_t * USBDevice::stringIConfigurationDesc() {
|
||||
static const uint8_t stringIconfigurationDescriptor[] = {
|
||||
0x06, /*bLength*/
|
||||
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
|
||||
'0',0,'1',0, /*bString iConfiguration - 01*/
|
||||
|
@ -986,8 +969,8 @@ uint8_t * USBDevice::stringIConfigurationDesc() {
|
|||
return stringIconfigurationDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBDevice::stringIinterfaceDesc() {
|
||||
static uint8_t stringIinterfaceDescriptor[] = {
|
||||
const uint8_t * USBDevice::stringIinterfaceDesc() {
|
||||
static const uint8_t stringIinterfaceDescriptor[] = {
|
||||
0x08, /*bLength*/
|
||||
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
|
||||
'U',0,'S',0,'B',0, /*bString iInterface - USB*/
|
||||
|
@ -995,8 +978,8 @@ uint8_t * USBDevice::stringIinterfaceDesc() {
|
|||
return stringIinterfaceDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBDevice::stringIproductDesc() {
|
||||
static uint8_t stringIproductDescriptor[] = {
|
||||
const uint8_t * USBDevice::stringIproductDesc() {
|
||||
static const uint8_t stringIproductDescriptor[] = {
|
||||
0x16, /*bLength*/
|
||||
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
|
||||
'U',0,'S',0,'B',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 /*bString iProduct - USB DEVICE*/
|
||||
|
|
|
@ -165,60 +165,60 @@ public:
|
|||
virtual bool USBCallback_setInterface(uint16_t interface, uint8_t alternate) { return false; };
|
||||
|
||||
/*
|
||||
* Get device descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
|
||||
* Get device descriptor.
|
||||
*
|
||||
* @returns pointer to the device descriptor
|
||||
*/
|
||||
virtual uint8_t * deviceDesc();
|
||||
virtual const uint8_t * deviceDesc();
|
||||
|
||||
/*
|
||||
* Get configuration descriptor
|
||||
*
|
||||
* @returns pointer to the configuration descriptor
|
||||
*/
|
||||
virtual uint8_t * configurationDesc(){return NULL;};
|
||||
virtual const uint8_t * configurationDesc(){return NULL;};
|
||||
|
||||
/*
|
||||
* Get string lang id descriptor
|
||||
*
|
||||
* @return pointer to the string lang id descriptor
|
||||
*/
|
||||
virtual uint8_t * stringLangidDesc();
|
||||
virtual const uint8_t * stringLangidDesc();
|
||||
|
||||
/*
|
||||
* Get string manufacturer descriptor
|
||||
*
|
||||
* @returns pointer to the string manufacturer descriptor
|
||||
*/
|
||||
virtual uint8_t * stringImanufacturerDesc();
|
||||
virtual const uint8_t * stringImanufacturerDesc();
|
||||
|
||||
/*
|
||||
* Get string product descriptor
|
||||
*
|
||||
* @returns pointer to the string product descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIproductDesc();
|
||||
virtual const uint8_t * stringIproductDesc();
|
||||
|
||||
/*
|
||||
* Get string serial descriptor
|
||||
*
|
||||
* @returns pointer to the string serial descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIserialDesc();
|
||||
virtual const uint8_t * stringIserialDesc();
|
||||
|
||||
/*
|
||||
* Get string configuration descriptor
|
||||
*
|
||||
* @returns pointer to the string configuration descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIConfigurationDesc();
|
||||
virtual const uint8_t * stringIConfigurationDesc();
|
||||
|
||||
/*
|
||||
* Get string interface descriptor
|
||||
*
|
||||
* @returns pointer to the string interface descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIinterfaceDesc();
|
||||
virtual const uint8_t * stringIinterfaceDesc();
|
||||
|
||||
/*
|
||||
* Get the length of the report descriptor
|
||||
|
@ -242,6 +242,7 @@ protected:
|
|||
uint16_t VENDOR_ID;
|
||||
uint16_t PRODUCT_ID;
|
||||
uint16_t PRODUCT_RELEASE;
|
||||
uint8_t deviceDescriptor[18];
|
||||
|
||||
private:
|
||||
bool addRateFeedbackEndpoint(uint8_t endpoint, uint32_t maxPacket);
|
||||
|
|
|
@ -105,7 +105,7 @@ bool USBHID::USBCallback_request() {
|
|||
&& (reportDescLength() != 0))
|
||||
{
|
||||
transfer->remaining = reportDescLength();
|
||||
transfer->ptr = reportDesc();
|
||||
transfer->ptr = (uint8_t*)reportDesc();
|
||||
transfer->direction = DEVICE_TO_HOST;
|
||||
success = true;
|
||||
}
|
||||
|
@ -177,8 +177,8 @@ bool USBHID::USBCallback_setConfiguration(uint8_t configuration) {
|
|||
}
|
||||
|
||||
|
||||
uint8_t * USBHID::stringIinterfaceDesc() {
|
||||
static uint8_t stringIinterfaceDescriptor[] = {
|
||||
const uint8_t * USBHID::stringIinterfaceDesc() {
|
||||
static const uint8_t stringIinterfaceDescriptor[] = {
|
||||
0x08, //bLength
|
||||
STRING_DESCRIPTOR, //bDescriptorType 0x03
|
||||
'H',0,'I',0,'D',0, //bString iInterface - HID
|
||||
|
@ -186,8 +186,8 @@ uint8_t * USBHID::stringIinterfaceDesc() {
|
|||
return stringIinterfaceDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBHID::stringIproductDesc() {
|
||||
static uint8_t stringIproductDescriptor[] = {
|
||||
const uint8_t * USBHID::stringIproductDesc() {
|
||||
static const uint8_t stringIproductDescriptor[] = {
|
||||
0x16, //bLength
|
||||
STRING_DESCRIPTOR, //bDescriptorType 0x03
|
||||
'H',0,'I',0,'D',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 //bString iProduct - HID device
|
||||
|
@ -197,8 +197,8 @@ uint8_t * USBHID::stringIproductDesc() {
|
|||
|
||||
|
||||
|
||||
uint8_t * USBHID::reportDesc() {
|
||||
static uint8_t reportDescriptor[] = {
|
||||
const uint8_t * USBHID::reportDesc() {
|
||||
uint8_t reportDescriptorTemp[] = {
|
||||
USAGE_PAGE(2), LSB(0xFFAB), MSB(0xFFAB),
|
||||
USAGE(2), LSB(0x0200), MSB(0x0200),
|
||||
COLLECTION(1), 0x01, // Collection (Application)
|
||||
|
@ -218,6 +218,8 @@ uint8_t * USBHID::reportDesc() {
|
|||
END_COLLECTION(0),
|
||||
};
|
||||
reportLength = sizeof(reportDescriptor);
|
||||
MBED_ASSERT(sizeof(reportDescriptorTemp) == sizeof(reportDescriptor));
|
||||
memcpy(reportDescriptor, reportDescriptorTemp, sizeof(reportDescriptor));
|
||||
return reportDescriptor;
|
||||
}
|
||||
|
||||
|
@ -227,8 +229,8 @@ uint8_t * USBHID::reportDesc() {
|
|||
+ (1 * HID_DESCRIPTOR_LENGTH) \
|
||||
+ (2 * ENDPOINT_DESCRIPTOR_LENGTH))
|
||||
|
||||
uint8_t * USBHID::configurationDesc() {
|
||||
static uint8_t configurationDescriptor[] = {
|
||||
const uint8_t * USBHID::configurationDesc() {
|
||||
uint8_t configurationDescriptorTemp[] = {
|
||||
CONFIGURATION_DESCRIPTOR_LENGTH, // bLength
|
||||
CONFIGURATION_DESCRIPTOR, // bDescriptorType
|
||||
LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
|
||||
|
@ -275,5 +277,7 @@ uint8_t * USBHID::configurationDesc() {
|
|||
MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
|
||||
1, // bInterval (milliseconds)
|
||||
};
|
||||
MBED_ASSERT(sizeof(configurationDescriptorTemp) == sizeof(configurationDescriptor));
|
||||
memcpy(configurationDescriptor, configurationDescriptorTemp, sizeof(configurationDescriptor));
|
||||
return configurationDescriptor;
|
||||
}
|
||||
|
|
|
@ -98,13 +98,14 @@ public:
|
|||
|
||||
protected:
|
||||
uint16_t reportLength;
|
||||
uint8_t reportDescriptor[27];
|
||||
|
||||
/*
|
||||
* Get the Report descriptor
|
||||
*
|
||||
* @returns pointer to the report descriptor
|
||||
*/
|
||||
virtual uint8_t * reportDesc();
|
||||
virtual const uint8_t * reportDesc();
|
||||
|
||||
/*
|
||||
* Get the length of the report descriptor
|
||||
|
@ -118,21 +119,21 @@ protected:
|
|||
*
|
||||
* @returns pointer to the string product descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIproductDesc();
|
||||
virtual const uint8_t * stringIproductDesc();
|
||||
|
||||
/*
|
||||
* Get string interface descriptor
|
||||
*
|
||||
* @returns pointer to the string interface descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIinterfaceDesc();
|
||||
virtual const uint8_t * stringIinterfaceDesc();
|
||||
|
||||
/*
|
||||
* Get configuration descriptor
|
||||
*
|
||||
* @returns pointer to the configuration descriptor
|
||||
*/
|
||||
virtual uint8_t * configurationDesc();
|
||||
virtual const uint8_t * configurationDesc();
|
||||
|
||||
|
||||
/*
|
||||
|
@ -164,6 +165,7 @@ protected:
|
|||
virtual bool USBCallback_setConfiguration(uint8_t configuration);
|
||||
|
||||
private:
|
||||
uint8_t configurationDescriptor[41];
|
||||
HID_REPORT outputReport;
|
||||
uint8_t output_length;
|
||||
uint8_t input_length;
|
||||
|
|
|
@ -352,8 +352,8 @@ const KEYMAP keymap[KEYMAP_SIZE] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
uint8_t * USBKeyboard::reportDesc() {
|
||||
static uint8_t reportDescriptor[] = {
|
||||
const uint8_t * USBKeyboard::reportDesc() {
|
||||
static const uint8_t reportDescriptor[] = {
|
||||
USAGE_PAGE(1), 0x01, // Generic Desktop
|
||||
USAGE(1), 0x06, // Keyboard
|
||||
COLLECTION(1), 0x01, // Application
|
||||
|
@ -501,8 +501,8 @@ bool USBKeyboard::mediaControl(MEDIA_KEY key) {
|
|||
+ (1 * HID_DESCRIPTOR_LENGTH) \
|
||||
+ (2 * ENDPOINT_DESCRIPTOR_LENGTH))
|
||||
|
||||
uint8_t * USBKeyboard::configurationDesc() {
|
||||
static uint8_t configurationDescriptor[] = {
|
||||
const uint8_t * USBKeyboard::configurationDesc() {
|
||||
uint8_t configurationDescriptorTemp[] = {
|
||||
CONFIGURATION_DESCRIPTOR_LENGTH, // bLength
|
||||
CONFIGURATION_DESCRIPTOR, // bDescriptorType
|
||||
LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
|
||||
|
@ -549,5 +549,7 @@ uint8_t * USBKeyboard::configurationDesc() {
|
|||
MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
|
||||
1, // bInterval (milliseconds)
|
||||
};
|
||||
MBED_ASSERT(sizeof(configurationDescriptorTemp) == sizeof(configurationDescriptor));
|
||||
memcpy(configurationDescriptor, configurationDescriptorTemp, sizeof(configurationDescriptor));
|
||||
return configurationDescriptor;
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ public:
|
|||
*
|
||||
* @returns pointer to the report descriptor
|
||||
*/
|
||||
virtual uint8_t * reportDesc();
|
||||
virtual const uint8_t * reportDesc();
|
||||
|
||||
/*
|
||||
* Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys
|
||||
|
@ -173,7 +173,7 @@ protected:
|
|||
*
|
||||
* @returns pointer to the configuration descriptor
|
||||
*/
|
||||
virtual uint8_t * configurationDesc();
|
||||
virtual const uint8_t * configurationDesc();
|
||||
|
||||
private:
|
||||
//dummy otherwise it doesn,t compile (we must define all methods of an abstract class)
|
||||
|
@ -181,6 +181,7 @@ private:
|
|||
return -1;
|
||||
};
|
||||
|
||||
uint8_t configurationDescriptor[41];
|
||||
uint8_t lock_status;
|
||||
|
||||
};
|
||||
|
|
|
@ -103,10 +103,10 @@ bool USBMouse::release(uint8_t button_) {
|
|||
}
|
||||
|
||||
|
||||
uint8_t * USBMouse::reportDesc() {
|
||||
const uint8_t * USBMouse::reportDesc() {
|
||||
|
||||
if (mouse_type == REL_MOUSE) {
|
||||
static uint8_t reportDescriptor[] = {
|
||||
static const uint8_t reportDescriptor[] = {
|
||||
USAGE_PAGE(1), 0x01, // Genric Desktop
|
||||
USAGE(1), 0x02, // Mouse
|
||||
COLLECTION(1), 0x01, // Application
|
||||
|
@ -141,7 +141,7 @@ uint8_t * USBMouse::reportDesc() {
|
|||
reportLength = sizeof(reportDescriptor);
|
||||
return reportDescriptor;
|
||||
} else if (mouse_type == ABS_MOUSE) {
|
||||
static uint8_t reportDescriptor[] = {
|
||||
static const uint8_t reportDescriptor[] = {
|
||||
USAGE_PAGE(1), 0x01, // Generic Desktop
|
||||
USAGE(1), 0x02, // Mouse
|
||||
COLLECTION(1), 0x01, // Application
|
||||
|
@ -192,8 +192,8 @@ uint8_t * USBMouse::reportDesc() {
|
|||
+ (1 * HID_DESCRIPTOR_LENGTH) \
|
||||
+ (2 * ENDPOINT_DESCRIPTOR_LENGTH))
|
||||
|
||||
uint8_t * USBMouse::configurationDesc() {
|
||||
static uint8_t configurationDescriptor[] = {
|
||||
const uint8_t * USBMouse::configurationDesc() {
|
||||
uint8_t configurationDescriptorTemp[] = {
|
||||
CONFIGURATION_DESCRIPTOR_LENGTH, // bLength
|
||||
CONFIGURATION_DESCRIPTOR, // bDescriptorType
|
||||
LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
|
||||
|
@ -240,5 +240,7 @@ uint8_t * USBMouse::configurationDesc() {
|
|||
MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
|
||||
1, // bInterval (milliseconds)
|
||||
};
|
||||
MBED_ASSERT(sizeof(configurationDescriptorTemp) == sizeof(configurationDescriptor));
|
||||
memcpy(configurationDescriptor, configurationDescriptorTemp, sizeof(configurationDescriptor));
|
||||
return configurationDescriptor;
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ class USBMouse: public USBHID
|
|||
*
|
||||
* @returns pointer to the report descriptor
|
||||
*/
|
||||
virtual uint8_t * reportDesc();
|
||||
virtual const uint8_t * reportDesc();
|
||||
|
||||
protected:
|
||||
/*
|
||||
|
@ -198,11 +198,12 @@ class USBMouse: public USBHID
|
|||
*
|
||||
* @returns pointer to the configuration descriptor
|
||||
*/
|
||||
virtual uint8_t * configurationDesc();
|
||||
virtual const uint8_t * configurationDesc();
|
||||
|
||||
private:
|
||||
MOUSE_TYPE mouse_type;
|
||||
uint8_t button;
|
||||
uint8_t configurationDescriptor[41];
|
||||
bool mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z);
|
||||
};
|
||||
|
||||
|
|
|
@ -348,9 +348,9 @@ const KEYMAP keymap[KEYMAP_SIZE] = {
|
|||
#endif
|
||||
|
||||
|
||||
uint8_t * USBMouseKeyboard::reportDesc() {
|
||||
const uint8_t * USBMouseKeyboard::reportDesc() {
|
||||
if (mouse_type == REL_MOUSE) {
|
||||
static uint8_t reportDescriptor[] = {
|
||||
static const uint8_t reportDescriptor[] = {
|
||||
// Keyboard
|
||||
USAGE_PAGE(1), 0x01,
|
||||
USAGE(1), 0x06,
|
||||
|
@ -442,7 +442,7 @@ uint8_t * USBMouseKeyboard::reportDesc() {
|
|||
reportLength = sizeof(reportDescriptor);
|
||||
return reportDescriptor;
|
||||
} else if (mouse_type == ABS_MOUSE) {
|
||||
static uint8_t reportDescriptor[] = {
|
||||
static const uint8_t reportDescriptor[] = {
|
||||
|
||||
// Keyboard
|
||||
USAGE_PAGE(1), 0x01,
|
||||
|
|
|
@ -195,7 +195,7 @@ class USBMouseKeyboard: public USBHID, public Stream
|
|||
*
|
||||
* @returns pointer to the report descriptor
|
||||
*/
|
||||
virtual uint8_t * reportDesc();
|
||||
virtual const uint8_t * reportDesc();
|
||||
|
||||
/*
|
||||
* Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys
|
||||
|
|
|
@ -157,8 +157,8 @@ bool USBMIDI::USBCallback_setConfiguration(uint8_t configuration) {
|
|||
}
|
||||
|
||||
|
||||
uint8_t * USBMIDI::stringIinterfaceDesc() {
|
||||
static uint8_t stringIinterfaceDescriptor[] = {
|
||||
const uint8_t * USBMIDI::stringIinterfaceDesc() {
|
||||
static const uint8_t stringIinterfaceDescriptor[] = {
|
||||
0x0c, //bLength
|
||||
STRING_DESCRIPTOR, //bDescriptorType 0x03
|
||||
'A',0,'u',0,'d',0,'i',0,'o',0 //bString iInterface - Audio
|
||||
|
@ -166,8 +166,8 @@ uint8_t * USBMIDI::stringIinterfaceDesc() {
|
|||
return stringIinterfaceDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBMIDI::stringIproductDesc() {
|
||||
static uint8_t stringIproductDescriptor[] = {
|
||||
const uint8_t * USBMIDI::stringIproductDesc() {
|
||||
static const uint8_t stringIproductDescriptor[] = {
|
||||
0x16, //bLength
|
||||
STRING_DESCRIPTOR, //bDescriptorType 0x03
|
||||
'M',0,'b',0,'e',0,'d',0,' ',0,'A',0,'u',0,'d',0,'i',0,'o',0 //bString iProduct - Mbed Audio
|
||||
|
@ -176,8 +176,8 @@ uint8_t * USBMIDI::stringIproductDesc() {
|
|||
}
|
||||
|
||||
|
||||
uint8_t * USBMIDI::configurationDesc() {
|
||||
static uint8_t configDescriptor[] = {
|
||||
const uint8_t * USBMIDI::configurationDesc() {
|
||||
static const uint8_t configDescriptor[] = {
|
||||
// configuration descriptor
|
||||
0x09, 0x02, 0x65, 0x00, 0x02, 0x01, 0x00, 0xc0, 0x50,
|
||||
|
||||
|
|
|
@ -85,21 +85,21 @@ protected:
|
|||
*
|
||||
* @returns pointer to the string product descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIproductDesc();
|
||||
virtual const uint8_t * stringIproductDesc();
|
||||
|
||||
/*
|
||||
* Get string interface descriptor
|
||||
*
|
||||
* @returns pointer to the string interface descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIinterfaceDesc();
|
||||
virtual const uint8_t * stringIinterfaceDesc();
|
||||
|
||||
/*
|
||||
* Get configuration descriptor
|
||||
*
|
||||
* @returns pointer to the configuration descriptor
|
||||
*/
|
||||
virtual uint8_t * configurationDesc();
|
||||
virtual const uint8_t * configurationDesc();
|
||||
|
||||
private:
|
||||
uint8_t data[MAX_MIDI_MESSAGE_SIZE+1];
|
||||
|
|
|
@ -589,8 +589,8 @@ bool USBMSD::USBCallback_setConfiguration(uint8_t configuration) {
|
|||
}
|
||||
|
||||
|
||||
uint8_t * USBMSD::stringIinterfaceDesc() {
|
||||
static uint8_t stringIinterfaceDescriptor[] = {
|
||||
const uint8_t * USBMSD::stringIinterfaceDesc() {
|
||||
static const uint8_t stringIinterfaceDescriptor[] = {
|
||||
0x08, //bLength
|
||||
STRING_DESCRIPTOR, //bDescriptorType 0x03
|
||||
'M',0,'S',0,'D',0 //bString iInterface - MSD
|
||||
|
@ -598,8 +598,8 @@ uint8_t * USBMSD::stringIinterfaceDesc() {
|
|||
return stringIinterfaceDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBMSD::stringIproductDesc() {
|
||||
static uint8_t stringIproductDescriptor[] = {
|
||||
const uint8_t * USBMSD::stringIproductDesc() {
|
||||
static const uint8_t stringIproductDescriptor[] = {
|
||||
0x12, //bLength
|
||||
STRING_DESCRIPTOR, //bDescriptorType 0x03
|
||||
'M',0,'b',0,'e',0,'d',0,' ',0,'M',0,'S',0,'D',0 //bString iProduct - Mbed Audio
|
||||
|
@ -608,8 +608,8 @@ uint8_t * USBMSD::stringIproductDesc() {
|
|||
}
|
||||
|
||||
|
||||
uint8_t * USBMSD::configurationDesc() {
|
||||
static uint8_t configDescriptor[] = {
|
||||
const uint8_t * USBMSD::configurationDesc() {
|
||||
static const uint8_t configDescriptor[] = {
|
||||
|
||||
// Configuration 1
|
||||
9, // bLength
|
||||
|
|
|
@ -139,21 +139,21 @@ protected:
|
|||
*
|
||||
* @returns pointer to the string product descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIproductDesc();
|
||||
virtual const uint8_t * stringIproductDesc();
|
||||
|
||||
/*
|
||||
* Get string interface descriptor
|
||||
*
|
||||
* @returns pointer to the string interface descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIinterfaceDesc();
|
||||
virtual const uint8_t * stringIinterfaceDesc();
|
||||
|
||||
/*
|
||||
* Get configuration descriptor
|
||||
*
|
||||
* @returns pointer to the configuration descriptor
|
||||
*/
|
||||
virtual uint8_t * configurationDesc();
|
||||
virtual const uint8_t * configurationDesc();
|
||||
|
||||
/*
|
||||
* Callback called when a packet is received
|
||||
|
|
|
@ -144,8 +144,8 @@ bool USBCDC::readEP_NB(uint8_t * buffer, uint32_t * size) {
|
|||
}
|
||||
|
||||
|
||||
uint8_t * USBCDC::deviceDesc() {
|
||||
static uint8_t deviceDescriptor[] = {
|
||||
const uint8_t * USBCDC::deviceDesc() {
|
||||
uint8_t deviceDescriptorTemp[] = {
|
||||
18, // bLength
|
||||
1, // bDescriptorType
|
||||
0x10, 0x01, // bcdUSB
|
||||
|
@ -161,11 +161,13 @@ uint8_t * USBCDC::deviceDesc() {
|
|||
3, // iSerialNumber
|
||||
1 // bNumConfigurations
|
||||
};
|
||||
MBED_ASSERT(sizeof(deviceDescriptorTemp) == sizeof(deviceDescriptor));
|
||||
memcpy(deviceDescriptor, deviceDescriptorTemp, sizeof(deviceDescriptor));
|
||||
return deviceDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBCDC::stringIinterfaceDesc() {
|
||||
static uint8_t stringIinterfaceDescriptor[] = {
|
||||
const uint8_t * USBCDC::stringIinterfaceDesc() {
|
||||
static const uint8_t stringIinterfaceDescriptor[] = {
|
||||
0x08,
|
||||
STRING_DESCRIPTOR,
|
||||
'C',0,'D',0,'C',0,
|
||||
|
@ -173,8 +175,8 @@ uint8_t * USBCDC::stringIinterfaceDesc() {
|
|||
return stringIinterfaceDescriptor;
|
||||
}
|
||||
|
||||
uint8_t * USBCDC::stringIproductDesc() {
|
||||
static uint8_t stringIproductDescriptor[] = {
|
||||
const uint8_t * USBCDC::stringIproductDesc() {
|
||||
static const uint8_t stringIproductDescriptor[] = {
|
||||
0x16,
|
||||
STRING_DESCRIPTOR,
|
||||
'C',0,'D',0,'C',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0
|
||||
|
@ -185,8 +187,8 @@ uint8_t * USBCDC::stringIproductDesc() {
|
|||
|
||||
#define CONFIG1_DESC_SIZE (9+8+9+5+5+4+5+7+9+7+7)
|
||||
|
||||
uint8_t * USBCDC::configurationDesc() {
|
||||
static uint8_t configDescriptor[] = {
|
||||
const uint8_t * USBCDC::configurationDesc() {
|
||||
static const uint8_t configDescriptor[] = {
|
||||
// configuration descriptor
|
||||
9, // bLength
|
||||
2, // bDescriptorType
|
||||
|
|
|
@ -46,28 +46,28 @@ protected:
|
|||
*
|
||||
* @returns pointer to the device descriptor
|
||||
*/
|
||||
virtual uint8_t * deviceDesc();
|
||||
virtual const uint8_t * deviceDesc();
|
||||
|
||||
/*
|
||||
* Get string product descriptor
|
||||
*
|
||||
* @returns pointer to the string product descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIproductDesc();
|
||||
virtual const uint8_t * stringIproductDesc();
|
||||
|
||||
/*
|
||||
* Get string interface descriptor
|
||||
*
|
||||
* @returns pointer to the string interface descriptor
|
||||
*/
|
||||
virtual uint8_t * stringIinterfaceDesc();
|
||||
virtual const uint8_t * stringIinterfaceDesc();
|
||||
|
||||
/*
|
||||
* Get configuration descriptor
|
||||
*
|
||||
* @returns pointer to the configuration descriptor
|
||||
*/
|
||||
virtual uint8_t * configurationDesc();
|
||||
virtual const uint8_t * configurationDesc();
|
||||
|
||||
/*
|
||||
* Send a buffer
|
||||
|
|
|
@ -127,7 +127,7 @@ public:
|
|||
template<typename T>
|
||||
void attach(T* tptr, void (T::*mptr)(void)) {
|
||||
if((mptr != NULL) && (tptr != NULL)) {
|
||||
rx.attach(tptr, mptr);
|
||||
rx = Callback<void()>(mptr, tptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,10 +138,19 @@ public:
|
|||
*/
|
||||
void attach(void (*fptr)(void)) {
|
||||
if(fptr != NULL) {
|
||||
rx.attach(fptr);
|
||||
rx = Callback<void()>(fptr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a Callback called when a packet is received
|
||||
*
|
||||
* @param cb Callback to attach
|
||||
*/
|
||||
void attach(Callback<void()> &cb) {
|
||||
rx = cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a callback to call when serial's settings are changed.
|
||||
*
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "fsl_common.h"
|
||||
#endif
|
||||
#include "USBHAL.h"
|
||||
#include "mbed_critical.h"
|
||||
|
||||
USBHAL * USBHAL::instance;
|
||||
|
||||
|
@ -64,6 +65,13 @@ typedef struct BDT {
|
|||
uint32_t address; // Addr
|
||||
} BDT;
|
||||
|
||||
typedef enum {
|
||||
CTRL_XFER_READY,
|
||||
CTRL_XFER_IN,
|
||||
CTRL_XFER_NONE,
|
||||
CTRL_XFER_OUT
|
||||
} ctrl_xfer_t;
|
||||
|
||||
// there are:
|
||||
// * 4 bidirectionnal endpt -> 8 physical endpt
|
||||
// * as there are ODD and EVEN buffer -> 8*2 bdt
|
||||
|
@ -73,6 +81,7 @@ uint8_t * endpoint_buffer[NUMBER_OF_PHYSICAL_ENDPOINTS * 2];
|
|||
|
||||
static uint8_t set_addr = 0;
|
||||
static uint8_t addr = 0;
|
||||
static ctrl_xfer_t ctrl_xfer = CTRL_XFER_READY;
|
||||
|
||||
static uint32_t Data1 = 0x55555555;
|
||||
|
||||
|
@ -223,11 +232,16 @@ bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flag
|
|||
USB_ENDPT_EPRXEN_MASK; // en RX (OUT) tran.
|
||||
bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket;
|
||||
bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address = (uint32_t) buf;
|
||||
bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_OWN_MASK | BD_DTS_MASK;
|
||||
bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_DTS_MASK;
|
||||
bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info = 0;
|
||||
if (log_endpoint == 0) {
|
||||
// Prepare for setup packet
|
||||
bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info |= BD_OWN_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
Data1 |= (1 << endpoint);
|
||||
// First transfer will be a DATA0 packet
|
||||
Data1 &= ~(1 << endpoint);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -239,13 +253,35 @@ void USBHAL::EP0setup(uint8_t *buffer) {
|
|||
}
|
||||
|
||||
void USBHAL::EP0readStage(void) {
|
||||
Data1 &= ~1UL; // set DATA0
|
||||
bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK);
|
||||
// Not needed
|
||||
}
|
||||
|
||||
void USBHAL::EP0read(void) {
|
||||
uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0);
|
||||
bdt[idx].byte_count = MAX_PACKET_SIZE_EP0;
|
||||
if (ctrl_xfer == CTRL_XFER_READY) {
|
||||
// Transfer is done so ignore call
|
||||
return;
|
||||
}
|
||||
if (ctrl_xfer == CTRL_XFER_IN) {
|
||||
ctrl_xfer = CTRL_XFER_READY;
|
||||
// Control transfer with a data IN stage.
|
||||
// The next packet received will be the status packet - an OUT packet using DATA1
|
||||
//
|
||||
// PROBLEM:
|
||||
// If a Setup packet is received after status packet of
|
||||
// a Control In transfer has been received in the RX buffer
|
||||
// but before the processor has had a chance the prepare
|
||||
// this buffer for the Setup packet, the Setup packet
|
||||
// will be dropped.
|
||||
//
|
||||
// WORKAROUND:
|
||||
// Set data toggle to DATA0 so if the status stage of a
|
||||
// Control In transfer arrives it will be ACKed by hardware
|
||||
// but will be discarded without filling the RX buffer.
|
||||
// This allows a subsequent SETUP packet to be stored
|
||||
// without any processor intervention.
|
||||
Data1 &= ~1UL; // set DATA0
|
||||
}
|
||||
endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
|
||||
}
|
||||
|
||||
uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
|
||||
|
@ -255,6 +291,15 @@ uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
|
|||
}
|
||||
|
||||
void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
|
||||
if (ctrl_xfer == CTRL_XFER_READY) {
|
||||
// Transfer is done so ignore call
|
||||
return;
|
||||
}
|
||||
if ((ctrl_xfer == CTRL_XFER_NONE) || (ctrl_xfer == CTRL_XFER_OUT)) {
|
||||
// Prepare for next setup packet
|
||||
endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
|
||||
ctrl_xfer = CTRL_XFER_READY;
|
||||
}
|
||||
endpointWrite(EP0IN, buffer, size);
|
||||
}
|
||||
|
||||
|
@ -262,13 +307,34 @@ void USBHAL::EP0getWriteResult(void) {
|
|||
}
|
||||
|
||||
void USBHAL::EP0stall(void) {
|
||||
if (ctrl_xfer == CTRL_XFER_READY) {
|
||||
// Transfer is done so ignore call
|
||||
return;
|
||||
}
|
||||
ctrl_xfer = CTRL_XFER_READY;
|
||||
core_util_critical_section_enter();
|
||||
stallEndpoint(EP0OUT);
|
||||
// Prepare for next setup packet
|
||||
// Note - time between stalling and setting up the endpoint
|
||||
// must be kept to a minimum to prevent a dropped SETUP
|
||||
// packet.
|
||||
endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
|
||||
endpoint = PHY_TO_LOG(endpoint);
|
||||
uint32_t idx = EP_BDT_IDX(endpoint, RX, 0);
|
||||
uint8_t log_endpoint = PHY_TO_LOG(endpoint);
|
||||
|
||||
uint32_t idx = EP_BDT_IDX(log_endpoint, RX, 0);
|
||||
bdt[idx].byte_count = maximumSize;
|
||||
if ((Data1 >> endpoint) & 1) {
|
||||
bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
|
||||
}
|
||||
else {
|
||||
bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
|
||||
}
|
||||
|
||||
Data1 ^= (1 << endpoint);
|
||||
return EP_PENDING;
|
||||
}
|
||||
|
||||
|
@ -307,18 +373,14 @@ EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_
|
|||
buffer[n] = ep_buf[n];
|
||||
}
|
||||
|
||||
if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) {
|
||||
if (setup && (buffer[6] == 0)) // if no setup data stage,
|
||||
Data1 &= ~1UL; // set DATA0
|
||||
else
|
||||
Data1 ^= (1 << endpoint);
|
||||
}
|
||||
|
||||
if (((Data1 >> endpoint) & 1)) {
|
||||
bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK;
|
||||
}
|
||||
else {
|
||||
bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK;
|
||||
if (setup) {
|
||||
// Record the setup type
|
||||
if (buffer[6] == 0) {
|
||||
ctrl_xfer = CTRL_XFER_NONE;
|
||||
} else {
|
||||
uint8_t in_xfer = (buffer[0] >> 7) & 1;
|
||||
ctrl_xfer = in_xfer ? CTRL_XFER_IN : CTRL_XFER_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
|
||||
|
@ -351,9 +413,9 @@ EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
|
|||
}
|
||||
|
||||
if ((Data1 >> endpoint) & 1) {
|
||||
bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
|
||||
} else {
|
||||
bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
|
||||
} else {
|
||||
bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
|
||||
}
|
||||
|
||||
Data1 ^= (1 << endpoint);
|
||||
|
@ -438,7 +500,7 @@ void USBHAL::usbisr(void) {
|
|||
if (istat & 1<<7) {
|
||||
if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK)
|
||||
USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
|
||||
USB0->ISTAT |= USB_ISTAT_STALL_MASK;
|
||||
USB0->ISTAT = USB_ISTAT_STALL_MASK;
|
||||
}
|
||||
|
||||
// token interrupt
|
||||
|
@ -450,7 +512,7 @@ void USBHAL::usbisr(void) {
|
|||
|
||||
// setup packet
|
||||
if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) {
|
||||
Data1 &= ~0x02;
|
||||
Data1 |= 0x02 | 0x01; // set DATA1 for TX and RX
|
||||
bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK;
|
||||
bdt[EP_BDT_IDX(0, TX, ODD)].info &= ~BD_OWN_MASK;
|
||||
|
||||
|
@ -493,13 +555,13 @@ void USBHAL::usbisr(void) {
|
|||
|
||||
// sleep interrupt
|
||||
if (istat & 1<<4) {
|
||||
USB0->ISTAT |= USB_ISTAT_SLEEP_MASK;
|
||||
USB0->ISTAT = USB_ISTAT_SLEEP_MASK;
|
||||
}
|
||||
|
||||
// error interrupt
|
||||
if (istat & USB_ISTAT_ERROR_MASK) {
|
||||
USB0->ERRSTAT = 0xFF;
|
||||
USB0->ISTAT |= USB_ISTAT_ERROR_MASK;
|
||||
USB0->ISTAT = USB_ISTAT_ERROR_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -275,11 +275,6 @@ uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
|
|||
|
||||
LPC_USB->USBCtrl = 0;
|
||||
|
||||
if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
|
||||
SIEselectEndpoint(endpoint);
|
||||
SIEclearBuffer();
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -431,7 +426,7 @@ void USBHAL::EP0setup(uint8_t *buffer) {
|
|||
}
|
||||
|
||||
void USBHAL::EP0read(void) {
|
||||
// Not required
|
||||
endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
|
||||
}
|
||||
|
||||
void USBHAL::EP0readStage(void) {
|
||||
|
@ -456,6 +451,11 @@ void USBHAL::EP0stall(void) {
|
|||
}
|
||||
|
||||
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
|
||||
// Don't clear isochronous endpoints
|
||||
if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
|
||||
SIEselectEndpoint(endpoint);
|
||||
SIEclearBuffer();
|
||||
}
|
||||
return EP_PENDING;
|
||||
}
|
||||
|
||||
|
@ -590,6 +590,25 @@ void USBHAL::usbisr(void) {
|
|||
if (LPC_USB->USBDevIntSt & EP_SLOW) {
|
||||
// (Slow) Endpoint Interrupt
|
||||
|
||||
// Process IN packets before SETUP packets
|
||||
// Note - order of OUT and SETUP does not matter as OUT packets
|
||||
// are clobbered by SETUP packets and thus ignored.
|
||||
//
|
||||
// A SETUP packet can arrive at any time where as an IN packet is
|
||||
// only sent after calling EP0write and an OUT packet after EP0read.
|
||||
// The functions EP0write and EP0read are called only in response to
|
||||
// a setup packet or IN/OUT packets sent in response to that
|
||||
// setup packet. Therefore, if an IN or OUT packet is pending
|
||||
// at the same time as a SETUP packet, the IN or OUT packet belongs
|
||||
// to the previous control transfer and should either be processed
|
||||
// before the SETUP packet (in the case of IN) or dropped (in the
|
||||
// case of OUT as SETUP clobbers the OUT data).
|
||||
if (LPC_USB->USBEpIntSt & EP(EP0IN)) {
|
||||
selectEndpointClearInterrupt(EP0IN);
|
||||
LPC_USB->USBDevIntClr = EP_SLOW;
|
||||
EP0in();
|
||||
}
|
||||
|
||||
// Process each endpoint interrupt
|
||||
if (LPC_USB->USBEpIntSt & EP(EP0OUT)) {
|
||||
if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
|
||||
|
@ -601,12 +620,6 @@ void USBHAL::usbisr(void) {
|
|||
LPC_USB->USBDevIntClr = EP_SLOW;
|
||||
}
|
||||
|
||||
if (LPC_USB->USBEpIntSt & EP(EP0IN)) {
|
||||
selectEndpointClearInterrupt(EP0IN);
|
||||
LPC_USB->USBDevIntClr = EP_SLOW;
|
||||
EP0in();
|
||||
}
|
||||
|
||||
for (uint8_t num = 2; num < 16*2; num++) {
|
||||
if (LPC_USB->USBEpIntSt & EP(num)) {
|
||||
selectEndpointClearInterrupt(num);
|
||||
|
|
|
@ -276,11 +276,6 @@ uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
|
|||
|
||||
LPC_USB->Ctrl = 0;
|
||||
|
||||
if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
|
||||
SIEselectEndpoint(endpoint);
|
||||
SIEclearBuffer();
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -436,7 +431,7 @@ void USBHAL::EP0setup(uint8_t *buffer) {
|
|||
}
|
||||
|
||||
void USBHAL::EP0read(void) {
|
||||
// Not required
|
||||
endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
|
||||
}
|
||||
|
||||
void USBHAL::EP0readStage(void) {
|
||||
|
@ -461,6 +456,11 @@ void USBHAL::EP0stall(void) {
|
|||
}
|
||||
|
||||
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
|
||||
// Don't clear isochronous endpoints
|
||||
if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
|
||||
SIEselectEndpoint(endpoint);
|
||||
SIEclearBuffer();
|
||||
}
|
||||
return EP_PENDING;
|
||||
}
|
||||
|
||||
|
@ -595,6 +595,25 @@ void USBHAL::usbisr(void) {
|
|||
if (LPC_USB->DevIntSt & EP_SLOW) {
|
||||
// (Slow) Endpoint Interrupt
|
||||
|
||||
// Process IN packets before SETUP packets
|
||||
// Note - order of OUT and SETUP does not matter as OUT packets
|
||||
// are clobbered by SETUP packets and thus ignored.
|
||||
//
|
||||
// A SETUP packet can arrive at any time where as an IN packet is
|
||||
// only sent after calling EP0write and an OUT packet after EP0read.
|
||||
// The functions EP0write and EP0read are called only in response to
|
||||
// a setup packet or IN/OUT packets sent in response to that
|
||||
// setup packet. Therefore, if an IN or OUT packet is pending
|
||||
// at the same time as a SETUP packet, the IN or OUT packet belongs
|
||||
// to the previous control transfer and should either be processed
|
||||
// before the SETUP packet (in the case of IN) or dropped (in the
|
||||
// case of OUT as SETUP clobbers the OUT data).
|
||||
if (LPC_USB->EpIntSt & EP(EP0IN)) {
|
||||
selectEndpointClearInterrupt(EP0IN);
|
||||
LPC_USB->DevIntClr = EP_SLOW;
|
||||
EP0in();
|
||||
}
|
||||
|
||||
// Process each endpoint interrupt
|
||||
if (LPC_USB->EpIntSt & EP(EP0OUT)) {
|
||||
if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
|
||||
|
@ -606,12 +625,6 @@ void USBHAL::usbisr(void) {
|
|||
LPC_USB->DevIntClr = EP_SLOW;
|
||||
}
|
||||
|
||||
if (LPC_USB->EpIntSt & EP(EP0IN)) {
|
||||
selectEndpointClearInterrupt(EP0IN);
|
||||
LPC_USB->DevIntClr = EP_SLOW;
|
||||
EP0in();
|
||||
}
|
||||
|
||||
for (uint8_t num = 2; num < 16*2; num++) {
|
||||
if (LPC_USB->EpIntSt & EP(num)) {
|
||||
selectEndpointClearInterrupt(num);
|
||||
|
|
|
@ -106,7 +106,7 @@ public:
|
|||
template<typename T>
|
||||
inline void onDisconnect(uint8_t intf_nb, T* tptr, void (T::*mptr)(void)) {
|
||||
if ((mptr != NULL) && (tptr != NULL)) {
|
||||
intf[intf_nb].detach.attach(tptr, mptr);
|
||||
intf[intf_nb].detach = callback(tptr, mptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ public:
|
|||
*/
|
||||
inline void onDisconnect(uint8_t intf_nb, void (*fn)(void)) {
|
||||
if (fn != NULL) {
|
||||
intf[intf_nb].detach.attach(fn);
|
||||
intf[intf_nb].detach = fn;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ public:
|
|||
template<typename T>
|
||||
inline void attach(T* tptr, void (T::*mptr)(void)) {
|
||||
if((mptr != NULL) && (tptr != NULL)) {
|
||||
rx.attach(tptr, mptr);
|
||||
rx = callback(tptr, mptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ public:
|
|||
*/
|
||||
inline void attach(void (*fptr)(void)) {
|
||||
if(fptr != NULL) {
|
||||
rx.attach(fptr);
|
||||
rx = fptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,11 +88,14 @@ void USBHost::usb_process()
|
|||
/* check that hub is connected to root port */
|
||||
if (usb_msg->hub_parent) {
|
||||
/* a hub device must be present */
|
||||
#if MAX_HUB_NB
|
||||
|
||||
for (k = 0; k < MAX_HUB_NB; k++) {
|
||||
if ((&hubs[k] == usb_msg->hub_parent) && (hub_in_use[k])) {
|
||||
hub_unplugged=false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
hub_unplugged = false;
|
||||
}
|
||||
|
@ -312,7 +315,7 @@ USBHost::USBHost() : usbThread(osPriorityNormal, USB_THREAD_STACK)
|
|||
}
|
||||
#endif
|
||||
|
||||
usbThread.start(this, &USBHost::usb_process);
|
||||
usbThread.start(callback(this, &USBHost::usb_process));
|
||||
}
|
||||
|
||||
USBHost::Lock::Lock(USBHost* pHost) : m_pHost(pHost)
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
#include "mbed.h"
|
||||
#include "test_env.h"
|
||||
|
||||
void print_char(char c = '*')
|
||||
{
|
||||
printf("%c", c);
|
||||
fflush(stdout);
|
||||
}
|
||||
RawSerial pc(USBTX, USBRX);
|
||||
|
||||
Ticker flipper_1;
|
||||
DigitalOut led1(LED1);
|
||||
|
@ -17,7 +13,7 @@ void flip_1() {
|
|||
} else {
|
||||
led1 = 1; led1_state = 1;
|
||||
}
|
||||
print_char();
|
||||
pc.putc('*');
|
||||
}
|
||||
|
||||
Ticker flipper_2;
|
||||
|
|
|
@ -110,7 +110,6 @@ static us_timestamp_t convert_timestamp(us_timestamp_t ref, timestamp_t timestam
|
|||
*/
|
||||
static void update_present_time(const ticker_data_t *const ticker)
|
||||
{
|
||||
|
||||
ticker_event_queue_t *queue = ticker->queue;
|
||||
uint32_t ticker_time = ticker->interface->read();
|
||||
if (ticker_time == ticker->queue->tick_last_read) {
|
||||
|
@ -252,11 +251,16 @@ static void schedule_interrupt(const ticker_data_t *const ticker)
|
|||
void ticker_set_handler(const ticker_data_t *const ticker, ticker_event_handler handler)
|
||||
{
|
||||
initialize(ticker);
|
||||
|
||||
core_util_critical_section_enter();
|
||||
set_handler(ticker, handler);
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
void ticker_irq_handler(const ticker_data_t *const ticker)
|
||||
{
|
||||
core_util_critical_section_enter();
|
||||
|
||||
ticker->interface->clear_interrupt();
|
||||
|
||||
/* Go through all the pending TimerEvents */
|
||||
|
@ -284,6 +288,8 @@ void ticker_irq_handler(const ticker_data_t *const ticker)
|
|||
}
|
||||
|
||||
schedule_interrupt(ticker);
|
||||
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
void ticker_insert_event(const ticker_data_t *const ticker, ticker_event_t *obj, timestamp_t timestamp, uint32_t id)
|
||||
|
@ -296,13 +302,14 @@ void ticker_insert_event(const ticker_data_t *const ticker, ticker_event_t *obj,
|
|||
ticker->queue->present_time,
|
||||
timestamp
|
||||
);
|
||||
core_util_critical_section_exit();
|
||||
|
||||
// defer to ticker_insert_event_us
|
||||
ticker_insert_event_us(
|
||||
ticker,
|
||||
obj, absolute_timestamp, id
|
||||
);
|
||||
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
void ticker_insert_event_us(const ticker_data_t *const ticker, ticker_event_t *obj, us_timestamp_t timestamp, uint32_t id)
|
||||
|
@ -343,6 +350,7 @@ void ticker_insert_event_us(const ticker_data_t *const ticker, ticker_event_t *o
|
|||
schedule_interrupt(ticker);
|
||||
|
||||
core_util_critical_section_exit();
|
||||
|
||||
}
|
||||
|
||||
void ticker_remove_event(const ticker_data_t *const ticker, ticker_event_t *obj)
|
||||
|
@ -377,7 +385,11 @@ timestamp_t ticker_read(const ticker_data_t *const ticker)
|
|||
us_timestamp_t ticker_read_us(const ticker_data_t *const ticker)
|
||||
{
|
||||
initialize(ticker);
|
||||
|
||||
core_util_critical_section_enter();
|
||||
update_present_time(ticker);
|
||||
core_util_critical_section_exit();
|
||||
|
||||
return ticker->queue->present_time;
|
||||
}
|
||||
|
||||
|
|
4
mbed.h
4
mbed.h
|
@ -16,13 +16,13 @@
|
|||
#ifndef MBED_H
|
||||
#define MBED_H
|
||||
|
||||
#define MBED_LIBRARY_VERSION 158
|
||||
#define MBED_LIBRARY_VERSION 159
|
||||
|
||||
#if MBED_CONF_RTOS_PRESENT
|
||||
// RTOS present, this is valid only for mbed OS 5
|
||||
#define MBED_MAJOR_VERSION 5
|
||||
#define MBED_MINOR_VERSION 7
|
||||
#define MBED_PATCH_VERSION 3
|
||||
#define MBED_PATCH_VERSION 4
|
||||
|
||||
#else
|
||||
// mbed 2
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define MBED_CRITICALSECTIONLOCK_H
|
||||
|
||||
#include "platform/mbed_critical.h"
|
||||
#include "platform/mbed_toolchain.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
|
|
|
@ -81,12 +81,18 @@ extern "C" {
|
|||
void * __real__realloc_r(struct _reent * r, void * ptr, size_t size);
|
||||
void __real__free_r(struct _reent * r, void * ptr);
|
||||
void* __real__calloc_r(struct _reent * r, size_t nmemb, size_t size);
|
||||
void* malloc_wrapper(struct _reent * r, size_t size, void * caller);
|
||||
void free_wrapper(struct _reent * r, void * ptr, void* caller);
|
||||
}
|
||||
|
||||
// TODO: memory tracing doesn't work with uVisor enabled.
|
||||
#if !defined(FEATURE_UVISOR)
|
||||
|
||||
extern "C" void * __wrap__malloc_r(struct _reent * r, size_t size) {
|
||||
return malloc_wrapper(r, size, MBED_CALLER_ADDR());
|
||||
}
|
||||
|
||||
extern "C" void * malloc_wrapper(struct _reent * r, size_t size, void * caller) {
|
||||
void *ptr = NULL;
|
||||
#ifdef MBED_MEM_TRACING_ENABLED
|
||||
mbed_mem_trace_lock();
|
||||
|
@ -111,7 +117,7 @@ extern "C" void * __wrap__malloc_r(struct _reent * r, size_t size) {
|
|||
ptr = __real__malloc_r(r, size);
|
||||
#endif // #ifdef MBED_HEAP_STATS_ENABLED
|
||||
#ifdef MBED_MEM_TRACING_ENABLED
|
||||
mbed_mem_trace_malloc(ptr, size, MBED_CALLER_ADDR());
|
||||
mbed_mem_trace_malloc(ptr, size, caller);
|
||||
mbed_mem_trace_unlock();
|
||||
#endif // #ifdef MBED_MEM_TRACING_ENABLED
|
||||
return ptr;
|
||||
|
@ -160,6 +166,10 @@ extern "C" void * __wrap__realloc_r(struct _reent * r, void * ptr, size_t size)
|
|||
}
|
||||
|
||||
extern "C" void __wrap__free_r(struct _reent * r, void * ptr) {
|
||||
free_wrapper(r, ptr, MBED_CALLER_ADDR());
|
||||
}
|
||||
|
||||
extern "C" void free_wrapper(struct _reent * r, void * ptr, void * caller) {
|
||||
#ifdef MBED_MEM_TRACING_ENABLED
|
||||
mbed_mem_trace_lock();
|
||||
#endif
|
||||
|
@ -177,7 +187,7 @@ extern "C" void __wrap__free_r(struct _reent * r, void * ptr) {
|
|||
__real__free_r(r, ptr);
|
||||
#endif // #ifdef MBED_HEAP_STATS_ENABLED
|
||||
#ifdef MBED_MEM_TRACING_ENABLED
|
||||
mbed_mem_trace_free(ptr, MBED_CALLER_ADDR());
|
||||
mbed_mem_trace_free(ptr, caller);
|
||||
mbed_mem_trace_unlock();
|
||||
#endif // #ifdef MBED_MEM_TRACING_ENABLED
|
||||
}
|
||||
|
@ -245,9 +255,16 @@ extern "C" {
|
|||
void *SUPER_REALLOC(void *ptr, size_t size);
|
||||
void *SUPER_CALLOC(size_t nmemb, size_t size);
|
||||
void SUPER_FREE(void *ptr);
|
||||
void *malloc_wrapper(size_t size, void* caller);
|
||||
void free_wrapper(void *ptr, void* caller);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void* SUB_MALLOC(size_t size) {
|
||||
return malloc_wrapper(size, MBED_CALLER_ADDR());
|
||||
}
|
||||
|
||||
extern "C" void* malloc_wrapper(size_t size, void* caller) {
|
||||
void *ptr = NULL;
|
||||
#ifdef MBED_MEM_TRACING_ENABLED
|
||||
mbed_mem_trace_lock();
|
||||
|
@ -272,12 +289,13 @@ extern "C" void* SUB_MALLOC(size_t size) {
|
|||
ptr = SUPER_MALLOC(size);
|
||||
#endif // #ifdef MBED_HEAP_STATS_ENABLED
|
||||
#ifdef MBED_MEM_TRACING_ENABLED
|
||||
mbed_mem_trace_malloc(ptr, size, MBED_CALLER_ADDR());
|
||||
mbed_mem_trace_malloc(ptr, size, caller);
|
||||
mbed_mem_trace_unlock();
|
||||
#endif // #ifdef MBED_MEM_TRACING_ENABLED
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void* SUB_REALLOC(void *ptr, size_t size) {
|
||||
void *new_ptr = NULL;
|
||||
#ifdef MBED_MEM_TRACING_ENABLED
|
||||
|
@ -337,6 +355,10 @@ extern "C" void *SUB_CALLOC(size_t nmemb, size_t size) {
|
|||
}
|
||||
|
||||
extern "C" void SUB_FREE(void *ptr) {
|
||||
free_wrapper(ptr, MBED_CALLER_ADDR());
|
||||
}
|
||||
|
||||
extern "C" void free_wrapper(void *ptr, void* caller) {
|
||||
#ifdef MBED_MEM_TRACING_ENABLED
|
||||
mbed_mem_trace_lock();
|
||||
#endif
|
||||
|
@ -354,7 +376,7 @@ extern "C" void SUB_FREE(void *ptr) {
|
|||
SUPER_FREE(ptr);
|
||||
#endif // #ifdef MBED_HEAP_STATS_ENABLED
|
||||
#ifdef MBED_MEM_TRACING_ENABLED
|
||||
mbed_mem_trace_free(ptr, MBED_CALLER_ADDR());
|
||||
mbed_mem_trace_free(ptr, caller);
|
||||
mbed_mem_trace_unlock();
|
||||
#endif // #ifdef MBED_MEM_TRACING_ENABLED
|
||||
}
|
||||
|
|
|
@ -1022,6 +1022,99 @@ extern "C" void __cxa_guard_abort(int *guard_object_p)
|
|||
|
||||
#endif
|
||||
|
||||
#if defined(MBED_MEM_TRACING_ENABLED) && (defined(__CC_ARM) || defined(__ICCARM__))
|
||||
|
||||
// If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp
|
||||
// provide the implementation for these. Note: this needs to use the wrappers
|
||||
// instead of malloc()/free() as the caller address would point to wrappers,
|
||||
// not the caller of "new" or "delete".
|
||||
extern "C" void* malloc_wrapper(size_t size, const void* caller);
|
||||
extern "C" void free_wrapper(void *ptr, const void* caller);
|
||||
|
||||
void *operator new(std::size_t count)
|
||||
{
|
||||
void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR());
|
||||
if (NULL == buffer) {
|
||||
error("Operator new out of memory\r\n");
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void *operator new[](std::size_t count)
|
||||
{
|
||||
void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR());
|
||||
if (NULL == buffer) {
|
||||
error("Operator new[] out of memory\r\n");
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void *operator new(std::size_t count, const std::nothrow_t& tag)
|
||||
{
|
||||
return malloc_wrapper(count, MBED_CALLER_ADDR());
|
||||
}
|
||||
|
||||
void *operator new[](std::size_t count, const std::nothrow_t& tag)
|
||||
{
|
||||
return malloc_wrapper(count, MBED_CALLER_ADDR());
|
||||
}
|
||||
|
||||
void operator delete(void *ptr)
|
||||
{
|
||||
free_wrapper(ptr, MBED_CALLER_ADDR());
|
||||
}
|
||||
void operator delete[](void *ptr)
|
||||
{
|
||||
free_wrapper(ptr, MBED_CALLER_ADDR());
|
||||
}
|
||||
|
||||
#elif defined(MBED_MEM_TRACING_ENABLED) && defined(__GNUC__)
|
||||
|
||||
#include <reent.h>
|
||||
|
||||
extern "C" void* malloc_wrapper(struct _reent * r, size_t size, void * caller);
|
||||
extern "C" void free_wrapper(struct _reent * r, void * ptr, void * caller);
|
||||
|
||||
void *operator new(std::size_t count)
|
||||
{
|
||||
void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
|
||||
if (NULL == buffer) {
|
||||
error("Operator new out of memory\r\n");
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void *operator new[](std::size_t count)
|
||||
{
|
||||
void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
|
||||
if (NULL == buffer) {
|
||||
error("Operator new[] out of memory\r\n");
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void *operator new(std::size_t count, const std::nothrow_t& tag)
|
||||
{
|
||||
return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
|
||||
}
|
||||
|
||||
void *operator new[](std::size_t count, const std::nothrow_t& tag)
|
||||
{
|
||||
return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
|
||||
}
|
||||
|
||||
void operator delete(void *ptr)
|
||||
{
|
||||
free_wrapper(_REENT, ptr, MBED_CALLER_ADDR());
|
||||
}
|
||||
|
||||
void operator delete[](void *ptr)
|
||||
{
|
||||
free_wrapper(_REENT, ptr, MBED_CALLER_ADDR());
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void *operator new(std::size_t count)
|
||||
{
|
||||
void *buffer = malloc(count);
|
||||
|
@ -1059,6 +1152,8 @@ void operator delete[](void *ptr)
|
|||
free(ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* @brief standard c library clock() function.
|
||||
*
|
||||
* This function returns the number of clock ticks elapsed since the start of the program.
|
||||
|
|
|
@ -118,7 +118,10 @@ struct Waiter;
|
|||
*/
|
||||
class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
|
||||
public:
|
||||
/** Create and Initialize a ConditionVariable object */
|
||||
/** Create and Initialize a ConditionVariable object
|
||||
*
|
||||
* @note You may call this function from ISR context.
|
||||
*/
|
||||
ConditionVariable(Mutex &mutex);
|
||||
|
||||
/** Wait for a notification
|
||||
|
@ -142,6 +145,8 @@ public:
|
|||
*
|
||||
* mutex.unlock();
|
||||
* @endcode
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
void wait();
|
||||
|
||||
|
@ -176,21 +181,31 @@ public:
|
|||
*
|
||||
* mutex.unlock();
|
||||
* @endcode
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
bool wait_for(uint32_t millisec);
|
||||
|
||||
/** Notify one waiter on this condition variable that a condition changed.
|
||||
*
|
||||
* @note - The thread calling this function must be the owner of the ConditionVariable's mutex
|
||||
*
|
||||
* @note This function may be called from ISR context.
|
||||
*/
|
||||
void notify_one();
|
||||
|
||||
/** Notify all waiters on this condition variable that a condition changed.
|
||||
*
|
||||
* @note - The thread calling this function must be the owner of the ConditionVariable's mutex
|
||||
*
|
||||
* @note This function may be called from ISR context.
|
||||
*/
|
||||
void notify_all();
|
||||
|
||||
/** ConditionVariable destructor
|
||||
*
|
||||
* @note You may call this function from ISR context.
|
||||
*/
|
||||
~ConditionVariable();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -46,29 +46,40 @@ namespace rtos {
|
|||
*/
|
||||
class EventFlags : private mbed::NonCopyable<EventFlags> {
|
||||
public:
|
||||
/** Create and Initialize a EventFlags object */
|
||||
/** Create and Initialize an EventFlags object
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
EventFlags();
|
||||
|
||||
/** Create and Initialize a EventFlags object
|
||||
|
||||
@param name name to be used for this EventFlags. It has to stay allocated for the lifetime of the thread.
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
EventFlags(const char *name);
|
||||
|
||||
/** Set the specified Event Flags.
|
||||
@param flags specifies the flags that shall be set.
|
||||
@return event flags after setting or error code if highest bit set (@a osFlagsError).
|
||||
|
||||
@note This function may be called from ISR context.
|
||||
*/
|
||||
uint32_t set(uint32_t flags);
|
||||
|
||||
/** Clear the specified Event Flags.
|
||||
@param flags specifies the flags that shall be cleared. (default: 0x7fffffff - all flags)
|
||||
@return event flags before clearing or error code if highest bit set (@a osFlagsError).
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
uint32_t clear(uint32_t flags = 0x7fffffff);
|
||||
|
||||
/** Get the currently set Event Flags.
|
||||
@return set event flags.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
uint32_t get() const;
|
||||
|
||||
|
@ -77,6 +88,8 @@ public:
|
|||
@param timeout timeout value or 0 in case of no time-out. (default: osWaitForever)
|
||||
@param clear specifies wether to clear the flags after waiting for them. (default: true)
|
||||
@return event flags before clearing or error code if highest bit set (@a osFlagsError).
|
||||
|
||||
@note You may call this function from ISR context if the timeout parameter is set to 0.
|
||||
*/
|
||||
uint32_t wait_all(uint32_t flags = 0, uint32_t timeout = osWaitForever, bool clear = true);
|
||||
|
||||
|
@ -85,9 +98,15 @@ public:
|
|||
@param timeout timeout value or 0 in case of no time-out. (default: osWaitForever)
|
||||
@param clear specifies wether to clear the flags after waiting for them. (default: true)
|
||||
@return event flags before clearing or error code if highest bit set (@a osFlagsError).
|
||||
|
||||
@note This function may be called from ISR context if the timeout parameter is set to 0.
|
||||
*/
|
||||
uint32_t wait_any(uint32_t flags = 0, uint32_t timeout = osWaitForever, bool clear = true);
|
||||
|
||||
/** Event flags destructor
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
~EventFlags();
|
||||
|
||||
private:
|
||||
|
|
19
rtos/Mail.h
19
rtos/Mail.h
|
@ -55,12 +55,17 @@ namespace rtos {
|
|||
template<typename T, uint32_t queue_sz>
|
||||
class Mail : private mbed::NonCopyable<Mail<T, queue_sz> > {
|
||||
public:
|
||||
/** Create and Initialise Mail queue. */
|
||||
/** Create and Initialize Mail queue.
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
Mail() { };
|
||||
|
||||
/** Check if the mail queue is empty
|
||||
*
|
||||
* @return True if the mail queue is empty, false if not
|
||||
*
|
||||
* @note You may call this function from ISR context.
|
||||
*/
|
||||
bool empty() const {
|
||||
return _queue.empty();
|
||||
|
@ -69,6 +74,8 @@ public:
|
|||
/** Check if the mail queue is full
|
||||
*
|
||||
* @return True if the mail queue is full, false if not
|
||||
*
|
||||
* @note You may call this function from ISR context.
|
||||
*/
|
||||
bool full() const {
|
||||
return _queue.full();
|
||||
|
@ -77,6 +84,8 @@ public:
|
|||
/** Allocate a memory block of type T
|
||||
@param millisec timeout value or 0 in case of no time-out. (default: 0).
|
||||
@return pointer to memory block that can be filled with mail or NULL in case error.
|
||||
|
||||
@note You may call this function from ISR context if the millisec parameter is set to 0.
|
||||
*/
|
||||
T* alloc(uint32_t millisec=0) {
|
||||
return _pool.alloc();
|
||||
|
@ -85,6 +94,8 @@ public:
|
|||
/** Allocate a memory block of type T and set memory block to zero.
|
||||
@param millisec timeout value or 0 in case of no time-out. (default: 0).
|
||||
@return pointer to memory block that can be filled with mail or NULL in case error.
|
||||
|
||||
@note You may call this function from ISR context if the millisec parameter is set to 0.
|
||||
*/
|
||||
T* calloc(uint32_t millisec=0) {
|
||||
return _pool.calloc();
|
||||
|
@ -93,6 +104,8 @@ public:
|
|||
/** Put a mail in the queue.
|
||||
@param mptr memory block previously allocated with Mail::alloc or Mail::calloc.
|
||||
@return status code that indicates the execution status of the function.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
osStatus put(T *mptr) {
|
||||
return _queue.put(mptr);
|
||||
|
@ -101,6 +114,8 @@ public:
|
|||
/** Get a mail from a queue.
|
||||
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever).
|
||||
@return event that contains mail information or error code.
|
||||
|
||||
@note You may call this function from ISR context if the millisec parameter is set to 0.
|
||||
*/
|
||||
osEvent get(uint32_t millisec=osWaitForever) {
|
||||
osEvent evt = _queue.get(millisec);
|
||||
|
@ -113,6 +128,8 @@ public:
|
|||
/** Free a memory block from a mail.
|
||||
@param mptr pointer to the memory block that was obtained with Mail::get.
|
||||
@return status code that indicates the execution status of the function.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
osStatus free(T *mptr) {
|
||||
return _pool.free(mptr);
|
||||
|
|
|
@ -50,7 +50,10 @@ template<typename T, uint32_t pool_sz>
|
|||
class MemoryPool : private mbed::NonCopyable<MemoryPool<T, pool_sz> > {
|
||||
MBED_STATIC_ASSERT(pool_sz > 0, "Invalid memory pool size. Must be greater than 0.");
|
||||
public:
|
||||
/** Create and Initialize a memory pool. */
|
||||
/** Create and Initialize a memory pool.
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
MemoryPool() {
|
||||
memset(_pool_mem, 0, sizeof(_pool_mem));
|
||||
memset(&_obj_mem, 0, sizeof(_obj_mem));
|
||||
|
@ -63,13 +66,18 @@ public:
|
|||
MBED_ASSERT(_id);
|
||||
}
|
||||
|
||||
/** Destroy a memory pool */
|
||||
/** Destroy a memory pool
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
~MemoryPool() {
|
||||
osMemoryPoolDelete(_id);
|
||||
}
|
||||
|
||||
/** Allocate a memory block of type T from a memory pool.
|
||||
@return address of the allocated memory block or NULL in case of no memory available.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
T* alloc(void) {
|
||||
return (T*)osMemoryPoolAlloc(_id, 0);
|
||||
|
@ -77,6 +85,8 @@ public:
|
|||
|
||||
/** Allocate a memory block of type T from a memory pool and set memory block to zero.
|
||||
@return address of the allocated memory block or NULL in case of no memory available.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
T* calloc(void) {
|
||||
T *item = (T*)osMemoryPoolAlloc(_id, 0);
|
||||
|
@ -92,6 +102,7 @@ public:
|
|||
is NULL or invalid, or osErrorResource if given memory block is in an
|
||||
invalid memory pool state.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
osStatus free(T *block) {
|
||||
return osMemoryPoolFree(_id, (void*)block);
|
||||
|
|
22
rtos/Mutex.h
22
rtos/Mutex.h
|
@ -40,18 +40,26 @@ namespace rtos {
|
|||
/** The Mutex class is used to synchronize the execution of threads.
|
||||
This is for example used to protect access to a shared resource.
|
||||
|
||||
@note You cannot use member functions of this class in ISR context. If you require Mutex functionality within
|
||||
ISR handler, consider using @a Semaphore.
|
||||
|
||||
@note
|
||||
Memory considerations: The mutex control structures will be created on current thread's stack, both for the mbed OS
|
||||
and underlying RTOS objects (static or dynamic RTOS memory pools are not being used).
|
||||
*/
|
||||
class Mutex : private mbed::NonCopyable<Mutex> {
|
||||
public:
|
||||
/** Create and Initialize a Mutex object */
|
||||
/** Create and Initialize a Mutex object
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
Mutex();
|
||||
|
||||
/** Create and Initialize a Mutex object
|
||||
|
||||
@param name name to be used for this mutex. It has to stay allocated for the lifetime of the thread.
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
Mutex(const char *name);
|
||||
|
||||
|
@ -63,11 +71,15 @@ public:
|
|||
@a osErrorParameter internal error.
|
||||
@a osErrorResource the mutex could not be obtained when no timeout was specified.
|
||||
@a osErrorISR this function cannot be called from the interrupt service routine.
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
osStatus lock(uint32_t millisec=osWaitForever);
|
||||
|
||||
/** Try to lock the mutex, and return immediately
|
||||
@return true if the mutex was acquired, false otherwise.
|
||||
|
||||
@note This function cannot be called from ISR context.
|
||||
*/
|
||||
bool trylock();
|
||||
|
||||
|
@ -77,14 +89,22 @@ public:
|
|||
@a osErrorParameter internal error.
|
||||
@a osErrorResource the mutex was not locked or the current thread wasn't the owner.
|
||||
@a osErrorISR this function cannot be called from the interrupt service routine.
|
||||
|
||||
@note This function cannot be called from ISR context.
|
||||
*/
|
||||
osStatus unlock();
|
||||
|
||||
/** Get the owner the this mutex
|
||||
@return the current owner of this mutex.
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
osThreadId get_owner();
|
||||
|
||||
/** Mutex destructor
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
~Mutex();
|
||||
|
||||
private:
|
||||
|
|
18
rtos/Queue.h
18
rtos/Queue.h
|
@ -52,7 +52,10 @@ namespace rtos {
|
|||
template<typename T, uint32_t queue_sz>
|
||||
class Queue : private mbed::NonCopyable<Queue<T, queue_sz> > {
|
||||
public:
|
||||
/** Create and initialize a message Queue. */
|
||||
/** Create and initialize a message Queue.
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
Queue() {
|
||||
memset(&_obj_mem, 0, sizeof(_obj_mem));
|
||||
osMessageQueueAttr_t attr = { 0 };
|
||||
|
@ -63,7 +66,10 @@ public:
|
|||
_id = osMessageQueueNew(queue_sz, sizeof(T*), &attr);
|
||||
MBED_ASSERT(_id);
|
||||
}
|
||||
|
||||
/** Queue destructor
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
~Queue() {
|
||||
osMessageQueueDelete(_id);
|
||||
}
|
||||
|
@ -71,6 +77,8 @@ public:
|
|||
/** Check if the queue is empty
|
||||
*
|
||||
* @return True if the queue is empty, false if not
|
||||
*
|
||||
* @note You may call this function from ISR context.
|
||||
*/
|
||||
bool empty() const {
|
||||
return osMessageQueueGetCount(_id) == 0;
|
||||
|
@ -79,6 +87,8 @@ public:
|
|||
/** Check if the queue is full
|
||||
*
|
||||
* @return True if the queue is full, false if not
|
||||
*
|
||||
* @note You may call this function from ISR context.
|
||||
*/
|
||||
bool full() const {
|
||||
return osMessageQueueGetSpace(_id) == 0;
|
||||
|
@ -93,6 +103,8 @@ public:
|
|||
@a osErrorTimeout the message could not be put into the queue in the given time.
|
||||
@a osErrorResource not enough space in the queue.
|
||||
@a osErrorParameter internal error or non-zero timeout specified in an ISR.
|
||||
|
||||
@note You may call this function from ISR context if the millisec parameter is set to 0.
|
||||
*/
|
||||
osStatus put(T* data, uint32_t millisec=0, uint8_t prio=0) {
|
||||
return osMessageQueuePut(_id, &data, prio, millisec);
|
||||
|
@ -106,6 +118,8 @@ public:
|
|||
@a osOK no message is available in the queue and no timeout was specified.
|
||||
@a osEventTimeout no message has arrived during the given timeout period.
|
||||
@a osErrorParameter a parameter is invalid or outside of a permitted range.
|
||||
|
||||
@note You may call this function from ISR context if the millisec parameter is set to 0.
|
||||
*/
|
||||
osEvent get(uint32_t millisec=osWaitForever) {
|
||||
osEvent event;
|
||||
|
|
|
@ -93,6 +93,8 @@ public:
|
|||
@deprecated Replaced with RtosTimer(Callback<void()>, os_timer_type)
|
||||
@deprecated
|
||||
The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.1",
|
||||
"Replaced with RtosTimer(Callback<void()>, os_timer_type)")
|
||||
|
@ -107,6 +109,8 @@ public:
|
|||
@param type osTimerOnce for one-shot or osTimerPeriodic for periodic behaviour. (default: osTimerPeriodic)
|
||||
@deprecated
|
||||
The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.2",
|
||||
"The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details")
|
||||
|
@ -123,6 +127,8 @@ public:
|
|||
RtosTimer(callback(obj, method), os_timer_type).
|
||||
@deprecated
|
||||
The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
template <typename T, typename M>
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.1",
|
||||
|
@ -140,6 +146,8 @@ public:
|
|||
@a osErrorISR @a stop cannot be called from interrupt service routines.
|
||||
@a osErrorParameter internal error.
|
||||
@a osErrorResource the timer is not running.
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
osStatus stop(void);
|
||||
|
||||
|
@ -150,9 +158,15 @@ public:
|
|||
@a osErrorISR @a start cannot be called from interrupt service routines.
|
||||
@a osErrorParameter internal error or incorrect parameter value.
|
||||
@a osErrorResource internal error (the timer is in an invalid timer state).
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
osStatus start(uint32_t millisec);
|
||||
|
||||
/** RtosTimer destructor
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
~RtosTimer();
|
||||
|
||||
private:
|
||||
|
|
|
@ -46,18 +46,24 @@ class Semaphore : private mbed::NonCopyable<Semaphore> {
|
|||
public:
|
||||
/** Create and Initialize a Semaphore object used for managing resources.
|
||||
@param count number of available resources; maximum index value is (count-1). (default: 0).
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
Semaphore(int32_t count=0);
|
||||
|
||||
/** Create and Initialize a Semaphore object used for managing resources.
|
||||
@param count number of available resources
|
||||
@param max_count maximum number of available resources
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
Semaphore(int32_t count, uint16_t max_count);
|
||||
|
||||
/** Wait until a Semaphore resource becomes available.
|
||||
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever).
|
||||
@return number of available tokens, before taking one; or -1 in case of incorrect parameters
|
||||
|
||||
@note You may call this function from ISR context if the millisec parameter is set to 0.
|
||||
*/
|
||||
int32_t wait(uint32_t millisec=osWaitForever);
|
||||
|
||||
|
@ -66,9 +72,15 @@ public:
|
|||
@a osOK the token has been correctly released.
|
||||
@a osErrorResource the maximum token count has been reached.
|
||||
@a osErrorParameter internal error.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
osStatus release(void);
|
||||
|
||||
/** Semaphore destructor
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
~Semaphore();
|
||||
|
||||
private:
|
||||
|
|
|
@ -194,13 +194,10 @@ static void default_idle_hook(void)
|
|||
|
||||
core_util_critical_section_enter();
|
||||
uint32_t ticks_to_sleep = svcRtxKernelSuspend();
|
||||
MBED_ASSERT(os_timer->get_tick() == svcRtxKernelGetTickCount());
|
||||
if (ticks_to_sleep) {
|
||||
os_timer->schedule_tick(ticks_to_sleep);
|
||||
|
||||
sleep_manager_lock_deep_sleep();
|
||||
sleep();
|
||||
sleep_manager_unlock_deep_sleep();
|
||||
|
||||
os_timer->cancel_tick();
|
||||
// calculate how long we slept
|
||||
|
|
|
@ -80,6 +80,8 @@ public:
|
|||
@param stack_size stack size (in bytes) requirements for the thread function. (default: OS_STACK_SIZE).
|
||||
@param stack_mem pointer to the stack area to be used by this thread (default: NULL).
|
||||
@param name name to be used for this thread. It has to stay allocated for the lifetime of the thread (default: NULL)
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
Thread(osPriority priority=osPriorityNormal,
|
||||
uint32_t stack_size=OS_STACK_SIZE,
|
||||
|
@ -103,6 +105,8 @@ public:
|
|||
error("oh no!");
|
||||
}
|
||||
@endcode
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.1",
|
||||
"Thread-spawning constructors hide errors. "
|
||||
|
@ -131,6 +135,8 @@ public:
|
|||
error("oh no!");
|
||||
}
|
||||
@endcode
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
template <typename T>
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.1",
|
||||
|
@ -161,6 +167,8 @@ public:
|
|||
error("oh no!");
|
||||
}
|
||||
@endcode
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
template <typename T>
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.1",
|
||||
|
@ -192,6 +200,8 @@ public:
|
|||
error("oh no!");
|
||||
}
|
||||
@endcode
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.1",
|
||||
"Thread-spawning constructors hide errors. "
|
||||
|
@ -208,6 +218,8 @@ public:
|
|||
@param task function to be executed by this thread.
|
||||
@return status code that indicates the execution status of the function.
|
||||
@note a thread can only be started once
|
||||
|
||||
@note You cannot call this function ISR context.
|
||||
*/
|
||||
osStatus start(mbed::Callback<void()> task);
|
||||
|
||||
|
@ -217,6 +229,8 @@ public:
|
|||
@return status code that indicates the execution status of the function.
|
||||
@deprecated
|
||||
The start function does not support cv-qualifiers. Replaced by start(callback(obj, method)).
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
template <typename T, typename M>
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.1",
|
||||
|
@ -229,28 +243,38 @@ public:
|
|||
/** Wait for thread to terminate
|
||||
@return status code that indicates the execution status of the function.
|
||||
@note not callable from interrupt
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
osStatus join();
|
||||
|
||||
/** Terminate execution of a thread and remove it from Active Threads
|
||||
@return status code that indicates the execution status of the function.
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
osStatus terminate();
|
||||
|
||||
/** Set priority of an active thread
|
||||
@param priority new priority value for the thread function.
|
||||
@return status code that indicates the execution status of the function.
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
osStatus set_priority(osPriority priority);
|
||||
|
||||
/** Get priority of an active thread
|
||||
@return current priority value of the thread function.
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
osPriority get_priority();
|
||||
|
||||
/** Set the specified Thread Flags for the thread.
|
||||
@param signals specifies the signal flags of the thread that should be set.
|
||||
@return signal flags after setting or osFlagsError in case of incorrect parameters.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
int32_t signal_set(int32_t signals);
|
||||
|
||||
|
@ -279,37 +303,51 @@ public:
|
|||
|
||||
/** State of this Thread
|
||||
@return the State of this Thread
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
State get_state();
|
||||
|
||||
/** Get the total stack memory size for this Thread
|
||||
@return the total stack memory size in bytes
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
uint32_t stack_size();
|
||||
|
||||
/** Get the currently unused stack memory for this Thread
|
||||
@return the currently unused stack memory in bytes
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
uint32_t free_stack();
|
||||
|
||||
/** Get the currently used stack memory for this Thread
|
||||
@return the currently used stack memory in bytes
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
uint32_t used_stack();
|
||||
|
||||
/** Get the maximum stack memory usage to date for this Thread
|
||||
@return the maximum stack memory usage to date in bytes
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
uint32_t max_stack();
|
||||
|
||||
/** Get thread name
|
||||
@return thread name or NULL if the name was not set.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
const char *get_name();
|
||||
|
||||
/** Clears the specified Thread Flags of the currently running thread.
|
||||
@param signals specifies the signal flags of the thread that should be cleared.
|
||||
@return signal flags before clearing or osFlagsError in case of incorrect parameters.
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
static int32_t signal_clr(int32_t signals);
|
||||
|
||||
|
@ -317,38 +355,51 @@ public:
|
|||
@param signals wait until all specified signal flags are set or 0 for any single signal flag.
|
||||
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever).
|
||||
@return event flag information or error code. @note if @a millisec is set to 0 and flag is no set the event carries osOK value.
|
||||
@note not callable from interrupt
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
static osEvent signal_wait(int32_t signals, uint32_t millisec=osWaitForever);
|
||||
|
||||
/** Wait for a specified time period in millisec:
|
||||
@param millisec time delay value
|
||||
@return status code that indicates the execution status of the function.
|
||||
@note not callable from interrupt
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
static osStatus wait(uint32_t millisec);
|
||||
|
||||
/** Pass control to next thread that is in state READY.
|
||||
@return status code that indicates the execution status of the function.
|
||||
@note not callable from interrupt
|
||||
|
||||
@note You cannot call this function from ISR context.
|
||||
*/
|
||||
static osStatus yield();
|
||||
|
||||
/** Get the thread id of the current running thread.
|
||||
@return thread ID for reference by other functions or NULL in case of error.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
static osThreadId gettid();
|
||||
|
||||
/** Attach a function to be called by the RTOS idle task
|
||||
@param fptr pointer to the function to be called
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
static void attach_idle_hook(void (*fptr)(void));
|
||||
|
||||
/** Attach a function to be called when a task is killed
|
||||
@param fptr pointer to the function to be called
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
static void attach_terminate_hook(void (*fptr)(osThreadId id));
|
||||
|
||||
/** Thread destructor
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
virtual ~Thread();
|
||||
|
||||
private:
|
||||
|
|
|
@ -37,6 +37,11 @@ uint32_t gpio_set(PinName pin)
|
|||
return (uint32_t)(1 << pin_index); // Return the pin mask
|
||||
}
|
||||
|
||||
int gpio_is_connected(const gpio_t *obj)
|
||||
{
|
||||
return (obj->pin != (PinName) NC);
|
||||
}
|
||||
|
||||
void gpio_init(gpio_t *obj, PinName pin)
|
||||
{
|
||||
obj->pin = pin;
|
||||
|
|
|
@ -37,6 +37,11 @@ uint32_t gpio_set(PinName pin)
|
|||
return (uint32_t)(1 << pin_index); // Return the pin mask
|
||||
}
|
||||
|
||||
int gpio_is_connected(const gpio_t *obj)
|
||||
{
|
||||
return (obj->pin != (PinName) NC);
|
||||
}
|
||||
|
||||
void gpio_init(gpio_t *obj, PinName pin)
|
||||
{
|
||||
obj->pin = pin;
|
||||
|
|
|
@ -34,6 +34,11 @@ uint32_t gpio_set(PinName pin)
|
|||
return (uint32_t)(1 << pin_index); // Return the pin mask
|
||||
}
|
||||
|
||||
int gpio_is_connected(const gpio_t *obj)
|
||||
{
|
||||
return (obj->pin != (PinName) NC);
|
||||
}
|
||||
|
||||
void gpio_init(gpio_t *obj, PinName pin)
|
||||
{
|
||||
obj->pin = pin;
|
||||
|
|
|
@ -37,6 +37,11 @@ uint32_t gpio_set(PinName pin)
|
|||
return (uint32_t)(1 << pin_index); // Return the pin mask
|
||||
}
|
||||
|
||||
int gpio_is_connected(const gpio_t *obj)
|
||||
{
|
||||
return (obj->pin != (PinName) NC);
|
||||
}
|
||||
|
||||
void gpio_init(gpio_t *obj, PinName pin)
|
||||
{
|
||||
obj->pin = pin;
|
||||
|
|
|
@ -69,6 +69,7 @@ static const PinMap PinMap_SPI_SSEL[] = {
|
|||
{P1_28, SPI_0, 5},
|
||||
{P2_23, SPI_0, 2},
|
||||
{P4_21, SPI_1, 3},
|
||||
{P5_3, SPI_2, 2},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* DISCLAIMER
|
||||
* This software is supplied by Renesas Electronics Corporation and is only
|
||||
* intended for use with Renesas products. No other uses are authorized. This
|
||||
* software is owned by Renesas Electronics Corporation and is protected under
|
||||
* all applicable laws, including copyright laws.
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
|
||||
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
|
||||
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
|
||||
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
|
||||
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
|
||||
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
|
||||
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
* Renesas reserves the right, without notice, to make changes to this software
|
||||
* and to discontinue the availability of this software. By using this software,
|
||||
* you agree to the additional terms and conditions found by accessing the
|
||||
* following link:
|
||||
* http://www.renesas.com/disclaimer
|
||||
* Copyright (C) 2012 - 2013 Renesas Electronics Corporation. All rights reserved.
|
||||
*******************************************************************************/
|
||||
/*******************************************************************************
|
||||
* File Name : r_typedefs.h
|
||||
* $Rev: 788 $
|
||||
* $Date:: 2014-04-07 18:57:13 +0900#$
|
||||
* Description : basic type definition
|
||||
******************************************************************************/
|
||||
#ifndef R_TYPEDEFS_H
|
||||
#define R_TYPEDEFS_H
|
||||
|
||||
/******************************************************************************
|
||||
Includes <System Includes> , "Project Includes"
|
||||
******************************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(__ARM_NEON__)
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#else /* __ARM_NEON__ */
|
||||
|
||||
typedef float float32_t;
|
||||
typedef double float64_t;
|
||||
|
||||
#endif /* __ARM_NEON__ */
|
||||
|
||||
/******************************************************************************
|
||||
Typedef definitions
|
||||
******************************************************************************/
|
||||
typedef char char_t;
|
||||
typedef int bool_t;
|
||||
typedef int int_t;
|
||||
typedef long double float128_t;
|
||||
typedef signed long long_t;
|
||||
typedef unsigned long ulong_t;
|
||||
|
||||
#endif /* R_TYPEDEFS_H */
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-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.
|
||||
*/
|
||||
#ifndef MBED_OBJECTS_H
|
||||
#define MBED_OBJECTS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "cmsis.h"
|
||||
#include "PortNames.h"
|
||||
#include "PeripheralNames.h"
|
||||
#include "PinNames.h"
|
||||
#include "gpio_object.h"
|
||||
#include "rspi_iodefine.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct i2c_s {
|
||||
uint32_t i2c;
|
||||
uint32_t dummy;
|
||||
uint8_t pclk_bit;
|
||||
uint8_t width_low;
|
||||
uint8_t width_hi;
|
||||
int bbsy_wait_cnt;
|
||||
int last_stop_flag;
|
||||
};
|
||||
|
||||
struct spi_s {
|
||||
struct st_rspi *spi;
|
||||
uint32_t bits;
|
||||
int index;
|
||||
};
|
||||
|
||||
struct gpio_irq_s {
|
||||
uint32_t port;
|
||||
uint32_t pin;
|
||||
uint32_t ch;
|
||||
uint8_t int_enable;
|
||||
};
|
||||
|
||||
struct port_s {
|
||||
__IO uint32_t *reg_dir;
|
||||
__IO uint32_t *reg_out;
|
||||
__I uint32_t *reg_in;
|
||||
PortName port;
|
||||
uint32_t mask;
|
||||
};
|
||||
|
||||
struct serial_s {
|
||||
struct st_scif *uart;
|
||||
int index;
|
||||
};
|
||||
|
||||
struct pwmout_s {
|
||||
uint32_t ch;
|
||||
PWMName pwm;
|
||||
};
|
||||
|
||||
struct analogin_s {
|
||||
ADCName adc;
|
||||
};
|
||||
|
||||
struct can_s {
|
||||
uint32_t ch;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,172 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-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.
|
||||
*/
|
||||
#include "pinmap.h"
|
||||
#include "mbed_error.h"
|
||||
#include "gpio_addrdefine.h"
|
||||
|
||||
PinName gpio_multi_guard = (PinName)NC; /* If set pin name here, setting of the "pin" is just one time */
|
||||
|
||||
typedef struct {
|
||||
PinName pin;
|
||||
int function;
|
||||
int pm;
|
||||
} PinFunc;
|
||||
|
||||
static const PinFunc PIPC_0_tbl[] = {
|
||||
// pin func pm
|
||||
{P4_0 , 2 , -1}, /* TIOC0A */
|
||||
{P5_0 , 6 , -1}, /* TIOC0A */
|
||||
{P7_0 , 7 , -1}, /* TIOC0A */
|
||||
{P10_4 , 2 , -1}, /* TIOC0A */
|
||||
{P4_1 , 2 , -1}, /* TIOC0B */
|
||||
{P5_1 , 6 , -1}, /* TIOC0B */
|
||||
{P7_1 , 7 , -1}, /* TIOC0B */
|
||||
{P10_5 , 2 , -1}, /* TIOC0B */
|
||||
{P4_2 , 2 , -1}, /* TIOC0C */
|
||||
{P5_5 , 6 , -1}, /* TIOC0C */
|
||||
{P7_2 , 7 , -1}, /* TIOC0C */
|
||||
{P10_6 , 2 , -1}, /* TIOC0C */
|
||||
{P4_3 , 2 , -1}, /* TIOC0D */
|
||||
{P5_7 , 6 , -1}, /* TIOC0D */
|
||||
{P7_3 , 7 , -1}, /* TIOC0D */
|
||||
{P10_7 , 2 , -1}, /* TIOC0D */
|
||||
{P2_11 , 5 , -1}, /* TIOC1A */
|
||||
{P6_0 , 5 , -1}, /* TIOC1A */
|
||||
{P7_4 , 7 , -1}, /* TIOC1A */
|
||||
{P8_8 , 5 , -1}, /* TIOC1A */
|
||||
{P9_7 , 4 , -1}, /* TIOC1A */
|
||||
{P10_8 , 2 , -1}, /* TIOC1A */
|
||||
{P2_12 , 8 , -1}, /* TIOC1B */
|
||||
{P5_2 , 6 , -1}, /* TIOC1B */
|
||||
{P6_1 , 5 , -1}, /* TIOC1B */
|
||||
{P7_5 , 7 , -1}, /* TIOC1B */
|
||||
{P8_9 , 5 , -1}, /* TIOC1B */
|
||||
{P10_9 , 2 , -1}, /* TIOC1B */
|
||||
{P2_1 , 6 , -1}, /* TIOC2A */
|
||||
{P6_2 , 6 , -1}, /* TIOC2A */
|
||||
{P7_6 , 7 , -1}, /* TIOC2A */
|
||||
{P8_14 , 4 , -1}, /* TIOC2A */
|
||||
{P10_10 , 2 , -1}, /* TIOC2A */
|
||||
{P2_2 , 6 , -1}, /* TIOC2B */
|
||||
{P6_3 , 6 , -1}, /* TIOC2B */
|
||||
{P7_7 , 7 , -1}, /* TIOC2B */
|
||||
{P8_15 , 4 , -1}, /* TIOC2B */
|
||||
{P10_11 , 2 , -1}, /* TIOC2B */
|
||||
{P10_11 , 2 , -1}, /* TIOC2B */
|
||||
{P3_4 , 6 , -1}, /* TIOC3A */
|
||||
{P7_8 , 7 , -1}, /* TIOC3A */
|
||||
{P8_10 , 4 , -1}, /* TIOC3A */
|
||||
{P3_5 , 6 , -1}, /* TIOC3B */
|
||||
{P7_9 , 7 , -1}, /* TIOC3B */
|
||||
{P8_11 , 4 , -1}, /* TIOC3B */
|
||||
{P3_6 , 6 , -1}, /* TIOC3C */
|
||||
{P5_3 , 6 , -1}, /* TIOC3C */
|
||||
{P7_10 , 7 , -1}, /* TIOC3C */
|
||||
{P8_12 , 4 , -1}, /* TIOC3C */
|
||||
{P3_7 , 6 , -1}, /* TIOC3D */
|
||||
{P5_4 , 6 , -1}, /* TIOC3D */
|
||||
{P7_11 , 7 , -1}, /* TIOC3D */
|
||||
{P8_13 , 4 , -1}, /* TIOC3D */
|
||||
{P3_8 , 6 , -1}, /* TIOC4A */
|
||||
{P4_4 , 3 , -1}, /* TIOC4A */
|
||||
{P7_12 , 7 , -1}, /* TIOC4A */
|
||||
{P11_0 , 2 , -1}, /* TIOC4A */
|
||||
{P3_9 , 6 , -1}, /* TIOC4B */
|
||||
{P4_5 , 3 , -1}, /* TIOC4B */
|
||||
{P7_13 , 7 , -1}, /* TIOC4B */
|
||||
{P11_1 , 2 , -1}, /* TIOC4B */
|
||||
{P3_10 , 6 , -1}, /* TIOC4C */
|
||||
{P4_6 , 3 , -1}, /* TIOC4C */
|
||||
{P7_14 , 7 , -1}, /* TIOC4C */
|
||||
{P11_2 , 2 , -1}, /* TIOC4C */
|
||||
{P3_11 , 6 , -1}, /* TIOC4D */
|
||||
{P4_7 , 3 , -1}, /* TIOC4D */
|
||||
{P7_15 , 7 , -1}, /* TIOC4D */
|
||||
{P11_3 , 2 , -1}, /* TIOC4D */
|
||||
{P5_7 , 1 , 1 }, /* TXOUT0M */
|
||||
{P5_6 , 1 , 1 }, /* TXOUT0P */
|
||||
{P5_5 , 1 , 1 }, /* TXOUT1M */
|
||||
{P5_4 , 1 , 1 }, /* TXOUT1P */
|
||||
{P5_3 , 1 , 1 }, /* TXOUT2M */
|
||||
{P5_2 , 1 , 1 }, /* TXOUT2P */
|
||||
{P5_1 , 1 , 1 }, /* TXCLKOUTM */
|
||||
{P5_0 , 1 , 1 }, /* TXCLKOUTP */
|
||||
{P2_11 , 4 , 0 }, /* SSITxD0 */
|
||||
{P4_7 , 5 , 0 }, /* SSITxD0 */
|
||||
{P7_4 , 6 , 0 }, /* SSITxD1 */
|
||||
{P10_15 , 2 , 0 }, /* SSITxD1 */
|
||||
{P4_15 , 6 , 0 }, /* SSITxD3 */
|
||||
{P7_11 , 2 , 0 }, /* SSITxD3 */
|
||||
{P2_7 , 4 , 0 }, /* SSITxD5 */
|
||||
{P4_11 , 5 , 0 }, /* SSITxD5 */
|
||||
{P8_10 , 8 , 0 }, /* SSITxD5 */
|
||||
{P3_7 , 8 , 0 }, /* WDTOVF */
|
||||
{NC , 0 , -1}
|
||||
};
|
||||
|
||||
void pin_function(PinName pin, int function) {
|
||||
if (pin == (PinName)NC) return;
|
||||
|
||||
int n = pin >> 4;
|
||||
int bitmask = 1<<(pin & 0xf);
|
||||
const PinFunc * Pipc_0_func = PIPC_0_tbl;
|
||||
int pipc_data = 1;
|
||||
|
||||
if (gpio_multi_guard != pin) {
|
||||
if (function == 0) {
|
||||
// means GPIO mode
|
||||
*PMC(n) &= ~bitmask;
|
||||
} else {
|
||||
// alt-function mode
|
||||
--function;
|
||||
|
||||
if (function & (1 << 2)) { *PFCAE(n) |= bitmask;}else { *PFCAE(n) &= ~bitmask;}
|
||||
if (function & (1 << 1)) { *PFCE(n) |= bitmask;}else { *PFCE(n) &= ~bitmask;}
|
||||
if (function & (1 << 0)) { *PFC(n) |= bitmask;}else { *PFC(n) &= ~bitmask;}
|
||||
|
||||
while (Pipc_0_func->pin != NC) {
|
||||
if ((Pipc_0_func->pin == pin) && ((Pipc_0_func->function - 1) == function)) {
|
||||
pipc_data = 0;
|
||||
if (Pipc_0_func->pm == 0) {
|
||||
*PMSR(n) = (bitmask << 16) | 0;
|
||||
} else if (Pipc_0_func->pm == 1) {
|
||||
*PMSR(n) = (bitmask << 16) | bitmask;
|
||||
} else {
|
||||
// Do Nothing
|
||||
}
|
||||
break;
|
||||
}
|
||||
Pipc_0_func++;
|
||||
}
|
||||
if (pipc_data == 1) {
|
||||
*PIPC(n) |= bitmask;
|
||||
} else {
|
||||
*PIPC(n) &= ~bitmask;
|
||||
}
|
||||
|
||||
if (P1_0 <= pin && pin <= P1_7 && function == 0) {
|
||||
*PBDC(n) |= bitmask;
|
||||
}
|
||||
*PMC(n) |= bitmask;
|
||||
}
|
||||
} else {
|
||||
gpio_multi_guard = (PinName)NC;
|
||||
}
|
||||
}
|
||||
|
||||
void pin_mode(PinName pin, PinMode mode) {
|
||||
// if (pin == (PinName)NC) { return; }
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-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.
|
||||
*/
|
||||
#include "port_api.h"
|
||||
#include "pinmap.h"
|
||||
#include "gpio_api.h"
|
||||
|
||||
PinName port_pin(PortName port, int pin_n) {
|
||||
return (PinName)(0);
|
||||
}
|
||||
|
||||
void port_init(port_t *obj, PortName port, int mask, PinDirection dir) {
|
||||
obj->port = port;
|
||||
obj->mask = mask;
|
||||
|
||||
// Do not use masking, because it prevents the use of the unmasked pins
|
||||
// port_reg->FIOMASK = ~mask;
|
||||
|
||||
uint32_t i;
|
||||
// The function is set per pin: reuse gpio logic
|
||||
for (i=0; i<32; i++) {
|
||||
if (obj->mask & (1<<i)) {
|
||||
gpio_set(port_pin(obj->port, i));
|
||||
}
|
||||
}
|
||||
|
||||
port_dir(obj, dir);
|
||||
}
|
||||
|
||||
void port_mode(port_t *obj, PinMode mode) {
|
||||
uint32_t i;
|
||||
// The mode is set per pin: reuse pinmap logic
|
||||
for (i=0; i<32; i++) {
|
||||
if (obj->mask & (1<<i)) {
|
||||
pin_mode(port_pin(obj->port, i), mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void port_dir(port_t *obj, PinDirection dir) {
|
||||
switch (dir) {
|
||||
case PIN_INPUT : *obj->reg_dir &= ~obj->mask; break;
|
||||
case PIN_OUTPUT: *obj->reg_dir |= obj->mask; break;
|
||||
}
|
||||
}
|
||||
|
||||
void port_write(port_t *obj, int value) {
|
||||
*obj->reg_out = (*obj->reg_in & ~obj->mask) | (value & obj->mask);
|
||||
}
|
||||
|
||||
int port_read(port_t *obj) {
|
||||
return (*obj->reg_in & obj->mask);
|
||||
}
|
|
@ -1,378 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2015 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_assert.h"
|
||||
#include "device.h"
|
||||
|
||||
#if DEVICE_RTC
|
||||
|
||||
#include "rtc_api.h"
|
||||
#include "rtc_iodefine.h"
|
||||
#include "mbed_mktime.h"
|
||||
|
||||
|
||||
#define RCR1_VAL_ON (0x08u) // AIE = 1
|
||||
#define RCR1_VAL_OFF (0x00u)
|
||||
#define RCR2_VAL_ALLSTOP (0x00u)
|
||||
#define RCR2_VAL_START (0x01u) // START = 1
|
||||
#define RCR2_VAL_RESET (0x02u) // RESET = 1
|
||||
#define RCR3_VAL (0x00u)
|
||||
#define RCR5_VAL_EXTAL (0x01u) // RCKSEL = connect EXTAL
|
||||
#define RCR5_VAL_RTCX1 (0x00u) // RCKSEL = disconnect EXTAL
|
||||
#define RFRH_VAL_13333 (0x8003u) // 13.3333MHz (= 64Hz * 0x32DCD)
|
||||
#define RFRL_VAL_13333 (0x2DCDu) //
|
||||
#define RFRH_VAL_MAX (0x0007u) // MAX value (= 128Hz * 0x7FFFF)
|
||||
#define RFRL_VAL_MAX (0xFFFFu) //
|
||||
|
||||
#define MASK_00_03_POS (0x000Fu)
|
||||
#define MASK_04_07_POS (0x00F0u)
|
||||
#define MASK_08_11_POS (0x0F00u)
|
||||
#define MASK_12_15_POS (0xF000u)
|
||||
#define MASK_16_20_POS (0x000F0000u)
|
||||
#define SHIFT_1_HBYTE (4u)
|
||||
#define SHIFT_2_HBYTE (8u)
|
||||
#define SHIFT_3_HBYTE (12u)
|
||||
#define SHIFT_1BYTE (8u)
|
||||
#define SHIFT_2BYTE (16u)
|
||||
|
||||
#define TIME_ERROR_VAL (0xFFFFFFFFu)
|
||||
|
||||
static int rtc_dec8_to_hex(uint8_t dec_val, uint8_t offset, int *hex_val);
|
||||
static int rtc_dec16_to_hex(uint16_t dec_val, uint16_t offset, int *hex_val);
|
||||
static uint8_t rtc_hex8_to_dec(uint8_t hex_val);
|
||||
static uint16_t rtc_hex16_to_dec(uint16_t hex_val);
|
||||
|
||||
|
||||
/*
|
||||
* Setup the RTC based on a time structure.
|
||||
* The rtc_init function should be executed first.
|
||||
* [in]
|
||||
* None.
|
||||
* [out]
|
||||
* None.
|
||||
*/
|
||||
void rtc_init(void) {
|
||||
volatile uint8_t dummy_read;
|
||||
|
||||
// Set control register
|
||||
RTC.RCR2 = RCR2_VAL_ALLSTOP;
|
||||
RTC.RCR1 = RCR1_VAL_ON;
|
||||
RTC.RCR3 = RCR3_VAL;
|
||||
RTC.RCR5 = RCR5_VAL_EXTAL;
|
||||
RTC.RFRH = RFRH_VAL_13333;
|
||||
RTC.RFRL = RFRL_VAL_13333;
|
||||
|
||||
// Dummy read
|
||||
dummy_read = RTC.RCR2;
|
||||
dummy_read = RTC.RCR2;
|
||||
|
||||
RTC.RCR2 = RCR2_VAL_RESET; // RESET = 1
|
||||
|
||||
// Dummy read
|
||||
dummy_read = RTC.RCR2;
|
||||
dummy_read = RTC.RCR2;
|
||||
|
||||
// Set timer and alarm. Default value :01-01-1970 00:00:00
|
||||
RTC.RSECCNT = 0;
|
||||
RTC.RMINCNT = 0;
|
||||
RTC.RHRCNT = 0;
|
||||
RTC.RWKCNT = 0;
|
||||
RTC.RDAYCNT = 1;
|
||||
RTC.RMONCNT = 1;
|
||||
RTC.RYRCNT = 0x1970;
|
||||
RTC.RSECAR = 0;
|
||||
RTC.RMINAR = 0;
|
||||
RTC.RHRAR = 0;
|
||||
RTC.RWKAR = 0;
|
||||
RTC.RDAYAR = 1;
|
||||
RTC.RMONAR = 1;
|
||||
RTC.RYRAR = 0x1970;
|
||||
|
||||
// Dummy read
|
||||
dummy_read = RTC.RYRCNT;
|
||||
dummy_read = RTC.RYRCNT;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Release the RTC based on a time structure.
|
||||
* [in]
|
||||
* None.
|
||||
* [out]
|
||||
* None.
|
||||
*/
|
||||
void rtc_free(void) {
|
||||
volatile uint8_t dummy_read;
|
||||
|
||||
// Set control register
|
||||
RTC.RCR2 = RCR2_VAL_ALLSTOP;
|
||||
RTC.RCR1 = RCR1_VAL_OFF;
|
||||
RTC.RCR3 = RCR3_VAL;
|
||||
RTC.RCR5 = RCR5_VAL_RTCX1;
|
||||
RTC.RFRH = RFRH_VAL_MAX;
|
||||
RTC.RFRL = RFRL_VAL_MAX;
|
||||
|
||||
// Dummy read
|
||||
dummy_read = RTC.RCR2;
|
||||
dummy_read = RTC.RCR2;
|
||||
RTC.RCR2 = RCR2_VAL_RESET; // RESET = 1
|
||||
|
||||
// Dummy read
|
||||
dummy_read = RTC.RCR2;
|
||||
dummy_read = RTC.RCR2;
|
||||
|
||||
// Set timer and alarm. Default value :01-01-1970 00:00:00
|
||||
RTC.RSECCNT = 0;
|
||||
RTC.RMINCNT = 0;
|
||||
RTC.RHRCNT = 0;
|
||||
RTC.RWKCNT = 0;
|
||||
RTC.RDAYCNT = 1;
|
||||
RTC.RMONCNT = 1;
|
||||
RTC.RYRCNT = 0x1970;
|
||||
RTC.RSECAR = 0;
|
||||
RTC.RMINAR = 0;
|
||||
RTC.RHRAR = 0;
|
||||
RTC.RWKAR = 0;
|
||||
RTC.RDAYAR = 1;
|
||||
RTC.RMONAR = 1;
|
||||
RTC.RYRAR = 0x1970;
|
||||
|
||||
// Dummy read
|
||||
dummy_read = RTC.RYRCNT;
|
||||
dummy_read = RTC.RYRCNT;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check the RTC has been enabled.
|
||||
* Clock Control Register RTC.RCR1(bit3): 0 = Disabled, 1 = Enabled.
|
||||
* [in]
|
||||
* None.
|
||||
* [out]
|
||||
* 0:Disabled, 1:Enabled.
|
||||
*/
|
||||
int rtc_isenabled(void) {
|
||||
int ret_val = 0;
|
||||
|
||||
if ((RTC.RCR1 & RCR1_VAL_ON) != 0) { // RTC ON ?
|
||||
ret_val = 1;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RTC read function.
|
||||
* [in]
|
||||
* None.
|
||||
* [out]
|
||||
* UNIX timestamp value.
|
||||
*/
|
||||
time_t rtc_read(void) {
|
||||
|
||||
struct tm timeinfo;
|
||||
int err = 0;
|
||||
uint8_t tmp_regdata;
|
||||
time_t t;
|
||||
|
||||
if (rtc_isenabled() != 0) {
|
||||
RTC.RCR1 &= ~0x10u; // CIE = 0
|
||||
do {
|
||||
// before reading process
|
||||
tmp_regdata = RTC.RCR1;
|
||||
tmp_regdata &= ~0x80u; // CF = 0
|
||||
tmp_regdata |= 0x01u; // AF = 1
|
||||
RTC.RCR1 = tmp_regdata;
|
||||
|
||||
// Read RTC register
|
||||
err = rtc_dec8_to_hex(RTC.RSECCNT , 0 , &timeinfo.tm_sec);
|
||||
err += rtc_dec8_to_hex(RTC.RMINCNT , 0 , &timeinfo.tm_min);
|
||||
err += rtc_dec8_to_hex(RTC.RHRCNT , 0 , &timeinfo.tm_hour);
|
||||
err += rtc_dec8_to_hex(RTC.RDAYCNT , 0 , &timeinfo.tm_mday);
|
||||
err += rtc_dec8_to_hex(RTC.RMONCNT , 1 , &timeinfo.tm_mon);
|
||||
err += rtc_dec16_to_hex(RTC.RYRCNT , 1900 , &timeinfo.tm_year);
|
||||
} while ((RTC.RCR1 & 0x80u) != 0);
|
||||
} else {
|
||||
err = 1;
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
// Convert to timestamp
|
||||
t = _rtc_mktime(&timeinfo);
|
||||
} else {
|
||||
// Error
|
||||
t = TIME_ERROR_VAL;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dec(8bit) to Hex function for RTC.
|
||||
* [in]
|
||||
* dec_val:Decimal value (from 0x00 to 0x99).
|
||||
* offset:Subtract offset from dec_val.
|
||||
* hex_val:Pointer of output hexadecimal value.
|
||||
* [out]
|
||||
* 0:Success
|
||||
* 1:Error
|
||||
*/
|
||||
static int rtc_dec8_to_hex(uint8_t dec_val, uint8_t offset, int *hex_val) {
|
||||
int err = 0;
|
||||
uint8_t ret_val;
|
||||
|
||||
if (hex_val != NULL) {
|
||||
if (((dec_val & MASK_04_07_POS) >= (0x0A << SHIFT_1_HBYTE)) ||
|
||||
((dec_val & MASK_00_03_POS) >= 0x0A)) {
|
||||
err = 1;
|
||||
} else {
|
||||
ret_val = ((dec_val & MASK_04_07_POS) >> SHIFT_1_HBYTE) * 10 +
|
||||
(dec_val & MASK_00_03_POS);
|
||||
if (ret_val < offset) {
|
||||
err = 1;
|
||||
} else {
|
||||
*hex_val = ret_val - offset;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = 1;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dec(16bit) to Hex function for RTC
|
||||
* [in]
|
||||
* dec_val:Decimal value (from 0x0000 to 0x9999).
|
||||
* offset:Subtract offset from dec_val.
|
||||
* hex_val:Pointer of output hexadecimal value.
|
||||
* [out]
|
||||
* 0:Success
|
||||
* 1:Error
|
||||
*/
|
||||
static int rtc_dec16_to_hex(uint16_t dec_val, uint16_t offset, int *hex_val) {
|
||||
int err = 0;
|
||||
uint16_t ret_val;
|
||||
|
||||
if (hex_val != NULL) {
|
||||
if (((dec_val & MASK_12_15_POS) >= (0x0A << SHIFT_3_HBYTE)) ||
|
||||
((dec_val & MASK_08_11_POS) >= (0x0A << SHIFT_2_HBYTE)) ||
|
||||
((dec_val & MASK_04_07_POS) >= (0x0A << SHIFT_1_HBYTE)) ||
|
||||
((dec_val & MASK_00_03_POS) >= 0x0A)) {
|
||||
err = 1;
|
||||
*hex_val = 0;
|
||||
} else {
|
||||
ret_val = (((dec_val & MASK_12_15_POS)) >> SHIFT_3_HBYTE) * 1000 +
|
||||
(((dec_val & MASK_08_11_POS)) >> SHIFT_2_HBYTE) * 100 +
|
||||
(((dec_val & MASK_04_07_POS)) >> SHIFT_1_HBYTE) * 10 +
|
||||
(dec_val & MASK_00_03_POS);
|
||||
if (ret_val < offset) {
|
||||
err = 1;
|
||||
} else {
|
||||
*hex_val = ret_val - offset;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = 1;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* RTC write function
|
||||
* [in]
|
||||
* t:UNIX timestamp value
|
||||
* [out]
|
||||
* None.
|
||||
*/
|
||||
void rtc_write(time_t t) {
|
||||
|
||||
struct tm timeinfo;
|
||||
if (_rtc_localtime(t, &timeinfo) == false) {
|
||||
return;
|
||||
}
|
||||
volatile uint16_t dummy_read;
|
||||
|
||||
if (rtc_isenabled() != 0) {
|
||||
RTC.RCR2 = RCR2_VAL_ALLSTOP;
|
||||
dummy_read = (uint16_t)RTC.RCR2;
|
||||
dummy_read = (uint16_t)RTC.RCR2;
|
||||
RTC.RCR2 = RCR2_VAL_RESET; // RESET = 1
|
||||
dummy_read = (uint16_t)RTC.RCR2;
|
||||
dummy_read = (uint16_t)RTC.RCR2;
|
||||
|
||||
RTC.RSECCNT = rtc_hex8_to_dec(timeinfo.tm_sec);
|
||||
RTC.RMINCNT = rtc_hex8_to_dec(timeinfo.tm_min);
|
||||
RTC.RHRCNT = rtc_hex8_to_dec(timeinfo.tm_hour);
|
||||
RTC.RDAYCNT = rtc_hex8_to_dec(timeinfo.tm_mday);
|
||||
RTC.RMONCNT = rtc_hex8_to_dec(timeinfo.tm_mon + 1);
|
||||
RTC.RYRCNT = rtc_hex16_to_dec(timeinfo.tm_year + 1900);
|
||||
dummy_read = (uint16_t)RTC.RYRCNT;
|
||||
dummy_read = (uint16_t)RTC.RYRCNT;
|
||||
|
||||
RTC.RCR2 = RCR2_VAL_START; // START = 1
|
||||
|
||||
dummy_read = (uint16_t)RTC.RCR2;
|
||||
dummy_read = (uint16_t)RTC.RCR2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* HEX to Dec(8bit) function for RTC.
|
||||
* [in]
|
||||
* hex_val:Hexadecimal value.
|
||||
* [out]
|
||||
* decimal value:From 0x00 to 0x99.
|
||||
*/
|
||||
static uint8_t rtc_hex8_to_dec(uint8_t hex_val) {
|
||||
uint32_t calc_data;
|
||||
|
||||
calc_data = hex_val / 10 * 0x10;
|
||||
calc_data += hex_val % 10;
|
||||
|
||||
if (calc_data > 0x99) {
|
||||
calc_data = 0;
|
||||
}
|
||||
|
||||
return (uint8_t)calc_data;
|
||||
}
|
||||
|
||||
/*
|
||||
* HEX to Dec(16bit) function for RTC.
|
||||
* [in]
|
||||
* hex_val:Hexadecimal value.
|
||||
* [out]
|
||||
* decimal value:From 0x0000 to 0x9999.
|
||||
*/
|
||||
static uint16_t rtc_hex16_to_dec(uint16_t hex_val) {
|
||||
uint32_t calc_data;
|
||||
calc_data = hex_val / 1000 * 0x1000;
|
||||
calc_data += ((hex_val / 100) % 10) * 0x100;
|
||||
calc_data += ((hex_val / 10) % 10) * 0x10;
|
||||
calc_data += hex_val % 10;
|
||||
|
||||
if (calc_data > 0x9999) {
|
||||
calc_data = 0;
|
||||
}
|
||||
return (uint16_t)calc_data;
|
||||
|
||||
}
|
||||
|
||||
#endif /* DEVICE_RTC */
|
|
@ -0,0 +1,64 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_PERIPHERALPINS_H
|
||||
#define MBED_PERIPHERALPINS_H
|
||||
|
||||
#include "pinmap.h"
|
||||
#include "PeripheralNames.h"
|
||||
|
||||
typedef struct {
|
||||
PinName pin;
|
||||
int function;
|
||||
int pm;
|
||||
} PinFunc;
|
||||
|
||||
/************IRQ***************/
|
||||
extern const PinMap PinMap_IRQ[];
|
||||
|
||||
/************PINMAP***************/
|
||||
extern const PinFunc PIPC_0_tbl[];
|
||||
|
||||
/************ADC***************/
|
||||
extern const PinMap PinMap_ADC[];
|
||||
|
||||
/************DAC***************/
|
||||
extern const PinMap PinMap_DAC[];
|
||||
|
||||
/************I2C***************/
|
||||
extern const PinMap PinMap_I2C_SDA[];
|
||||
extern const PinMap PinMap_I2C_SCL[];
|
||||
|
||||
/************UART***************/
|
||||
extern const PinMap PinMap_UART_TX[];
|
||||
extern const PinMap PinMap_UART_RX[];
|
||||
extern const PinMap PinMap_UART_CTS[];
|
||||
extern const PinMap PinMap_UART_RTS[];
|
||||
|
||||
/************SPI***************/
|
||||
extern const PinMap PinMap_SPI_SCLK[];
|
||||
extern const PinMap PinMap_SPI_MOSI[];
|
||||
extern const PinMap PinMap_SPI_MISO[];
|
||||
extern const PinMap PinMap_SPI_SSEL[];
|
||||
|
||||
/************PWM***************/
|
||||
extern const PinMap PinMap_PWM[];
|
||||
|
||||
/************CAN***************/
|
||||
extern const PinMap PinMap_CAN_RD[];
|
||||
extern const PinMap PinMap_CAN_TD[];
|
||||
|
||||
#endif
|
|
@ -34,82 +34,31 @@ typedef enum {
|
|||
UART7,
|
||||
} UARTName;
|
||||
|
||||
// PWMType & 1 == 1 then have to use PWDTR[12] == 1
|
||||
typedef enum {
|
||||
PWM1A = 0,
|
||||
PWM1B,
|
||||
PWM1C,
|
||||
PWM1D,
|
||||
PWM1E,
|
||||
PWM1F,
|
||||
PWM1G,
|
||||
PWM1H,
|
||||
PWM2A = 0x10,
|
||||
PWM2B,
|
||||
PWM2C,
|
||||
PWM2D,
|
||||
PWM2E,
|
||||
PWM2F,
|
||||
PWM2G,
|
||||
PWM2H,
|
||||
} PWMType;
|
||||
|
||||
typedef enum {
|
||||
TIOC0A = 0,
|
||||
TIOC0B,
|
||||
TIOC0C,
|
||||
TIOC0D,
|
||||
TIOC1A = 0x10,
|
||||
TIOC1B,
|
||||
TIOC2A = 0x20,
|
||||
TIOC2B,
|
||||
TIOC3A = 0x30,
|
||||
TIOC3B,
|
||||
TIOC3C,
|
||||
TIOC3D,
|
||||
TIOC4A = 0x40,
|
||||
TIOC4B,
|
||||
TIOC4C,
|
||||
TIOC4D,
|
||||
} MTU2_PWMType;
|
||||
|
||||
typedef enum {
|
||||
PWM0_PIN = 0,
|
||||
PWM1_PIN,
|
||||
PWM2_PIN,
|
||||
PWM3_PIN,
|
||||
PWM4_PIN,
|
||||
PWM5_PIN,
|
||||
PWM6_PIN,
|
||||
PWM7_PIN,
|
||||
PWM8_PIN,
|
||||
PWM9_PIN,
|
||||
PWM10_PIN,
|
||||
PWM11_PIN,
|
||||
PWM12_PIN,
|
||||
PWM13_PIN,
|
||||
MTU2_PWM0_PIN = 0x20,
|
||||
MTU2_PWM1_PIN,
|
||||
MTU2_PWM2_PIN,
|
||||
MTU2_PWM3_PIN,
|
||||
MTU2_PWM4_PIN,
|
||||
MTU2_PWM5_PIN,
|
||||
MTU2_PWM6_PIN,
|
||||
MTU2_PWM7_PIN,
|
||||
MTU2_PWM8_PIN,
|
||||
MTU2_PWM9_PIN,
|
||||
MTU2_PWM10_PIN,
|
||||
MTU2_PWM11_PIN,
|
||||
MTU2_PWM12_PIN,
|
||||
MTU2_PWM13_PIN,
|
||||
MTU2_PWM14_PIN,
|
||||
MTU2_PWM15_PIN,
|
||||
MTU2_PWM16_PIN,
|
||||
MTU2_PWM17_PIN,
|
||||
MTU2_PWM18_PIN,
|
||||
MTU2_PWM19_PIN,
|
||||
MTU2_PWM20_PIN,
|
||||
MTU2_PWM21_PIN,
|
||||
PWM_PWM1A = 0,
|
||||
PWM_PWM1B,
|
||||
PWM_PWM1C,
|
||||
PWM_PWM1D,
|
||||
PWM_PWM1E,
|
||||
PWM_PWM1F,
|
||||
PWM_PWM1G,
|
||||
PWM_PWM1H,
|
||||
PWM_PWM2A,
|
||||
PWM_PWM2B,
|
||||
PWM_PWM2C,
|
||||
PWM_PWM2D,
|
||||
PWM_PWM2E,
|
||||
PWM_PWM2F,
|
||||
PWM_PWM2G,
|
||||
PWM_PWM2H,
|
||||
PWM_TIOC0A = 0x20,
|
||||
PWM_TIOC0C,
|
||||
PWM_TIOC1A,
|
||||
PWM_TIOC2A,
|
||||
PWM_TIOC3A,
|
||||
PWM_TIOC3C,
|
||||
PWM_TIOC4A,
|
||||
PWM_TIOC4C,
|
||||
} PWMName;
|
||||
|
||||
typedef enum {
|
||||
|
@ -128,21 +77,22 @@ typedef enum {
|
|||
SPI_1,
|
||||
SPI_2,
|
||||
SPI_3,
|
||||
SPI_4,
|
||||
} SPIName;
|
||||
|
||||
typedef enum {
|
||||
I2C_0 = 0,
|
||||
I2C_1,
|
||||
I2C_2,
|
||||
I2C_3
|
||||
I2C_3,
|
||||
} I2CName;
|
||||
|
||||
typedef enum {
|
||||
CAN_0 = 0,
|
||||
CAN_1,
|
||||
CAN_2,
|
||||
CAN_3,
|
||||
CAN_4
|
||||
CAN_3,
|
||||
CAN_4,
|
||||
} CANName;
|
||||
|
||||
|
|
@ -0,0 +1,343 @@
|
|||
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2015 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 "PeripheralPins.h"
|
||||
|
||||
/************IRQ***************/
|
||||
enum {
|
||||
IRQ0,IRQ1,
|
||||
IRQ2,IRQ3,
|
||||
IRQ4,IRQ5,
|
||||
IRQ6,IRQ7,
|
||||
} IRQNo;
|
||||
const PinMap PinMap_IRQ[] = {
|
||||
{P1_0, IRQ0, 4}, {P1_1, IRQ1, 4}, {P1_2, IRQ2, 4},
|
||||
{P1_3, IRQ3, 4}, {P1_4, IRQ4, 4}, {P1_5, IRQ5, 4},
|
||||
{P1_6, IRQ6, 4}, {P1_7, IRQ7, 4}, {P1_8, IRQ2, 3},
|
||||
{P1_9, IRQ3, 3}, {P1_10, IRQ4, 3}, {P1_11, IRQ5, 3}, // 11
|
||||
{P2_0, IRQ5, 6}, {P2_12, IRQ6, 6}, {P2_13, IRQ7, 8},
|
||||
{P2_14, IRQ0, 8}, {P2_15, IRQ1, 8}, // 16
|
||||
{P3_0, IRQ2, 3}, {P3_1, IRQ6, 3}, {P3_3, IRQ4, 3},
|
||||
{P3_9, IRQ6, 8}, // 20
|
||||
{P4_8, IRQ0, 8}, {P4_9, IRQ1, 8}, {P4_10, IRQ2, 8},
|
||||
{P4_11, IRQ3, 8}, {P4_12, IRQ4, 8}, {P4_13, IRQ5, 8},
|
||||
{P4_14, IRQ6, 8}, {P4_15, IRQ7, 8}, // 28
|
||||
{P5_6, IRQ6, 6}, {P5_8, IRQ0, 2}, {P5_9, IRQ2, 4}, // 31
|
||||
{P6_0, IRQ5, 6}, {P6_1, IRQ4, 4}, {P6_2, IRQ7, 4},
|
||||
{P6_3, IRQ2, 4}, {P6_4, IRQ3, 4}, {P6_8, IRQ0, 8},
|
||||
{P6_9, IRQ1, 8}, {P6_10, IRQ2, 8}, {P6_11, IRQ3, 8},
|
||||
{P6_12, IRQ4, 8}, {P6_13, IRQ5, 8}, {P6_14, IRQ6, 8},
|
||||
{P6_15, IRQ7, 8}, // 44
|
||||
{P7_8, IRQ1, 8}, {P7_9, IRQ0, 8}, {P7_10, IRQ2, 8},
|
||||
{P7_11, IRQ3, 8}, {P7_12, IRQ4, 8}, {P7_13, IRQ5, 8},
|
||||
{P7_14, IRQ6, 8}, // 51
|
||||
{P8_2, IRQ0, 5}, {P8_3, IRQ1, 6}, {P8_7, IRQ5, 4},
|
||||
{P9_1, IRQ0, 4}, // 55
|
||||
{P11_12,IRQ3, 3}, {P11_15,IRQ1, 3}, // 57
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
/************PINMAP***************/
|
||||
const PinFunc PIPC_0_tbl[] = {
|
||||
// pin func pm
|
||||
{P4_0 , 2 , -1}, /* TIOC0A */
|
||||
{P5_0 , 6 , -1}, /* TIOC0A */
|
||||
{P7_0 , 7 , -1}, /* TIOC0A */
|
||||
{P10_4 , 2 , -1}, /* TIOC0A */
|
||||
{P4_1 , 2 , -1}, /* TIOC0B */
|
||||
{P5_1 , 6 , -1}, /* TIOC0B */
|
||||
{P7_1 , 7 , -1}, /* TIOC0B */
|
||||
{P10_5 , 2 , -1}, /* TIOC0B */
|
||||
{P4_2 , 2 , -1}, /* TIOC0C */
|
||||
{P5_5 , 6 , -1}, /* TIOC0C */
|
||||
{P7_2 , 7 , -1}, /* TIOC0C */
|
||||
{P10_6 , 2 , -1}, /* TIOC0C */
|
||||
{P4_3 , 2 , -1}, /* TIOC0D */
|
||||
{P5_7 , 6 , -1}, /* TIOC0D */
|
||||
{P7_3 , 7 , -1}, /* TIOC0D */
|
||||
{P10_7 , 2 , -1}, /* TIOC0D */
|
||||
{P2_11 , 5 , -1}, /* TIOC1A */
|
||||
{P6_0 , 5 , -1}, /* TIOC1A */
|
||||
{P7_4 , 7 , -1}, /* TIOC1A */
|
||||
{P8_8 , 5 , -1}, /* TIOC1A */
|
||||
{P9_7 , 4 , -1}, /* TIOC1A */
|
||||
{P10_8 , 2 , -1}, /* TIOC1A */
|
||||
{P2_12 , 8 , -1}, /* TIOC1B */
|
||||
{P5_2 , 6 , -1}, /* TIOC1B */
|
||||
{P6_1 , 5 , -1}, /* TIOC1B */
|
||||
{P7_5 , 7 , -1}, /* TIOC1B */
|
||||
{P8_9 , 5 , -1}, /* TIOC1B */
|
||||
{P10_9 , 2 , -1}, /* TIOC1B */
|
||||
{P2_1 , 6 , -1}, /* TIOC2A */
|
||||
{P6_2 , 6 , -1}, /* TIOC2A */
|
||||
{P7_6 , 7 , -1}, /* TIOC2A */
|
||||
{P8_14 , 4 , -1}, /* TIOC2A */
|
||||
{P10_10 , 2 , -1}, /* TIOC2A */
|
||||
{P2_2 , 6 , -1}, /* TIOC2B */
|
||||
{P6_3 , 6 , -1}, /* TIOC2B */
|
||||
{P7_7 , 7 , -1}, /* TIOC2B */
|
||||
{P8_15 , 4 , -1}, /* TIOC2B */
|
||||
{P10_11 , 2 , -1}, /* TIOC2B */
|
||||
{P10_11 , 2 , -1}, /* TIOC2B */
|
||||
{P3_4 , 6 , -1}, /* TIOC3A */
|
||||
{P7_8 , 7 , -1}, /* TIOC3A */
|
||||
{P8_10 , 4 , -1}, /* TIOC3A */
|
||||
{P3_5 , 6 , -1}, /* TIOC3B */
|
||||
{P7_9 , 7 , -1}, /* TIOC3B */
|
||||
{P8_11 , 4 , -1}, /* TIOC3B */
|
||||
{P3_6 , 6 , -1}, /* TIOC3C */
|
||||
{P5_3 , 6 , -1}, /* TIOC3C */
|
||||
{P7_10 , 7 , -1}, /* TIOC3C */
|
||||
{P8_12 , 4 , -1}, /* TIOC3C */
|
||||
{P3_7 , 6 , -1}, /* TIOC3D */
|
||||
{P5_4 , 6 , -1}, /* TIOC3D */
|
||||
{P7_11 , 7 , -1}, /* TIOC3D */
|
||||
{P8_13 , 4 , -1}, /* TIOC3D */
|
||||
{P3_8 , 6 , -1}, /* TIOC4A */
|
||||
{P4_4 , 3 , -1}, /* TIOC4A */
|
||||
{P7_12 , 7 , -1}, /* TIOC4A */
|
||||
{P11_0 , 2 , -1}, /* TIOC4A */
|
||||
{P3_9 , 6 , -1}, /* TIOC4B */
|
||||
{P4_5 , 3 , -1}, /* TIOC4B */
|
||||
{P7_13 , 7 , -1}, /* TIOC4B */
|
||||
{P11_1 , 2 , -1}, /* TIOC4B */
|
||||
{P3_10 , 6 , -1}, /* TIOC4C */
|
||||
{P4_6 , 3 , -1}, /* TIOC4C */
|
||||
{P7_14 , 7 , -1}, /* TIOC4C */
|
||||
{P11_2 , 2 , -1}, /* TIOC4C */
|
||||
{P3_11 , 6 , -1}, /* TIOC4D */
|
||||
{P4_7 , 3 , -1}, /* TIOC4D */
|
||||
{P7_15 , 7 , -1}, /* TIOC4D */
|
||||
{P11_3 , 2 , -1}, /* TIOC4D */
|
||||
{P5_7 , 1 , 1 }, /* TXOUT0M */
|
||||
{P5_6 , 1 , 1 }, /* TXOUT0P */
|
||||
{P5_5 , 1 , 1 }, /* TXOUT1M */
|
||||
{P5_4 , 1 , 1 }, /* TXOUT1P */
|
||||
{P5_3 , 1 , 1 }, /* TXOUT2M */
|
||||
{P5_2 , 1 , 1 }, /* TXOUT2P */
|
||||
{P5_1 , 1 , 1 }, /* TXCLKOUTM */
|
||||
{P5_0 , 1 , 1 }, /* TXCLKOUTP */
|
||||
{P2_11 , 4 , 0 }, /* SSITxD0 */
|
||||
{P4_7 , 5 , 0 }, /* SSITxD0 */
|
||||
{P7_4 , 6 , 0 }, /* SSITxD1 */
|
||||
{P10_15 , 2 , 0 }, /* SSITxD1 */
|
||||
{P4_15 , 6 , 0 }, /* SSITxD3 */
|
||||
{P7_11 , 2 , 0 }, /* SSITxD3 */
|
||||
{P2_7 , 4 , 0 }, /* SSITxD5 */
|
||||
{P4_11 , 5 , 0 }, /* SSITxD5 */
|
||||
{P8_10 , 8 , 0 }, /* SSITxD5 */
|
||||
{P3_7 , 8 , 0 }, /* WDTOVF */
|
||||
{NC , 0 , -1}
|
||||
};
|
||||
|
||||
/************ADC***************/
|
||||
const PinMap PinMap_ADC[] = {
|
||||
{P1_8, AN0, 1},
|
||||
{P1_9, AN1, 1},
|
||||
{P1_10, AN2, 1},
|
||||
{P1_11, AN3, 1},
|
||||
{P1_12, AN4, 1},
|
||||
{P1_13, AN5, 1},
|
||||
{P1_14, AN6, 1},
|
||||
{P1_15, AN7, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************I2C***************/
|
||||
const PinMap PinMap_I2C_SDA[] = {
|
||||
{P1_1 , I2C_0, 1},
|
||||
{P1_3 , I2C_1, 1},
|
||||
{P1_7 , I2C_3, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_I2C_SCL[] = {
|
||||
{P1_0 , I2C_0, 1},
|
||||
{P1_2 , I2C_1, 1},
|
||||
{P1_6 , I2C_3, 1},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************UART***************/
|
||||
const PinMap PinMap_UART_TX[] = {
|
||||
{P2_14 , UART0, 6},
|
||||
{P2_5 , UART1, 6},
|
||||
{P4_12 , UART1, 7},
|
||||
{P6_3 , UART2, 7},
|
||||
{P4_14 , UART2, 7},
|
||||
{P5_3 , UART3, 5},
|
||||
{P8_8 , UART3, 7},
|
||||
{P5_0 , UART4, 5},
|
||||
{P8_14 , UART4, 7},
|
||||
{P8_13 , UART5, 5},
|
||||
{P11_10, UART5, 3},
|
||||
{P6_6 , UART5, 5},
|
||||
{P5_6 , UART6, 5},
|
||||
{P11_1 , UART6, 4},
|
||||
{P7_4 , UART7, 4},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RX[] = {
|
||||
{P2_15 , UART0, 6},
|
||||
{P2_6 , UART1, 6},
|
||||
{P4_13 , UART1, 7},
|
||||
{P6_2 , UART2, 7},
|
||||
{P4_15 , UART2, 7},
|
||||
{P5_4 , UART3, 5},
|
||||
{P8_9 , UART3, 7},
|
||||
{P5_1 , UART4, 5},
|
||||
{P8_15 , UART4, 7},
|
||||
{P8_11 , UART5, 5},
|
||||
{P11_11, UART5, 3},
|
||||
{P6_7 , UART5, 5},
|
||||
{P5_7 , UART6, 5},
|
||||
{P11_2 , UART6, 4},
|
||||
{P7_5 , UART7, 4},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_CTS[] = {
|
||||
{P2_3 , UART1, 6},
|
||||
{P11_7 , UART5, 3},
|
||||
{P7_6 , UART7, 4},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RTS[] = {
|
||||
{P2_7 , UART1, 6},
|
||||
{P11_8 , UART5, 3},
|
||||
{P7_7 , UART7, 4},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************SPI***************/
|
||||
const PinMap PinMap_SPI_SCLK[] = {
|
||||
{P10_12, SPI_0, 4},
|
||||
{P4_4 , SPI_1, 2},
|
||||
{P6_4 , SPI_1, 7},
|
||||
{P11_12, SPI_1, 2},
|
||||
{P8_3 , SPI_2, 3},
|
||||
{P5_0 , SPI_3, 8},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_MOSI[] = {
|
||||
{P10_14, SPI_0, 4},
|
||||
{P4_6 , SPI_1, 2},
|
||||
{P6_6 , SPI_1, 7},
|
||||
{P11_14, SPI_1, 2},
|
||||
{P8_5 , SPI_2, 3},
|
||||
{P5_2 , SPI_3, 8},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_MISO[] = {
|
||||
{P10_15, SPI_0, 4},
|
||||
{P4_7 , SPI_1, 2},
|
||||
{P6_7 , SPI_1, 7},
|
||||
{P11_15, SPI_1, 2},
|
||||
{P8_6 , SPI_2, 3},
|
||||
{P5_3 , SPI_3, 8},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_SSEL[] = {
|
||||
{P10_13, SPI_0, 4},
|
||||
{P4_5 , SPI_1, 2},
|
||||
{P6_5 , SPI_1, 7},
|
||||
{P11_13, SPI_1, 2},
|
||||
{P8_4 , SPI_2, 3},
|
||||
{P5_1 , SPI_3, 8},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************PWM***************/
|
||||
const PinMap PinMap_PWM[] = {
|
||||
{P2_1 , PWM_TIOC2A, 6},
|
||||
{P2_11 , PWM_TIOC1A, 5},
|
||||
{P3_8 , PWM_TIOC4A, 6},
|
||||
{P3_10 , PWM_TIOC4C, 6},
|
||||
{P4_0 , PWM_TIOC0A, 2},
|
||||
{P4_4 , PWM_TIOC4A, 3},
|
||||
{P4_6 , PWM_TIOC4C, 3},
|
||||
{P5_0 , PWM_TIOC0A, 6},
|
||||
{P5_3 , PWM_TIOC3C, 6},
|
||||
{P5_5 , PWM_TIOC0C, 6},
|
||||
{P7_2 , PWM_TIOC0C, 7},
|
||||
{P7_4 , PWM_TIOC1A, 7},
|
||||
{P7_6 , PWM_TIOC2A, 7},
|
||||
{P7_10 , PWM_TIOC3C, 7},
|
||||
{P7_12 , PWM_TIOC4A, 7},
|
||||
{P7_14 , PWM_TIOC4C, 7},
|
||||
{P8_8 , PWM_TIOC1A, 5},
|
||||
{P8_10 , PWM_TIOC3A, 4},
|
||||
{P8_12 , PWM_TIOC3C, 4},
|
||||
{P8_14 , PWM_TIOC2A, 4},
|
||||
{P11_0 , PWM_TIOC4A, 2},
|
||||
{P11_2 , PWM_TIOC4C, 2},
|
||||
{P4_4 , PWM_PWM2E , 4},
|
||||
{P3_2 , PWM_PWM2C , 7},
|
||||
{P4_6 , PWM_PWM2G , 4},
|
||||
{P4_7 , PWM_PWM2H , 4},
|
||||
{P8_14 , PWM_PWM1G , 6},
|
||||
{P8_15 , PWM_PWM1H , 6},
|
||||
{P8_13 , PWM_PWM1F , 6},
|
||||
{P8_11 , PWM_PWM1D , 6},
|
||||
{P8_8 , PWM_PWM1A , 6},
|
||||
{P10_0 , PWM_PWM2A , 3},
|
||||
{P8_12 , PWM_PWM1E , 6},
|
||||
{P8_9 , PWM_PWM1B , 6},
|
||||
{P8_10 , PWM_PWM1C , 6},
|
||||
{P4_5 , PWM_PWM2F , 4},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
/************CAN***************/
|
||||
const PinMap PinMap_CAN_RD[] = {
|
||||
{P7_8 , CAN_0, 4},
|
||||
{P9_1 , CAN_0, 3},
|
||||
{P1_4 , CAN_1, 3},
|
||||
{P5_9 , CAN_1, 5},
|
||||
{P7_11 , CAN_1, 4},
|
||||
{P11_12, CAN_1, 1},
|
||||
{P4_9 , CAN_2, 6},
|
||||
{P6_4 , CAN_2, 3},
|
||||
{P7_2 , CAN_2, 5},
|
||||
{P2_12 , CAN_3, 5},
|
||||
{P4_2 , CAN_3, 4},
|
||||
{P1_5 , CAN_4, 3},
|
||||
{P2_14 , CAN_4, 5},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
||||
const PinMap PinMap_CAN_TD[] = {
|
||||
{P7_9 , CAN_0, 4},
|
||||
{P9_0 , CAN_0, 3},
|
||||
{P5_10 , CAN_1, 5},
|
||||
{P7_10 , CAN_1, 4},
|
||||
{P11_13, CAN_1, 1},
|
||||
{P4_8 , CAN_2, 6},
|
||||
{P6_5 , CAN_2, 3},
|
||||
{P7_3 , CAN_2, 5},
|
||||
{P2_13 , CAN_3, 5},
|
||||
{P4_3 , CAN_3, 4},
|
||||
{P4_11 , CAN_4, 6},
|
||||
{P8_10 , CAN_4, 5},
|
||||
{NC , NC , 0}
|
||||
};
|
||||
|
|
@ -25,7 +25,14 @@ typedef enum {
|
|||
Port1 = 1,
|
||||
Port2 = 2,
|
||||
Port3 = 3,
|
||||
Port4 = 4
|
||||
Port4 = 4,
|
||||
Port5 = 5,
|
||||
Port6 = 6,
|
||||
Port7 = 7,
|
||||
Port8 = 8,
|
||||
Port9 = 9,
|
||||
Port10 = 10,
|
||||
Port11 = 11
|
||||
} PortName;
|
||||
|
||||
#ifdef __cplusplus
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue