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

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
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -16,41 +16,480 @@
*/
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"
#include "unity.h"
#include "utest.h"
#include "rtos.h"
#include "rtc_api.h"
#if !DEVICE_RTC
#error [NOT_SUPPORTED] test not supported
#endif
using namespace utest::v1;
#define CUSTOM_TIME 1256729737
/* On some boards RTC counter can not be
* Initialised with 0 value in such case
* drivers sets RTC counter to 1. */
#define CUSTOM_TIME_0 1
#define CUSTOM_TIME_1 1256729737
#define CUSTOM_TIME_2 2147483637
void test_case_rtc_strftime() {
greentea_send_kv("timestamp", CUSTOM_TIME);
#define DELAY_10_SEC 10
#define MS_PER_SEC 1000
#define RTC_DELTA 1
char buffer[32] = {0};
char kv_buff[64] = {0};
set_time(CUSTOM_TIME); // Set RTC time to Wed, 28 Oct 2009 11:35:37
static volatile int rtc_enabled_ret;
static volatile time_t rtc_time_val;
static volatile bool rtc_read_called;
static volatile bool rtc_write_called;
static volatile bool rtc_init_called;
static volatile bool rtc_isenabled_called;
for (int i=0; i<10; ++i) {
time_t seconds = time(NULL);
sprintf(kv_buff, "[%ld] ", seconds);
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S %p", localtime(&seconds));
strcat(kv_buff, buffer);
greentea_send_kv("rtc", kv_buff);
wait(1);
}
/* Stub of RTC read function. */
static time_t read_rtc_stub(void)
{
rtc_read_called = true;
return rtc_time_val;
}
/* Stub of RTC write function. */
static void write_rtc_stub(time_t t)
{
rtc_write_called = true;
rtc_time_val = t;
}
/* Stub of RTC init function. */
static void init_rtc_stub(void)
{
rtc_init_called = true;
}
/* Stub of RTC isenabled function. */
static int isenabled_rtc_stub(void)
{
rtc_isenabled_called = true;
return rtc_enabled_ret;
}
/* This test verifies if attach_rtc provides availability to
* connect specific RTC driver functions.
*
* This is unit test to verify if correct functions are used
* to support RTC.
*
* Given specific RTC driver functions have been attached (stubs).
* When set_time/time functions are called.
* Then set_time/time functions use attached RTC functions.
*/
void test_attach_RTC_stub_funtions()
{
time_t seconds = 0;
/* Attache RTC read/write/init/isenabled stubs. */
attach_rtc(read_rtc_stub, write_rtc_stub, init_rtc_stub, isenabled_rtc_stub);
/* Init stub variables/set to unexpected. */
rtc_write_called = false;
rtc_init_called = false;
/* Call set_time() function. We expect that init and write RTC stubs
* will be executed.
*/
set_time(CUSTOM_TIME_1);
/* Verify results. */
TEST_ASSERT_EQUAL(true, rtc_write_called);
TEST_ASSERT_EQUAL(true, rtc_init_called);
/* Init stub variables/set to unexpected. */
rtc_time_val = CUSTOM_TIME_1;
rtc_enabled_ret = true;
rtc_isenabled_called = false;
rtc_read_called = false;
/* Call time() function. We expect that isenabled and read RTC stubs
* are be executed.
*/
time(NULL);
/* Verify results. */
TEST_ASSERT_EQUAL(true, rtc_isenabled_called);
TEST_ASSERT_EQUAL(true, rtc_read_called);
/* This part of the test can be executed only on RTC devices. */
/* Restore env. */
attach_rtc(rtc_read, rtc_write, rtc_init, rtc_isenabled);
/* Set to unexpected. */
rtc_write_called = false;
rtc_init_called = false;
rtc_isenabled_called = false;
rtc_init_called = false;
/* Set time. */
set_time(CUSTOM_TIME_1);
/* Get time. */
seconds = time(NULL);
/* Stub RTC functions should not be called now. */
TEST_ASSERT_EQUAL(false, rtc_isenabled_called);
TEST_ASSERT_EQUAL(false, rtc_init_called);
TEST_ASSERT_EQUAL(false, rtc_write_called);
TEST_ASSERT_EQUAL(false, rtc_init_called);
/* Check if time has been successfully set and retrieved. */
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, seconds);
}
/* This test verifies if attach_rtc provides availability to
* connect specific RTC driver functions.
*
* This is unit test to verify if correct functions are used
* to support RTC.
*
* Given specific RTC driver functions have been attached (original).
* When set_time/time functions are called.
* Then set_time/time functions use attached RTC functions.
*/
void test_attach_RTC_org_funtions()
{
time_t seconds = 0;
/* Attache original driver functions. */
attach_rtc(rtc_read, rtc_write, rtc_init, rtc_isenabled);
/* Set to unexpected. */
rtc_write_called = false;
rtc_init_called = false;
rtc_isenabled_called = false;
rtc_init_called = false;
/* Set time. */
set_time(CUSTOM_TIME_1);
/* Get time. */
seconds = time(NULL);
/* Stub RTC functions should not be called now. */
TEST_ASSERT_EQUAL(false, rtc_isenabled_called);
TEST_ASSERT_EQUAL(false, rtc_init_called);
TEST_ASSERT_EQUAL(false, rtc_write_called);
TEST_ASSERT_EQUAL(false, rtc_init_called);
/* Check if time has been successfully set and retrieved. */
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, seconds);
}
/* This test verifies if time() function returns
* current time when all RTC functions are
* defined and RTC is enabled.
*
* Note: Stubs are used instead of original RTC functions.
*
* Given environment has RTC functions defined and RTC is enabled.
* When time() functions is called.
* Then current time is returned.
*/
void test_time_RTC_func_defined_RTC_is_enabled()
{
time_t seconds = 0;
/* Attache RTC read/write/init/isenabled stubs. */
attach_rtc(read_rtc_stub, write_rtc_stub, init_rtc_stub, isenabled_rtc_stub);
/* Simulate that RTC is enabled. */
rtc_enabled_ret = true;
/* Simulate current time. */
rtc_time_val = CUSTOM_TIME_1;
/* Try to get current time. */
seconds = time(NULL);
/* Check if expected value has been returned. */
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, seconds);
}
/* This test verifies if time() function resets time
* when RTC functions are defined and RTC is disabled.
*
* Note: Stubs are used instead of original RTC functions.
*
* Given environment has RTC functions defined and RTC is disabled.
* When time() functions is called.
* Then function result is 0.
*/
void test_time_RTC_func_defined_RTC_is_disabled()
{
time_t seconds = 0;
/* Attache RTC read/write/init/isenabled stubs. */
attach_rtc(read_rtc_stub, write_rtc_stub, init_rtc_stub, isenabled_rtc_stub);
/* Simulate that RTC is disabled. */
rtc_enabled_ret = false;
/* Simulate current time. */
rtc_time_val = CUSTOM_TIME_1;
/* Try to get current time. */
seconds = time(NULL);
/* Check if expected value has been returned. */
TEST_ASSERT_EQUAL(0, seconds);
}
/* This test verifies if time() function can be successfully
* executed when isenabled RTC function is undefined.
*
* Note: Stubs are used instead of original RTC functions.
*
* Given environment has isenabled RTC function undefined.
* When time() functions is called.
* Then current time is returned.
*/
void test_time_isenabled_RTC_func_undefined()
{
time_t seconds = 0;
/* Attache RTC read/write/init stubs. */
attach_rtc(read_rtc_stub, write_rtc_stub, init_rtc_stub, NULL);
/* Simulate current time. */
rtc_time_val = CUSTOM_TIME_1;
/* Try to get current time. */
seconds = time(NULL);
/* Check if expected value has been returned. */
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, seconds);
}
/* This test verifies if time() function returns -1 if
* read RTC function is undefined.
*
* Note: Stubs are used instead of original RTC functions.
*
* Given environment has read RTC function undefined.
* When time() functions is called.
* Then -1 is returned.
*/
void test_time_read_RTC_func_undefined()
{
time_t seconds = 0;
/* Attache RTC write/init/isenabled stubs. */
attach_rtc(NULL, write_rtc_stub, init_rtc_stub, isenabled_rtc_stub);
/* Simulate current time. */
rtc_time_val = CUSTOM_TIME_1;
/* Try to get current time. */
seconds = time(NULL);
/* Check if expected value has been returned. */
TEST_ASSERT_EQUAL((time_t)-1, seconds);
}
/* This test verifies if time() function stores
* the result in given time buffer (if specified).
*
* Note: Stubs are used instead original RTC functions.
* Other test cases calls time() routine with
* undefined time buffer.
*
* Given environment has all RTC function defined, RTC is enabled and time buffer is passed to time() function.
* When time() functions is called.
* Then current time is stored in the specified buffer.
*/
void test_time_called_with_param()
{
time_t seconds = 0;
time_t buffer = 0;
/* Attache RTC read/write/init/isenabled stubs. */
attach_rtc(read_rtc_stub, write_rtc_stub, init_rtc_stub, isenabled_rtc_stub);
/* Simulate that RTC is enabled. */
rtc_enabled_ret = true;
/* Simulate current time. */
rtc_time_val = CUSTOM_TIME_1;
/* Try to get current time. */
seconds = time(&buffer);
/* Check if expected value has been returned. */
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, seconds);
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, buffer);
}
/* This test verifies if set_time() function inits the RTC
* and writes current time if RTC functions are defined.
*
* Note: Stubs are used instead of original RTC functions.
*
* Given environment has RTC functions defined.
* When set_time() functions is called.
* Then function initialises RTC and sets RTC time.
*/
void test_set_time_RTC_func_defined()
{
/* Attache RTC read/write/init/isenabled stubs. */
attach_rtc(read_rtc_stub, write_rtc_stub, init_rtc_stub, isenabled_rtc_stub);
/* Set to unexpected. */
rtc_time_val = 123;
rtc_init_called = false;
/* Set current time. */
rtc_time_val = 123;
/* Set new RTC time. */
set_time(CUSTOM_TIME_1);
/* Check if RTC init has been performed and RTC time has been updated. */
TEST_ASSERT_EQUAL(true, rtc_init_called);
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, time(NULL));
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, rtc_time_val);
}
/* This test verifies if set_time() function can be
* successfully executed when init RTC function is undefined.
*
* Note: Stubs are used instead of original RTC functions.
*
* Given environment has init RTC function undefined.
* When set_time() functions is called.
* Then function sets RTC time.
*/
void test_set_time_init_RTC_func_undefined()
{
/* Attache RTC read/write/isenabled stubs. */
attach_rtc(read_rtc_stub, write_rtc_stub, NULL, isenabled_rtc_stub);
/* Set to unexpected. */
rtc_time_val = 123;
/* Set new RTC time. */
set_time(CUSTOM_TIME_1);
/* Check if RTC time has been updated. */
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, time(NULL));
TEST_ASSERT_EQUAL(CUSTOM_TIME_1, rtc_time_val);
}
/* This test verifies if set_time() function can be
* successfully executed when write RTC function is undefined.
*
* Note: Stubs are used instead original RTC functions.
*
* Given environemt has write RTC function undefined.
* When set_time() function is called.
* Then function inits RTC and does not modify RTC time.
*/
void test_set_time_write_RTC_func_undefined()
{
/* Attache RTC read/write/init/isenabled stubs. */
attach_rtc(read_rtc_stub, NULL, init_rtc_stub, isenabled_rtc_stub);
/* Set to unexpected. */
rtc_time_val = 123;
rtc_init_called = false;
/* Set new RTC time. */
set_time(CUSTOM_TIME_1);
/* Check if RTC has been initialized and RTC time has not been updated. */
TEST_ASSERT_EQUAL(true, rtc_init_called);
TEST_ASSERT_EQUAL(123, time(NULL));
TEST_ASSERT_EQUAL(123, rtc_time_val);
}
/* This test verifies if RTC time can be successfully set.
*
* Note: Original RTC functions are used in this test.
*
* Given environment has RTC available.
* When set_time() functions is called.
* Then RTC time is retrieved.
*/
template<uint32_t timeValue>
void test_functional_set()
{
/* Set original RTC functions. */
attach_rtc(rtc_read, rtc_write, rtc_init, rtc_isenabled);
/* Set new RTC time. */
set_time(timeValue);
/* Get current time and verify that new value has been set. */
TEST_ASSERT_EQUAL(timeValue, time(NULL));
}
/* This test verifies if RTC counts seconds.
*
* Note: Original RTC functions are used in this test.
*
* Given RTC has time set.
* When some time has passed (seconds).
* Then RTC time is updated.
*/
void test_functional_count()
{
time_t seconds = 0;
/* Set original RTC functions. */
attach_rtc(rtc_read, rtc_write, rtc_init, rtc_isenabled);
/* Set new RTC time. */
set_time(CUSTOM_TIME_2);
/* Wait 10 sec. */
wait_ms(DELAY_10_SEC * MS_PER_SEC);
/* Get time. */
seconds = time(NULL);
/* Verify that RTC counts seconds. */
TEST_ASSERT_UINT_WITHIN(RTC_DELTA, (unsigned int)seconds, CUSTOM_TIME_2 + DELAY_10_SEC);
}
utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(20, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("RTC strftime", test_case_rtc_strftime),
Case("Unit Test: attach stub RTC functions.", test_attach_RTC_stub_funtions),
Case("Unit Test: attach original RTC functions.", test_attach_RTC_org_funtions),
Case("Unit Test: time() - RTC functions are defined, RTC is enabled.", test_time_RTC_func_defined_RTC_is_enabled),
Case("Unit Test: time() - RTC functions are defined, RTC is disabled.", test_time_RTC_func_defined_RTC_is_disabled),
Case("Unit Test: time() - isenabled RTC function is undefined.", test_time_isenabled_RTC_func_undefined),
Case("Unit Test: time() - read RTC function is undefined.", test_time_read_RTC_func_undefined),
Case("Unit Test: time() - result is stored in given buffer.", test_time_called_with_param),
Case("Unit Test: set_time() - RTC functions are defined.", test_set_time_RTC_func_defined),
Case("Unit Test: set_time() - init RTC function is undefined.", test_set_time_init_RTC_func_undefined),
Case("Unit Test: set_time() - write RTC function is undefined.", test_set_time_write_RTC_func_undefined),
Case("Functional Test: set time - CUSTOM_TIME_0.", test_functional_set<CUSTOM_TIME_0>),
Case("Functional Test: set time - CUSTOM_TIME_1.", test_functional_set<CUSTOM_TIME_1>),
Case("Functional Test: set time - CUSTOM_TIME_2.", test_functional_set<CUSTOM_TIME_2>),
Case("Functional Test: RTC counts seconds.", test_functional_count),
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(20, "rtc_auto");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
Specification specification(test_setup, cases);
int main() {
Harness::run(specification);
return !Harness::run(specification);
}

View File

@ -28,7 +28,7 @@
using namespace utest::v1;
#define TEST_CYCLES 1000000
#define ALLOWED_DRIFT_PPM 1000 //0.1%
#define ALLOWED_DRIFT_PPM 5000 //0.5%
/*
return values to be checked are documented at:

View File

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

View File

@ -76,9 +76,15 @@ void test_tcp_hello_world() {
sock.send(buffer, strlen(buffer));
// Server will respond with HTTP GET's success code
const int ret = sock.recv(buffer, sizeof(buffer) - 1);
buffer[ret] = '\0';
int ret = 0;
int bytes_recvd = 0;
do {
ret += bytes_recvd;
bytes_recvd = sock.recv(buffer+ret, sizeof(buffer) - 1 - ret);
}while(bytes_recvd > 0);
buffer[ret] = '\0';
// Find 200 OK HTTP status in reply
bool found_200_ok = find_substring(buffer, buffer + ret, HTTP_OK_STR, HTTP_OK_STR + strlen(HTTP_OK_STR));
// Find "Hello World!" string in reply

View File

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

View File

@ -210,6 +210,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
bool has_variable_len,
const uint8_t *userDescriptionDescriptorValuePtr,
uint16_t userDescriptionDescriptorValueLen,
const uint8_t *presentationFormatDescriptorValuePtr,
uint16_t presentationFormatDescriptorValueLen,
bool readAuthorization,
bool writeAuthorization,
ble_gatts_char_handles_t *p_char_handle)
@ -238,6 +240,11 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
char_md.char_user_desc_max_size = userDescriptionDescriptorValueLen;
char_md.char_user_desc_size = userDescriptionDescriptorValueLen;
}
if ((presentationFormatDescriptorValueLen > 0) && (presentationFormatDescriptorValuePtr != NULL)) {
ASSERT_TRUE( sizeof(ble_gatts_char_pf_t) == sizeof(GattCharacteristic::PresentationFormat_t), ERROR_INVALID_PARAM );
ASSERT_TRUE( presentationFormatDescriptorValueLen == sizeof(GattCharacteristic::PresentationFormat_t), ERROR_INVALID_PARAM );
char_md.p_char_pf = const_cast<ble_gatts_char_pf_t *>(reinterpret_cast<const ble_gatts_char_pf_t *>(presentationFormatDescriptorValuePtr));
}
/* Attribute declaration */
ble_gatts_attr_md_t attr_md = {0};

View File

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

View File

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

View File

@ -1,5 +1,21 @@
# Change Log
## [v4.1.1](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.1.1)
**Closed issues:**
- IOTCLT-2203 mbed-coap does not handle PUT or POST if they indicate a smaller block size preference (fixed regression)
-[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.1.0...v4.1.1)
## [v4.1.0](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.1.0)
-[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.0.10...v4.1.0)
**New feature:**
- New API to disable automatic GET(BLOCK2) request sending.
**Closed issues:**
- IOTCLT-2203 mbed-coap does not handle PUT or POST if they indicate a smaller block size preference
## [v4.0.10](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.0.10)
-[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.0.9...v4.0.10)

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);
/**
* \fn int8_t sn_coap_convert_block_size(uint16_t block_size)
*
* \brief Utility function to convert block size.
*
* \param block_size Block size to convert.
*
* \return Value of range 0 - 6
*/
extern int8_t sn_coap_convert_block_size(uint16_t block_size);
/**
* \fn int8_t sn_coap_protocol_handle_block2_response_internally(struct coap_s *handle, uint8_t handle_response)
*
* \brief This function change the state whether CoAP library sends the block 2 response automatically or not.
*
* \param *handle Pointer to CoAP library handle
* \param handle_response 1 if CoAP library handles the response sending otherwise 0.
*
* \return 0 = success, -1 = failure
*/
extern int8_t sn_coap_protocol_handle_block2_response_internally(struct coap_s *handle, uint8_t handle_response);
#endif /* SN_COAP_PROTOCOL_H_ */
#ifdef __cplusplus

