Merge pull request #5954 from ARMmbed/release-candidate

Release candidate for mbed-os-5.7.4
pull/6195/merge mbed-os-5.7.4
Cruz Monrreal 2018-01-29 18:22:46 -06:00 committed by GitHub
commit caeaa49d68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
745 changed files with 90891 additions and 49581 deletions

View File

@ -127,6 +127,7 @@ matrix:
before_script: before_script:
# Setup and patch littlefs-fuse # Setup and patch littlefs-fuse
- git clone https://github.com/geky/littlefs-fuse littlefs_fuse - git clone https://github.com/geky/littlefs-fuse littlefs_fuse
- git -C littlefs_fuse checkout 3f1ed6e37799e49e3710830dc6abb926d5503cf2
- echo '*' > littlefs_fuse/.mbedignore - echo '*' > littlefs_fuse/.mbedignore
- rm -rf littlefs_fuse/littlefs/* - rm -rf littlefs_fuse/littlefs/*
- cp -r $(git ls-tree --name-only HEAD $LITTLEFS/littlefs/) 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 # Run local littlefs tests
- CFLAGS="-Wno-format" make -C$LITTLEFS/littlefs test QUIET=1 - CFLAGS="-Wno-format" make -C$LITTLEFS/littlefs test QUIET=1
# Run local littlefs tests with set of variations # 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=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=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_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_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048" make -C$LITTLEFS/littlefs test QUIET=1
- CFLAGS="-Wno-format -DLFS_LOOKAHEAD=2048" make -C$LITTLEFS/littlefs test QUIET=1
# Self-hosting littlefs fuzz test with littlefs-fuse # Self-hosting littlefs fuzz test with littlefs-fuse
- make -Clittlefs_fuse - make -Clittlefs_fuse
- littlefs_fuse/lfs --format /dev/loop0 - littlefs_fuse/lfs --format /dev/loop0

View File

@ -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 * SPDX-License-Identifier: Apache-2.0
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may * Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -16,41 +16,480 @@
*/ */
#include "mbed.h" #include "mbed.h"
#include "greentea-client/test_env.h" #include "greentea-client/test_env.h"
#include "unity/unity.h" #include "unity.h"
#include "utest/utest.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; 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() { #define DELAY_10_SEC 10
greentea_send_kv("timestamp", CUSTOM_TIME); #define MS_PER_SEC 1000
#define RTC_DELTA 1
char buffer[32] = {0}; static volatile int rtc_enabled_ret;
char kv_buff[64] = {0}; static volatile time_t rtc_time_val;
set_time(CUSTOM_TIME); // Set RTC time to Wed, 28 Oct 2009 11:35:37 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) { /* Stub of RTC read function. */
time_t seconds = time(NULL); static time_t read_rtc_stub(void)
sprintf(kv_buff, "[%ld] ", seconds); {
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S %p", localtime(&seconds)); rtc_read_called = true;
strcat(kv_buff, buffer);
greentea_send_kv("rtc", kv_buff); return rtc_time_val;
wait(1); }
}
/* 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 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) { Specification specification(test_setup, cases);
GREENTEA_SETUP(20, "rtc_auto");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main() { int main() {
Harness::run(specification); return !Harness::run(specification);
} }

View File

@ -28,7 +28,7 @@
using namespace utest::v1; using namespace utest::v1;
#define TEST_CYCLES 1000000 #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: return values to be checked are documented at:

View File

@ -28,13 +28,13 @@
using namespace utest::v1; using namespace utest::v1;
#ifndef MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE #ifndef MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE
#define MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE 256 #define MBED_CONF_APP_TCP_CLIENT_ECHO_BUFFER_SIZE 256
#endif #endif
namespace { namespace {
char tx_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_CFG_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) { 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() { void test_tcp_echo() {
int n = 0;
NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION; NetworkInterface* net = MBED_CONF_APP_OBJECT_CONSTRUCTION;
int err = MBED_CONF_APP_CONNECT_STATEMENT; int err = MBED_CONF_APP_CONNECT_STATEMENT;
@ -86,7 +86,12 @@ void test_tcp_echo() {
prep_buffer(tx_buffer, sizeof(tx_buffer)); prep_buffer(tx_buffer, sizeof(tx_buffer));
#if defined(MBED_CONF_APP_TCP_ECHO_PREFIX) #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 */ #endif /* MBED_CONF_APP_TCP_ECHO_PREFIX */
const int ret = sock.send(tx_buffer, sizeof(tx_buffer)); const int ret = sock.send(tx_buffer, sizeof(tx_buffer));
if (ret >= 0) { if (ret >= 0) {
@ -95,7 +100,7 @@ void test_tcp_echo() {
printf("Network error %d\n", ret); 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) { if (n >= 0) {
printf("recv %d bytes - %.*s \n", n, n, rx_buffer); printf("recv %d bytes - %.*s \n", n, n, rx_buffer);
} else { } else {

View File

@ -76,9 +76,15 @@ void test_tcp_hello_world() {
sock.send(buffer, strlen(buffer)); sock.send(buffer, strlen(buffer));
// Server will respond with HTTP GET's success code // Server will respond with HTTP GET's success code
const int ret = sock.recv(buffer, sizeof(buffer) - 1); int ret = 0;
buffer[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 // 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)); 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 // Find "Hello World!" string in reply

View File

@ -20,7 +20,7 @@
#include <new> #include <new>
#include "EventQueue.h" #include "EventQueue.h"
#include "ble/BLEInstanceBase.h" #include "ble/BLEInstanceBase.h"
#include "BLE/ble.h" #include "ble/BLE.h"
namespace ble { namespace ble {
namespace pal { namespace pal {

View File

@ -210,6 +210,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
bool has_variable_len, bool has_variable_len,
const uint8_t *userDescriptionDescriptorValuePtr, const uint8_t *userDescriptionDescriptorValuePtr,
uint16_t userDescriptionDescriptorValueLen, uint16_t userDescriptionDescriptorValueLen,
const uint8_t *presentationFormatDescriptorValuePtr,
uint16_t presentationFormatDescriptorValueLen,
bool readAuthorization, bool readAuthorization,
bool writeAuthorization, bool writeAuthorization,
ble_gatts_char_handles_t *p_char_handle) 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_max_size = userDescriptionDescriptorValueLen;
char_md.char_user_desc_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 */ /* Attribute declaration */
ble_gatts_attr_md_t attr_md = {0}; ble_gatts_attr_md_t attr_md = {0};

View File

@ -52,6 +52,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
bool has_variable_len, bool has_variable_len,
const uint8_t *userDescriptionDescriptorValuePtr, const uint8_t *userDescriptionDescriptorValuePtr,
uint16_t userDescriptionDescriptorValueLen, uint16_t userDescriptionDescriptorValueLen,
const uint8_t *presentationFormatDescriptorValuePtr,
uint16_t presentationFormatDescriptorValueLen,
bool readAuthorization, bool readAuthorization,
bool writeAuthorization, bool writeAuthorization,
ble_gatts_char_handles_t *p_char_handle); ble_gatts_char_handles_t *p_char_handle);

View File

@ -131,6 +131,7 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
} }
GattCharacteristic *p_char = service.getCharacteristic(i); GattCharacteristic *p_char = service.getCharacteristic(i);
GattAttribute *p_description_descriptor = NULL; GattAttribute *p_description_descriptor = NULL;
GattAttribute *p_presentation_format_descriptor = NULL;
/* Skip any incompletely defined, read-only characteristics. */ /* Skip any incompletely defined, read-only characteristics. */
if ((p_char->getValueAttribute().getValuePtr() == NULL) && 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()); nordicUUID = custom_convert_to_nordic_uuid(p_char->getValueAttribute().getUUID());
/* The user-description descriptor is a special case which needs to be /* The user-description and presentation-format descriptors are special cases
* handled at the time of adding the characteristic. The following block * that need to be handled at the time of adding each characteristic. The
* is meant to discover its presence. */ * following block is meant to discover their presence. */
const uint8_t *userDescriptionDescriptorValuePtr = NULL; const uint8_t *userDescriptionDescriptorValuePtr = NULL;
uint16_t userDescriptionDescriptorValueLen = 0; uint16_t userDescriptionDescriptorValueLen = 0;
const uint8_t *presentationFormatDescriptorValuePtr = NULL;
uint16_t presentationFormatDescriptorValueLen = 0;
for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) { for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) {
GattAttribute *p_desc = p_char->getDescriptor(j); GattAttribute *p_desc = p_char->getDescriptor(j);
if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) { 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(); userDescriptionDescriptorValuePtr = p_desc->getValuePtr();
userDescriptionDescriptorValueLen = p_desc->getLength(); 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 == ASSERT_TRUE ( ERROR_NONE ==
@ -166,6 +174,8 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
p_char->getValueAttribute().hasVariableLength(), p_char->getValueAttribute().hasVariableLength(),
userDescriptionDescriptorValuePtr, userDescriptionDescriptorValuePtr,
userDescriptionDescriptorValueLen, userDescriptionDescriptorValueLen,
presentationFormatDescriptorValuePtr,
presentationFormatDescriptorValueLen,
p_char->isReadAuthorizationEnabled(), p_char->isReadAuthorizationEnabled(),
p_char->isWriteAuthorizationEnabled(), p_char->isWriteAuthorizationEnabled(),
&nrfCharacteristicHandles[characteristicCount]), &nrfCharacteristicHandles[characteristicCount]),
@ -179,6 +189,10 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
nrfCharacteristicHandles[characteristicCount].user_desc_handle 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++; characteristicCount++;
/* Add optional descriptors if any */ /* Add optional descriptors if any */
@ -188,8 +202,10 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
} }
GattAttribute *p_desc = p_char->getDescriptor(j); GattAttribute *p_desc = p_char->getDescriptor(j);
/* skip the user-description-descriptor here; this has already been handled when adding the characteristic (above). */ /* skip the user-description or presentation-format descriptor here;
if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) { * 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; continue;
} }

View File

@ -1,5 +1,21 @@
# Change Log # 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) ## [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) -[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.0.9...v4.0.10)

View File

@ -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); 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_ */ #endif /* SN_COAP_PROTOCOL_H_ */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,6 +1,6 @@
{ {
"name": "mbed-coap", "name": "mbed-coap",
"version": "4.0.10", "version": "4.1.1",
"description": "COAP library", "description": "COAP library",
"keywords": [ "keywords": [
"coap", "coap",

View File

@ -229,6 +229,7 @@ struct coap_s {
uint8_t sn_coap_resending_count; uint8_t sn_coap_resending_count;
uint8_t sn_coap_resending_intervall; uint8_t sn_coap_resending_intervall;
uint8_t sn_coap_duplication_buffer_size; 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 #ifdef __cplusplus

View File

@ -63,18 +63,22 @@ sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap
return NULL; 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_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code; coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
coap_res_ptr->msg_id = coap_packet_ptr->msg_id; coap_res_ptr->msg_id = coap_packet_ptr->msg_id;
} }
else if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE) { 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_type = COAP_MSG_TYPE_NON_CONFIRMABLE;
coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code; coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
/* msg_id needs to be set by the caller in this case */ /* msg_id needs to be set by the caller in this case */
} }
else { else {
handle->sn_coap_protocol_free( coap_res_ptr ); handle->sn_coap_protocol_free( coap_res_ptr );
return NULL; return NULL;

View File

@ -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 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 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 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); static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, sn_coap_hdr_s *source_header_ptr);
#endif #endif
#if ENABLE_RESENDINGS #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 */ /* If pointer = 0, then re-sending does not return error when failed */
handle->sn_coap_rx_callback = used_rx_callback_ptr; 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 */ #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 * * * */ /* * * * Create Linked list for storing active resending messages * * * */
ns_list_init(&handle->linked_list_resent_msgs); ns_list_init(&handle->linked_list_resent_msgs);
handle->sn_coap_resending_queue_msgs = SN_COAP_RESENDING_QUEUE_SIZE_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; 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) int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size)
{ {
(void) handle; (void) handle;
@ -1730,17 +1739,9 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
return NULL; 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) { if (!blocks_in_order) {
tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE!"); 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; 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) { } 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; 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) { } 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->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; // Response with COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE if the payload size is more than we can handle
src_coap_blockwise_ack_msg_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT; 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 */ /* Check block size */
block_temp = (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 & 0x07); 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)) { uint16_t block_size = 1u << (block_temp + 4);
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 &= 0xFFFFF8; if (block_size > handle->sn_coap_block_data_size) {
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_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; 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 { else {
//This is response to request we made //This is response to request we made
if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) { 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 */ /* Store blockwise payload to Linked list */
//todo: add block number to stored values - just to make sure all packets are in order //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, sn_coap_protocol_linked_list_blockwise_payload_store(handle,
src_addr_ptr, src_addr_ptr,
received_coap_msg_ptr->payload_len, received_coap_msg_ptr->payload_len,
received_coap_msg_ptr->payload_ptr, received_coap_msg_ptr->payload_ptr,
received_coap_msg_ptr->options_list_ptr->block1 >> 4); 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) */ ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) {
if (received_coap_msg_ptr->options_list_ptr->block2 & 0x08) { if (received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) {
coap_blockwise_msg_s *previous_blockwise_msg_ptr = NULL; previous_blockwise_msg_ptr = msg;
//build and send ack break;
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;
} }
}
if (!previous_blockwise_msg_ptr || !previous_blockwise_msg_ptr->coap_msg_ptr) { if (!previous_blockwise_msg_ptr || !previous_blockwise_msg_ptr->coap_msg_ptr) {
tr_error("sn_coap_handle_blockwise_message - (send block2) previous message null!"); 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); sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
return 0; 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;
} }
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) { /* * * Then build CoAP Acknowledgement message * * */
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;
}
src_coap_blockwise_ack_msg_ptr->msg_id = message_id++; if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) {
if (message_id == 0) { tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate options!");
message_id = 1; 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 */ src_coap_blockwise_ack_msg_ptr->msg_id = message_id++;
block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07; if (message_id == 0) {
message_id = 1;
}
block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4; /* Update block option */
block_number ++; 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 */ src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = (block_number << 4) | block_temp;
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) { /* Set BLOCK2 (subsequent) GET msg code and copy uri path from previous msg*/
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate packet!"); if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CONTENT) {
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr); src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_REQUEST_GET;
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0; if (previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_ptr) {
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_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 = 0; src_coap_blockwise_ack_msg_ptr->uri_path_ptr = handle->sn_coap_protocol_malloc(previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len);
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); if (!src_coap_blockwise_ack_msg_ptr->uri_path_ptr) {
return NULL; 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!");
memset(dst_ack_packet_data_ptr, 0, dst_packed_data_needed_mem); 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 * * */ ns_list_remove(&handle->linked_list_blockwise_sent_msgs, previous_blockwise_msg_ptr);
if ((sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size)) < 0) { if (previous_blockwise_msg_ptr->coap_msg_ptr) {
tr_error("sn_coap_handle_blockwise_message - (send block2) builder failed!"); 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); handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
dst_ack_packet_data_ptr = 0; 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 * * */ //Last block received
coap_blockwise_msg_s *stored_blockwise_msg_ptr; 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)); /* Store last Blockwise payload to Linked list */
if (!stored_blockwise_msg_ptr) { uint16_t payload_len = 0;
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate blockwise message!"); uint8_t *payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len);
handle->sn_coap_protocol_free(dst_ack_packet_data_ptr); uint16_t whole_payload_len = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr);
dst_ack_packet_data_ptr = 0; uint8_t *temp_whole_payload_ptr = NULL;
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0; temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len);
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr); if (!temp_whole_payload_ptr) {
src_coap_blockwise_ack_msg_ptr = 0; tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate whole payload!");
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr); return 0;
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 //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; 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) { if (block_size == 16) {
return 0; return 0;

View File

@ -23,4 +23,11 @@
#define MEM_SIZE (1600 * 16) #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 #endif

View File

@ -5,11 +5,73 @@
#include "mbed_interface.h" #include "mbed_interface.h"
#include "ethernet_api.h" #include "ethernet_api.h"
#include "ethernetext_api.h" #include "ethernetext_api.h"
#include "platform/mbed_toolchain.h"
#define RECV_TASK_PRI (osPriorityNormal) #define RECV_TASK_PRI (osPriorityNormal)
#define PHY_TASK_PRI (osPriorityNormal) #define PHY_TASK_PRI (osPriorityNormal)
#define PHY_TASK_WAIT (200) #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 */ /* memory */
static sys_sem_t recv_ready_sem; /* receive ready semaphore */ 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); sys_sem_new(&recv_ready_sem, 0);
/* task */ /* task */
sys_thread_new("rza1_emac_rx_thread", rza1_recv_task, netif, DEFAULT_THREAD_STACKSIZE, RECV_TASK_PRI); sys_thread_new("rza1_recv_task", 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_phy_task", rza1_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_TASK_PRI);
return ERR_OK; return ERR_OK;
} }

View File

@ -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

View File

@ -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(&ethcfg);
/* 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);
}

View File

@ -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); debug_if(FFS_DBG, "disk_read(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv);
DWORD ssize = disk_get_sector_size(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; 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); debug_if(FFS_DBG, "disk_write(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv);
DWORD ssize = disk_get_sector_size(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) { if (err) {
return RES_PARERR; return RES_PARERR;
} }
err = _ffs[pdrv]->program(buff, sector*ssize, count*ssize); err = _ffs[pdrv]->program(buff, addr, size);
if (err) { if (err) {
return RES_PARERR; return RES_PARERR;
} }
@ -250,7 +254,9 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
} else { } else {
DWORD *sectors = (DWORD*)buff; DWORD *sectors = (DWORD*)buff;
DWORD ssize = disk_get_sector_size(pdrv); 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; return err ? RES_PARERR : RES_OK;
} }
} }

View File

@ -85,19 +85,19 @@ static int lfs_totype(int type)
static int lfs_bd_read(const struct lfs_config *c, lfs_block_t block, static int lfs_bd_read(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size) { lfs_off_t off, void *buffer, lfs_size_t size) {
BlockDevice *bd = (BlockDevice *)c->context; 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, 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) { lfs_off_t off, const void *buffer, lfs_size_t size) {
BlockDevice *bd = (BlockDevice *)c->context; 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) static int lfs_bd_erase(const struct lfs_config *c, lfs_block_t block)
{ {
BlockDevice *bd = (BlockDevice *)c->context; 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) static int lfs_bd_sync(const struct lfs_config *c)

View File

@ -12,10 +12,9 @@ script:
- make test QUIET=1 - make test QUIET=1
# run tests with a few different configurations # run tests with a few different configurations
- CFLAGS="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" 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_READ_SIZE=512 -DLFS_PROG_SIZE=512" make test QUIET=1
- CFLAGS="-DLFS_BLOCK_COUNT=1023" make test QUIET=1 - CFLAGS="-DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048" make test QUIET=1
- CFLAGS="-DLFS_LOOKAHEAD=2048" make test QUIET=1
# self-host with littlefs-fuse for fuzz test # self-host with littlefs-fuse for fuzz test
- make -C littlefs-fuse - make -C littlefs-fuse

View File

@ -1261,6 +1261,9 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
file->pos = 0; file->pos = 0;
if (flags & LFS_O_TRUNC) { if (flags & LFS_O_TRUNC) {
if (file->size != 0) {
file->flags |= LFS_F_DIRTY;
}
file->head = 0xffffffff; file->head = 0xffffffff;
file->size = 0; file->size = 0;
} }
@ -2039,9 +2042,9 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
return err; return err;
} }
// setup free lookahead // setup free lookahead, rewind so first allocation triggers a scan
lfs->free.begin = -lfs->cfg->lookahead; lfs->free.begin = -lfs_min(lfs->cfg->lookahead, lfs->cfg->block_count);
lfs->free.off = lfs->cfg->lookahead; lfs->free.off = -lfs->free.begin;
lfs->free.end = lfs->free.begin + lfs->free.off + lfs->cfg->block_count; lfs->free.end = lfs->free.begin + lfs->free.off + lfs->cfg->block_count;
// load superblock // load superblock

View File

@ -34,7 +34,8 @@ tests/test.py << TEST
lfs_size_t chunk = 31; lfs_size_t chunk = 31;
srand(0); srand(0);
lfs_mount(&lfs, &cfg) => 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) { for (lfs_size_t i = 0; i < size; i += chunk) {
chunk = (chunk < size - i) ? chunk : size - i; chunk = (chunk < size - i) ? chunk : size - i;
for (lfs_size_t b = 0; b < chunk; b++) { for (lfs_size_t b = 0; b < chunk; b++) {
@ -53,7 +54,10 @@ tests/test.py << TEST
lfs_size_t chunk = 29; lfs_size_t chunk = 29;
srand(0); srand(0);
lfs_mount(&lfs, &cfg) => 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) { for (lfs_size_t i = 0; i < size; i += chunk) {
chunk = (chunk < size - i) ? chunk : size - i; chunk = (chunk < size - i) ? chunk : size - i;
lfs_file_read(&lfs, &file[0], buffer, chunk) => chunk; lfs_file_read(&lfs, &file[0], buffer, chunk) => chunk;
@ -78,10 +82,27 @@ echo "--- Large file test ---"
w_test $LARGESIZE largeavacado w_test $LARGESIZE largeavacado
r_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 ---" echo "--- Non-overlap check ---"
r_test $SMALLSIZE smallavacado r_test $SMALLSIZE smallavacado
r_test $MEDIUMSIZE mediumavacado r_test $MEDIUMSIZE mediumavacado
r_test $LARGESIZE largeavacado r_test $LARGESIZE largeavacado
r_test 0 noavacado
echo "--- Dir check ---" echo "--- Dir check ---"
tests/test.py << TEST tests/test.py << TEST
@ -105,6 +126,10 @@ tests/test.py << TEST
strcmp(info.name, "largeavacado") => 0; strcmp(info.name, "largeavacado") => 0;
info.type => LFS_TYPE_REG; info.type => LFS_TYPE_REG;
info.size => $LARGESIZE; 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_read(&lfs, &dir[0], &info) => 0;
lfs_dir_close(&lfs, &dir[0]) => 0; lfs_dir_close(&lfs, &dir[0]) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;

View File

@ -48,10 +48,7 @@ override CFLAGS += -I$(EVENTLOOP_DIR)/nanostack-event-loop/
COAPSERVICE_DIR := ../coap-service COAPSERVICE_DIR := ../coap-service
override CFLAGS += -I$(COAPSERVICE_DIR)/coap-service/ override CFLAGS += -I$(COAPSERVICE_DIR)/coap-service/
override CFLAGS += -I$(COAPSERVICE_DIR)/source/include/ override CFLAGS += -I$(COAPSERVICE_DIR)/source/include/
ifeq (Linux,$(shell uname))
override CFLAGS += -DHAVE_DEBUG override CFLAGS += -DHAVE_DEBUG
endif
LIB = libcoap-service.a LIB = libcoap-service.a

View File

@ -46,13 +46,16 @@ static void own_free(void *ptr)
static NS_LIST_DEFINE(request_list, coap_transaction_t, link); 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; coap_transaction_t *this = NULL;
ns_list_foreach(coap_transaction_t, cur_ptr, &request_list) { 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; this = cur_ptr;
break; break;
} }
} }
return this; 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; coap_transaction_t *this = NULL;
(void)address_ptr; (void)address_ptr;
(void)param; (void)param;
tr_warn("transaction was not handled %d", resp_ptr->msg_id); tr_warn("transaction was not handled %d", resp_ptr->msg_id);
if (!resp_ptr) { if (!resp_ptr) {
return -1; return -1;
} }
if( resp_ptr->token_ptr ){ if(resp_ptr->token_ptr){
this = transaction_find_client_by_token(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) { if (!this) {
return 0; 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); memcpy(transaction_ptr->remote_address, source_addr_ptr, 16);
if (coap_message->token_len) { if (coap_message->token_len) {
memcpy(transaction_ptr->token, coap_message->token_ptr, 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; transaction_ptr->remote_port = port;
if (cb(socket_id, coap_message, transaction_ptr) < 0) { 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 { } else {
coap_transaction_t *this = NULL; coap_transaction_t *this = NULL;
if (coap_message->token_ptr) { 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) { if (!this) {
tr_error("client transaction not found"); 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{ do{
randLIB_get_n_bytes_random(token,4); 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); memcpy(transaction_ptr->token,token,4);
transaction_ptr->token_len = 4;
request.token_ptr = transaction_ptr->token; request.token_ptr = transaction_ptr->token;
request.token_len = 4; 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_len = payload_len;
response.payload_ptr = (uint8_t *) payload_ptr; // Cast away const and trust that nsdl doesn't modify... response.payload_ptr = (uint8_t *) payload_ptr; // Cast away const and trust that nsdl doesn't modify...
response.content_format = content_type; response.content_format = content_type;
response.token_len = 4; response.token_len = transaction_ptr->token_len;
response.token_ptr = transaction_ptr->token; response.token_ptr = transaction_ptr->token;
response.msg_code = message_code; response.msg_code = message_code;
if (transaction_ptr->req_msg_type == COAP_MSG_TYPE_CONFIRMABLE) { if (transaction_ptr->req_msg_type == COAP_MSG_TYPE_CONFIRMABLE) {

View File

@ -50,18 +50,19 @@ typedef struct coap_msg_handler_s {
typedef struct coap_transaction { typedef struct coap_transaction {
uint8_t remote_address[16]; uint8_t remote_address[16];
uint8_t local_address[16]; uint8_t local_address[16];
uint8_t token[4]; uint8_t token[8];
uint32_t create_time; uint32_t create_time;
uint8_t *data_ptr;
coap_message_handler_response_recv *resp_cb;
uint16_t remote_port; uint16_t remote_port;
uint16_t msg_id; uint16_t msg_id;
uint16_t data_len; uint16_t data_len;
int8_t service_id; int8_t service_id;
uint8_t options; uint8_t options;
uint8_t *data_ptr; uint8_t token_len;
sn_coap_msg_type_e req_msg_type; sn_coap_msg_type_e req_msg_type;
bool client_request: 1; bool client_request: 1;
coap_message_handler_response_recv *resp_cb;
ns_list_link_t link; ns_list_link_t link;
} coap_transaction_t; } coap_transaction_t;

View File

@ -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());
}
```

View File

@ -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); 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) { void* NanostackSocket::operator new(std::size_t sz) {
return MALLOC(sz); return MALLOC(sz);
} }
@ -693,17 +707,50 @@ nsapi_error_t NanostackInterface::setsockopt(void *handle, int level, int optnam
return NSAPI_ERROR_NO_SOCKET; return NSAPI_ERROR_NO_SOCKET;
} }
nsapi_error_t ret;
NanostackLockGuard lock; NanostackLockGuard lock;
if (::socket_setsockopt(socket->socket_id, level, optname, optval, optlen) == 0) { ns_ipv6_mreq_t ns_mreq;
ret = NSAPI_ERROR_OK;
} else { if (level == NSAPI_SOCKET) {
ret = NSAPI_ERROR_PARAMETER; 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) nsapi_error_t NanostackInterface::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)

View File

@ -111,7 +111,9 @@ public:
* @param data Destination buffer for data received from the host * @param data Destination buffer for data received from the host
* @param size Size of the buffer in bytes * @param size Size of the buffer in bytes
* @return Number of received bytes on success, negative error * @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); nsapi_size_or_error_t recv(void *data, nsapi_size_t size);

View File

@ -94,17 +94,18 @@ public:
nsapi_size_or_error_t sendto(const SocketAddress &address, nsapi_size_or_error_t sendto(const SocketAddress &address,
const void *data, nsapi_size_t size); 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 * Receives a datagram and stores the source address in address if address
* is not NULL. Returns the number of bytes received into the buffer. * 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 * By default, recvfrom blocks until a datagram is received. If socket is set to
* non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned * non-blocking or times out with no datagram, NSAPI_ERROR_WOULD_BLOCK
* immediately. * is returned.
* *
* @param address Destination for the source address or NULL * @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 * @param size Size of the buffer in bytes
* @return Number of received bytes on success, negative error * @return Number of received bytes on success, negative error
* code on failure * code on failure

View File

@ -56,6 +56,8 @@ USBAudio::USBAudio(uint32_t frequency_in, uint8_t channel_nb_in, uint32_t freque
volume = 0; volume = 0;
_build_configurationDesc();
// connect the device // connect the device
USBDevice::connect(); USBDevice::connect();
} }
@ -377,8 +379,8 @@ void USBAudio::USBCallback_requestCompleted(uint8_t * buf, uint32_t length) {
FEATURE_UNIT_DESCRIPTOR_LENGTH + \ FEATURE_UNIT_DESCRIPTOR_LENGTH + \
2*OUTPUT_TERMINAL_DESCRIPTOR_LENGTH) 2*OUTPUT_TERMINAL_DESCRIPTOR_LENGTH)
uint8_t * USBAudio::configurationDesc() { void USBAudio::_build_configurationDesc() {
static uint8_t configDescriptor[] = { uint8_t configDescriptorTemp[] = {
// Configuration 1 // Configuration 1
CONFIGURATION_DESCRIPTOR_LENGTH, // bLength CONFIGURATION_DESCRIPTOR_LENGTH, // bLength
CONFIGURATION_DESCRIPTOR, // bDescriptorType CONFIGURATION_DESCRIPTOR, // bDescriptorType
@ -615,15 +617,19 @@ uint8_t * USBAudio::configurationDesc() {
0x00, // bLockDelayUnits 0x00, // bLockDelayUnits
LSB(0x0000), // wLockDelay LSB(0x0000), // wLockDelay
MSB(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; return configDescriptor;
} }
uint8_t * USBAudio::stringIinterfaceDesc() { const uint8_t * USBAudio::stringIinterfaceDesc() {
static uint8_t stringIinterfaceDescriptor[] = { static const uint8_t stringIinterfaceDescriptor[] = {
0x0c, //bLength 0x0c, //bLength
STRING_DESCRIPTOR, //bDescriptorType 0x03 STRING_DESCRIPTOR, //bDescriptorType 0x03
'A',0,'u',0,'d',0,'i',0,'o',0 //bString iInterface - Audio 'A',0,'u',0,'d',0,'i',0,'o',0 //bString iInterface - Audio
@ -631,8 +637,8 @@ uint8_t * USBAudio::stringIinterfaceDesc() {
return stringIinterfaceDescriptor; return stringIinterfaceDescriptor;
} }
uint8_t * USBAudio::stringIproductDesc() { const uint8_t * USBAudio::stringIproductDesc() {
static uint8_t stringIproductDescriptor[] = { static const uint8_t stringIproductDescriptor[] = {
0x16, //bLength 0x16, //bLength
STRING_DESCRIPTOR, //bDescriptorType 0x03 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 'M',0,'b',0,'e',0,'d',0,' ',0,'A',0,'u',0,'d',0,'i',0,'o',0 //bString iProduct - Mbed Audio

View File

@ -152,7 +152,7 @@ public:
* *
*/ */
void attach(void(*fptr)(void)) { void attach(void(*fptr)(void)) {
updateVol.attach(fptr); updateVol = Callback<void()>(fptr);
} }
/** attach a handler to Tx Done /** attach a handler to Tx Done
* *
@ -160,7 +160,7 @@ public:
* *
*/ */
void attachTx(void(*fptr)(void)) { void attachTx(void(*fptr)(void)) {
txDone.attach(fptr); txDone = Callback<void()>(fptr);
} }
/** attach a handler to Rx Done /** attach a handler to Rx Done
* *
@ -168,7 +168,7 @@ public:
* *
*/ */
void attachRx(void(*fptr)(void)) { void attachRx(void(*fptr)(void)) {
rxDone.attach(fptr); rxDone = Callback<void()>(fptr);
} }
/** Attach a nonstatic void/void member function to update the volume /** Attach a nonstatic void/void member function to update the volume
@ -179,15 +179,52 @@ public:
*/ */
template<typename T> template<typename T>
void attach(T *tptr, void(T::*mptr)(void)) { 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> template<typename T>
void attachTx(T *tptr, void(T::*mptr)(void)) { 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> template<typename T>
void attachRx(T *tptr, void(T::*mptr)(void)) { 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 * @returns pointer to the string product descriptor
*/ */
virtual uint8_t * stringIproductDesc(); virtual const uint8_t * stringIproductDesc();
/* /*
* Get string interface descriptor * Get string interface descriptor
* *
* @returns pointer to the string interface descriptor * @returns pointer to the string interface descriptor
*/ */
virtual uint8_t * stringIinterfaceDesc(); virtual const uint8_t * stringIinterfaceDesc();
/* /*
* Get configuration descriptor * Get configuration descriptor
* *
* @returns pointer to the 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. * Called by USBDevice layer. Set interface/alternate of the device.
@ -270,6 +307,20 @@ protected:
private: 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 ? // stream available ?
volatile bool available; volatile bool available;

View File

@ -58,7 +58,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("device descr\r\n"); printf("device descr\r\n");
#endif #endif
transfer.remaining = DEVICE_DESCRIPTOR_LENGTH; transfer.remaining = DEVICE_DESCRIPTOR_LENGTH;
transfer.ptr = deviceDesc(); transfer.ptr = (uint8_t*)deviceDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
} }
@ -77,7 +77,7 @@ bool USBDevice::requestGetDescriptor(void)
transfer.remaining = configurationDesc()[2] \ transfer.remaining = configurationDesc()[2] \
| (configurationDesc()[3] << 8); | (configurationDesc()[3] << 8);
transfer.ptr = configurationDesc(); transfer.ptr = (uint8_t*)configurationDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
} }
@ -94,7 +94,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("1\r\n"); printf("1\r\n");
#endif #endif
transfer.remaining = stringLangidDesc()[0]; transfer.remaining = stringLangidDesc()[0];
transfer.ptr = stringLangidDesc(); transfer.ptr = (uint8_t*)stringLangidDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
break; break;
@ -103,7 +103,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("2\r\n"); printf("2\r\n");
#endif #endif
transfer.remaining = stringImanufacturerDesc()[0]; transfer.remaining = stringImanufacturerDesc()[0];
transfer.ptr = stringImanufacturerDesc(); transfer.ptr = (uint8_t*)stringImanufacturerDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
break; break;
@ -112,7 +112,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("3\r\n"); printf("3\r\n");
#endif #endif
transfer.remaining = stringIproductDesc()[0]; transfer.remaining = stringIproductDesc()[0];
transfer.ptr = stringIproductDesc(); transfer.ptr = (uint8_t*)stringIproductDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
break; break;
@ -121,7 +121,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("4\r\n"); printf("4\r\n");
#endif #endif
transfer.remaining = stringIserialDesc()[0]; transfer.remaining = stringIserialDesc()[0];
transfer.ptr = stringIserialDesc(); transfer.ptr = (uint8_t*)stringIserialDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
break; break;
@ -130,7 +130,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("5\r\n"); printf("5\r\n");
#endif #endif
transfer.remaining = stringIConfigurationDesc()[0]; transfer.remaining = stringIConfigurationDesc()[0];
transfer.ptr = stringIConfigurationDesc(); transfer.ptr = (uint8_t*)stringIConfigurationDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
break; break;
@ -139,7 +139,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("6\r\n"); printf("6\r\n");
#endif #endif
transfer.remaining = stringIinterfaceDesc()[0]; transfer.remaining = stringIinterfaceDesc()[0];
transfer.ptr = stringIinterfaceDesc(); transfer.ptr = (uint8_t*)stringIinterfaceDesc();
transfer.direction = DEVICE_TO_HOST; transfer.direction = DEVICE_TO_HOST;
success = true; success = true;
break; break;
@ -187,27 +187,8 @@ bool USBDevice::controlOut(void)
/* Check we should be transferring data OUT */ /* Check we should be transferring data OUT */
if (transfer.direction != HOST_TO_DEVICE) 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 */ /* for other platforms, count on the HAL to handle this case */
return false; return false;
#endif
} }
/* Read from endpoint */ /* Read from endpoint */
@ -790,7 +771,7 @@ uint8_t * USBDevice::findDescriptor(uint8_t descriptorType)
} }
/* Start at first descriptor after the configuration descriptor */ /* Start at first descriptor after the configuration descriptor */
ptr = &(configurationDesc()[CONFIGURATION_DESCRIPTOR_LENGTH]); ptr = &(((uint8_t*)configurationDesc())[CONFIGURATION_DESCRIPTOR_LENGTH]);
do { do {
if (ptr[1] /* bDescriptorType */ == descriptorType) 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() { const uint8_t * USBDevice::deviceDesc() {
static uint8_t deviceDescriptor[] = { uint8_t deviceDescriptorTemp[] = {
DEVICE_DESCRIPTOR_LENGTH, /* bLength */ DEVICE_DESCRIPTOR_LENGTH, /* bLength */
DEVICE_DESCRIPTOR, /* bDescriptorType */ DEVICE_DESCRIPTOR, /* bDescriptorType */
LSB(USB_VERSION_2_0), /* bcdUSB (LSB) */ LSB(USB_VERSION_2_0), /* bcdUSB (LSB) */
@ -947,20 +928,22 @@ uint8_t * USBDevice::deviceDesc() {
STRING_OFFSET_ISERIAL, /* iSerialNumber */ STRING_OFFSET_ISERIAL, /* iSerialNumber */
0x01 /* bNumConfigurations */ 0x01 /* bNumConfigurations */
}; };
MBED_ASSERT(sizeof(deviceDescriptorTemp) == sizeof(deviceDescriptor));
memcpy(deviceDescriptor, deviceDescriptorTemp, sizeof(deviceDescriptor));
return deviceDescriptor; return deviceDescriptor;
} }
uint8_t * USBDevice::stringLangidDesc() { const uint8_t * USBDevice::stringLangidDesc() {
static uint8_t stringLangidDescriptor[] = { static const uint8_t stringLangidDescriptor[] = {
0x04, /*bLength*/ 0x04, /*bLength*/
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/ STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
0x09,0x04, /*bString Lang ID - 0x0409 - English*/ 0x09,0x04, /*bString Lang ID - 0x0409 - English*/
}; };
return stringLangidDescriptor; return (uint8_t *)stringLangidDescriptor;
} }
uint8_t * USBDevice::stringImanufacturerDesc() { const uint8_t * USBDevice::stringImanufacturerDesc() {
static uint8_t stringImanufacturerDescriptor[] = { static const uint8_t stringImanufacturerDescriptor[] = {
0x12, /*bLength*/ 0x12, /*bLength*/
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/ STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
'm',0,'b',0,'e',0,'d',0,'.',0,'o',0,'r',0,'g',0, /*bString iManufacturer - mbed.org*/ '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; return stringImanufacturerDescriptor;
} }
uint8_t * USBDevice::stringIserialDesc() { const uint8_t * USBDevice::stringIserialDesc() {
static uint8_t stringIserialDescriptor[] = { static const uint8_t stringIserialDescriptor[] = {
0x16, /*bLength*/ 0x16, /*bLength*/
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/ 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*/ '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; return stringIserialDescriptor;
} }
uint8_t * USBDevice::stringIConfigurationDesc() { const uint8_t * USBDevice::stringIConfigurationDesc() {
static uint8_t stringIconfigurationDescriptor[] = { static const uint8_t stringIconfigurationDescriptor[] = {
0x06, /*bLength*/ 0x06, /*bLength*/
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/ STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
'0',0,'1',0, /*bString iConfiguration - 01*/ '0',0,'1',0, /*bString iConfiguration - 01*/
@ -986,8 +969,8 @@ uint8_t * USBDevice::stringIConfigurationDesc() {
return stringIconfigurationDescriptor; return stringIconfigurationDescriptor;
} }
uint8_t * USBDevice::stringIinterfaceDesc() { const uint8_t * USBDevice::stringIinterfaceDesc() {
static uint8_t stringIinterfaceDescriptor[] = { static const uint8_t stringIinterfaceDescriptor[] = {
0x08, /*bLength*/ 0x08, /*bLength*/
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/ STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
'U',0,'S',0,'B',0, /*bString iInterface - USB*/ 'U',0,'S',0,'B',0, /*bString iInterface - USB*/
@ -995,8 +978,8 @@ uint8_t * USBDevice::stringIinterfaceDesc() {
return stringIinterfaceDescriptor; return stringIinterfaceDescriptor;
} }
uint8_t * USBDevice::stringIproductDesc() { const uint8_t * USBDevice::stringIproductDesc() {
static uint8_t stringIproductDescriptor[] = { static const uint8_t stringIproductDescriptor[] = {
0x16, /*bLength*/ 0x16, /*bLength*/
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/ 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*/ 'U',0,'S',0,'B',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 /*bString iProduct - USB DEVICE*/

View File

@ -165,60 +165,60 @@ public:
virtual bool USBCallback_setInterface(uint16_t interface, uint8_t alternate) { return false; }; 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 * @returns pointer to the device descriptor
*/ */
virtual uint8_t * deviceDesc(); virtual const uint8_t * deviceDesc();
/* /*
* Get configuration descriptor * Get configuration descriptor
* *
* @returns pointer to the 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 * Get string lang id descriptor
* *
* @return pointer to the 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 * Get string manufacturer descriptor
* *
* @returns pointer to the string manufacturer descriptor * @returns pointer to the string manufacturer descriptor
*/ */
virtual uint8_t * stringImanufacturerDesc(); virtual const uint8_t * stringImanufacturerDesc();
/* /*
* Get string product descriptor * Get string product descriptor
* *
* @returns pointer to the string product descriptor * @returns pointer to the string product descriptor
*/ */
virtual uint8_t * stringIproductDesc(); virtual const uint8_t * stringIproductDesc();
/* /*
* Get string serial descriptor * Get string serial descriptor
* *
* @returns pointer to the string serial descriptor * @returns pointer to the string serial descriptor
*/ */
virtual uint8_t * stringIserialDesc(); virtual const uint8_t * stringIserialDesc();
/* /*
* Get string configuration descriptor * Get string configuration descriptor
* *
* @returns pointer to the string configuration descriptor * @returns pointer to the string configuration descriptor
*/ */
virtual uint8_t * stringIConfigurationDesc(); virtual const uint8_t * stringIConfigurationDesc();
/* /*
* Get string interface descriptor * Get string interface descriptor
* *
* @returns pointer to the 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 * Get the length of the report descriptor
@ -242,6 +242,7 @@ protected:
uint16_t VENDOR_ID; uint16_t VENDOR_ID;
uint16_t PRODUCT_ID; uint16_t PRODUCT_ID;
uint16_t PRODUCT_RELEASE; uint16_t PRODUCT_RELEASE;
uint8_t deviceDescriptor[18];
private: private:
bool addRateFeedbackEndpoint(uint8_t endpoint, uint32_t maxPacket); bool addRateFeedbackEndpoint(uint8_t endpoint, uint32_t maxPacket);

View File

@ -105,7 +105,7 @@ bool USBHID::USBCallback_request() {
&& (reportDescLength() != 0)) && (reportDescLength() != 0))
{ {
transfer->remaining = reportDescLength(); transfer->remaining = reportDescLength();
transfer->ptr = reportDesc(); transfer->ptr = (uint8_t*)reportDesc();
transfer->direction = DEVICE_TO_HOST; transfer->direction = DEVICE_TO_HOST;
success = true; success = true;
} }
@ -177,8 +177,8 @@ bool USBHID::USBCallback_setConfiguration(uint8_t configuration) {
} }
uint8_t * USBHID::stringIinterfaceDesc() { const uint8_t * USBHID::stringIinterfaceDesc() {
static uint8_t stringIinterfaceDescriptor[] = { static const uint8_t stringIinterfaceDescriptor[] = {
0x08, //bLength 0x08, //bLength
STRING_DESCRIPTOR, //bDescriptorType 0x03 STRING_DESCRIPTOR, //bDescriptorType 0x03
'H',0,'I',0,'D',0, //bString iInterface - HID 'H',0,'I',0,'D',0, //bString iInterface - HID
@ -186,8 +186,8 @@ uint8_t * USBHID::stringIinterfaceDesc() {
return stringIinterfaceDescriptor; return stringIinterfaceDescriptor;
} }
uint8_t * USBHID::stringIproductDesc() { const uint8_t * USBHID::stringIproductDesc() {
static uint8_t stringIproductDescriptor[] = { static const uint8_t stringIproductDescriptor[] = {
0x16, //bLength 0x16, //bLength
STRING_DESCRIPTOR, //bDescriptorType 0x03 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 '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() { const uint8_t * USBHID::reportDesc() {
static uint8_t reportDescriptor[] = { uint8_t reportDescriptorTemp[] = {
USAGE_PAGE(2), LSB(0xFFAB), MSB(0xFFAB), USAGE_PAGE(2), LSB(0xFFAB), MSB(0xFFAB),
USAGE(2), LSB(0x0200), MSB(0x0200), USAGE(2), LSB(0x0200), MSB(0x0200),
COLLECTION(1), 0x01, // Collection (Application) COLLECTION(1), 0x01, // Collection (Application)
@ -218,6 +218,8 @@ uint8_t * USBHID::reportDesc() {
END_COLLECTION(0), END_COLLECTION(0),
}; };
reportLength = sizeof(reportDescriptor); reportLength = sizeof(reportDescriptor);
MBED_ASSERT(sizeof(reportDescriptorTemp) == sizeof(reportDescriptor));
memcpy(reportDescriptor, reportDescriptorTemp, sizeof(reportDescriptor));
return reportDescriptor; return reportDescriptor;
} }
@ -227,8 +229,8 @@ uint8_t * USBHID::reportDesc() {
+ (1 * HID_DESCRIPTOR_LENGTH) \ + (1 * HID_DESCRIPTOR_LENGTH) \
+ (2 * ENDPOINT_DESCRIPTOR_LENGTH)) + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
uint8_t * USBHID::configurationDesc() { const uint8_t * USBHID::configurationDesc() {
static uint8_t configurationDescriptor[] = { uint8_t configurationDescriptorTemp[] = {
CONFIGURATION_DESCRIPTOR_LENGTH, // bLength CONFIGURATION_DESCRIPTOR_LENGTH, // bLength
CONFIGURATION_DESCRIPTOR, // bDescriptorType CONFIGURATION_DESCRIPTOR, // bDescriptorType
LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB) LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
@ -275,5 +277,7 @@ uint8_t * USBHID::configurationDesc() {
MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
1, // bInterval (milliseconds) 1, // bInterval (milliseconds)
}; };
MBED_ASSERT(sizeof(configurationDescriptorTemp) == sizeof(configurationDescriptor));
memcpy(configurationDescriptor, configurationDescriptorTemp, sizeof(configurationDescriptor));
return configurationDescriptor; return configurationDescriptor;
} }

View File

@ -98,13 +98,14 @@ public:
protected: protected:
uint16_t reportLength; uint16_t reportLength;
uint8_t reportDescriptor[27];
/* /*
* Get the Report descriptor * Get the Report descriptor
* *
* @returns pointer to 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 * Get the length of the report descriptor
@ -118,21 +119,21 @@ protected:
* *
* @returns pointer to the string product descriptor * @returns pointer to the string product descriptor
*/ */
virtual uint8_t * stringIproductDesc(); virtual const uint8_t * stringIproductDesc();
/* /*
* Get string interface descriptor * Get string interface descriptor
* *
* @returns pointer to the string interface descriptor * @returns pointer to the string interface descriptor
*/ */
virtual uint8_t * stringIinterfaceDesc(); virtual const uint8_t * stringIinterfaceDesc();
/* /*
* Get configuration descriptor * Get configuration descriptor
* *
* @returns pointer to the 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); virtual bool USBCallback_setConfiguration(uint8_t configuration);
private: private:
uint8_t configurationDescriptor[41];
HID_REPORT outputReport; HID_REPORT outputReport;
uint8_t output_length; uint8_t output_length;
uint8_t input_length; uint8_t input_length;

View File

@ -352,8 +352,8 @@ const KEYMAP keymap[KEYMAP_SIZE] = {
}; };
#endif #endif
uint8_t * USBKeyboard::reportDesc() { const uint8_t * USBKeyboard::reportDesc() {
static uint8_t reportDescriptor[] = { static const uint8_t reportDescriptor[] = {
USAGE_PAGE(1), 0x01, // Generic Desktop USAGE_PAGE(1), 0x01, // Generic Desktop
USAGE(1), 0x06, // Keyboard USAGE(1), 0x06, // Keyboard
COLLECTION(1), 0x01, // Application COLLECTION(1), 0x01, // Application
@ -501,8 +501,8 @@ bool USBKeyboard::mediaControl(MEDIA_KEY key) {
+ (1 * HID_DESCRIPTOR_LENGTH) \ + (1 * HID_DESCRIPTOR_LENGTH) \
+ (2 * ENDPOINT_DESCRIPTOR_LENGTH)) + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
uint8_t * USBKeyboard::configurationDesc() { const uint8_t * USBKeyboard::configurationDesc() {
static uint8_t configurationDescriptor[] = { uint8_t configurationDescriptorTemp[] = {
CONFIGURATION_DESCRIPTOR_LENGTH, // bLength CONFIGURATION_DESCRIPTOR_LENGTH, // bLength
CONFIGURATION_DESCRIPTOR, // bDescriptorType CONFIGURATION_DESCRIPTOR, // bDescriptorType
LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB) LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
@ -549,5 +549,7 @@ uint8_t * USBKeyboard::configurationDesc() {
MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
1, // bInterval (milliseconds) 1, // bInterval (milliseconds)
}; };
MBED_ASSERT(sizeof(configurationDescriptorTemp) == sizeof(configurationDescriptor));
memcpy(configurationDescriptor, configurationDescriptorTemp, sizeof(configurationDescriptor));
return configurationDescriptor; return configurationDescriptor;
} }

View File

@ -148,7 +148,7 @@ public:
* *
* @returns pointer to the report descriptor * @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 * 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 * @returns pointer to the configuration descriptor
*/ */
virtual uint8_t * configurationDesc(); virtual const uint8_t * configurationDesc();
private: private:
//dummy otherwise it doesn,t compile (we must define all methods of an abstract class) //dummy otherwise it doesn,t compile (we must define all methods of an abstract class)
@ -181,6 +181,7 @@ private:
return -1; return -1;
}; };
uint8_t configurationDescriptor[41];
uint8_t lock_status; uint8_t lock_status;
}; };

View File

@ -103,10 +103,10 @@ bool USBMouse::release(uint8_t button_) {
} }
uint8_t * USBMouse::reportDesc() { const uint8_t * USBMouse::reportDesc() {
if (mouse_type == REL_MOUSE) { if (mouse_type == REL_MOUSE) {
static uint8_t reportDescriptor[] = { static const uint8_t reportDescriptor[] = {
USAGE_PAGE(1), 0x01, // Genric Desktop USAGE_PAGE(1), 0x01, // Genric Desktop
USAGE(1), 0x02, // Mouse USAGE(1), 0x02, // Mouse
COLLECTION(1), 0x01, // Application COLLECTION(1), 0x01, // Application
@ -141,7 +141,7 @@ uint8_t * USBMouse::reportDesc() {
reportLength = sizeof(reportDescriptor); reportLength = sizeof(reportDescriptor);
return reportDescriptor; return reportDescriptor;
} else if (mouse_type == ABS_MOUSE) { } else if (mouse_type == ABS_MOUSE) {
static uint8_t reportDescriptor[] = { static const uint8_t reportDescriptor[] = {
USAGE_PAGE(1), 0x01, // Generic Desktop USAGE_PAGE(1), 0x01, // Generic Desktop
USAGE(1), 0x02, // Mouse USAGE(1), 0x02, // Mouse
COLLECTION(1), 0x01, // Application COLLECTION(1), 0x01, // Application
@ -192,8 +192,8 @@ uint8_t * USBMouse::reportDesc() {
+ (1 * HID_DESCRIPTOR_LENGTH) \ + (1 * HID_DESCRIPTOR_LENGTH) \
+ (2 * ENDPOINT_DESCRIPTOR_LENGTH)) + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
uint8_t * USBMouse::configurationDesc() { const uint8_t * USBMouse::configurationDesc() {
static uint8_t configurationDescriptor[] = { uint8_t configurationDescriptorTemp[] = {
CONFIGURATION_DESCRIPTOR_LENGTH, // bLength CONFIGURATION_DESCRIPTOR_LENGTH, // bLength
CONFIGURATION_DESCRIPTOR, // bDescriptorType CONFIGURATION_DESCRIPTOR, // bDescriptorType
LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB) LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
@ -240,5 +240,7 @@ uint8_t * USBMouse::configurationDesc() {
MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB) MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
1, // bInterval (milliseconds) 1, // bInterval (milliseconds)
}; };
MBED_ASSERT(sizeof(configurationDescriptorTemp) == sizeof(configurationDescriptor));
memcpy(configurationDescriptor, configurationDescriptorTemp, sizeof(configurationDescriptor));
return configurationDescriptor; return configurationDescriptor;
} }

View File

@ -190,7 +190,7 @@ class USBMouse: public USBHID
* *
* @returns pointer to the report descriptor * @returns pointer to the report descriptor
*/ */
virtual uint8_t * reportDesc(); virtual const uint8_t * reportDesc();
protected: protected:
/* /*
@ -198,11 +198,12 @@ class USBMouse: public USBHID
* *
* @returns pointer to the configuration descriptor * @returns pointer to the configuration descriptor
*/ */
virtual uint8_t * configurationDesc(); virtual const uint8_t * configurationDesc();
private: private:
MOUSE_TYPE mouse_type; MOUSE_TYPE mouse_type;
uint8_t button; uint8_t button;
uint8_t configurationDescriptor[41];
bool mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z); bool mouseSend(int8_t x, int8_t y, uint8_t buttons, int8_t z);
}; };

View File

@ -348,9 +348,9 @@ const KEYMAP keymap[KEYMAP_SIZE] = {
#endif #endif
uint8_t * USBMouseKeyboard::reportDesc() { const uint8_t * USBMouseKeyboard::reportDesc() {
if (mouse_type == REL_MOUSE) { if (mouse_type == REL_MOUSE) {
static uint8_t reportDescriptor[] = { static const uint8_t reportDescriptor[] = {
// Keyboard // Keyboard
USAGE_PAGE(1), 0x01, USAGE_PAGE(1), 0x01,
USAGE(1), 0x06, USAGE(1), 0x06,
@ -442,7 +442,7 @@ uint8_t * USBMouseKeyboard::reportDesc() {
reportLength = sizeof(reportDescriptor); reportLength = sizeof(reportDescriptor);
return reportDescriptor; return reportDescriptor;
} else if (mouse_type == ABS_MOUSE) { } else if (mouse_type == ABS_MOUSE) {
static uint8_t reportDescriptor[] = { static const uint8_t reportDescriptor[] = {
// Keyboard // Keyboard
USAGE_PAGE(1), 0x01, USAGE_PAGE(1), 0x01,

View File

@ -195,7 +195,7 @@ class USBMouseKeyboard: public USBHID, public Stream
* *
* @returns pointer to the report descriptor * @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 * Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys

View File

@ -157,8 +157,8 @@ bool USBMIDI::USBCallback_setConfiguration(uint8_t configuration) {
} }
uint8_t * USBMIDI::stringIinterfaceDesc() { const uint8_t * USBMIDI::stringIinterfaceDesc() {
static uint8_t stringIinterfaceDescriptor[] = { static const uint8_t stringIinterfaceDescriptor[] = {
0x0c, //bLength 0x0c, //bLength
STRING_DESCRIPTOR, //bDescriptorType 0x03 STRING_DESCRIPTOR, //bDescriptorType 0x03
'A',0,'u',0,'d',0,'i',0,'o',0 //bString iInterface - Audio 'A',0,'u',0,'d',0,'i',0,'o',0 //bString iInterface - Audio
@ -166,8 +166,8 @@ uint8_t * USBMIDI::stringIinterfaceDesc() {
return stringIinterfaceDescriptor; return stringIinterfaceDescriptor;
} }
uint8_t * USBMIDI::stringIproductDesc() { const uint8_t * USBMIDI::stringIproductDesc() {
static uint8_t stringIproductDescriptor[] = { static const uint8_t stringIproductDescriptor[] = {
0x16, //bLength 0x16, //bLength
STRING_DESCRIPTOR, //bDescriptorType 0x03 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 '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() { const uint8_t * USBMIDI::configurationDesc() {
static uint8_t configDescriptor[] = { static const uint8_t configDescriptor[] = {
// configuration descriptor // configuration descriptor
0x09, 0x02, 0x65, 0x00, 0x02, 0x01, 0x00, 0xc0, 0x50, 0x09, 0x02, 0x65, 0x00, 0x02, 0x01, 0x00, 0xc0, 0x50,

View File

@ -85,21 +85,21 @@ protected:
* *
* @returns pointer to the string product descriptor * @returns pointer to the string product descriptor
*/ */
virtual uint8_t * stringIproductDesc(); virtual const uint8_t * stringIproductDesc();
/* /*
* Get string interface descriptor * Get string interface descriptor
* *
* @returns pointer to the string interface descriptor * @returns pointer to the string interface descriptor
*/ */
virtual uint8_t * stringIinterfaceDesc(); virtual const uint8_t * stringIinterfaceDesc();
/* /*
* Get configuration descriptor * Get configuration descriptor
* *
* @returns pointer to the configuration descriptor * @returns pointer to the configuration descriptor
*/ */
virtual uint8_t * configurationDesc(); virtual const uint8_t * configurationDesc();
private: private:
uint8_t data[MAX_MIDI_MESSAGE_SIZE+1]; uint8_t data[MAX_MIDI_MESSAGE_SIZE+1];

View File

@ -589,8 +589,8 @@ bool USBMSD::USBCallback_setConfiguration(uint8_t configuration) {
} }
uint8_t * USBMSD::stringIinterfaceDesc() { const uint8_t * USBMSD::stringIinterfaceDesc() {
static uint8_t stringIinterfaceDescriptor[] = { static const uint8_t stringIinterfaceDescriptor[] = {
0x08, //bLength 0x08, //bLength
STRING_DESCRIPTOR, //bDescriptorType 0x03 STRING_DESCRIPTOR, //bDescriptorType 0x03
'M',0,'S',0,'D',0 //bString iInterface - MSD 'M',0,'S',0,'D',0 //bString iInterface - MSD
@ -598,8 +598,8 @@ uint8_t * USBMSD::stringIinterfaceDesc() {
return stringIinterfaceDescriptor; return stringIinterfaceDescriptor;
} }
uint8_t * USBMSD::stringIproductDesc() { const uint8_t * USBMSD::stringIproductDesc() {
static uint8_t stringIproductDescriptor[] = { static const uint8_t stringIproductDescriptor[] = {
0x12, //bLength 0x12, //bLength
STRING_DESCRIPTOR, //bDescriptorType 0x03 STRING_DESCRIPTOR, //bDescriptorType 0x03
'M',0,'b',0,'e',0,'d',0,' ',0,'M',0,'S',0,'D',0 //bString iProduct - Mbed Audio '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() { const uint8_t * USBMSD::configurationDesc() {
static uint8_t configDescriptor[] = { static const uint8_t configDescriptor[] = {
// Configuration 1 // Configuration 1
9, // bLength 9, // bLength

View File

@ -139,21 +139,21 @@ protected:
* *
* @returns pointer to the string product descriptor * @returns pointer to the string product descriptor
*/ */
virtual uint8_t * stringIproductDesc(); virtual const uint8_t * stringIproductDesc();
/* /*
* Get string interface descriptor * Get string interface descriptor
* *
* @returns pointer to the string interface descriptor * @returns pointer to the string interface descriptor
*/ */
virtual uint8_t * stringIinterfaceDesc(); virtual const uint8_t * stringIinterfaceDesc();
/* /*
* Get configuration descriptor * Get configuration descriptor
* *
* @returns pointer to the configuration descriptor * @returns pointer to the configuration descriptor
*/ */
virtual uint8_t * configurationDesc(); virtual const uint8_t * configurationDesc();
/* /*
* Callback called when a packet is received * Callback called when a packet is received

View File

@ -144,8 +144,8 @@ bool USBCDC::readEP_NB(uint8_t * buffer, uint32_t * size) {
} }
uint8_t * USBCDC::deviceDesc() { const uint8_t * USBCDC::deviceDesc() {
static uint8_t deviceDescriptor[] = { uint8_t deviceDescriptorTemp[] = {
18, // bLength 18, // bLength
1, // bDescriptorType 1, // bDescriptorType
0x10, 0x01, // bcdUSB 0x10, 0x01, // bcdUSB
@ -161,11 +161,13 @@ uint8_t * USBCDC::deviceDesc() {
3, // iSerialNumber 3, // iSerialNumber
1 // bNumConfigurations 1 // bNumConfigurations
}; };
MBED_ASSERT(sizeof(deviceDescriptorTemp) == sizeof(deviceDescriptor));
memcpy(deviceDescriptor, deviceDescriptorTemp, sizeof(deviceDescriptor));
return deviceDescriptor; return deviceDescriptor;
} }
uint8_t * USBCDC::stringIinterfaceDesc() { const uint8_t * USBCDC::stringIinterfaceDesc() {
static uint8_t stringIinterfaceDescriptor[] = { static const uint8_t stringIinterfaceDescriptor[] = {
0x08, 0x08,
STRING_DESCRIPTOR, STRING_DESCRIPTOR,
'C',0,'D',0,'C',0, 'C',0,'D',0,'C',0,
@ -173,8 +175,8 @@ uint8_t * USBCDC::stringIinterfaceDesc() {
return stringIinterfaceDescriptor; return stringIinterfaceDescriptor;
} }
uint8_t * USBCDC::stringIproductDesc() { const uint8_t * USBCDC::stringIproductDesc() {
static uint8_t stringIproductDescriptor[] = { static const uint8_t stringIproductDescriptor[] = {
0x16, 0x16,
STRING_DESCRIPTOR, STRING_DESCRIPTOR,
'C',0,'D',0,'C',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 '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) #define CONFIG1_DESC_SIZE (9+8+9+5+5+4+5+7+9+7+7)
uint8_t * USBCDC::configurationDesc() { const uint8_t * USBCDC::configurationDesc() {
static uint8_t configDescriptor[] = { static const uint8_t configDescriptor[] = {
// configuration descriptor // configuration descriptor
9, // bLength 9, // bLength
2, // bDescriptorType 2, // bDescriptorType

View File

@ -46,28 +46,28 @@ protected:
* *
* @returns pointer to the device descriptor * @returns pointer to the device descriptor
*/ */
virtual uint8_t * deviceDesc(); virtual const uint8_t * deviceDesc();
/* /*
* Get string product descriptor * Get string product descriptor
* *
* @returns pointer to the string product descriptor * @returns pointer to the string product descriptor
*/ */
virtual uint8_t * stringIproductDesc(); virtual const uint8_t * stringIproductDesc();
/* /*
* Get string interface descriptor * Get string interface descriptor
* *
* @returns pointer to the string interface descriptor * @returns pointer to the string interface descriptor
*/ */
virtual uint8_t * stringIinterfaceDesc(); virtual const uint8_t * stringIinterfaceDesc();
/* /*
* Get configuration descriptor * Get configuration descriptor
* *
* @returns pointer to the configuration descriptor * @returns pointer to the configuration descriptor
*/ */
virtual uint8_t * configurationDesc(); virtual const uint8_t * configurationDesc();
/* /*
* Send a buffer * Send a buffer

View File

@ -127,7 +127,7 @@ public:
template<typename T> template<typename T>
void attach(T* tptr, void (T::*mptr)(void)) { void attach(T* tptr, void (T::*mptr)(void)) {
if((mptr != NULL) && (tptr != NULL)) { if((mptr != NULL) && (tptr != NULL)) {
rx.attach(tptr, mptr); rx = Callback<void()>(mptr, tptr);
} }
} }
@ -138,10 +138,19 @@ public:
*/ */
void attach(void (*fptr)(void)) { void attach(void (*fptr)(void)) {
if(fptr != NULL) { 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. * Attach a callback to call when serial's settings are changed.
* *

View File

@ -22,6 +22,7 @@
#include "fsl_common.h" #include "fsl_common.h"
#endif #endif
#include "USBHAL.h" #include "USBHAL.h"
#include "mbed_critical.h"
USBHAL * USBHAL::instance; USBHAL * USBHAL::instance;
@ -64,6 +65,13 @@ typedef struct BDT {
uint32_t address; // Addr uint32_t address; // Addr
} BDT; } BDT;
typedef enum {
CTRL_XFER_READY,
CTRL_XFER_IN,
CTRL_XFER_NONE,
CTRL_XFER_OUT
} ctrl_xfer_t;
// there are: // there are:
// * 4 bidirectionnal endpt -> 8 physical endpt // * 4 bidirectionnal endpt -> 8 physical endpt
// * as there are ODD and EVEN buffer -> 8*2 bdt // * 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 set_addr = 0;
static uint8_t addr = 0; static uint8_t addr = 0;
static ctrl_xfer_t ctrl_xfer = CTRL_XFER_READY;
static uint32_t Data1 = 0x55555555; 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. 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 )].byte_count = maxPacket;
bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address = (uint32_t) buf; 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; 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; return true;
} }
@ -239,13 +253,35 @@ void USBHAL::EP0setup(uint8_t *buffer) {
} }
void USBHAL::EP0readStage(void) { void USBHAL::EP0readStage(void) {
Data1 &= ~1UL; // set DATA0 // Not needed
bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK);
} }
void USBHAL::EP0read(void) { void USBHAL::EP0read(void) {
uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0); if (ctrl_xfer == CTRL_XFER_READY) {
bdt[idx].byte_count = MAX_PACKET_SIZE_EP0; // 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) { 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) { 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); endpointWrite(EP0IN, buffer, size);
} }
@ -262,13 +307,34 @@ void USBHAL::EP0getWriteResult(void) {
} }
void USBHAL::EP0stall(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); 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) { EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
endpoint = PHY_TO_LOG(endpoint); uint8_t log_endpoint = PHY_TO_LOG(endpoint);
uint32_t idx = EP_BDT_IDX(endpoint, RX, 0);
uint32_t idx = EP_BDT_IDX(log_endpoint, RX, 0);
bdt[idx].byte_count = maximumSize; 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; return EP_PENDING;
} }
@ -307,18 +373,14 @@ EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_
buffer[n] = ep_buf[n]; buffer[n] = ep_buf[n];
} }
if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) { if (setup) {
if (setup && (buffer[6] == 0)) // if no setup data stage, // Record the setup type
Data1 &= ~1UL; // set DATA0 if (buffer[6] == 0) {
else ctrl_xfer = CTRL_XFER_NONE;
Data1 ^= (1 << endpoint); } else {
} uint8_t in_xfer = (buffer[0] >> 7) & 1;
ctrl_xfer = in_xfer ? CTRL_XFER_IN : CTRL_XFER_OUT;
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;
} }
USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; 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) { 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; 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); Data1 ^= (1 << endpoint);
@ -438,7 +500,7 @@ void USBHAL::usbisr(void) {
if (istat & 1<<7) { if (istat & 1<<7) {
if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK) if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK)
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 // token interrupt
@ -450,7 +512,7 @@ void USBHAL::usbisr(void) {
// setup packet // setup packet
if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) { 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, EVEN)].info &= ~BD_OWN_MASK;
bdt[EP_BDT_IDX(0, TX, ODD)].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 // sleep interrupt
if (istat & 1<<4) { if (istat & 1<<4) {
USB0->ISTAT |= USB_ISTAT_SLEEP_MASK; USB0->ISTAT = USB_ISTAT_SLEEP_MASK;
} }
// error interrupt // error interrupt
if (istat & USB_ISTAT_ERROR_MASK) { if (istat & USB_ISTAT_ERROR_MASK) {
USB0->ERRSTAT = 0xFF; USB0->ERRSTAT = 0xFF;
USB0->ISTAT |= USB_ISTAT_ERROR_MASK; USB0->ISTAT = USB_ISTAT_ERROR_MASK;
} }
} }

View File

@ -275,11 +275,6 @@ uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
LPC_USB->USBCtrl = 0; LPC_USB->USBCtrl = 0;
if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
SIEselectEndpoint(endpoint);
SIEclearBuffer();
}
return size; return size;
} }
@ -431,7 +426,7 @@ void USBHAL::EP0setup(uint8_t *buffer) {
} }
void USBHAL::EP0read(void) { void USBHAL::EP0read(void) {
// Not required endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
} }
void USBHAL::EP0readStage(void) { void USBHAL::EP0readStage(void) {
@ -456,6 +451,11 @@ void USBHAL::EP0stall(void) {
} }
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { 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; return EP_PENDING;
} }
@ -590,6 +590,25 @@ void USBHAL::usbisr(void) {
if (LPC_USB->USBDevIntSt & EP_SLOW) { if (LPC_USB->USBDevIntSt & EP_SLOW) {
// (Slow) Endpoint Interrupt // (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 // Process each endpoint interrupt
if (LPC_USB->USBEpIntSt & EP(EP0OUT)) { if (LPC_USB->USBEpIntSt & EP(EP0OUT)) {
if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) { if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
@ -601,12 +620,6 @@ void USBHAL::usbisr(void) {
LPC_USB->USBDevIntClr = EP_SLOW; 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++) { for (uint8_t num = 2; num < 16*2; num++) {
if (LPC_USB->USBEpIntSt & EP(num)) { if (LPC_USB->USBEpIntSt & EP(num)) {
selectEndpointClearInterrupt(num); selectEndpointClearInterrupt(num);

View File

@ -276,11 +276,6 @@ uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
LPC_USB->Ctrl = 0; LPC_USB->Ctrl = 0;
if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
SIEselectEndpoint(endpoint);
SIEclearBuffer();
}
return size; return size;
} }
@ -436,7 +431,7 @@ void USBHAL::EP0setup(uint8_t *buffer) {
} }
void USBHAL::EP0read(void) { void USBHAL::EP0read(void) {
// Not required endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
} }
void USBHAL::EP0readStage(void) { void USBHAL::EP0readStage(void) {
@ -461,6 +456,11 @@ void USBHAL::EP0stall(void) {
} }
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { 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; return EP_PENDING;
} }
@ -595,6 +595,25 @@ void USBHAL::usbisr(void) {
if (LPC_USB->DevIntSt & EP_SLOW) { if (LPC_USB->DevIntSt & EP_SLOW) {
// (Slow) Endpoint Interrupt // (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 // Process each endpoint interrupt
if (LPC_USB->EpIntSt & EP(EP0OUT)) { if (LPC_USB->EpIntSt & EP(EP0OUT)) {
if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) { if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
@ -606,12 +625,6 @@ void USBHAL::usbisr(void) {
LPC_USB->DevIntClr = EP_SLOW; 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++) { for (uint8_t num = 2; num < 16*2; num++) {
if (LPC_USB->EpIntSt & EP(num)) { if (LPC_USB->EpIntSt & EP(num)) {
selectEndpointClearInterrupt(num); selectEndpointClearInterrupt(num);

View File

@ -106,7 +106,7 @@ public:
template<typename T> template<typename T>
inline void onDisconnect(uint8_t intf_nb, T* tptr, void (T::*mptr)(void)) { inline void onDisconnect(uint8_t intf_nb, T* tptr, void (T::*mptr)(void)) {
if ((mptr != NULL) && (tptr != NULL)) { 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)) { inline void onDisconnect(uint8_t intf_nb, void (*fn)(void)) {
if (fn != NULL) { if (fn != NULL) {
intf[intf_nb].detach.attach(fn); intf[intf_nb].detach = fn;
} }
} }

View File

@ -89,7 +89,7 @@ public:
template<typename T> template<typename T>
inline void attach(T* tptr, void (T::*mptr)(void)) { inline void attach(T* tptr, void (T::*mptr)(void)) {
if((mptr != NULL) && (tptr != NULL)) { if((mptr != NULL) && (tptr != NULL)) {
rx.attach(tptr, mptr); rx = callback(tptr, mptr);
} }
} }
@ -100,7 +100,7 @@ public:
*/ */
inline void attach(void (*fptr)(void)) { inline void attach(void (*fptr)(void)) {
if(fptr != NULL) { if(fptr != NULL) {
rx.attach(fptr); rx = fptr;
} }
} }

View File

@ -88,11 +88,14 @@ void USBHost::usb_process()
/* check that hub is connected to root port */ /* check that hub is connected to root port */
if (usb_msg->hub_parent) { if (usb_msg->hub_parent) {
/* a hub device must be present */ /* a hub device must be present */
#if MAX_HUB_NB
for (k = 0; k < MAX_HUB_NB; k++) { for (k = 0; k < MAX_HUB_NB; k++) {
if ((&hubs[k] == usb_msg->hub_parent) && (hub_in_use[k])) { if ((&hubs[k] == usb_msg->hub_parent) && (hub_in_use[k])) {
hub_unplugged=false; hub_unplugged=false;
} }
} }
#endif
} else { } else {
hub_unplugged = false; hub_unplugged = false;
} }
@ -312,7 +315,7 @@ USBHost::USBHost() : usbThread(osPriorityNormal, USB_THREAD_STACK)
} }
#endif #endif
usbThread.start(this, &USBHost::usb_process); usbThread.start(callback(this, &USBHost::usb_process));
} }
USBHost::Lock::Lock(USBHost* pHost) : m_pHost(pHost) USBHost::Lock::Lock(USBHost* pHost) : m_pHost(pHost)

View File

@ -1,11 +1,7 @@
#include "mbed.h" #include "mbed.h"
#include "test_env.h" #include "test_env.h"
void print_char(char c = '*') RawSerial pc(USBTX, USBRX);
{
printf("%c", c);
fflush(stdout);
}
Ticker flipper_1; Ticker flipper_1;
DigitalOut led1(LED1); DigitalOut led1(LED1);
@ -17,7 +13,7 @@ void flip_1() {
} else { } else {
led1 = 1; led1_state = 1; led1 = 1; led1_state = 1;
} }
print_char(); pc.putc('*');
} }
Ticker flipper_2; Ticker flipper_2;

View File

@ -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) static void update_present_time(const ticker_data_t *const ticker)
{ {
ticker_event_queue_t *queue = ticker->queue; ticker_event_queue_t *queue = ticker->queue;
uint32_t ticker_time = ticker->interface->read(); uint32_t ticker_time = ticker->interface->read();
if (ticker_time == ticker->queue->tick_last_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) void ticker_set_handler(const ticker_data_t *const ticker, ticker_event_handler handler)
{ {
initialize(ticker); initialize(ticker);
core_util_critical_section_enter();
set_handler(ticker, handler); set_handler(ticker, handler);
core_util_critical_section_exit();
} }
void ticker_irq_handler(const ticker_data_t *const ticker) void ticker_irq_handler(const ticker_data_t *const ticker)
{ {
core_util_critical_section_enter();
ticker->interface->clear_interrupt(); ticker->interface->clear_interrupt();
/* Go through all the pending TimerEvents */ /* Go through all the pending TimerEvents */
@ -284,6 +288,8 @@ void ticker_irq_handler(const ticker_data_t *const ticker)
} }
schedule_interrupt(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) 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, ticker->queue->present_time,
timestamp timestamp
); );
core_util_critical_section_exit();
// defer to ticker_insert_event_us // defer to ticker_insert_event_us
ticker_insert_event_us( ticker_insert_event_us(
ticker, ticker,
obj, absolute_timestamp, id 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) 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); schedule_interrupt(ticker);
core_util_critical_section_exit(); core_util_critical_section_exit();
} }
void ticker_remove_event(const ticker_data_t *const ticker, ticker_event_t *obj) 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) us_timestamp_t ticker_read_us(const ticker_data_t *const ticker)
{ {
initialize(ticker); initialize(ticker);
core_util_critical_section_enter();
update_present_time(ticker); update_present_time(ticker);
core_util_critical_section_exit();
return ticker->queue->present_time; return ticker->queue->present_time;
} }

4
mbed.h
View File

@ -16,13 +16,13 @@
#ifndef MBED_H #ifndef MBED_H
#define MBED_H #define MBED_H
#define MBED_LIBRARY_VERSION 158 #define MBED_LIBRARY_VERSION 159
#if MBED_CONF_RTOS_PRESENT #if MBED_CONF_RTOS_PRESENT
// RTOS present, this is valid only for mbed OS 5 // RTOS present, this is valid only for mbed OS 5
#define MBED_MAJOR_VERSION 5 #define MBED_MAJOR_VERSION 5
#define MBED_MINOR_VERSION 7 #define MBED_MINOR_VERSION 7
#define MBED_PATCH_VERSION 3 #define MBED_PATCH_VERSION 4
#else #else
// mbed 2 // mbed 2

View File

@ -19,6 +19,7 @@
#define MBED_CRITICALSECTIONLOCK_H #define MBED_CRITICALSECTIONLOCK_H
#include "platform/mbed_critical.h" #include "platform/mbed_critical.h"
#include "platform/mbed_toolchain.h"
namespace mbed { namespace mbed {

View File

@ -81,12 +81,18 @@ extern "C" {
void * __real__realloc_r(struct _reent * r, void * ptr, size_t size); void * __real__realloc_r(struct _reent * r, void * ptr, size_t size);
void __real__free_r(struct _reent * r, void * ptr); void __real__free_r(struct _reent * r, void * ptr);
void* __real__calloc_r(struct _reent * r, size_t nmemb, size_t size); 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. // TODO: memory tracing doesn't work with uVisor enabled.
#if !defined(FEATURE_UVISOR) #if !defined(FEATURE_UVISOR)
extern "C" void * __wrap__malloc_r(struct _reent * r, size_t size) { 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; void *ptr = NULL;
#ifdef MBED_MEM_TRACING_ENABLED #ifdef MBED_MEM_TRACING_ENABLED
mbed_mem_trace_lock(); 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); ptr = __real__malloc_r(r, size);
#endif // #ifdef MBED_HEAP_STATS_ENABLED #endif // #ifdef MBED_HEAP_STATS_ENABLED
#ifdef MBED_MEM_TRACING_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(); mbed_mem_trace_unlock();
#endif // #ifdef MBED_MEM_TRACING_ENABLED #endif // #ifdef MBED_MEM_TRACING_ENABLED
return ptr; 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) { 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 #ifdef MBED_MEM_TRACING_ENABLED
mbed_mem_trace_lock(); mbed_mem_trace_lock();
#endif #endif
@ -177,7 +187,7 @@ extern "C" void __wrap__free_r(struct _reent * r, void * ptr) {
__real__free_r(r, ptr); __real__free_r(r, ptr);
#endif // #ifdef MBED_HEAP_STATS_ENABLED #endif // #ifdef MBED_HEAP_STATS_ENABLED
#ifdef MBED_MEM_TRACING_ENABLED #ifdef MBED_MEM_TRACING_ENABLED
mbed_mem_trace_free(ptr, MBED_CALLER_ADDR()); mbed_mem_trace_free(ptr, caller);
mbed_mem_trace_unlock(); mbed_mem_trace_unlock();
#endif // #ifdef MBED_MEM_TRACING_ENABLED #endif // #ifdef MBED_MEM_TRACING_ENABLED
} }
@ -245,9 +255,16 @@ extern "C" {
void *SUPER_REALLOC(void *ptr, size_t size); void *SUPER_REALLOC(void *ptr, size_t size);
void *SUPER_CALLOC(size_t nmemb, size_t size); void *SUPER_CALLOC(size_t nmemb, size_t size);
void SUPER_FREE(void *ptr); 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) { 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; void *ptr = NULL;
#ifdef MBED_MEM_TRACING_ENABLED #ifdef MBED_MEM_TRACING_ENABLED
mbed_mem_trace_lock(); mbed_mem_trace_lock();
@ -272,12 +289,13 @@ extern "C" void* SUB_MALLOC(size_t size) {
ptr = SUPER_MALLOC(size); ptr = SUPER_MALLOC(size);
#endif // #ifdef MBED_HEAP_STATS_ENABLED #endif // #ifdef MBED_HEAP_STATS_ENABLED
#ifdef MBED_MEM_TRACING_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(); mbed_mem_trace_unlock();
#endif // #ifdef MBED_MEM_TRACING_ENABLED #endif // #ifdef MBED_MEM_TRACING_ENABLED
return ptr; return ptr;
} }
extern "C" void* SUB_REALLOC(void *ptr, size_t size) { extern "C" void* SUB_REALLOC(void *ptr, size_t size) {
void *new_ptr = NULL; void *new_ptr = NULL;
#ifdef MBED_MEM_TRACING_ENABLED #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) { 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 #ifdef MBED_MEM_TRACING_ENABLED
mbed_mem_trace_lock(); mbed_mem_trace_lock();
#endif #endif
@ -354,7 +376,7 @@ extern "C" void SUB_FREE(void *ptr) {
SUPER_FREE(ptr); SUPER_FREE(ptr);
#endif // #ifdef MBED_HEAP_STATS_ENABLED #endif // #ifdef MBED_HEAP_STATS_ENABLED
#ifdef MBED_MEM_TRACING_ENABLED #ifdef MBED_MEM_TRACING_ENABLED
mbed_mem_trace_free(ptr, MBED_CALLER_ADDR()); mbed_mem_trace_free(ptr, caller);
mbed_mem_trace_unlock(); mbed_mem_trace_unlock();
#endif // #ifdef MBED_MEM_TRACING_ENABLED #endif // #ifdef MBED_MEM_TRACING_ENABLED
} }

View File

@ -1022,6 +1022,99 @@ extern "C" void __cxa_guard_abort(int *guard_object_p)
#endif #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 *operator new(std::size_t count)
{ {
void *buffer = malloc(count); void *buffer = malloc(count);
@ -1059,6 +1152,8 @@ void operator delete[](void *ptr)
free(ptr); free(ptr);
} }
#endif
/* @brief standard c library clock() function. /* @brief standard c library clock() function.
* *
* This function returns the number of clock ticks elapsed since the start of the program. * This function returns the number of clock ticks elapsed since the start of the program.

View File

@ -118,7 +118,10 @@ struct Waiter;
*/ */
class ConditionVariable : private mbed::NonCopyable<ConditionVariable> { class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
public: 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); ConditionVariable(Mutex &mutex);
/** Wait for a notification /** Wait for a notification
@ -142,6 +145,8 @@ public:
* *
* mutex.unlock(); * mutex.unlock();
* @endcode * @endcode
*
* @note You cannot call this function from ISR context.
*/ */
void wait(); void wait();
@ -176,21 +181,31 @@ public:
* *
* mutex.unlock(); * mutex.unlock();
* @endcode * @endcode
*
* @note You cannot call this function from ISR context.
*/ */
bool wait_for(uint32_t millisec); bool wait_for(uint32_t millisec);
/** Notify one waiter on this condition variable that a condition changed. /** 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 - 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(); void notify_one();
/** Notify all waiters on this condition variable that a condition changed. /** 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 - 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(); void notify_all();
/** ConditionVariable destructor
*
* @note You may call this function from ISR context.
*/
~ConditionVariable(); ~ConditionVariable();
protected: protected:

View File

@ -46,29 +46,40 @@ namespace rtos {
*/ */
class EventFlags : private mbed::NonCopyable<EventFlags> { class EventFlags : private mbed::NonCopyable<EventFlags> {
public: public:
/** Create and Initialize a EventFlags object */ /** Create and Initialize an EventFlags object
*
* @note You cannot call this function from ISR context.
*/
EventFlags(); EventFlags();
/** Create and Initialize a EventFlags object /** 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. @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); EventFlags(const char *name);
/** Set the specified Event Flags. /** Set the specified Event Flags.
@param flags specifies the flags that shall be set. @param flags specifies the flags that shall be set.
@return event flags after setting or error code if highest bit set (@a osFlagsError). @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); uint32_t set(uint32_t flags);
/** Clear the specified Event Flags. /** Clear the specified Event Flags.
@param flags specifies the flags that shall be cleared. (default: 0x7fffffff - all 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). @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); uint32_t clear(uint32_t flags = 0x7fffffff);
/** Get the currently set Event Flags. /** Get the currently set Event Flags.
@return set event flags. @return set event flags.
@note You may call this function from ISR context.
*/ */
uint32_t get() const; uint32_t get() const;
@ -77,6 +88,8 @@ public:
@param timeout timeout value or 0 in case of no time-out. (default: osWaitForever) @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) @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). @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); 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 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) @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). @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); 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(); ~EventFlags();
private: private:

View File

@ -55,12 +55,17 @@ namespace rtos {
template<typename T, uint32_t queue_sz> template<typename T, uint32_t queue_sz>
class Mail : private mbed::NonCopyable<Mail<T, queue_sz> > { class Mail : private mbed::NonCopyable<Mail<T, queue_sz> > {
public: public:
/** Create and Initialise Mail queue. */ /** Create and Initialize Mail queue.
*
* @note You cannot call this function from ISR context.
*/
Mail() { }; Mail() { };
/** Check if the mail queue is empty /** Check if the mail queue is empty
* *
* @return True if the mail queue is empty, false if not * @return True if the mail queue is empty, false if not
*
* @note You may call this function from ISR context.
*/ */
bool empty() const { bool empty() const {
return _queue.empty(); return _queue.empty();
@ -69,6 +74,8 @@ public:
/** Check if the mail queue is full /** Check if the mail queue is full
* *
* @return True if the mail queue is full, false if not * @return True if the mail queue is full, false if not
*
* @note You may call this function from ISR context.
*/ */
bool full() const { bool full() const {
return _queue.full(); return _queue.full();
@ -77,6 +84,8 @@ public:
/** Allocate a memory block of type T /** Allocate a memory block of type T
@param millisec timeout value or 0 in case of no time-out. (default: 0). @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. @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) { T* alloc(uint32_t millisec=0) {
return _pool.alloc(); return _pool.alloc();
@ -85,6 +94,8 @@ public:
/** Allocate a memory block of type T and set memory block to zero. /** 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). @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. @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) { T* calloc(uint32_t millisec=0) {
return _pool.calloc(); return _pool.calloc();
@ -93,6 +104,8 @@ public:
/** Put a mail in the queue. /** Put a mail in the queue.
@param mptr memory block previously allocated with Mail::alloc or Mail::calloc. @param mptr memory block previously allocated with Mail::alloc or Mail::calloc.
@return status code that indicates the execution status of the function. @return status code that indicates the execution status of the function.
@note You may call this function from ISR context.
*/ */
osStatus put(T *mptr) { osStatus put(T *mptr) {
return _queue.put(mptr); return _queue.put(mptr);
@ -101,6 +114,8 @@ public:
/** Get a mail from a queue. /** Get a mail from a queue.
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever). @param millisec timeout value or 0 in case of no time-out. (default: osWaitForever).
@return event that contains mail information or error code. @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 get(uint32_t millisec=osWaitForever) {
osEvent evt = _queue.get(millisec); osEvent evt = _queue.get(millisec);
@ -113,6 +128,8 @@ public:
/** Free a memory block from a mail. /** Free a memory block from a mail.
@param mptr pointer to the memory block that was obtained with Mail::get. @param mptr pointer to the memory block that was obtained with Mail::get.
@return status code that indicates the execution status of the function. @return status code that indicates the execution status of the function.
@note You may call this function from ISR context.
*/ */
osStatus free(T *mptr) { osStatus free(T *mptr) {
return _pool.free(mptr); return _pool.free(mptr);

View File

@ -50,7 +50,10 @@ template<typename T, uint32_t pool_sz>
class MemoryPool : private mbed::NonCopyable<MemoryPool<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."); MBED_STATIC_ASSERT(pool_sz > 0, "Invalid memory pool size. Must be greater than 0.");
public: public:
/** Create and Initialize a memory pool. */ /** Create and Initialize a memory pool.
*
* @note You cannot call this function from ISR context.
*/
MemoryPool() { MemoryPool() {
memset(_pool_mem, 0, sizeof(_pool_mem)); memset(_pool_mem, 0, sizeof(_pool_mem));
memset(&_obj_mem, 0, sizeof(_obj_mem)); memset(&_obj_mem, 0, sizeof(_obj_mem));
@ -63,13 +66,18 @@ public:
MBED_ASSERT(_id); MBED_ASSERT(_id);
} }
/** Destroy a memory pool */ /** Destroy a memory pool
*
* @note You cannot call this function from ISR context.
*/
~MemoryPool() { ~MemoryPool() {
osMemoryPoolDelete(_id); osMemoryPoolDelete(_id);
} }
/** Allocate a memory block of type T from a memory pool. /** 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. @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) { T* alloc(void) {
return (T*)osMemoryPoolAlloc(_id, 0); 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. /** 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. @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* calloc(void) {
T *item = (T*)osMemoryPoolAlloc(_id, 0); T *item = (T*)osMemoryPoolAlloc(_id, 0);
@ -92,6 +102,7 @@ public:
is NULL or invalid, or osErrorResource if given memory block is in an is NULL or invalid, or osErrorResource if given memory block is in an
invalid memory pool state. invalid memory pool state.
@note You may call this function from ISR context.
*/ */
osStatus free(T *block) { osStatus free(T *block) {
return osMemoryPoolFree(_id, (void*)block); return osMemoryPoolFree(_id, (void*)block);

View File

@ -40,18 +40,26 @@ namespace rtos {
/** The Mutex class is used to synchronize the execution of threads. /** The Mutex class is used to synchronize the execution of threads.
This is for example used to protect access to a shared resource. 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 @note
Memory considerations: The mutex control structures will be created on current thread's stack, both for the mbed OS 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). and underlying RTOS objects (static or dynamic RTOS memory pools are not being used).
*/ */
class Mutex : private mbed::NonCopyable<Mutex> { class Mutex : private mbed::NonCopyable<Mutex> {
public: public:
/** Create and Initialize a Mutex object */ /** Create and Initialize a Mutex object
*
* @note You cannot call this function from ISR context.
*/
Mutex(); Mutex();
/** Create and Initialize a Mutex object /** 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. @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); Mutex(const char *name);
@ -63,11 +71,15 @@ public:
@a osErrorParameter internal error. @a osErrorParameter internal error.
@a osErrorResource the mutex could not be obtained when no timeout was specified. @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. @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); osStatus lock(uint32_t millisec=osWaitForever);
/** Try to lock the mutex, and return immediately /** Try to lock the mutex, and return immediately
@return true if the mutex was acquired, false otherwise. @return true if the mutex was acquired, false otherwise.
@note This function cannot be called from ISR context.
*/ */
bool trylock(); bool trylock();
@ -77,14 +89,22 @@ public:
@a osErrorParameter internal error. @a osErrorParameter internal error.
@a osErrorResource the mutex was not locked or the current thread wasn't the owner. @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. @a osErrorISR this function cannot be called from the interrupt service routine.
@note This function cannot be called from ISR context.
*/ */
osStatus unlock(); osStatus unlock();
/** Get the owner the this mutex /** Get the owner the this mutex
@return the current owner of this mutex. @return the current owner of this mutex.
@note You cannot call this function from ISR context.
*/ */
osThreadId get_owner(); osThreadId get_owner();
/** Mutex destructor
*
* @note You cannot call this function from ISR context.
*/
~Mutex(); ~Mutex();
private: private:

View File

@ -52,7 +52,10 @@ namespace rtos {
template<typename T, uint32_t queue_sz> template<typename T, uint32_t queue_sz>
class Queue : private mbed::NonCopyable<Queue<T, queue_sz> > { class Queue : private mbed::NonCopyable<Queue<T, queue_sz> > {
public: public:
/** Create and initialize a message Queue. */ /** Create and initialize a message Queue.
*
* @note You cannot call this function from ISR context.
*/
Queue() { Queue() {
memset(&_obj_mem, 0, sizeof(_obj_mem)); memset(&_obj_mem, 0, sizeof(_obj_mem));
osMessageQueueAttr_t attr = { 0 }; osMessageQueueAttr_t attr = { 0 };
@ -63,7 +66,10 @@ public:
_id = osMessageQueueNew(queue_sz, sizeof(T*), &attr); _id = osMessageQueueNew(queue_sz, sizeof(T*), &attr);
MBED_ASSERT(_id); MBED_ASSERT(_id);
} }
/** Queue destructor
*
* @note You cannot call this function from ISR context.
*/
~Queue() { ~Queue() {
osMessageQueueDelete(_id); osMessageQueueDelete(_id);
} }
@ -71,6 +77,8 @@ public:
/** Check if the queue is empty /** Check if the queue is empty
* *
* @return True if the queue is empty, false if not * @return True if the queue is empty, false if not
*
* @note You may call this function from ISR context.
*/ */
bool empty() const { bool empty() const {
return osMessageQueueGetCount(_id) == 0; return osMessageQueueGetCount(_id) == 0;
@ -79,6 +87,8 @@ public:
/** Check if the queue is full /** Check if the queue is full
* *
* @return True if the queue is full, false if not * @return True if the queue is full, false if not
*
* @note You may call this function from ISR context.
*/ */
bool full() const { bool full() const {
return osMessageQueueGetSpace(_id) == 0; 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 osErrorTimeout the message could not be put into the queue in the given time.
@a osErrorResource not enough space in the queue. @a osErrorResource not enough space in the queue.
@a osErrorParameter internal error or non-zero timeout specified in an ISR. @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) { osStatus put(T* data, uint32_t millisec=0, uint8_t prio=0) {
return osMessageQueuePut(_id, &data, prio, millisec); 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 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 osEventTimeout no message has arrived during the given timeout period.
@a osErrorParameter a parameter is invalid or outside of a permitted range. @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 get(uint32_t millisec=osWaitForever) {
osEvent event; osEvent event;

View File

@ -93,6 +93,8 @@ public:
@deprecated Replaced with RtosTimer(Callback<void()>, os_timer_type) @deprecated Replaced with RtosTimer(Callback<void()>, os_timer_type)
@deprecated @deprecated
The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details 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", MBED_DEPRECATED_SINCE("mbed-os-5.1",
"Replaced with RtosTimer(Callback<void()>, os_timer_type)") "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) @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behaviour. (default: osTimerPeriodic)
@deprecated @deprecated
The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details 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", MBED_DEPRECATED_SINCE("mbed-os-5.2",
"The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details") "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). RtosTimer(callback(obj, method), os_timer_type).
@deprecated @deprecated
The RtosTimer has been superseded by the EventQueue. See RtosTimer.h for more details 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> template <typename T, typename M>
MBED_DEPRECATED_SINCE("mbed-os-5.1", MBED_DEPRECATED_SINCE("mbed-os-5.1",
@ -140,6 +146,8 @@ public:
@a osErrorISR @a stop cannot be called from interrupt service routines. @a osErrorISR @a stop cannot be called from interrupt service routines.
@a osErrorParameter internal error. @a osErrorParameter internal error.
@a osErrorResource the timer is not running. @a osErrorResource the timer is not running.
@note You cannot call this function from ISR context.
*/ */
osStatus stop(void); osStatus stop(void);
@ -150,9 +158,15 @@ public:
@a osErrorISR @a start cannot be called from interrupt service routines. @a osErrorISR @a start cannot be called from interrupt service routines.
@a osErrorParameter internal error or incorrect parameter value. @a osErrorParameter internal error or incorrect parameter value.
@a osErrorResource internal error (the timer is in an invalid timer state). @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); osStatus start(uint32_t millisec);
/** RtosTimer destructor
*
* @note You cannot call this function from ISR context.
*/
~RtosTimer(); ~RtosTimer();
private: private:

View File

@ -46,18 +46,24 @@ class Semaphore : private mbed::NonCopyable<Semaphore> {
public: public:
/** Create and Initialize a Semaphore object used for managing resources. /** Create and Initialize a Semaphore object used for managing resources.
@param count number of available resources; maximum index value is (count-1). (default: 0). @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); Semaphore(int32_t count=0);
/** Create and Initialize a Semaphore object used for managing resources. /** Create and Initialize a Semaphore object used for managing resources.
@param count number of available resources @param count number of available resources
@param max_count maximum 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); Semaphore(int32_t count, uint16_t max_count);
/** Wait until a Semaphore resource becomes available. /** Wait until a Semaphore resource becomes available.
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever). @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 @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); int32_t wait(uint32_t millisec=osWaitForever);
@ -66,9 +72,15 @@ public:
@a osOK the token has been correctly released. @a osOK the token has been correctly released.
@a osErrorResource the maximum token count has been reached. @a osErrorResource the maximum token count has been reached.
@a osErrorParameter internal error. @a osErrorParameter internal error.
@note You may call this function from ISR context.
*/ */
osStatus release(void); osStatus release(void);
/** Semaphore destructor
*
* @note You cannot call this function from ISR context.
*/
~Semaphore(); ~Semaphore();
private: private:

View File

@ -194,13 +194,10 @@ static void default_idle_hook(void)
core_util_critical_section_enter(); core_util_critical_section_enter();
uint32_t ticks_to_sleep = svcRtxKernelSuspend(); uint32_t ticks_to_sleep = svcRtxKernelSuspend();
MBED_ASSERT(os_timer->get_tick() == svcRtxKernelGetTickCount());
if (ticks_to_sleep) { if (ticks_to_sleep) {
os_timer->schedule_tick(ticks_to_sleep); os_timer->schedule_tick(ticks_to_sleep);
sleep_manager_lock_deep_sleep();
sleep(); sleep();
sleep_manager_unlock_deep_sleep();
os_timer->cancel_tick(); os_timer->cancel_tick();
// calculate how long we slept // calculate how long we slept

View File

@ -80,6 +80,8 @@ public:
@param stack_size stack size (in bytes) requirements for the thread function. (default: OS_STACK_SIZE). @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 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) @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, Thread(osPriority priority=osPriorityNormal,
uint32_t stack_size=OS_STACK_SIZE, uint32_t stack_size=OS_STACK_SIZE,
@ -103,6 +105,8 @@ public:
error("oh no!"); error("oh no!");
} }
@endcode @endcode
@note You cannot call this function from ISR context.
*/ */
MBED_DEPRECATED_SINCE("mbed-os-5.1", MBED_DEPRECATED_SINCE("mbed-os-5.1",
"Thread-spawning constructors hide errors. " "Thread-spawning constructors hide errors. "
@ -131,6 +135,8 @@ public:
error("oh no!"); error("oh no!");
} }
@endcode @endcode
@note You cannot call this function from ISR context.
*/ */
template <typename T> template <typename T>
MBED_DEPRECATED_SINCE("mbed-os-5.1", MBED_DEPRECATED_SINCE("mbed-os-5.1",
@ -161,6 +167,8 @@ public:
error("oh no!"); error("oh no!");
} }
@endcode @endcode
@note You cannot call this function from ISR context.
*/ */
template <typename T> template <typename T>
MBED_DEPRECATED_SINCE("mbed-os-5.1", MBED_DEPRECATED_SINCE("mbed-os-5.1",
@ -192,6 +200,8 @@ public:
error("oh no!"); error("oh no!");
} }
@endcode @endcode
@note You cannot call this function from ISR context.
*/ */
MBED_DEPRECATED_SINCE("mbed-os-5.1", MBED_DEPRECATED_SINCE("mbed-os-5.1",
"Thread-spawning constructors hide errors. " "Thread-spawning constructors hide errors. "
@ -208,6 +218,8 @@ public:
@param task function to be executed by this thread. @param task function to be executed by this thread.
@return status code that indicates the execution status of the function. @return status code that indicates the execution status of the function.
@note a thread can only be started once @note a thread can only be started once
@note You cannot call this function ISR context.
*/ */
osStatus start(mbed::Callback<void()> task); osStatus start(mbed::Callback<void()> task);
@ -217,6 +229,8 @@ public:
@return status code that indicates the execution status of the function. @return status code that indicates the execution status of the function.
@deprecated @deprecated
The start function does not support cv-qualifiers. Replaced by start(callback(obj, method)). 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> template <typename T, typename M>
MBED_DEPRECATED_SINCE("mbed-os-5.1", MBED_DEPRECATED_SINCE("mbed-os-5.1",
@ -229,28 +243,38 @@ public:
/** Wait for thread to terminate /** Wait for thread to terminate
@return status code that indicates the execution status of the function. @return status code that indicates the execution status of the function.
@note not callable from interrupt @note not callable from interrupt
@note You cannot call this function from ISR context.
*/ */
osStatus join(); osStatus join();
/** Terminate execution of a thread and remove it from Active Threads /** Terminate execution of a thread and remove it from Active Threads
@return status code that indicates the execution status of the function. @return status code that indicates the execution status of the function.
@note You cannot call this function from ISR context.
*/ */
osStatus terminate(); osStatus terminate();
/** Set priority of an active thread /** Set priority of an active thread
@param priority new priority value for the thread function. @param priority new priority value for the thread function.
@return status code that indicates the execution status of the 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); osStatus set_priority(osPriority priority);
/** Get priority of an active thread /** Get priority of an active thread
@return current priority value of the thread function. @return current priority value of the thread function.
@note You cannot call this function from ISR context.
*/ */
osPriority get_priority(); osPriority get_priority();
/** Set the specified Thread Flags for the thread. /** Set the specified Thread Flags for the thread.
@param signals specifies the signal flags of the thread that should be set. @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. @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); int32_t signal_set(int32_t signals);
@ -279,37 +303,51 @@ public:
/** State of this Thread /** State of this Thread
@return the State of this Thread @return the State of this Thread
@note You cannot call this function from ISR context.
*/ */
State get_state(); State get_state();
/** Get the total stack memory size for this Thread /** Get the total stack memory size for this Thread
@return the total stack memory size in bytes @return the total stack memory size in bytes
@note You cannot call this function from ISR context.
*/ */
uint32_t stack_size(); uint32_t stack_size();
/** Get the currently unused stack memory for this Thread /** Get the currently unused stack memory for this Thread
@return the currently unused stack memory in bytes @return the currently unused stack memory in bytes
@note You cannot call this function from ISR context.
*/ */
uint32_t free_stack(); uint32_t free_stack();
/** Get the currently used stack memory for this Thread /** Get the currently used stack memory for this Thread
@return the currently used stack memory in bytes @return the currently used stack memory in bytes
@note You cannot call this function from ISR context.
*/ */
uint32_t used_stack(); uint32_t used_stack();
/** Get the maximum stack memory usage to date for this Thread /** Get the maximum stack memory usage to date for this Thread
@return the maximum stack memory usage to date in bytes @return the maximum stack memory usage to date in bytes
@note You cannot call this function from ISR context.
*/ */
uint32_t max_stack(); uint32_t max_stack();
/** Get thread name /** Get thread name
@return thread name or NULL if the name was not set. @return thread name or NULL if the name was not set.
@note You may call this function from ISR context.
*/ */
const char *get_name(); const char *get_name();
/** Clears the specified Thread Flags of the currently running thread. /** Clears the specified Thread Flags of the currently running thread.
@param signals specifies the signal flags of the thread that should be cleared. @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. @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); 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 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). @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. @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); static osEvent signal_wait(int32_t signals, uint32_t millisec=osWaitForever);
/** Wait for a specified time period in millisec: /** Wait for a specified time period in millisec:
@param millisec time delay value @param millisec time delay value
@return status code that indicates the execution status of the function. @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); static osStatus wait(uint32_t millisec);
/** Pass control to next thread that is in state READY. /** Pass control to next thread that is in state READY.
@return status code that indicates the execution status of the function. @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(); static osStatus yield();
/** Get the thread id of the current running thread. /** Get the thread id of the current running thread.
@return thread ID for reference by other functions or NULL in case of error. @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(); static osThreadId gettid();
/** Attach a function to be called by the RTOS idle task /** Attach a function to be called by the RTOS idle task
@param fptr pointer to the function to be called @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)); static void attach_idle_hook(void (*fptr)(void));
/** Attach a function to be called when a task is killed /** Attach a function to be called when a task is killed
@param fptr pointer to the function to be called @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)); static void attach_terminate_hook(void (*fptr)(osThreadId id));
/** Thread destructor
*
* @note You cannot call this function from ISR context.
*/
virtual ~Thread(); virtual ~Thread();
private: private:

View File

@ -37,6 +37,11 @@ uint32_t gpio_set(PinName pin)
return (uint32_t)(1 << pin_index); // Return the pin mask 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) void gpio_init(gpio_t *obj, PinName pin)
{ {
obj->pin = pin; obj->pin = pin;

View File

@ -37,6 +37,11 @@ uint32_t gpio_set(PinName pin)
return (uint32_t)(1 << pin_index); // Return the pin mask 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) void gpio_init(gpio_t *obj, PinName pin)
{ {
obj->pin = pin; obj->pin = pin;

View File

@ -34,6 +34,11 @@ uint32_t gpio_set(PinName pin)
return (uint32_t)(1 << pin_index); // Return the pin mask 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) void gpio_init(gpio_t *obj, PinName pin)
{ {
obj->pin = pin; obj->pin = pin;

View File

@ -37,6 +37,11 @@ uint32_t gpio_set(PinName pin)
return (uint32_t)(1 << pin_index); // Return the pin mask 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) void gpio_init(gpio_t *obj, PinName pin)
{ {
obj->pin = pin; obj->pin = pin;

View File

@ -69,6 +69,7 @@ static const PinMap PinMap_SPI_SSEL[] = {
{P1_28, SPI_0, 5}, {P1_28, SPI_0, 5},
{P2_23, SPI_0, 2}, {P2_23, SPI_0, 2},
{P4_21, SPI_1, 3}, {P4_21, SPI_1, 3},
{P5_3, SPI_2, 2},
{NC , NC , 0} {NC , NC , 0}
}; };

View File

@ -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 */

View File

@ -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

View File

@ -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; }
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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

View File

@ -34,82 +34,31 @@ typedef enum {
UART7, UART7,
} UARTName; } UARTName;
// PWMType & 1 == 1 then have to use PWDTR[12] == 1
typedef enum { typedef enum {
PWM1A = 0, PWM_PWM1A = 0,
PWM1B, PWM_PWM1B,
PWM1C, PWM_PWM1C,
PWM1D, PWM_PWM1D,
PWM1E, PWM_PWM1E,
PWM1F, PWM_PWM1F,
PWM1G, PWM_PWM1G,
PWM1H, PWM_PWM1H,
PWM2A = 0x10, PWM_PWM2A,
PWM2B, PWM_PWM2B,
PWM2C, PWM_PWM2C,
PWM2D, PWM_PWM2D,
PWM2E, PWM_PWM2E,
PWM2F, PWM_PWM2F,
PWM2G, PWM_PWM2G,
PWM2H, PWM_PWM2H,
} PWMType; PWM_TIOC0A = 0x20,
PWM_TIOC0C,
typedef enum { PWM_TIOC1A,
TIOC0A = 0, PWM_TIOC2A,
TIOC0B, PWM_TIOC3A,
TIOC0C, PWM_TIOC3C,
TIOC0D, PWM_TIOC4A,
TIOC1A = 0x10, PWM_TIOC4C,
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,
} PWMName; } PWMName;
typedef enum { typedef enum {
@ -128,21 +77,22 @@ typedef enum {
SPI_1, SPI_1,
SPI_2, SPI_2,
SPI_3, SPI_3,
SPI_4,
} SPIName; } SPIName;
typedef enum { typedef enum {
I2C_0 = 0, I2C_0 = 0,
I2C_1, I2C_1,
I2C_2, I2C_2,
I2C_3 I2C_3,
} I2CName; } I2CName;
typedef enum { typedef enum {
CAN_0 = 0, CAN_0 = 0,
CAN_1, CAN_1,
CAN_2, CAN_2,
CAN_3, CAN_3,
CAN_4 CAN_4,
} CANName; } CANName;

View File

@ -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}
};

View File

@ -25,7 +25,14 @@ typedef enum {
Port1 = 1, Port1 = 1,
Port2 = 2, Port2 = 2,
Port3 = 3, Port3 = 3,
Port4 = 4 Port4 = 4,
Port5 = 5,
Port6 = 6,
Port7 = 7,
Port8 = 8,
Port9 = 9,
Port10 = 10,
Port11 = 11
} PortName; } PortName;
#ifdef __cplusplus #ifdef __cplusplus

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