View File

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

View File

@ -229,6 +229,7 @@ struct coap_s {
uint8_t sn_coap_resending_count;
uint8_t sn_coap_resending_intervall;
uint8_t sn_coap_duplication_buffer_size;
uint8_t sn_coap_internal_block2_resp_handling; /* If this is set then coap itself sends a next GET request automatically */
};
#ifdef __cplusplus

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;
}
if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
if (msg_code == COAP_MSG_CODE_REQUEST_GET) {
// Blockwise message response is new GET
coap_res_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
/* msg_id needs to be set by the caller in this case */
}
else if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
coap_res_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
coap_res_ptr->msg_id = coap_packet_ptr->msg_id;
}
else if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE) {
coap_res_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE;
coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
/* msg_id needs to be set by the caller in this case */
}
else {
handle->sn_coap_protocol_free( coap_res_ptr );
return NULL;

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 void sn_coap_protocol_linked_list_blockwise_remove_old_data(struct coap_s *handle);
static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr, void *param);
static int8_t sn_coap_convert_block_size(uint16_t block_size);
static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, sn_coap_hdr_s *source_header_ptr);
#endif
#if ENABLE_RESENDINGS
@ -182,10 +181,10 @@ struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), vo
/* If pointer = 0, then re-sending does not return error when failed */
handle->sn_coap_rx_callback = used_rx_callback_ptr;
// Handles internally all GET req responses
handle->sn_coap_internal_block2_resp_handling = true;
#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */
/* * * * Create Linked list for storing active resending messages * * * */
ns_list_init(&handle->linked_list_resent_msgs);
handle->sn_coap_resending_queue_msgs = SN_COAP_RESENDING_QUEUE_SIZE_MSGS;
@ -220,6 +219,16 @@ struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), vo
return handle;
}
int8_t sn_coap_protocol_handle_block2_response_internally(struct coap_s *handle, uint8_t build_response)
{
if (handle == NULL) {
return -1;
}
handle->sn_coap_internal_block2_resp_handling = build_response;
return 0;
}
int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size)
{
(void) handle;
@ -1730,17 +1739,9 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
return NULL;
}
// Response with COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE if the payload size is more than we can handle
uint32_t max_size = SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE;
if (!blocks_in_order) {
tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE!");
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE;
} else if (received_coap_msg_ptr->options_list_ptr->size1 > max_size) {
// Include maximum size that stack can handle into response
tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE!");
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
src_coap_blockwise_ack_msg_ptr->options_list_ptr->size1 = max_size;
} else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) {
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
} else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) {
@ -1751,14 +1752,31 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_DELETED;
}
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = received_coap_msg_ptr->options_list_ptr->block1;
src_coap_blockwise_ack_msg_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
// Response with COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE if the payload size is more than we can handle
if (received_coap_msg_ptr->options_list_ptr->size1 > SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE) {
// Include maximum size that stack can handle into response
tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE!");
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
}
else {
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = received_coap_msg_ptr->options_list_ptr->block1;
src_coap_blockwise_ack_msg_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
/* Check block size */
block_temp = (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 & 0x07);
if (block_temp > sn_coap_convert_block_size(handle->sn_coap_block_data_size)) {
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 &= 0xFFFFF8;
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size);
/* Check block size */
block_temp = (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 & 0x07);
uint16_t block_size = 1u << (block_temp + 4);
if (block_size > handle->sn_coap_block_data_size) {
// Include maximum size that stack can handle into response
tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE!");
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
src_coap_blockwise_ack_msg_ptr->options_list_ptr->size1 = handle->sn_coap_block_data_size;
sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle);
}
if (block_temp > sn_coap_convert_block_size(handle->sn_coap_block_data_size)) {
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 &= 0xFFFFF8;
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size);
}
}
src_coap_blockwise_ack_msg_ptr->msg_id = received_coap_msg_ptr->msg_id;
@ -1832,178 +1850,204 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
else {
//This is response to request we made
if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) {
uint32_t block_number = 0;
if (handle->sn_coap_internal_block2_resp_handling) {
uint32_t block_number = 0;
/* Store blockwise payload to Linked list */
//todo: add block number to stored values - just to make sure all packets are in order
sn_coap_protocol_linked_list_blockwise_payload_store(handle,
src_addr_ptr,
received_coap_msg_ptr->payload_len,
received_coap_msg_ptr->payload_ptr,
received_coap_msg_ptr->options_list_ptr->block1 >> 4);
/* Store blockwise payload to Linked list */
//todo: add block number to stored values - just to make sure all packets are in order
sn_coap_protocol_linked_list_blockwise_payload_store(handle,
src_addr_ptr,
received_coap_msg_ptr->payload_len,
received_coap_msg_ptr->payload_ptr,
received_coap_msg_ptr->options_list_ptr->block2 >> 4);
/* If not last block (more value is set) */
if (received_coap_msg_ptr->options_list_ptr->block2 & 0x08) {
coap_blockwise_msg_s *previous_blockwise_msg_ptr = NULL;
//build and send ack
received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING;
/* If not last block (more value is set) */
if (received_coap_msg_ptr->options_list_ptr->block2 & 0x08) {
coap_blockwise_msg_s *previous_blockwise_msg_ptr = NULL;
//build and send ack
received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING;
ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) {
if (received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) {
previous_blockwise_msg_ptr = msg;
break;
ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) {
if (received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) {
previous_blockwise_msg_ptr = msg;
break;
}
}
}
if (!previous_blockwise_msg_ptr || !previous_blockwise_msg_ptr->coap_msg_ptr) {
tr_error("sn_coap_handle_blockwise_message - (send block2) previous message null!");
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
return 0;
}
src_coap_blockwise_ack_msg_ptr = sn_coap_parser_alloc_message(handle);
if (src_coap_blockwise_ack_msg_ptr == NULL) {
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate message!");
return 0;
}
ns_list_remove(&handle->linked_list_blockwise_sent_msgs, previous_blockwise_msg_ptr);
if( previous_blockwise_msg_ptr->coap_msg_ptr ){
if(previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr){
handle->sn_coap_protocol_free(previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr);
previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr = 0;
if (!previous_blockwise_msg_ptr || !previous_blockwise_msg_ptr->coap_msg_ptr) {
tr_error("sn_coap_handle_blockwise_message - (send block2) previous message null!");
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
return 0;
}
sn_coap_parser_release_allocated_coap_msg_mem(handle, previous_blockwise_msg_ptr->coap_msg_ptr);
previous_blockwise_msg_ptr->coap_msg_ptr = 0;
}
handle->sn_coap_protocol_free(previous_blockwise_msg_ptr);
previous_blockwise_msg_ptr = 0;
/* * * Then build CoAP Acknowledgement message * * */
src_coap_blockwise_ack_msg_ptr = sn_coap_parser_alloc_message(handle);
if (src_coap_blockwise_ack_msg_ptr == NULL) {
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate message!");
return 0;
}
if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) {
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate options!");
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
src_coap_blockwise_ack_msg_ptr = 0;
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
return NULL;
}
/* * * Then build CoAP Acknowledgement message * * */
src_coap_blockwise_ack_msg_ptr->msg_id = message_id++;
if (message_id == 0) {
message_id = 1;
}
if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) {
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate options!");
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
src_coap_blockwise_ack_msg_ptr = 0;
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
return NULL;
}
/* Update block option */
block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07;
src_coap_blockwise_ack_msg_ptr->msg_id = message_id++;
if (message_id == 0) {
message_id = 1;
}
block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4;
block_number ++;
/* Update block option */
block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07;
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = (block_number << 4) | block_temp;
block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4;
block_number ++;
/* Then get needed memory count for Packet data */
dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr ,handle->sn_coap_block_data_size);
src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = (block_number << 4) | block_temp;
/* Then allocate memory for Packet data */
dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem);
if (dst_ack_packet_data_ptr == NULL) {
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate packet!");
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
src_coap_blockwise_ack_msg_ptr = 0;
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
return NULL;
}
memset(dst_ack_packet_data_ptr, 0, dst_packed_data_needed_mem);
/* Set BLOCK2 (subsequent) GET msg code and copy uri path from previous msg*/
if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CONTENT) {
src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_REQUEST_GET;
if (previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_ptr) {
src_coap_blockwise_ack_msg_ptr->uri_path_len = previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len;
src_coap_blockwise_ack_msg_ptr->uri_path_ptr = handle->sn_coap_protocol_malloc(previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len);
if (!src_coap_blockwise_ack_msg_ptr->uri_path_ptr) {
sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
tr_error("sn_coap_handle_blockwise_message - failed to allocate for uri path ptr!");
return NULL;
}
memcpy(src_coap_blockwise_ack_msg_ptr->uri_path_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len);
}
if (previous_blockwise_msg_ptr->coap_msg_ptr->token_ptr) {
src_coap_blockwise_ack_msg_ptr->token_len = previous_blockwise_msg_ptr->coap_msg_ptr->token_len;
src_coap_blockwise_ack_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(previous_blockwise_msg_ptr->coap_msg_ptr->token_len);
if (!src_coap_blockwise_ack_msg_ptr->token_ptr) {
sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
tr_error("sn_coap_handle_blockwise_message - failed to allocate for token ptr!");
return NULL;
}
memcpy(src_coap_blockwise_ack_msg_ptr->token_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->token_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->token_len);
}
}
/* * * Then build Acknowledgement message to Packed data * * */
if ((sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size)) < 0) {
tr_error("sn_coap_handle_blockwise_message - (send block2) builder failed!");
ns_list_remove(&handle->linked_list_blockwise_sent_msgs, previous_blockwise_msg_ptr);
if (previous_blockwise_msg_ptr->coap_msg_ptr) {
if (previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr) {
handle->sn_coap_protocol_free(previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr);
previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr = 0;
}
sn_coap_parser_release_allocated_coap_msg_mem(handle, previous_blockwise_msg_ptr->coap_msg_ptr);
previous_blockwise_msg_ptr->coap_msg_ptr = 0;
}
handle->sn_coap_protocol_free(previous_blockwise_msg_ptr);
previous_blockwise_msg_ptr = 0;
/* Then get needed memory count for Packet data */
dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr ,handle->sn_coap_block_data_size);
/* Then allocate memory for Packet data */
dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem);
if (dst_ack_packet_data_ptr == NULL) {
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate packet!");
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
src_coap_blockwise_ack_msg_ptr = 0;
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
return NULL;
}
memset(dst_ack_packet_data_ptr, 0, dst_packed_data_needed_mem);
/* * * Then build Acknowledgement message to Packed data * * */
if ((sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size)) < 0) {
tr_error("sn_coap_handle_blockwise_message - (send block2) builder failed!");
handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
dst_ack_packet_data_ptr = 0;
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
src_coap_blockwise_ack_msg_ptr = 0;
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
return NULL;
}
/* * * Save to linked list * * */
coap_blockwise_msg_s *stored_blockwise_msg_ptr;
stored_blockwise_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_msg_s));
if (!stored_blockwise_msg_ptr) {
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate blockwise message!");
handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
dst_ack_packet_data_ptr = 0;
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
src_coap_blockwise_ack_msg_ptr = 0;
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
return 0;
}
memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s));
stored_blockwise_msg_ptr->timestamp = handle->system_time;
stored_blockwise_msg_ptr->coap_msg_ptr = src_coap_blockwise_ack_msg_ptr;
stored_blockwise_msg_ptr->coap = handle;
ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr);
/* * * Then release memory of CoAP Acknowledgement message * * */
handle->sn_coap_tx_callback(dst_ack_packet_data_ptr,
dst_packed_data_needed_mem, src_addr_ptr, param);
#if ENABLE_RESENDINGS
uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0);
sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr,
dst_packed_data_needed_mem,
dst_ack_packet_data_ptr,
resend_time, param);
#endif
handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
dst_ack_packet_data_ptr = 0;
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
src_coap_blockwise_ack_msg_ptr = 0;
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
return NULL;
}
/* * * Save to linked list * * */
coap_blockwise_msg_s *stored_blockwise_msg_ptr;
//Last block received
else {
/* * * This is the last block when whole Blockwise payload from received * * */
/* * * blockwise messages is gathered and returned to User * * */
stored_blockwise_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_msg_s));
if (!stored_blockwise_msg_ptr) {
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate blockwise message!");
handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
dst_ack_packet_data_ptr = 0;
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
src_coap_blockwise_ack_msg_ptr = 0;
sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
return 0;
/* Store last Blockwise payload to Linked list */
uint16_t payload_len = 0;
uint8_t *payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len);
uint16_t whole_payload_len = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr);
uint8_t *temp_whole_payload_ptr = NULL;
temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len);
if (!temp_whole_payload_ptr) {
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate whole payload!");
return 0;
}
received_coap_msg_ptr->payload_ptr = temp_whole_payload_ptr;
received_coap_msg_ptr->payload_len = whole_payload_len;
/* Copy stored Blockwise payloads to returned whole Blockwise payload pointer */
while (payload_ptr != NULL) {
memcpy(temp_whole_payload_ptr, payload_ptr, payload_len);
temp_whole_payload_ptr += payload_len;
sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle);
payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len);
}
received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED;
//todo: remove previous msg from list
}
memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s));
stored_blockwise_msg_ptr->timestamp = handle->system_time;
stored_blockwise_msg_ptr->coap_msg_ptr = src_coap_blockwise_ack_msg_ptr;
stored_blockwise_msg_ptr->coap = handle;
ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr);
/* * * Then release memory of CoAP Acknowledgement message * * */
handle->sn_coap_tx_callback(dst_ack_packet_data_ptr,
dst_packed_data_needed_mem, src_addr_ptr, param);
#if ENABLE_RESENDINGS
uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0);
sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr,
dst_packed_data_needed_mem,
dst_ack_packet_data_ptr,
resend_time, param);
#endif
handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
dst_ack_packet_data_ptr = 0;
}
//Last block received
else {
/* * * This is the last block when whole Blockwise payload from received * * */
/* * * blockwise messages is gathered and returned to User * * */
/* Store last Blockwise payload to Linked list */
uint16_t payload_len = 0;
uint8_t *payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len);
uint16_t whole_payload_len = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr);
uint8_t *temp_whole_payload_ptr = NULL;
temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len);
if (!temp_whole_payload_ptr) {
tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate whole payload!");
return 0;
}
received_coap_msg_ptr->payload_ptr = temp_whole_payload_ptr;
received_coap_msg_ptr->payload_len = whole_payload_len;
/* Copy stored Blockwise payloads to returned whole Blockwise payload pointer */
while (payload_ptr != NULL) {
memcpy(temp_whole_payload_ptr, payload_ptr, payload_len);
temp_whole_payload_ptr += payload_len;
sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle);
payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len);
}
received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED;
//todo: remove previous msg from list
}
}
//Now we send data to request
@ -2108,7 +2152,7 @@ static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn
return received_coap_msg_ptr;
}
static int8_t sn_coap_convert_block_size(uint16_t block_size)
int8_t sn_coap_convert_block_size(uint16_t block_size)
{
if (block_size == 16) {
return 0;

View File

@ -23,4 +23,11 @@
#define MEM_SIZE (1600 * 16)
#define MEMP_NUM_TCP_SEG 32
#define TCP_MSS 1460
#define PBUF_POOL_SIZE 16
#define TCP_SND_BUF (8 * TCP_MSS)
#define TCP_WND (TCP_MSS * 8)
#define PBUF_POOL_BUFSIZE 1600
#endif

View File

@ -5,11 +5,73 @@
#include "mbed_interface.h"
#include "ethernet_api.h"
#include "ethernetext_api.h"
#include "platform/mbed_toolchain.h"
#define RECV_TASK_PRI (osPriorityNormal)
#define PHY_TASK_PRI (osPriorityNormal)
#define PHY_TASK_WAIT (200)
WEAK int ethernetext_init(ethernet_cfg_t *p_ethcfg)
{
return -1;
}
WEAK void ethernetext_start_stop(int32_t mode)
{
}
WEAK int ethernetext_chk_link_mode(void)
{
return NEGO_FAIL;
}
WEAK void ethernetext_set_link_mode(int32_t link)
{
}
WEAK int ethernet_init(void)
{
return -1;
}
WEAK void ethernet_free(void)
{
}
WEAK int ethernet_write(const char *data, int size)
{
return 0;
}
WEAK int ethernet_send(void)
{
return 0;
}
WEAK int ethernet_receive(void)
{
return 0;
}
WEAK int ethernet_read(char *data, int size)
{
return 0;
}
WEAK void ethernet_address(char *mac)
{
}
WEAK int ethernet_link(void)
{
return 0;
}
WEAK void ethernet_set_link(int speed, int duplex)
{
}
/* memory */
static sys_sem_t recv_ready_sem; /* receive ready semaphore */
@ -195,8 +257,8 @@ err_t eth_arch_enetif_init(struct netif *netif)
sys_sem_new(&recv_ready_sem, 0);
/* task */
sys_thread_new("rza1_emac_rx_thread", rza1_recv_task, netif, DEFAULT_THREAD_STACKSIZE, RECV_TASK_PRI);
sys_thread_new("rza1_emac_phy_thread", rza1_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_TASK_PRI);
sys_thread_new("rza1_recv_task", rza1_recv_task, netif, DEFAULT_THREAD_STACKSIZE, RECV_TASK_PRI);
sys_thread_new("rza1_phy_task", rza1_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_TASK_PRI);
return ERR_OK;
}

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);
DWORD ssize = disk_get_sector_size(pdrv);
int err = _ffs[pdrv]->read(buff, sector*ssize, count*ssize);
bd_addr_t addr = (bd_addr_t)sector*ssize;
bd_size_t size = (bd_size_t)count*ssize;
int err = _ffs[pdrv]->read(buff, addr, size);
return err ? RES_PARERR : RES_OK;
}
@ -204,12 +206,14 @@ DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
{
debug_if(FFS_DBG, "disk_write(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv);
DWORD ssize = disk_get_sector_size(pdrv);
int err = _ffs[pdrv]->erase(sector*ssize, count*ssize);
bd_addr_t addr = (bd_addr_t)sector*ssize;
bd_size_t size = (bd_size_t)count*ssize;
int err = _ffs[pdrv]->erase(addr, size);
if (err) {
return RES_PARERR;
}
err = _ffs[pdrv]->program(buff, sector*ssize, count*ssize);
err = _ffs[pdrv]->program(buff, addr, size);
if (err) {
return RES_PARERR;
}
@ -250,7 +254,9 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
} else {
DWORD *sectors = (DWORD*)buff;
DWORD ssize = disk_get_sector_size(pdrv);
int err = _ffs[pdrv]->trim(sectors[0]*ssize, (sectors[1]-sectors[0]+1)*ssize);
bd_addr_t addr = (bd_addr_t)sectors[0]*ssize;
bd_size_t size = (bd_size_t)(sectors[1]-sectors[0]+1)*ssize;
int err = _ffs[pdrv]->trim(addr, size);
return err ? RES_PARERR : RES_OK;
}
}

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,
lfs_off_t off, void *buffer, lfs_size_t size) {
BlockDevice *bd = (BlockDevice *)c->context;
return bd->read(buffer, block*c->block_size + off, size);
return bd->read(buffer, (bd_addr_t)block*c->block_size + off, size);
}
static int lfs_bd_prog(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size) {
BlockDevice *bd = (BlockDevice *)c->context;
return bd->program(buffer, block*c->block_size + off, size);
return bd->program(buffer, (bd_addr_t)block*c->block_size + off, size);
}
static int lfs_bd_erase(const struct lfs_config *c, lfs_block_t block)
{
BlockDevice *bd = (BlockDevice *)c->context;
return bd->erase(block*c->block_size, c->block_size);
return bd->erase((bd_addr_t)block*c->block_size, c->block_size);
}
static int lfs_bd_sync(const struct lfs_config *c)

View File

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

View File

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

View File

@ -34,7 +34,8 @@ tests/test.py << TEST
lfs_size_t chunk = 31;
srand(0);
lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file[0], "$2", LFS_O_WRONLY | LFS_O_CREAT) => 0;
lfs_file_open(&lfs, &file[0], "$2",
${3:-LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC}) => 0;
for (lfs_size_t i = 0; i < size; i += chunk) {
chunk = (chunk < size - i) ? chunk : size - i;
for (lfs_size_t b = 0; b < chunk; b++) {
@ -53,7 +54,10 @@ tests/test.py << TEST
lfs_size_t chunk = 29;
srand(0);
lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file[0], "$2", LFS_O_RDONLY) => 0;
lfs_stat(&lfs, "$2", &info) => 0;
info.type => LFS_TYPE_REG;
info.size => size;
lfs_file_open(&lfs, &file[0], "$2", ${3:-LFS_O_RDONLY}) => 0;
for (lfs_size_t i = 0; i < size; i += chunk) {
chunk = (chunk < size - i) ? chunk : size - i;
lfs_file_read(&lfs, &file[0], buffer, chunk) => chunk;
@ -78,10 +82,27 @@ echo "--- Large file test ---"
w_test $LARGESIZE largeavacado
r_test $LARGESIZE largeavacado
echo "--- Zero file test ---"
w_test 0 noavacado
r_test 0 noavacado
echo "--- Truncate small test ---"
w_test $SMALLSIZE mediumavacado
r_test $SMALLSIZE mediumavacado
w_test $MEDIUMSIZE mediumavacado
r_test $MEDIUMSIZE mediumavacado
echo "--- Truncate zero test ---"
w_test $SMALLSIZE noavacado
r_test $SMALLSIZE noavacado
w_test 0 noavacado
r_test 0 noavacado
echo "--- Non-overlap check ---"
r_test $SMALLSIZE smallavacado
r_test $MEDIUMSIZE mediumavacado
r_test $LARGESIZE largeavacado
r_test 0 noavacado
echo "--- Dir check ---"
tests/test.py << TEST
@ -105,6 +126,10 @@ tests/test.py << TEST
strcmp(info.name, "largeavacado") => 0;
info.type => LFS_TYPE_REG;
info.size => $LARGESIZE;
lfs_dir_read(&lfs, &dir[0], &info) => 1;
strcmp(info.name, "noavacado") => 0;
info.type => LFS_TYPE_REG;
info.size => 0;
lfs_dir_read(&lfs, &dir[0], &info) => 0;
lfs_dir_close(&lfs, &dir[0]) => 0;
lfs_unmount(&lfs) => 0;

View File

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

View File

@ -46,13 +46,16 @@ static void own_free(void *ptr)
static NS_LIST_DEFINE(request_list, coap_transaction_t, link);
static coap_transaction_t *transaction_find_client_by_token(uint8_t token[4])
static coap_transaction_t *transaction_find_client_by_token(uint8_t *token, uint8_t token_len, const uint8_t address[static 16], uint16_t port)
{
(void) address;
(void) port;
coap_transaction_t *this = NULL;
ns_list_foreach(coap_transaction_t, cur_ptr, &request_list) {
if (memcmp(cur_ptr->token,token,4) == 0 && cur_ptr->client_request) {
if ((cur_ptr->token_len == token_len) && (memcmp(cur_ptr->token, token, token_len) == 0) && cur_ptr->client_request) {
this = cur_ptr;
break;
break;
}
}
return this;
@ -147,12 +150,13 @@ static int8_t coap_rx_function(sn_coap_hdr_s *resp_ptr, sn_nsdl_addr_s *address_
coap_transaction_t *this = NULL;
(void)address_ptr;
(void)param;
tr_warn("transaction was not handled %d", resp_ptr->msg_id);
if (!resp_ptr) {
return -1;
}
if( resp_ptr->token_ptr ){
this = transaction_find_client_by_token(resp_ptr->token_ptr);
if(resp_ptr->token_ptr){
this = transaction_find_client_by_token(resp_ptr->token_ptr, resp_ptr->token_len, address_ptr->addr_ptr, address_ptr->port);
}
if (!this) {
return 0;
@ -278,6 +282,7 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
memcpy(transaction_ptr->remote_address, source_addr_ptr, 16);
if (coap_message->token_len) {
memcpy(transaction_ptr->token, coap_message->token_ptr, coap_message->token_len);
transaction_ptr->token_len = coap_message->token_len;
}
transaction_ptr->remote_port = port;
if (cb(socket_id, coap_message, transaction_ptr) < 0) {
@ -292,7 +297,7 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
} else {
coap_transaction_t *this = NULL;
if (coap_message->token_ptr) {
this = transaction_find_client_by_token(coap_message->token_ptr);
this = transaction_find_client_by_token(coap_message->token_ptr, coap_message->token_len, source_addr_ptr, port);
}
if (!this) {
tr_error("client transaction not found");
@ -352,8 +357,9 @@ uint16_t coap_message_handler_request_send(coap_msg_handler_t *handle, int8_t se
do{
randLIB_get_n_bytes_random(token,4);
}while(transaction_find_client_by_token(token));
}while(transaction_find_client_by_token(token, 4, destination_addr, destination_port));
memcpy(transaction_ptr->token,token,4);
transaction_ptr->token_len = 4;
request.token_ptr = transaction_ptr->token;
request.token_len = 4;
@ -464,7 +470,7 @@ int8_t coap_message_handler_response_send_by_msg_id(coap_msg_handler_t *handle,
response.payload_len = payload_len;
response.payload_ptr = (uint8_t *) payload_ptr; // Cast away const and trust that nsdl doesn't modify...
response.content_format = content_type;
response.token_len = 4;
response.token_len = transaction_ptr->token_len;
response.token_ptr = transaction_ptr->token;
response.msg_code = message_code;
if (transaction_ptr->req_msg_type == COAP_MSG_TYPE_CONFIRMABLE) {

View File

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

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);
}
static int8_t find_interface_by_address(const uint8_t target_addr[16])
{
for (int if_id = 1; if_id <= 127; if_id++) {
int i = 0;
uint8_t if_addr[16];
while (arm_net_address_list_get_next(if_id, &i, if_addr) == 0) {
if (memcmp(target_addr, if_addr, 16) == 0) {
return if_id;
}
}
}
return -1;
}
void* NanostackSocket::operator new(std::size_t sz) {
return MALLOC(sz);
}
@ -693,17 +707,50 @@ nsapi_error_t NanostackInterface::setsockopt(void *handle, int level, int optnam
return NSAPI_ERROR_NO_SOCKET;
}
nsapi_error_t ret;
NanostackLockGuard lock;
if (::socket_setsockopt(socket->socket_id, level, optname, optval, optlen) == 0) {
ret = NSAPI_ERROR_OK;
} else {
ret = NSAPI_ERROR_PARAMETER;
ns_ipv6_mreq_t ns_mreq;
if (level == NSAPI_SOCKET) {
switch (optname) {
case NSAPI_ADD_MEMBERSHIP:
case NSAPI_DROP_MEMBERSHIP: {
if (optlen != sizeof(nsapi_ip_mreq_t)) {
return NSAPI_ERROR_PARAMETER;
}
const nsapi_ip_mreq_t *imr = static_cast<const nsapi_ip_mreq_t *>(optval);
/* Check address types are IPv6, or unspecified for interface */
if (imr->imr_multiaddr.version != NSAPI_IPv6 ||
(imr->imr_interface.version != NSAPI_UNSPEC && imr->imr_interface.version != NSAPI_IPv6)) {
return NSAPI_ERROR_PARAMETER;
}
/* Convert all parameters to Nanostack native, and proceed with setsockopt */
memcpy(ns_mreq.ipv6mr_multiaddr, imr->imr_multiaddr.bytes, 16);
if (imr->imr_interface.version == NSAPI_UNSPEC || memcmp(imr->imr_interface.bytes, ns_in6addr_any, 16) == 0) {
ns_mreq.ipv6mr_interface = 0;
} else {
// If this fails, Nanostack will itself fault the invalid -1 interface ID
ns_mreq.ipv6mr_interface = find_interface_by_address(imr->imr_interface.bytes);
}
level = SOCKET_IPPROTO_IPV6;
optname = optname == NSAPI_ADD_MEMBERSHIP ? SOCKET_IPV6_JOIN_GROUP : SOCKET_IPV6_LEAVE_GROUP;
optval = &ns_mreq;
optlen = sizeof ns_mreq;
break;
}
default:
return NSAPI_ERROR_PARAMETER;
}
}
return ret;
if (::socket_setsockopt(socket->socket_id, level, optname, optval, optlen) == 0) {
return NSAPI_ERROR_OK;
} else {
return NSAPI_ERROR_PARAMETER;
}
}
nsapi_error_t NanostackInterface::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)

View File

@ -111,7 +111,9 @@ public:
* @param data Destination buffer for data received from the host
* @param size Size of the buffer in bytes
* @return Number of received bytes on success, negative error
* code on failure
* code on failure. If no data is available to be received
* and the peer has performed an orderly shutdown,
* recv() returns 0.
*/
nsapi_size_or_error_t recv(void *data, nsapi_size_t size);

View File

@ -94,17 +94,18 @@ public:
nsapi_size_or_error_t sendto(const SocketAddress &address,
const void *data, nsapi_size_t size);
/** Receive a packet over a UDP socket
/** Receive a datagram over a UDP socket
*
* Receives data and stores the source address in address if address
* is not NULL. Returns the number of bytes received into the buffer.
* Receives a datagram and stores the source address in address if address
* is not NULL. Returns the number of bytes written into the buffer. If the
* datagram is larger than the buffer, the excess data is silently discarded.
*
* By default, recvfrom blocks until data is sent. If socket is set to
* non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
* immediately.
* By default, recvfrom blocks until a datagram is received. If socket is set to
* non-blocking or times out with no datagram, NSAPI_ERROR_WOULD_BLOCK
* is returned.
*
* @param address Destination for the source address or NULL
* @param data Destination buffer for data received from the host
* @param data Destination buffer for datagram received from the host
* @param size Size of the buffer in bytes
* @return Number of received bytes on success, negative error
* code on failure

View File

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

View File

@ -152,7 +152,7 @@ public:
*
*/
void attach(void(*fptr)(void)) {
updateVol.attach(fptr);
updateVol = Callback<void()>(fptr);
}
/** attach a handler to Tx Done
*
@ -160,7 +160,7 @@ public:
*
*/
void attachTx(void(*fptr)(void)) {
txDone.attach(fptr);
txDone = Callback<void()>(fptr);
}
/** attach a handler to Rx Done
*
@ -168,7 +168,7 @@ public:
*
*/
void attachRx(void(*fptr)(void)) {
rxDone.attach(fptr);
rxDone = Callback<void()>(fptr);
}
/** Attach a nonstatic void/void member function to update the volume
@ -179,15 +179,52 @@ public:
*/
template<typename T>
void attach(T *tptr, void(T::*mptr)(void)) {
updateVol.attach(tptr, mptr);
updateVol = Callback<void()>(tptr, mptr);
}
/** Attach a nonstatic void/void member function to Tx Done
*
* @param tptr Object pointer
* @param mptr Member function pointer
*
*/
template<typename T>
void attachTx(T *tptr, void(T::*mptr)(void)) {
txDone.attach(tptr, mptr);
txDone = Callback<void()>(tptr, mptr);
}
/** Attach a nonstatic void/void member function to Rx Done
*
* @param tptr Object pointer
* @param mptr Member function pointer
*
*/
template<typename T>
void attachRx(T *tptr, void(T::*mptr)(void)) {
rxDone.attach(tptr, mptr);
rxDone = Callback<void()>(tptr, mptr);
}
/** Attach a Callback to update the volume
*
* @param cb Callback to attach
*
*/
void attach(Callback<void()> &cb) {
updateVol = cb;
}
/** attach a Callback to Tx Done
*
* @param cb Callback to attach
*
*/
void attachTx(Callback<void()> &cb) {
txDone = cb;
}
/** attach a Callback to Rx Done
*
* @param cb Callback to attach
*
*/
void attachRx(Callback<void()> &cb) {
rxDone = cb;
}
@ -216,21 +253,21 @@ protected:
*
* @returns pointer to the string product descriptor
*/
virtual uint8_t * stringIproductDesc();
virtual const uint8_t * stringIproductDesc();
/*
* Get string interface descriptor
*
* @returns pointer to the string interface descriptor
*/
virtual uint8_t * stringIinterfaceDesc();
virtual const uint8_t * stringIinterfaceDesc();
/*
* Get configuration descriptor
*
* @returns pointer to the configuration descriptor
*/
virtual uint8_t * configurationDesc();
virtual const uint8_t * configurationDesc();
/*
* Called by USBDevice layer. Set interface/alternate of the device.
@ -270,6 +307,20 @@ protected:
private:
/*
* Call to rebuild the configuration descriptor
*
* This function should be called on creation or when any
* value that is part of the configuration descriptor
* changes.
* @note This function uses ~200 bytes of stack so
* make sure your stack is big enough for it.
*/
void _build_configurationDesc();
// configuration descriptor
uint8_t configDescriptor[183];
// stream available ?
volatile bool available;

View File

@ -58,7 +58,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("device descr\r\n");
#endif
transfer.remaining = DEVICE_DESCRIPTOR_LENGTH;
transfer.ptr = deviceDesc();
transfer.ptr = (uint8_t*)deviceDesc();
transfer.direction = DEVICE_TO_HOST;
success = true;
}
@ -77,7 +77,7 @@ bool USBDevice::requestGetDescriptor(void)
transfer.remaining = configurationDesc()[2] \
| (configurationDesc()[3] << 8);
transfer.ptr = configurationDesc();
transfer.ptr = (uint8_t*)configurationDesc();
transfer.direction = DEVICE_TO_HOST;
success = true;
}
@ -94,7 +94,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("1\r\n");
#endif
transfer.remaining = stringLangidDesc()[0];
transfer.ptr = stringLangidDesc();
transfer.ptr = (uint8_t*)stringLangidDesc();
transfer.direction = DEVICE_TO_HOST;
success = true;
break;
@ -103,7 +103,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("2\r\n");
#endif
transfer.remaining = stringImanufacturerDesc()[0];
transfer.ptr = stringImanufacturerDesc();
transfer.ptr = (uint8_t*)stringImanufacturerDesc();
transfer.direction = DEVICE_TO_HOST;
success = true;
break;
@ -112,7 +112,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("3\r\n");
#endif
transfer.remaining = stringIproductDesc()[0];
transfer.ptr = stringIproductDesc();
transfer.ptr = (uint8_t*)stringIproductDesc();
transfer.direction = DEVICE_TO_HOST;
success = true;
break;
@ -121,7 +121,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("4\r\n");
#endif
transfer.remaining = stringIserialDesc()[0];
transfer.ptr = stringIserialDesc();
transfer.ptr = (uint8_t*)stringIserialDesc();
transfer.direction = DEVICE_TO_HOST;
success = true;
break;
@ -130,7 +130,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("5\r\n");
#endif
transfer.remaining = stringIConfigurationDesc()[0];
transfer.ptr = stringIConfigurationDesc();
transfer.ptr = (uint8_t*)stringIConfigurationDesc();
transfer.direction = DEVICE_TO_HOST;
success = true;
break;
@ -139,7 +139,7 @@ bool USBDevice::requestGetDescriptor(void)
printf("6\r\n");
#endif
transfer.remaining = stringIinterfaceDesc()[0];
transfer.ptr = stringIinterfaceDesc();
transfer.ptr = (uint8_t*)stringIinterfaceDesc();
transfer.direction = DEVICE_TO_HOST;
success = true;
break;
@ -187,27 +187,8 @@ bool USBDevice::controlOut(void)
/* Check we should be transferring data OUT */
if (transfer.direction != HOST_TO_DEVICE)
{
#if defined(TARGET_KL25Z) | defined(TARGET_KL43Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D5M) | defined(TARGET_K64F) | defined(TARGET_K22F) | defined(TARGET_TEENSY3_1)
/*
* We seem to have a pending device-to-host transfer. The host must have
* sent a new control request without waiting for us to finish processing
* the previous one. This appears to happen when we're connected to certain
* USB 3.0 host chip set. Do a zeor-length send to tell the host we're not
* ready for the new request - that'll make it resend - and then just
* pretend we were successful here so that the pending transfer can finish.
*/
uint8_t buf[1] = { 0 };
EP0write(buf, 0);
/* execute our pending ttransfer */
controlIn();
/* indicate success */
return true;
#else
/* for other platforms, count on the HAL to handle this case */
return false;
#endif
}
/* Read from endpoint */
@ -790,7 +771,7 @@ uint8_t * USBDevice::findDescriptor(uint8_t descriptorType)
}
/* Start at first descriptor after the configuration descriptor */
ptr = &(configurationDesc()[CONFIGURATION_DESCRIPTOR_LENGTH]);
ptr = &(((uint8_t*)configurationDesc())[CONFIGURATION_DESCRIPTOR_LENGTH]);
do {
if (ptr[1] /* bDescriptorType */ == descriptorType)
@ -926,8 +907,8 @@ bool USBDevice::readEP_NB(uint8_t endpoint, uint8_t * buffer, uint32_t * size, u
uint8_t * USBDevice::deviceDesc() {
static uint8_t deviceDescriptor[] = {
const uint8_t * USBDevice::deviceDesc() {
uint8_t deviceDescriptorTemp[] = {
DEVICE_DESCRIPTOR_LENGTH, /* bLength */
DEVICE_DESCRIPTOR, /* bDescriptorType */
LSB(USB_VERSION_2_0), /* bcdUSB (LSB) */
@ -947,20 +928,22 @@ uint8_t * USBDevice::deviceDesc() {
STRING_OFFSET_ISERIAL, /* iSerialNumber */
0x01 /* bNumConfigurations */
};
MBED_ASSERT(sizeof(deviceDescriptorTemp) == sizeof(deviceDescriptor));
memcpy(deviceDescriptor, deviceDescriptorTemp, sizeof(deviceDescriptor));
return deviceDescriptor;
}
uint8_t * USBDevice::stringLangidDesc() {
static uint8_t stringLangidDescriptor[] = {
const uint8_t * USBDevice::stringLangidDesc() {
static const uint8_t stringLangidDescriptor[] = {
0x04, /*bLength*/
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
0x09,0x04, /*bString Lang ID - 0x0409 - English*/
};
return stringLangidDescriptor;
return (uint8_t *)stringLangidDescriptor;
}
uint8_t * USBDevice::stringImanufacturerDesc() {
static uint8_t stringImanufacturerDescriptor[] = {
const uint8_t * USBDevice::stringImanufacturerDesc() {
static const uint8_t stringImanufacturerDescriptor[] = {
0x12, /*bLength*/
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
'm',0,'b',0,'e',0,'d',0,'.',0,'o',0,'r',0,'g',0, /*bString iManufacturer - mbed.org*/
@ -968,8 +951,8 @@ uint8_t * USBDevice::stringImanufacturerDesc() {
return stringImanufacturerDescriptor;
}
uint8_t * USBDevice::stringIserialDesc() {
static uint8_t stringIserialDescriptor[] = {
const uint8_t * USBDevice::stringIserialDesc() {
static const uint8_t stringIserialDescriptor[] = {
0x16, /*bLength*/
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
'0',0,'1',0,'2',0,'3',0,'4',0,'5',0,'6',0,'7',0,'8',0,'9',0, /*bString iSerial - 0123456789*/
@ -977,8 +960,8 @@ uint8_t * USBDevice::stringIserialDesc() {
return stringIserialDescriptor;
}
uint8_t * USBDevice::stringIConfigurationDesc() {
static uint8_t stringIconfigurationDescriptor[] = {
const uint8_t * USBDevice::stringIConfigurationDesc() {
static const uint8_t stringIconfigurationDescriptor[] = {
0x06, /*bLength*/
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
'0',0,'1',0, /*bString iConfiguration - 01*/
@ -986,8 +969,8 @@ uint8_t * USBDevice::stringIConfigurationDesc() {
return stringIconfigurationDescriptor;
}
uint8_t * USBDevice::stringIinterfaceDesc() {
static uint8_t stringIinterfaceDescriptor[] = {
const uint8_t * USBDevice::stringIinterfaceDesc() {
static const uint8_t stringIinterfaceDescriptor[] = {
0x08, /*bLength*/
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
'U',0,'S',0,'B',0, /*bString iInterface - USB*/
@ -995,8 +978,8 @@ uint8_t * USBDevice::stringIinterfaceDesc() {
return stringIinterfaceDescriptor;
}
uint8_t * USBDevice::stringIproductDesc() {
static uint8_t stringIproductDescriptor[] = {
const uint8_t * USBDevice::stringIproductDesc() {
static const uint8_t stringIproductDescriptor[] = {
0x16, /*bLength*/
STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
'U',0,'S',0,'B',0,' ',0,'D',0,'E',0,'V',0,'I',0,'C',0,'E',0 /*bString iProduct - USB DEVICE*/

View File

@ -165,60 +165,60 @@ public:
virtual bool USBCallback_setInterface(uint16_t interface, uint8_t alternate) { return false; };
/*
* Get device descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
* Get device descriptor.
*
* @returns pointer to the device descriptor
*/
virtual uint8_t * deviceDesc();
virtual const uint8_t * deviceDesc();
/*
* Get configuration descriptor
*
* @returns pointer to the configuration descriptor
*/
virtual uint8_t * configurationDesc(){return NULL;};
virtual const uint8_t * configurationDesc(){return NULL;};
/*
* Get string lang id descriptor
*
* @return pointer to the string lang id descriptor
*/
virtual uint8_t * stringLangidDesc();
virtual const uint8_t * stringLangidDesc();
/*
* Get string manufacturer descriptor
*
* @returns pointer to the string manufacturer descriptor
*/
virtual uint8_t * stringImanufacturerDesc();
virtual const uint8_t * stringImanufacturerDesc();
/*
* Get string product descriptor
*
* @returns pointer to the string product descriptor
*/
virtual uint8_t * stringIproductDesc();
virtual const uint8_t * stringIproductDesc();
/*
* Get string serial descriptor
*
* @returns pointer to the string serial descriptor
*/
virtual uint8_t * stringIserialDesc();
virtual const uint8_t * stringIserialDesc();
/*
* Get string configuration descriptor
*
* @returns pointer to the string configuration descriptor
*/
virtual uint8_t * stringIConfigurationDesc();
virtual const uint8_t * stringIConfigurationDesc();
/*
* Get string interface descriptor
*
* @returns pointer to the string interface descriptor
*/
virtual uint8_t * stringIinterfaceDesc();
virtual const uint8_t * stringIinterfaceDesc();
/*
* Get the length of the report descriptor
@ -242,6 +242,7 @@ protected:
uint16_t VENDOR_ID;
uint16_t PRODUCT_ID;
uint16_t PRODUCT_RELEASE;
uint8_t deviceDescriptor[18];
private:
bool addRateFeedbackEndpoint(uint8_t endpoint, uint32_t maxPacket);

View File

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

View File

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

View File

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

View File

@ -148,7 +148,7 @@ public:
*
* @returns pointer to the report descriptor
*/
virtual uint8_t * reportDesc();
virtual const uint8_t * reportDesc();
/*
* Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys
@ -173,7 +173,7 @@ protected:
*
* @returns pointer to the configuration descriptor
*/
virtual uint8_t * configurationDesc();
virtual const uint8_t * configurationDesc();
private:
//dummy otherwise it doesn,t compile (we must define all methods of an abstract class)
@ -181,6 +181,7 @@ private:
return -1;
};
uint8_t configurationDescriptor[41];
uint8_t lock_status;
};

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

View File

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

View File

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

View File

@ -195,7 +195,7 @@ class USBMouseKeyboard: public USBHID, public Stream
*
* @returns pointer to the report descriptor
*/
virtual uint8_t * reportDesc();
virtual const uint8_t * reportDesc();
/*
* Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -22,6 +22,7 @@
#include "fsl_common.h"
#endif
#include "USBHAL.h"
#include "mbed_critical.h"
USBHAL * USBHAL::instance;
@ -64,6 +65,13 @@ typedef struct BDT {
uint32_t address; // Addr
} BDT;
typedef enum {
CTRL_XFER_READY,
CTRL_XFER_IN,
CTRL_XFER_NONE,
CTRL_XFER_OUT
} ctrl_xfer_t;
// there are:
// * 4 bidirectionnal endpt -> 8 physical endpt
// * as there are ODD and EVEN buffer -> 8*2 bdt
@ -73,6 +81,7 @@ uint8_t * endpoint_buffer[NUMBER_OF_PHYSICAL_ENDPOINTS * 2];
static uint8_t set_addr = 0;
static uint8_t addr = 0;
static ctrl_xfer_t ctrl_xfer = CTRL_XFER_READY;
static uint32_t Data1 = 0x55555555;
@ -223,11 +232,16 @@ bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flag
USB_ENDPT_EPRXEN_MASK; // en RX (OUT) tran.
bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket;
bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address = (uint32_t) buf;
bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_OWN_MASK | BD_DTS_MASK;
bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_DTS_MASK;
bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info = 0;
if (log_endpoint == 0) {
// Prepare for setup packet
bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info |= BD_OWN_MASK;
}
}
Data1 |= (1 << endpoint);
// First transfer will be a DATA0 packet
Data1 &= ~(1 << endpoint);
return true;
}
@ -239,13 +253,35 @@ void USBHAL::EP0setup(uint8_t *buffer) {
}
void USBHAL::EP0readStage(void) {
Data1 &= ~1UL; // set DATA0
bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK);
// Not needed
}
void USBHAL::EP0read(void) {
uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0);
bdt[idx].byte_count = MAX_PACKET_SIZE_EP0;
if (ctrl_xfer == CTRL_XFER_READY) {
// Transfer is done so ignore call
return;
}
if (ctrl_xfer == CTRL_XFER_IN) {
ctrl_xfer = CTRL_XFER_READY;
// Control transfer with a data IN stage.
// The next packet received will be the status packet - an OUT packet using DATA1
//
// PROBLEM:
// If a Setup packet is received after status packet of
// a Control In transfer has been received in the RX buffer
// but before the processor has had a chance the prepare
// this buffer for the Setup packet, the Setup packet
// will be dropped.
//
// WORKAROUND:
// Set data toggle to DATA0 so if the status stage of a
// Control In transfer arrives it will be ACKed by hardware
// but will be discarded without filling the RX buffer.
// This allows a subsequent SETUP packet to be stored
// without any processor intervention.
Data1 &= ~1UL; // set DATA0
}
endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
}
uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
@ -255,6 +291,15 @@ uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
}
void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
if (ctrl_xfer == CTRL_XFER_READY) {
// Transfer is done so ignore call
return;
}
if ((ctrl_xfer == CTRL_XFER_NONE) || (ctrl_xfer == CTRL_XFER_OUT)) {
// Prepare for next setup packet
endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
ctrl_xfer = CTRL_XFER_READY;
}
endpointWrite(EP0IN, buffer, size);
}
@ -262,13 +307,34 @@ void USBHAL::EP0getWriteResult(void) {
}
void USBHAL::EP0stall(void) {
if (ctrl_xfer == CTRL_XFER_READY) {
// Transfer is done so ignore call
return;
}
ctrl_xfer = CTRL_XFER_READY;
core_util_critical_section_enter();
stallEndpoint(EP0OUT);
// Prepare for next setup packet
// Note - time between stalling and setting up the endpoint
// must be kept to a minimum to prevent a dropped SETUP
// packet.
endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
core_util_critical_section_exit();
}
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
endpoint = PHY_TO_LOG(endpoint);
uint32_t idx = EP_BDT_IDX(endpoint, RX, 0);
uint8_t log_endpoint = PHY_TO_LOG(endpoint);
uint32_t idx = EP_BDT_IDX(log_endpoint, RX, 0);
bdt[idx].byte_count = maximumSize;
if ((Data1 >> endpoint) & 1) {
bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
}
else {
bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
}
Data1 ^= (1 << endpoint);
return EP_PENDING;
}
@ -307,18 +373,14 @@ EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_
buffer[n] = ep_buf[n];
}
if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) {
if (setup && (buffer[6] == 0)) // if no setup data stage,
Data1 &= ~1UL; // set DATA0
else
Data1 ^= (1 << endpoint);
}
if (((Data1 >> endpoint) & 1)) {
bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK;
}
else {
bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK;
if (setup) {
// Record the setup type
if (buffer[6] == 0) {
ctrl_xfer = CTRL_XFER_NONE;
} else {
uint8_t in_xfer = (buffer[0] >> 7) & 1;
ctrl_xfer = in_xfer ? CTRL_XFER_IN : CTRL_XFER_OUT;
}
}
USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
@ -351,9 +413,9 @@ EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
}
if ((Data1 >> endpoint) & 1) {
bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
} else {
bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
} else {
bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
}
Data1 ^= (1 << endpoint);
@ -438,7 +500,7 @@ void USBHAL::usbisr(void) {
if (istat & 1<<7) {
if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK)
USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
USB0->ISTAT |= USB_ISTAT_STALL_MASK;
USB0->ISTAT = USB_ISTAT_STALL_MASK;
}
// token interrupt
@ -450,7 +512,7 @@ void USBHAL::usbisr(void) {
// setup packet
if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) {
Data1 &= ~0x02;
Data1 |= 0x02 | 0x01; // set DATA1 for TX and RX
bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK;
bdt[EP_BDT_IDX(0, TX, ODD)].info &= ~BD_OWN_MASK;
@ -493,13 +555,13 @@ void USBHAL::usbisr(void) {
// sleep interrupt
if (istat & 1<<4) {
USB0->ISTAT |= USB_ISTAT_SLEEP_MASK;
USB0->ISTAT = USB_ISTAT_SLEEP_MASK;
}
// error interrupt
if (istat & USB_ISTAT_ERROR_MASK) {
USB0->ERRSTAT = 0xFF;
USB0->ISTAT |= USB_ISTAT_ERROR_MASK;
USB0->ISTAT = USB_ISTAT_ERROR_MASK;
}
}

View File

@ -275,11 +275,6 @@ uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
LPC_USB->USBCtrl = 0;
if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
SIEselectEndpoint(endpoint);
SIEclearBuffer();
}
return size;
}
@ -431,7 +426,7 @@ void USBHAL::EP0setup(uint8_t *buffer) {
}
void USBHAL::EP0read(void) {
// Not required
endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
}
void USBHAL::EP0readStage(void) {
@ -456,6 +451,11 @@ void USBHAL::EP0stall(void) {
}
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
// Don't clear isochronous endpoints
if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
SIEselectEndpoint(endpoint);
SIEclearBuffer();
}
return EP_PENDING;
}
@ -590,6 +590,25 @@ void USBHAL::usbisr(void) {
if (LPC_USB->USBDevIntSt & EP_SLOW) {
// (Slow) Endpoint Interrupt
// Process IN packets before SETUP packets
// Note - order of OUT and SETUP does not matter as OUT packets
// are clobbered by SETUP packets and thus ignored.
//
// A SETUP packet can arrive at any time where as an IN packet is
// only sent after calling EP0write and an OUT packet after EP0read.
// The functions EP0write and EP0read are called only in response to
// a setup packet or IN/OUT packets sent in response to that
// setup packet. Therefore, if an IN or OUT packet is pending
// at the same time as a SETUP packet, the IN or OUT packet belongs
// to the previous control transfer and should either be processed
// before the SETUP packet (in the case of IN) or dropped (in the
// case of OUT as SETUP clobbers the OUT data).
if (LPC_USB->USBEpIntSt & EP(EP0IN)) {
selectEndpointClearInterrupt(EP0IN);
LPC_USB->USBDevIntClr = EP_SLOW;
EP0in();
}
// Process each endpoint interrupt
if (LPC_USB->USBEpIntSt & EP(EP0OUT)) {
if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
@ -601,12 +620,6 @@ void USBHAL::usbisr(void) {
LPC_USB->USBDevIntClr = EP_SLOW;
}
if (LPC_USB->USBEpIntSt & EP(EP0IN)) {
selectEndpointClearInterrupt(EP0IN);
LPC_USB->USBDevIntClr = EP_SLOW;
EP0in();
}
for (uint8_t num = 2; num < 16*2; num++) {
if (LPC_USB->USBEpIntSt & EP(num)) {
selectEndpointClearInterrupt(num);

View File

@ -276,11 +276,6 @@ uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
LPC_USB->Ctrl = 0;
if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
SIEselectEndpoint(endpoint);
SIEclearBuffer();
}
return size;
}
@ -436,7 +431,7 @@ void USBHAL::EP0setup(uint8_t *buffer) {
}
void USBHAL::EP0read(void) {
// Not required
endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
}
void USBHAL::EP0readStage(void) {
@ -461,6 +456,11 @@ void USBHAL::EP0stall(void) {
}
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
// Don't clear isochronous endpoints
if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
SIEselectEndpoint(endpoint);
SIEclearBuffer();
}
return EP_PENDING;
}
@ -595,6 +595,25 @@ void USBHAL::usbisr(void) {
if (LPC_USB->DevIntSt & EP_SLOW) {
// (Slow) Endpoint Interrupt
// Process IN packets before SETUP packets
// Note - order of OUT and SETUP does not matter as OUT packets
// are clobbered by SETUP packets and thus ignored.
//
// A SETUP packet can arrive at any time where as an IN packet is
// only sent after calling EP0write and an OUT packet after EP0read.
// The functions EP0write and EP0read are called only in response to
// a setup packet or IN/OUT packets sent in response to that
// setup packet. Therefore, if an IN or OUT packet is pending
// at the same time as a SETUP packet, the IN or OUT packet belongs
// to the previous control transfer and should either be processed
// before the SETUP packet (in the case of IN) or dropped (in the
// case of OUT as SETUP clobbers the OUT data).
if (LPC_USB->EpIntSt & EP(EP0IN)) {
selectEndpointClearInterrupt(EP0IN);
LPC_USB->DevIntClr = EP_SLOW;
EP0in();
}
// Process each endpoint interrupt
if (LPC_USB->EpIntSt & EP(EP0OUT)) {
if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
@ -606,12 +625,6 @@ void USBHAL::usbisr(void) {
LPC_USB->DevIntClr = EP_SLOW;
}
if (LPC_USB->EpIntSt & EP(EP0IN)) {
selectEndpointClearInterrupt(EP0IN);
LPC_USB->DevIntClr = EP_SLOW;
EP0in();
}
for (uint8_t num = 2; num < 16*2; num++) {
if (LPC_USB->EpIntSt & EP(num)) {
selectEndpointClearInterrupt(num);

View File

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

View File

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

View File

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

View File

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

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)
{
ticker_event_queue_t *queue = ticker->queue;
uint32_t ticker_time = ticker->interface->read();
if (ticker_time == ticker->queue->tick_last_read) {
@ -252,11 +251,16 @@ static void schedule_interrupt(const ticker_data_t *const ticker)
void ticker_set_handler(const ticker_data_t *const ticker, ticker_event_handler handler)
{
initialize(ticker);
core_util_critical_section_enter();
set_handler(ticker, handler);
core_util_critical_section_exit();
}
void ticker_irq_handler(const ticker_data_t *const ticker)
{
core_util_critical_section_enter();
ticker->interface->clear_interrupt();
/* Go through all the pending TimerEvents */
@ -284,6 +288,8 @@ void ticker_irq_handler(const ticker_data_t *const ticker)
}
schedule_interrupt(ticker);
core_util_critical_section_exit();
}
void ticker_insert_event(const ticker_data_t *const ticker, ticker_event_t *obj, timestamp_t timestamp, uint32_t id)
@ -296,13 +302,14 @@ void ticker_insert_event(const ticker_data_t *const ticker, ticker_event_t *obj,
ticker->queue->present_time,
timestamp
);
core_util_critical_section_exit();
// defer to ticker_insert_event_us
ticker_insert_event_us(
ticker,
obj, absolute_timestamp, id
);
core_util_critical_section_exit();
}
void ticker_insert_event_us(const ticker_data_t *const ticker, ticker_event_t *obj, us_timestamp_t timestamp, uint32_t id)
@ -343,6 +350,7 @@ void ticker_insert_event_us(const ticker_data_t *const ticker, ticker_event_t *o
schedule_interrupt(ticker);
core_util_critical_section_exit();
}
void ticker_remove_event(const ticker_data_t *const ticker, ticker_event_t *obj)
@ -377,7 +385,11 @@ timestamp_t ticker_read(const ticker_data_t *const ticker)
us_timestamp_t ticker_read_us(const ticker_data_t *const ticker)
{
initialize(ticker);
core_util_critical_section_enter();
update_present_time(ticker);
core_util_critical_section_exit();
return ticker->queue->present_time;
}

4
mbed.h
View File

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

View File

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

View File

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

View File

@ -1022,6 +1022,99 @@ extern "C" void __cxa_guard_abort(int *guard_object_p)
#endif
#if defined(MBED_MEM_TRACING_ENABLED) && (defined(__CC_ARM) || defined(__ICCARM__))
// If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp
// provide the implementation for these. Note: this needs to use the wrappers
// instead of malloc()/free() as the caller address would point to wrappers,
// not the caller of "new" or "delete".
extern "C" void* malloc_wrapper(size_t size, const void* caller);
extern "C" void free_wrapper(void *ptr, const void* caller);
void *operator new(std::size_t count)
{
void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR());
if (NULL == buffer) {
error("Operator new out of memory\r\n");
}
return buffer;
}
void *operator new[](std::size_t count)
{
void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR());
if (NULL == buffer) {
error("Operator new[] out of memory\r\n");
}
return buffer;
}
void *operator new(std::size_t count, const std::nothrow_t& tag)
{
return malloc_wrapper(count, MBED_CALLER_ADDR());
}
void *operator new[](std::size_t count, const std::nothrow_t& tag)
{
return malloc_wrapper(count, MBED_CALLER_ADDR());
}
void operator delete(void *ptr)
{
free_wrapper(ptr, MBED_CALLER_ADDR());
}
void operator delete[](void *ptr)
{
free_wrapper(ptr, MBED_CALLER_ADDR());
}
#elif defined(MBED_MEM_TRACING_ENABLED) && defined(__GNUC__)
#include <reent.h>
extern "C" void* malloc_wrapper(struct _reent * r, size_t size, void * caller);
extern "C" void free_wrapper(struct _reent * r, void * ptr, void * caller);
void *operator new(std::size_t count)
{
void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
if (NULL == buffer) {
error("Operator new out of memory\r\n");
}
return buffer;
}
void *operator new[](std::size_t count)
{
void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
if (NULL == buffer) {
error("Operator new[] out of memory\r\n");
}
return buffer;
}
void *operator new(std::size_t count, const std::nothrow_t& tag)
{
return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
}
void *operator new[](std::size_t count, const std::nothrow_t& tag)
{
return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
}
void operator delete(void *ptr)
{
free_wrapper(_REENT, ptr, MBED_CALLER_ADDR());
}
void operator delete[](void *ptr)
{
free_wrapper(_REENT, ptr, MBED_CALLER_ADDR());
}
#else
void *operator new(std::size_t count)
{
void *buffer = malloc(count);
@ -1059,6 +1152,8 @@ void operator delete[](void *ptr)
free(ptr);
}
#endif
/* @brief standard c library clock() function.
*
* This function returns the number of clock ticks elapsed since the start of the program.

View File

@ -118,7 +118,10 @@ struct Waiter;
*/
class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
public:
/** Create and Initialize a ConditionVariable object */
/** Create and Initialize a ConditionVariable object
*
* @note You may call this function from ISR context.
*/
ConditionVariable(Mutex &mutex);
/** Wait for a notification
@ -142,6 +145,8 @@ public:
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
*/
void wait();
@ -176,21 +181,31 @@ public:
*
* mutex.unlock();
* @endcode
*
* @note You cannot call this function from ISR context.
*/
bool wait_for(uint32_t millisec);
/** Notify one waiter on this condition variable that a condition changed.
*
* @note - The thread calling this function must be the owner of the ConditionVariable's mutex
*
* @note This function may be called from ISR context.
*/
void notify_one();
/** Notify all waiters on this condition variable that a condition changed.
*
* @note - The thread calling this function must be the owner of the ConditionVariable's mutex
*
* @note This function may be called from ISR context.
*/
void notify_all();
/** ConditionVariable destructor
*
* @note You may call this function from ISR context.
*/
~ConditionVariable();
protected:

View File

@ -46,29 +46,40 @@ namespace rtos {
*/
class EventFlags : private mbed::NonCopyable<EventFlags> {
public:
/** Create and Initialize a EventFlags object */
/** Create and Initialize an EventFlags object
*
* @note You cannot call this function from ISR context.
*/
EventFlags();
/** Create and Initialize a EventFlags object
@param name name to be used for this EventFlags. It has to stay allocated for the lifetime of the thread.
@note You cannot call this function from ISR context.
*/
EventFlags(const char *name);
/** Set the specified Event Flags.
@param flags specifies the flags that shall be set.
@return event flags after setting or error code if highest bit set (@a osFlagsError).
@note This function may be called from ISR context.
*/
uint32_t set(uint32_t flags);
/** Clear the specified Event Flags.
@param flags specifies the flags that shall be cleared. (default: 0x7fffffff - all flags)
@return event flags before clearing or error code if highest bit set (@a osFlagsError).
@note You may call this function from ISR context.
*/
uint32_t clear(uint32_t flags = 0x7fffffff);
/** Get the currently set Event Flags.
@return set event flags.
@note You may call this function from ISR context.
*/
uint32_t get() const;
@ -77,6 +88,8 @@ public:
@param timeout timeout value or 0 in case of no time-out. (default: osWaitForever)
@param clear specifies wether to clear the flags after waiting for them. (default: true)
@return event flags before clearing or error code if highest bit set (@a osFlagsError).
@note You may call this function from ISR context if the timeout parameter is set to 0.
*/
uint32_t wait_all(uint32_t flags = 0, uint32_t timeout = osWaitForever, bool clear = true);
@ -85,9 +98,15 @@ public:
@param timeout timeout value or 0 in case of no time-out. (default: osWaitForever)
@param clear specifies wether to clear the flags after waiting for them. (default: true)
@return event flags before clearing or error code if highest bit set (@a osFlagsError).
@note This function may be called from ISR context if the timeout parameter is set to 0.
*/
uint32_t wait_any(uint32_t flags = 0, uint32_t timeout = osWaitForever, bool clear = true);
/** Event flags destructor
@note You cannot call this function from ISR context.
*/
~EventFlags();
private:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

@ -37,6 +37,11 @@ uint32_t gpio_set(PinName pin)
return (uint32_t)(1 << pin_index); // Return the pin mask
}
int gpio_is_connected(const gpio_t *obj)
{
return (obj->pin != (PinName) NC);
}
void gpio_init(gpio_t *obj, PinName pin)
{
obj->pin = pin;

View File

@ -37,6 +37,11 @@ uint32_t gpio_set(PinName pin)
return (uint32_t)(1 << pin_index); // Return the pin mask
}
int gpio_is_connected(const gpio_t *obj)
{
return (obj->pin != (PinName) NC);
}
void gpio_init(gpio_t *obj, PinName pin)
{
obj->pin = pin;

View File

@ -34,6 +34,11 @@ uint32_t gpio_set(PinName pin)
return (uint32_t)(1 << pin_index); // Return the pin mask
}
int gpio_is_connected(const gpio_t *obj)
{
return (obj->pin != (PinName) NC);
}
void gpio_init(gpio_t *obj, PinName pin)
{
obj->pin = pin;

View File

@ -37,6 +37,11 @@ uint32_t gpio_set(PinName pin)
return (uint32_t)(1 << pin_index); // Return the pin mask
}
int gpio_is_connected(const gpio_t *obj)
{
return (obj->pin != (PinName) NC);
}
void gpio_init(gpio_t *obj, PinName pin)
{
obj->pin = pin;

View File

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

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,
} UARTName;
// PWMType & 1 == 1 then have to use PWDTR[12] == 1
typedef enum {
PWM1A = 0,
PWM1B,
PWM1C,
PWM1D,
PWM1E,
PWM1F,
PWM1G,
PWM1H,
PWM2A = 0x10,
PWM2B,
PWM2C,
PWM2D,
PWM2E,
PWM2F,
PWM2G,
PWM2H,
} PWMType;
typedef enum {
TIOC0A = 0,
TIOC0B,
TIOC0C,
TIOC0D,
TIOC1A = 0x10,
TIOC1B,
TIOC2A = 0x20,
TIOC2B,
TIOC3A = 0x30,
TIOC3B,
TIOC3C,
TIOC3D,
TIOC4A = 0x40,
TIOC4B,
TIOC4C,
TIOC4D,
} MTU2_PWMType;
typedef enum {
PWM0_PIN = 0,
PWM1_PIN,
PWM2_PIN,
PWM3_PIN,
PWM4_PIN,
PWM5_PIN,
PWM6_PIN,
PWM7_PIN,
PWM8_PIN,
PWM9_PIN,
PWM10_PIN,
PWM11_PIN,
PWM12_PIN,
PWM13_PIN,
MTU2_PWM0_PIN = 0x20,
MTU2_PWM1_PIN,
MTU2_PWM2_PIN,
MTU2_PWM3_PIN,
MTU2_PWM4_PIN,
MTU2_PWM5_PIN,
MTU2_PWM6_PIN,
MTU2_PWM7_PIN,
MTU2_PWM8_PIN,
MTU2_PWM9_PIN,
MTU2_PWM10_PIN,
MTU2_PWM11_PIN,
MTU2_PWM12_PIN,
MTU2_PWM13_PIN,
MTU2_PWM14_PIN,
MTU2_PWM15_PIN,
MTU2_PWM16_PIN,
MTU2_PWM17_PIN,
MTU2_PWM18_PIN,
MTU2_PWM19_PIN,
MTU2_PWM20_PIN,
MTU2_PWM21_PIN,
PWM_PWM1A = 0,
PWM_PWM1B,
PWM_PWM1C,
PWM_PWM1D,
PWM_PWM1E,
PWM_PWM1F,
PWM_PWM1G,
PWM_PWM1H,
PWM_PWM2A,
PWM_PWM2B,
PWM_PWM2C,
PWM_PWM2D,
PWM_PWM2E,
PWM_PWM2F,
PWM_PWM2G,
PWM_PWM2H,
PWM_TIOC0A = 0x20,
PWM_TIOC0C,
PWM_TIOC1A,
PWM_TIOC2A,
PWM_TIOC3A,
PWM_TIOC3C,
PWM_TIOC4A,
PWM_TIOC4C,
} PWMName;
typedef enum {
@ -128,21 +77,22 @@ typedef enum {
SPI_1,
SPI_2,
SPI_3,
SPI_4,
} SPIName;
typedef enum {
I2C_0 = 0,
I2C_1,
I2C_2,
I2C_3
I2C_3,
} I2CName;
typedef enum {
CAN_0 = 0,
CAN_1,
CAN_2,
CAN_3,
CAN_4
CAN_3,
CAN_4,
} CANName;

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,
Port2 = 2,
Port3 = 3,
Port4 = 4
Port4 = 4,
Port5 = 5,
Port6 = 6,
Port7 = 7,
Port8 = 8,
Port9 = 9,
Port10 = 10,
Port11 = 11
} PortName;
#ifdef __cplusplus

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