Merge pull request #5523 from ARMmbed/release-candidate

Release candidate for mbed-os-5.6.5
pull/5540/head
Martin Kojtal 2017-11-20 11:38:30 +00:00 committed by GitHub
commit 34b61d1612
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
427 changed files with 128981 additions and 795 deletions

View File

@ -22,7 +22,10 @@
using namespace utest::v1;
#define TEST_EQUEUE_SIZE 1024
// TEST_EQUEUE_SIZE was reduced below 1024B to fit this test to devices with small RAM (RAM <= 16kB)
// additionally TEST_EQUEUE_SIZE was expressed in EVENTS_EVENT_SIZE to increase readability
// (for more details about EVENTS_EVENT_SIZE see EventQueue constructor)
#define TEST_EQUEUE_SIZE (18*EVENTS_EVENT_SIZE)
// flag for called
volatile bool touched = false;

View File

@ -48,19 +48,22 @@ extern uint32_t SystemCoreClock;
* DELTA = TOLERANCE_FACTOR / SystemCoreClock * US_FACTOR
*
* e.g.
* For K64F DELTA = (40000 / 120000000) * 1000000 = 333[us]
* For NUCLEO_F070RB DELTA = (40000 / 48000000) * 1000000 = 833[us]
* For NRF51_DK DELTA = (40000 / 16000000) * 1000000 = 2500[us]
* For K64F DELTA = (80000 / 120000000) * 1000000 = 666[us]
* For NUCLEO_F070RB DELTA = (80000 / 48000000) * 1000000 = 1666[us]
* For NRF51_DK DELTA = (80000 / 16000000) * 1000000 = 5000[us]
*/
#define US_PER_SEC 1000000
#define TOLERANCE_FACTOR 40000.0f
#define US_PER_MSEC 1000
#define TOLERANCE_FACTOR 80000.0f
#define US_FACTOR 1000000.0f
static const int delta_sys_clk_us = ((int) (TOLERANCE_FACTOR / (float) SystemCoreClock * US_FACTOR));
#define DELTA_US delta_sys_clk_us
#define DELTA_S ((float)delta_sys_clk_us/US_PER_SEC)
#define DELTA_MS 1
/* When test performs time measurement using Timer in sequence, then measurement error accumulates
* in the successive attempts. */
#define DELTA_US(i) (delta_sys_clk_us * i)
#define DELTA_S(i) ((float)delta_sys_clk_us * i / US_PER_SEC)
#define DELTA_MS(i) (1 + ( (i * delta_sys_clk_us) / US_PER_MSEC))
/* This test verifies if low power timer is stopped after
* creation.
@ -75,9 +78,9 @@ void test_lptimer_creation()
/* Check results. */
TEST_ASSERT_EQUAL_FLOAT(0, lp_timer.read());
TEST_ASSERT_EQUAL(0, lp_timer.read_ms());
TEST_ASSERT_EQUAL(0, lp_timer.read_us());
TEST_ASSERT_EQUAL(0, lp_timer.read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(0, lp_timer.read_ms());
TEST_ASSERT_EQUAL_INT32(0, lp_timer.read_us());
TEST_ASSERT_EQUAL_UINT64(0, lp_timer.read_high_resolution_us());
/* Wait 10 ms.
* After that operation timer read routines should still return 0. */
@ -85,9 +88,9 @@ void test_lptimer_creation()
/* Check results. */
TEST_ASSERT_EQUAL_FLOAT(0, lp_timer.read());
TEST_ASSERT_EQUAL(0, lp_timer.read_ms());
TEST_ASSERT_EQUAL(0, lp_timer.read_us());
TEST_ASSERT_EQUAL(0, lp_timer.read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(0, lp_timer.read_ms());
TEST_ASSERT_EQUAL_INT32(0, lp_timer.read_us());
TEST_ASSERT_EQUAL_UINT64(0, lp_timer.read_high_resolution_us());
}
/* This test verifies if read(), read_us(), read_ms(),
@ -115,10 +118,10 @@ void test_lptimer_time_accumulation()
lp_timer.stop();
/* Check results - totally 10 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, 0.010f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, 10, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US, 10000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US, 10000, lp_timer.read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 10, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 10000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 10000, lp_timer.read_high_resolution_us());
/* Wait 50 ms - this is done to show that time elapsed when
* the timer is stopped does not have influence on the
@ -137,10 +140,10 @@ void test_lptimer_time_accumulation()
lp_timer.stop();
/* Check results - totally 30 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(2 * DELTA_S, 0.030f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, 30, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(2 * DELTA_US, 30000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(2 * DELTA_US, 30000, lp_timer.read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(2), 0.030f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(2), 30, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(2), 30000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(2), 30000, lp_timer.read_high_resolution_us());
/* Wait 50 ms - this is done to show that time elapsed when
* the timer is stopped does not have influence on the
@ -158,10 +161,10 @@ void test_lptimer_time_accumulation()
lp_timer.stop();
/* Check results - totally 60 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(3 * DELTA_S, 0.060f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, 60, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(3 * DELTA_US, 60000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(3 * DELTA_US, 60000, lp_timer.read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(3), 0.060f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(3), 60, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(3), 60000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(3), 60000, lp_timer.read_high_resolution_us());
/* Wait 50 ms - this is done to show that time elapsed when
* the timer is stopped does not have influence on the
@ -179,11 +182,11 @@ void test_lptimer_time_accumulation()
/* Stop the timer. */
lp_timer.stop();
/* Check results - totally 5060 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(4 * DELTA_S, 1.060f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, 1060, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(4 * DELTA_US, 1060000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(4 * DELTA_US, 1060000, lp_timer.read_high_resolution_us());
/* Check results - totally 1060 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(4), 1.060f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(4), 1060, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(4), 1060000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(4), 1060000, lp_timer.read_high_resolution_us());
}
/* This test verifies if reset() function resets the
@ -209,10 +212,10 @@ void test_lptimer_reset()
lp_timer.stop();
/* Check results - totally 10 ms elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, 0.010f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, 10, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US, 10000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US, 10000, lp_timer.read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 10, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 10000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 10000, lp_timer.read_high_resolution_us());
/* Reset the timer - previous measured time should be lost now. */
lp_timer.reset();
@ -227,10 +230,10 @@ void test_lptimer_reset()
lp_timer.stop();
/* Check results - 20 ms elapsed since the reset. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, 0.020f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, 20, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US, 20000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US, 20000, lp_timer.read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.020f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 20, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 20000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 20000, lp_timer.read_high_resolution_us());
}
/* This test verifies if calling start() for already
@ -260,10 +263,10 @@ void test_lptimer_start_started_timer()
lp_timer.stop();
/* Check results - 30 ms have elapsed since the first start. */
TEST_ASSERT_FLOAT_WITHIN(2 * DELTA_S, 0.030f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, 30, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(2 * DELTA_US, 30000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(2 * DELTA_US, 30000, lp_timer.read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(2), 0.030f, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(2), 30, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(2), 30000, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(2), 30000, lp_timer.read_high_resolution_us());
}
/* This test verifies low power timer float operator.
@ -287,7 +290,7 @@ void test_lptimer_float_operator()
lp_timer.stop();
/* Check result - 10 ms elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, 0.010f, (float )(lp_timer));
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, (float )(lp_timer));
}
/* This test verifies if time counted by the low power timer is
@ -313,10 +316,10 @@ void test_lptimer_time_measurement()
lp_timer.stop();
/* Check results - wait_val_us us have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, (float )wait_val_us / 1000000, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, wait_val_us / 1000, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US, wait_val_us, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US, wait_val_us, lp_timer.read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), (float )wait_val_us / 1000000, lp_timer.read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), wait_val_us / 1000, lp_timer.read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(1), wait_val_us, lp_timer.read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), wait_val_us, lp_timer.read_high_resolution_us());
}
utest::v1::status_t test_setup(const size_t number_of_cases)

View File

@ -1,24 +1,110 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
/* mbed Microcontroller Library
* Copyright (c) 2013-2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* 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
* 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.
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "utest/utest.h"
#include "unity/unity.h"
/*
* Tests is to measure the accuracy of Ticker over a period of time
*
using utest::v1::Case;
#define ONE_MILLI_SEC 1000
#define TICKER_COUNT 16
#define MULTI_TICKER_TIME_MS 100
volatile uint32_t callback_trigger_count = 0;
static const int test_timeout = 240;
static const int total_ticks = 10;
/* Tolerance is quite arbitrary due to large number of boards with varying level of accuracy */
#define TOLERANCE_US 1000
volatile uint32_t ticker_callback_flag;
volatile uint32_t multi_counter;
DigitalOut led1(LED1);
DigitalOut led2(LED2);
Ticker *volatile ticker1;
Ticker *volatile ticker2;
Timer gtimer;
volatile int ticker_count = 0;
volatile bool print_tick = false;
void ticker_callback_1_switch_to_2(void);
void ticker_callback_2_switch_to_1(void);
void increment_ticker_counter(void)
{
++callback_trigger_count;
}
void switch_led1_state(void)
{
led1 = !led1;
}
void switch_led2_state(void)
{
led2 = !led2;
}
void ticker_callback_1_switch_to_2(void)
{
++callback_trigger_count;
// If ticker is NULL then it is being or has been deleted
if (ticker1) {
ticker1->detach();
ticker1->attach_us(ticker_callback_2_switch_to_1, ONE_MILLI_SEC);
}
switch_led1_state();
}
void ticker_callback_2_switch_to_1(void)
{
++callback_trigger_count;
// If ticker is NULL then it is being or has been deleted
if (ticker2) {
ticker2->detach();
ticker2->attach_us(ticker_callback_1_switch_to_2, ONE_MILLI_SEC);
}
switch_led2_state();
}
void sem_release(Semaphore *sem)
{
sem->release();
}
void stop_gtimer_set_flag(void)
{
gtimer.stop();
core_util_atomic_incr_u32((uint32_t*)&ticker_callback_flag, 1);
}
void increment_multi_counter(void)
{
core_util_atomic_incr_u32((uint32_t*)&multi_counter, 1);
}
/* Tests is to measure the accuracy of Ticker over a period of time
*
* 1) DUT would start to update callback_trigger_count every milli sec, in 2x callback we use 2 tickers
* to update the count alternatively.
@ -28,81 +114,14 @@
* 5) Finally host send the results back to device pass/fail based on tolerance.
* 6) More details on tests can be found in timing_drift_auto.py
*/
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "utest/utest.h"
#include "unity/unity.h"
using namespace utest::v1;
#define ONE_MILLI_SEC 1000
volatile uint32_t callback_trigger_count = 0;
static const int test_timeout = 240;
static const int total_ticks = 10;
DigitalOut led1(LED1);
DigitalOut led2(LED2);
Ticker *volatile ticker1;
Ticker *volatile ticker2;
volatile int ticker_count = 0;
volatile bool print_tick = false;
void ticker_callback_1_switch_to_2(void);
void ticker_callback_2_switch_to_1(void);
void ticker_callback_0(void) {
++callback_trigger_count;
}
void ticker_callback_1_led(void) {
led1 = !led1;
}
void ticker_callback_2_led(void) {
led2 = !led2;
}
void ticker_callback_1_switch_to_2(void) {
++callback_trigger_count;
// If ticker is NULL then it is being or has been deleted
if (ticker1) {
ticker1->detach();
ticker1->attach_us(ticker_callback_2_switch_to_1, ONE_MILLI_SEC);
}
ticker_callback_1_led();
}
void ticker_callback_2_switch_to_1(void) {
++callback_trigger_count;
// If ticker is NULL then it is being or has been deleted
if (ticker2) {
ticker2->detach();
ticker2->attach_us(ticker_callback_1_switch_to_2, ONE_MILLI_SEC);
}
ticker_callback_2_led();
}
void wait_and_print() {
while (ticker_count <= total_ticks) {
if (print_tick) {
print_tick = false;
greentea_send_kv("tick", ticker_count++);
}
}
}
void test_case_1x_ticker() {
void test_case_1x_ticker()
{
char _key[11] = { };
char _value[128] = { };
uint8_t results_size = 0;
int expected_key = 1;
greentea_send_kv("timing_drift_check_start", 0);
ticker1->attach_us(&ticker_callback_0, ONE_MILLI_SEC);
ticker1->attach_us(&increment_ticker_counter, ONE_MILLI_SEC);
// wait for 1st signal from host
do {
@ -119,13 +138,12 @@ void test_case_1x_ticker() {
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
TEST_ASSERT_EQUAL_STRING_MESSAGE("pass", _key,"Host side script reported a fail...");
}
void test_case_2x_callbacks() {
void test_case_2x_callbacks()
{
char _key[11] = { };
char _value[128] = { };
uint8_t results_size = 0;
int expected_key = 1;
led1 = 0;
@ -150,50 +168,198 @@ void test_case_2x_callbacks() {
greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
TEST_ASSERT_EQUAL_STRING_MESSAGE("pass", _key,"Host side script reported a fail...");
}
utest::v1::status_t one_ticker_case_setup_handler_t(const Case *const source, const size_t index_of_case) {
/** Test many tickers run one after the other
Given many Tickers
When schedule them one after the other with the same time intervals
Then tickers properly execute callbacks
When schedule them one after the other with the different time intervals
Then tickers properly execute callbacks
*/
void test_multi_ticker(void)
{
Ticker ticker[TICKER_COUNT];
const uint32_t extra_wait = 5; // extra 5ms wait time
multi_counter = 0;
for (int i = 0; i < TICKER_COUNT; i++) {
ticker[i].attach_us(callback(increment_multi_counter), MULTI_TICKER_TIME_MS * 1000);
}
Thread::wait(MULTI_TICKER_TIME_MS + extra_wait);
for (int i = 0; i < TICKER_COUNT; i++) {
ticker[i].detach();
}
TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter);
multi_counter = 0;
for (int i = 0; i < TICKER_COUNT; i++) {
ticker[i].attach_us(callback(increment_multi_counter), (MULTI_TICKER_TIME_MS + i) * 1000);
}
Thread::wait(MULTI_TICKER_TIME_MS + TICKER_COUNT + extra_wait);
for (int i = 0; i < TICKER_COUNT; i++) {
ticker[i].detach();
}
TEST_ASSERT_EQUAL(TICKER_COUNT, multi_counter);
}
/** Test multi callback time
Given a Ticker
When the callback is attached multiple times
Then ticker properly execute callback multiple times
*/
void test_multi_call_time(void)
{
Ticker ticker;
int time_diff;
const int attach_count = 10;
for (int i = 0; i < attach_count; i++) {
ticker_callback_flag = 0;
gtimer.reset();
gtimer.start();
ticker.attach_us(callback(stop_gtimer_set_flag), MULTI_TICKER_TIME_MS * 1000);
while(!ticker_callback_flag);
time_diff = gtimer.read_us();
TEST_ASSERT_UINT32_WITHIN(TOLERANCE_US, MULTI_TICKER_TIME_MS * 1000, time_diff);
}
}
/** Test if detach cancel scheduled callback event
Given a Ticker with callback attached
When the callback is detached
Then the callback is not being called
*/
void test_detach(void)
{
Ticker ticker;
int32_t ret;
const float ticker_time_s = 0.1f;
const uint32_t wait_time_ms = 500;
Semaphore sem(0, 1);
ticker.attach(callback(sem_release, &sem), ticker_time_s);
ret = sem.wait();
TEST_ASSERT_TRUE(ret > 0);
ret = sem.wait();
ticker.detach(); /* cancel */
TEST_ASSERT_TRUE(ret > 0);
ret = sem.wait(wait_time_ms);
TEST_ASSERT_EQUAL(0, ret);
}
/** Test single callback time via attach
Given a Ticker
When callback attached with time interval specified
Then ticker properly executes callback within a specified time interval
*/
template<us_timestamp_t DELAY_US>
void test_attach_time(void)
{
Ticker ticker;
ticker_callback_flag = 0;
gtimer.reset();
gtimer.start();
ticker.attach(callback(stop_gtimer_set_flag), ((float)DELAY_US) / 1000000.0f);
while(!ticker_callback_flag);
ticker.detach();
const int time_diff = gtimer.read_us();
TEST_ASSERT_UINT64_WITHIN(TOLERANCE_US, DELAY_US, time_diff);
}
/** Test single callback time via attach_us
Given a Ticker
When callback attached with time interval specified
Then ticker properly executes callback within a specified time interval
*/
template<us_timestamp_t DELAY_US>
void test_attach_us_time(void)
{
Ticker ticker;
ticker_callback_flag = 0;
gtimer.reset();
gtimer.start();
ticker.attach_us(callback(stop_gtimer_set_flag), DELAY_US);
while(!ticker_callback_flag);
ticker.detach();
const int time_diff = gtimer.read_us();
TEST_ASSERT_UINT64_WITHIN(TOLERANCE_US, DELAY_US, time_diff);
}
utest::v1::status_t one_ticker_case_setup_handler_t(const Case *const source, const size_t index_of_case)
{
ticker1 = new Ticker();
return greentea_case_setup_handler(source, index_of_case);
}
utest::v1::status_t two_ticker_case_setup_handler_t(const Case *const source, const size_t index_of_case) {
utest::v1::status_t two_ticker_case_setup_handler_t(const Case *const source, const size_t index_of_case)
{
ticker1 = new Ticker();
ticker2 = new Ticker();
return greentea_case_setup_handler(source, index_of_case);
return utest::v1::greentea_case_setup_handler(source, index_of_case);
}
utest::v1::status_t one_ticker_case_teardown_handler_t(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) {
utest::v1::status_t one_ticker_case_teardown_handler_t(const Case *const source, const size_t passed, const size_t failed, const utest::v1::failure_t reason)
{
Ticker *temp1 = ticker1;
ticker1 = NULL;
delete temp1;
return greentea_case_teardown_handler(source, passed, failed, reason);
return utest::v1::greentea_case_teardown_handler(source, passed, failed, reason);
}
utest::v1::status_t two_ticker_case_teardown_handler_t(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) {
utest::v1::status_t two_ticker_case_teardown_handler_t(const Case *const source, const size_t passed, const size_t failed, const utest::v1::failure_t reason)
{
Ticker *temp1 = ticker1;
Ticker *temp2 = ticker2;
ticker1 = NULL;
ticker2 = NULL;
delete temp1;
delete temp2;
return greentea_case_teardown_handler(source, passed, failed, reason);
return utest::v1::greentea_case_teardown_handler(source, passed, failed, reason);
}
// Test cases
Case cases[] = {
Case("Timers: 1x ticker", one_ticker_case_setup_handler_t,test_case_1x_ticker, one_ticker_case_teardown_handler_t),
Case("Timers: 2x callbacks", two_ticker_case_setup_handler_t,test_case_2x_callbacks, two_ticker_case_teardown_handler_t),
Case("Test attach for 0.01s and time measure", test_attach_time<10000>),
Case("Test attach_us for 10ms and time measure", test_attach_us_time<10000>),
Case("Test attach for 0.1s and time measure", test_attach_time<100000>),
Case("Test attach_us for 100ms and time measure", test_attach_us_time<100000>),
Case("Test attach for 0.5s and time measure", test_attach_time<500000>),
Case("Test attach_us for 500ms and time measure", test_attach_us_time<500000>),
Case("Test detach", test_detach),
Case("Test multi call and time measure", test_multi_call_time),
Case("Test multi ticker", test_multi_ticker),
Case("Test timers: 1x ticker", one_ticker_case_setup_handler_t,test_case_1x_ticker, one_ticker_case_teardown_handler_t),
Case("Test timers: 2x callbacks", two_ticker_case_setup_handler_t,test_case_2x_callbacks, two_ticker_case_teardown_handler_t)
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(test_timeout, "timing_drift_auto");
return greentea_test_setup_handler(number_of_cases);
return utest::v1::greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
utest::v1::Specification specification(greentea_test_setup, cases, utest::v1::greentea_test_teardown_handler);
int main() {
Harness::run(specification);
int main()
{
utest::v1::Harness::run(specification);
}

View File

@ -39,19 +39,22 @@ extern uint32_t SystemCoreClock;
* DELTA = TOLERANCE_FACTOR / SystemCoreClock * US_FACTOR
*
* e.g.
* For K64F DELTA = (15000 / 120000000) * 1000000 = 125[us]
* For NUCLEO_F070RB DELTA = (15000 / 48000000) * 1000000 = 312[us]
* For NRF51_DK DELTA = (15000 / 16000000) * 1000000 = 937[us]
* For K64F DELTA = (30000 / 120000000) * 1000000 = 250[us]
* For NUCLEO_F070RB DELTA = (30000 / 48000000) * 1000000 = 625[us]
* For NRF51_DK DELTA = (30000 / 16000000) * 1000000 = 1875[us]
*/
#define US_PER_SEC 1000000
#define TOLERANCE_FACTOR 15000.0f
#define US_PER_MSEC 1000
#define TOLERANCE_FACTOR 30000.0f
#define US_FACTOR 1000000.0f
static const int delta_sys_clk_us = ((int) (TOLERANCE_FACTOR / (float)SystemCoreClock * US_FACTOR));
#define DELTA_US delta_sys_clk_us
#define DELTA_S ((float)delta_sys_clk_us/US_PER_SEC)
#define DELTA_MS 1
/* When test performs time measurement using Timer in sequence, then measurement error accumulates
* in the successive attempts. */
#define DELTA_US(i) (delta_sys_clk_us * i)
#define DELTA_S(i) ((float)delta_sys_clk_us * i / US_PER_SEC)
#define DELTA_MS(i) (1 + ( (i * delta_sys_clk_us) / US_PER_MSEC))
static Timer *p_timer = NULL;
@ -176,9 +179,9 @@ void test_timer_creation_os_ticker()
{
/* Check results. */
TEST_ASSERT_EQUAL_FLOAT(0, p_timer->read());
TEST_ASSERT_EQUAL(0, p_timer->read_ms());
TEST_ASSERT_EQUAL(0, p_timer->read_us());
TEST_ASSERT_EQUAL(0, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(0, p_timer->read_high_resolution_us());
/* Wait 10 ms.
* After that operation timer read routines should still return 0. */
@ -186,9 +189,9 @@ void test_timer_creation_os_ticker()
/* Check results. */
TEST_ASSERT_EQUAL_FLOAT(0, p_timer->read());
TEST_ASSERT_EQUAL(0, p_timer->read_ms());
TEST_ASSERT_EQUAL(0, p_timer->read_us());
TEST_ASSERT_EQUAL(0, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(0, p_timer->read_high_resolution_us());
}
/* This test verifies if timer is stopped after
@ -210,9 +213,9 @@ void test_timer_creation_user_ticker()
/* Check results. */
TEST_ASSERT_EQUAL_FLOAT(0, p_timer->read());
TEST_ASSERT_EQUAL(0, p_timer->read_ms());
TEST_ASSERT_EQUAL(0, p_timer->read_us());
TEST_ASSERT_EQUAL(0, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(0, p_timer->read_high_resolution_us());
/* Simulate that 10 ms has elapsed.
* After that operation timer read routines should still return 0. */
@ -220,9 +223,9 @@ void test_timer_creation_user_ticker()
/* Check results. */
TEST_ASSERT_EQUAL_FLOAT(0, p_timer->read());
TEST_ASSERT_EQUAL(0, p_timer->read_ms());
TEST_ASSERT_EQUAL(0, p_timer->read_us());
TEST_ASSERT_EQUAL(0, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(0, p_timer->read_high_resolution_us());
}
/* This test verifies verifies if read(), read_us(), read_ms(),
@ -254,9 +257,9 @@ void test_timer_time_accumulation_user_ticker()
/* Check results - 1 us has elapsed. */
TEST_ASSERT_EQUAL_FLOAT(0.000001f, p_timer->read());
TEST_ASSERT_EQUAL(0, p_timer->read_ms());
TEST_ASSERT_EQUAL(1, p_timer->read_us());
TEST_ASSERT_EQUAL(1, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(1, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(1, p_timer->read_high_resolution_us());
/* Simulate that 100 us has elapsed between stop and start. */
curr_ticker_us_val = 101;
@ -270,11 +273,11 @@ void test_timer_time_accumulation_user_ticker()
/* Stop the timer. */
p_timer->stop();
/* Check results - 126 us have elapsed. */
/* Check results - 125 us have elapsed. */
TEST_ASSERT_EQUAL_FLOAT(0.000125f, p_timer->read());
TEST_ASSERT_EQUAL(0, p_timer->read_ms());
TEST_ASSERT_EQUAL(125, p_timer->read_us());
TEST_ASSERT_EQUAL(125, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(0, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(125, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(125, p_timer->read_high_resolution_us());
/* Simulate that 100 us has elapsed between stop and start. */
curr_ticker_us_val = 325;
@ -290,9 +293,9 @@ void test_timer_time_accumulation_user_ticker()
/* Check results - 1 ms has elapsed. */
TEST_ASSERT_EQUAL_FLOAT(0.001000f, p_timer->read());
TEST_ASSERT_EQUAL(1, p_timer->read_ms());
TEST_ASSERT_EQUAL(1000, p_timer->read_us());
TEST_ASSERT_EQUAL(1000, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(1, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(1000, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(1000, p_timer->read_high_resolution_us());
/* Simulate that 100 us has elapsed between stop and start. */
curr_ticker_us_val = 1300;
@ -308,9 +311,9 @@ void test_timer_time_accumulation_user_ticker()
/* Check results - 125 ms have elapsed. */
TEST_ASSERT_EQUAL_FLOAT(0.125000f, p_timer->read());
TEST_ASSERT_EQUAL(125, p_timer->read_ms());
TEST_ASSERT_EQUAL(125000, p_timer->read_us());
TEST_ASSERT_EQUAL(125000, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(125, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(125000, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(125000, p_timer->read_high_resolution_us());
/* Simulate that 100 us has elapsed between stop and start. */
curr_ticker_us_val = 125400;
@ -326,9 +329,9 @@ void test_timer_time_accumulation_user_ticker()
/* Check results - 1 s has elapsed. */
TEST_ASSERT_EQUAL_FLOAT(1.000000f, p_timer->read());
TEST_ASSERT_EQUAL(1000, p_timer->read_ms());
TEST_ASSERT_EQUAL(1000000, p_timer->read_us());
TEST_ASSERT_EQUAL(1000000, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(1000, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(1000000, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(1000000, p_timer->read_high_resolution_us());
/* Simulate that 100 us has elapsed between stop and start. */
curr_ticker_us_val = 1000500;
@ -344,9 +347,9 @@ void test_timer_time_accumulation_user_ticker()
/* Check results - 125 s have elapsed. */
TEST_ASSERT_EQUAL_FLOAT(125.000000f, p_timer->read());
TEST_ASSERT_EQUAL(125000, p_timer->read_ms());
TEST_ASSERT_EQUAL(125000000, p_timer->read_us());
TEST_ASSERT_EQUAL(125000000, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(125000, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(125000000, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(125000000, p_timer->read_high_resolution_us());
/* Simulate that 100 us has elapsed between stop and start. */
curr_ticker_us_val = 125000600;
@ -368,9 +371,9 @@ void test_timer_time_accumulation_user_ticker()
/* Check results - 2147483647 (MAX_INT_32) us have elapsed. */
TEST_ASSERT_EQUAL_FLOAT(2147.483647f, p_timer->read());
TEST_ASSERT_EQUAL(2147483, p_timer->read_ms());
TEST_ASSERT_EQUAL(2147483647, p_timer->read_us());
TEST_ASSERT_EQUAL(2147483647, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_INT32(2147483, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(2147483647, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(2147483647, p_timer->read_high_resolution_us());
}
/* This test verifies if read(), read_us(), read_ms(),
@ -398,10 +401,10 @@ void test_timer_time_accumulation_os_ticker()
p_timer->stop();
/* Check results - totally 10 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, 0.010f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, 10, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US, 10000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US, 10000, p_timer->read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 10, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 10000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 10000, p_timer->read_high_resolution_us());
/* Wait 50 ms - this is done to show that time elapsed when
* the timer is stopped does not have influence on the
@ -420,10 +423,10 @@ void test_timer_time_accumulation_os_ticker()
p_timer->stop();
/* Check results - totally 30 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(2 * DELTA_S, 0.030f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(2 * DELTA_MS, 30, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(2 * DELTA_US, 30000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(2 * DELTA_US, 30000, p_timer->read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(2), 0.030f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(2), 30, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(2), 30000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(2), 30000, p_timer->read_high_resolution_us());
/* Wait 50 ms - this is done to show that time elapsed when
* the timer is stopped does not have influence on the
@ -441,10 +444,10 @@ void test_timer_time_accumulation_os_ticker()
p_timer->stop();
/* Check results - totally 60 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(3 * DELTA_S, 0.060f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(3 * DELTA_MS, 60, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(3 * DELTA_US, 60000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(3 * DELTA_US, 60000, p_timer->read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(3), 0.060f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(3), 60, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(3), 60000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(3), 60000, p_timer->read_high_resolution_us());
/* Wait 50 ms - this is done to show that time elapsed when
* the timer is stopped does not have influence on the
@ -463,10 +466,10 @@ void test_timer_time_accumulation_os_ticker()
p_timer->stop();
/* Check results - totally 1060 ms have elapsed. */
TEST_ASSERT_FLOAT_WITHIN(4 * DELTA_S, 1.060f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(4 * DELTA_MS, 1060, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(4 * DELTA_US, 1060000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(4 * DELTA_US, 1060000, p_timer->read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(4), 1.060f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(4), 1060, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(4), 1060000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(4), 1060000, p_timer->read_high_resolution_us());
}
/* This test verifies if reset() function resets the timer
@ -492,10 +495,10 @@ void test_timer_reset_os_ticker()
p_timer->stop();
/* Check results - totally 10 ms elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, 0.010f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, 10, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US, 10000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US, 10000, p_timer->read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 10, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 10000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 10000, p_timer->read_high_resolution_us());
/* Reset the timer - previous measured time should be lost now. */
p_timer->reset();
@ -510,10 +513,10 @@ void test_timer_reset_os_ticker()
p_timer->stop();
/* Check results - 20 ms elapsed since the reset. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, 0.020f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, 20, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US, 20000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US, 20000, p_timer->read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.020f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), 20, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(1), 20000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), 20000, p_timer->read_high_resolution_us());
}
/* This test verifies if reset() function resets the timer
@ -543,10 +546,10 @@ void test_timer_reset_user_ticker()
p_timer->stop();
/* Check results - totally 10 ms elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, 0.010f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, 10, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US, 10000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US, 10000, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_FLOAT(0.010f, p_timer->read());
TEST_ASSERT_EQUAL_INT32(10, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(10000, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(10000, p_timer->read_high_resolution_us());
/* Reset the timer - previous measured time should be lost now. */
p_timer->reset();
@ -561,10 +564,10 @@ void test_timer_reset_user_ticker()
p_timer->stop();
/* Check results - 20 ms elapsed since the reset. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, 0.020f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, 20, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US, 20000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US, 20000, p_timer->read_high_resolution_us());
TEST_ASSERT_EQUAL_FLOAT(0.020f, p_timer->read());
TEST_ASSERT_EQUAL_INT32(20, p_timer->read_ms());
TEST_ASSERT_EQUAL_INT32(20000, p_timer->read_us());
TEST_ASSERT_EQUAL_UINT64(20000, p_timer->read_high_resolution_us());
}
/* This test verifies if calling start() for already
@ -594,10 +597,10 @@ void test_timer_start_started_timer_os_ticker()
p_timer->stop();
/* Check results - 30 ms have elapsed since the first start. */
TEST_ASSERT_FLOAT_WITHIN(2 * DELTA_S, 0.030f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(2 * DELTA_MS, 30, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(2 * DELTA_US, 30000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(2 * DELTA_US, 30000, p_timer->read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(2), 0.030f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(2), 30, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(2), 30000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(2), 30000, p_timer->read_high_resolution_us());
}
/* This test verifies if calling start() for already
@ -631,10 +634,10 @@ void test_timer_start_started_timer_user_ticker()
p_timer->stop();
/* Check results - 30 ms have elapsed since the first start. */
TEST_ASSERT_FLOAT_WITHIN(2 * DELTA_S, 0.030f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(2 * DELTA_MS, 30, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(2 * DELTA_US, 30000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(2 * DELTA_US, 30000, p_timer->read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(2), 0.030f, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(2), 30, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(2), 30000, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(2), 30000, p_timer->read_high_resolution_us());
}
/* This test verifies Timer float operator.
@ -658,7 +661,7 @@ void test_timer_float_operator_os_ticker()
p_timer->stop();
/* Check result - 10 ms elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, 0.010f, (float)(*p_timer));
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), 0.010f, (float)(*p_timer));
}
/* This test verifies Timer float operator.
@ -686,7 +689,7 @@ void test_timer_float_operator_user_ticker()
p_timer->stop();
/* Check result - 10 ms elapsed. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, 0.010f, (float)(*p_timer));
TEST_ASSERT_EQUAL_FLOAT(0.010f, (float)(*p_timer));
}
/* This test verifies if time counted by the timer is
@ -713,10 +716,10 @@ void test_timer_time_measurement()
p_timer->stop();
/* Check results. */
TEST_ASSERT_FLOAT_WITHIN(DELTA_S, (float)wait_val_us / 1000000, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS, wait_val_us / 1000, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US, wait_val_us, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US, wait_val_us, p_timer->read_high_resolution_us());
TEST_ASSERT_FLOAT_WITHIN(DELTA_S(1), (float)wait_val_us / 1000000, p_timer->read());
TEST_ASSERT_INT32_WITHIN(DELTA_MS(1), wait_val_us / 1000, p_timer->read_ms());
TEST_ASSERT_INT32_WITHIN(DELTA_US(1), wait_val_us, p_timer->read_us());
TEST_ASSERT_UINT64_WITHIN(DELTA_US(1), wait_val_us, p_timer->read_high_resolution_us());
}
utest::v1::status_t test_setup(const size_t number_of_cases) {

View File

@ -56,7 +56,7 @@ int main()
{
// static stack for threads to reduce heap usage on devices with small RAM
// and eliminate run out of heap memory problem
MBED_ALIGN(8) uint8_t stack[THREAD_STACK_SIZE * NUM_THREADS];
uint8_t stack[NUM_THREADS][THREAD_STACK_SIZE];
Thread *thread_list[NUM_THREADS];
int test_time = 15;
@ -64,7 +64,7 @@ int main()
// Allocate threads for the test
for (int i = 0; i < NUM_THREADS; i++) {
thread_list[i] = new Thread(osPriorityNormal, THREAD_STACK_SIZE, stack + i * THREAD_STACK_SIZE);
thread_list[i] = new Thread(osPriorityNormal, THREAD_STACK_SIZE, stack[i]);
if (NULL == thread_list[i]) {
allocation_failure = true;
} else {

View File

@ -21,18 +21,55 @@
using namespace utest::v1;
#define TEST_DELAY_MS 50
#define TEST_DELAY2_MS 30
#define TEST_DELAY_MS_DELTA 1
#define TEST_RESTART_DELAY_MS 10
#define DELAY_MS 50
#define DELTA_MS 5
#define RESTART_DELAY_MS 10
#define DELAY2_MS 30
#if TEST_RESTART_DELAY_MS >= TEST_DELAY_MS
#error invalid TEST_RESTART_DELAY_MS value
#if RESTART_DELAY_MS >= DELAY_MS
#error invalid RESTART_DELAY_MS value
#endif
void timer_callback(void const *arg)
class Stopwatch: public Timer {
private:
Semaphore _sem;
public:
Stopwatch() :
Timer(), _sem(1)
{
}
~Stopwatch()
{
}
void start(void)
{
_sem.wait(0);
Timer::start();
}
void stop(void)
{
Timer::stop();
_sem.release();
}
int32_t wait_until_stopped(uint32_t millisec = osWaitForever)
{
core_util_critical_section_enter();
int running = _running;
core_util_critical_section_exit();
if (!running) {
return 1;
}
return _sem.wait(millisec);
}
};
void sem_callback(Semaphore *sem)
{
Semaphore *sem = (Semaphore *) arg;
sem->release();
}
@ -44,14 +81,15 @@ void timer_callback(void const *arg)
* which aborts test program.
*/
#if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED
void error(const char* format, ...) {
void error(const char* format, ...)
{
(void) format;
}
#endif
/** Test one-shot not restarted when elapsed
*
* Given a one-shot timer
* Given a one-shot RtosTimer
* When the timer is started
* and given time elapses
* Then timer stops
@ -60,32 +98,27 @@ void error(const char* format, ...) {
*/
void test_oneshot_not_restarted()
{
Semaphore sem(1);
RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
Stopwatch stopwatch;
RtosTimer rtostimer(mbed::callback(&stopwatch, &Stopwatch::stop), osTimerOnce);
Timer t;
sem.wait(0);
stat = timer.start(TEST_DELAY_MS);
t.start();
TEST_ASSERT_EQUAL(osOK, stat);
stopwatch.start();
osStatus status = rtostimer.start(DELAY_MS);
TEST_ASSERT_EQUAL(osOK, status);
int32_t slots = sem.wait(TEST_DELAY_MS + 1);
t.stop();
int32_t slots = stopwatch.wait_until_stopped();
TEST_ASSERT_EQUAL(1, slots);
TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, TEST_DELAY_MS * 1000, t.read_us());
TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY_MS, stopwatch.read_ms());
stopwatch.start();
slots = sem.wait(TEST_DELAY_MS + 1);
slots = stopwatch.wait_until_stopped(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(0, slots);
stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
}
/** Test periodic repeats continuously
*
* Given a periodic timer
* Given a periodic RtosTimer
* When timer is started
* and given time elapses
* Then timer repeats its operation
@ -94,77 +127,37 @@ void test_oneshot_not_restarted()
*/
void test_periodic_repeats()
{
Semaphore sem(1);
RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerPeriodic);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
Stopwatch stopwatch;
RtosTimer rtostimer(mbed::callback(&stopwatch, &Stopwatch::stop), osTimerPeriodic);
Timer t;
sem.wait(0);
stat = timer.start(TEST_DELAY_MS);
t.start();
TEST_ASSERT_EQUAL(osOK, stat);
stopwatch.start();
osStatus status = rtostimer.start(DELAY_MS);
TEST_ASSERT_EQUAL(osOK, status);
int32_t slots = sem.wait(TEST_DELAY_MS + 1);
int t1 = t.read_us();
int32_t slots = stopwatch.wait_until_stopped();
int t1 = stopwatch.read_ms();
stopwatch.reset();
stopwatch.start();
TEST_ASSERT_EQUAL(1, slots);
TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, TEST_DELAY_MS * 1000, t1);
TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY_MS, t1);
slots = sem.wait(TEST_DELAY_MS + 1);
t.stop();
slots = stopwatch.wait_until_stopped();
TEST_ASSERT_EQUAL(1, slots);
TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, TEST_DELAY_MS * 1000, t.read_us() - t1);
TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY_MS, stopwatch.read_ms());
stopwatch.start();
stat = timer.stop();
TEST_ASSERT_EQUAL(osOK, stat);
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osOK, status);
slots = sem.wait(TEST_DELAY_MS + 1);
slots = stopwatch.wait_until_stopped(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(0, slots);
stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
}
/** Test timer can be restarted
*
* Given a one-shot timer
* When the timer is started
* and @a start is called again before given time elapses
* and given time elapses
* Then timer stops
* and elapsed time is greater than original delay
*/
void test_restart()
{
Semaphore sem(1);
RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
Timer t;
sem.wait(0);
stat = timer.start(TEST_DELAY_MS);
t.start();
TEST_ASSERT_EQUAL(osOK, stat);
int32_t slots = sem.wait(TEST_RESTART_DELAY_MS);
TEST_ASSERT_EQUAL(0, slots);
stat = timer.start(TEST_DELAY_MS);
TEST_ASSERT_EQUAL(osOK, stat);
slots = sem.wait(TEST_DELAY_MS + 1);
t.stop();
TEST_ASSERT_EQUAL(1, slots);
TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, (TEST_DELAY_MS + TEST_RESTART_DELAY_MS) * 1000, t.read_us());
stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
}
/** Test timer can be started again
*
* Given a one-shot timer
* Given a one-shot Rtosimer
* When the timer is started
* and given time elapses
* Then timer stops
@ -174,34 +167,31 @@ void test_restart()
*/
void test_start_again()
{
Semaphore sem(1);
RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
Semaphore sem(0, 1);
RtosTimer rtostimer(mbed::callback(sem_callback, &sem), osTimerOnce);
sem.wait(0);
stat = timer.start(TEST_DELAY_MS);
TEST_ASSERT_EQUAL(osOK, stat);
osStatus status = rtostimer.start(DELAY_MS);
TEST_ASSERT_EQUAL(osOK, status);
int32_t slots = sem.wait(TEST_DELAY_MS + 1);
int32_t slots = sem.wait(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(1, slots);
stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
stat = timer.start(TEST_DELAY_MS);
TEST_ASSERT_EQUAL(osOK, stat);
status = rtostimer.start(DELAY_MS);
TEST_ASSERT_EQUAL(osOK, status);
slots = sem.wait(TEST_DELAY_MS + 1);
slots = sem.wait(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(1, slots);
stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
}
/** Test timer restart updates delay
*
* Given a one-shot timer
* Given a one-shot RtosTimer
* When the timer is started
* and @a start is called again with a different delay before given time elapses
* and updated delay elapses
@ -210,134 +200,127 @@ void test_start_again()
*/
void test_restart_updates_delay()
{
Semaphore sem(1);
RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
Stopwatch stopwatch;
RtosTimer rtostimer(mbed::callback(&stopwatch, &Stopwatch::stop), osTimerOnce);
sem.wait(0);
stat = timer.start(TEST_DELAY_MS);
TEST_ASSERT_EQUAL(osOK, stat);
stopwatch.start();
osStatus status = rtostimer.start(DELAY_MS);
TEST_ASSERT_EQUAL(osOK, status);
int32_t slots = sem.wait(TEST_RESTART_DELAY_MS);
int32_t slots = stopwatch.wait_until_stopped(RESTART_DELAY_MS);
TEST_ASSERT_EQUAL(0, slots);
Timer t;
stat = timer.start(TEST_DELAY2_MS);
t.start();
TEST_ASSERT_EQUAL(osOK, stat);
stopwatch.reset();
stopwatch.start();
status = rtostimer.start(DELAY2_MS);
TEST_ASSERT_EQUAL(osOK, status);
slots = sem.wait(TEST_DELAY2_MS + 1);
t.stop();
slots = stopwatch.wait_until_stopped();
TEST_ASSERT_EQUAL(1, slots);
TEST_ASSERT_INT_WITHIN(TEST_DELAY_MS_DELTA * 1000, TEST_DELAY2_MS * 1000, t.read_us());
TEST_ASSERT_INT_WITHIN(DELTA_MS, DELAY2_MS, stopwatch.read_ms());
stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
}
/** Test timer is created in stopped state
*
* Given a one-shot timer
* Given a one-shot RtosTimer
* When the timer has not been started
* Then the timer is stopped
*/
void test_created_stopped()
{
RtosTimer timer(mbed::callback(timer_callback, (void const *) NULL), osTimerOnce);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);
osStatus status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
}
/** Test one-shot can be stopped
*
* Given a one-shot timer
* Given a one-shot RtosTimer
* When the timer is started
* and timer is stopped while still running
* Then timer stops operation
*/
void test_stop()
{
Semaphore sem(1);
RtosTimer timer(mbed::callback(timer_callback, (void const *) &sem), osTimerOnce);
osStatus stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
Semaphore sem(0, 1);
RtosTimer rtostimer(mbed::callback(sem_callback, &sem), osTimerOnce);
sem.wait(0);
stat = timer.start(TEST_DELAY_MS);
TEST_ASSERT_EQUAL(osOK, stat);
osStatus status = rtostimer.start(DELAY_MS);
TEST_ASSERT_EQUAL(osOK, status);
int32_t slots = sem.wait(TEST_RESTART_DELAY_MS);
int32_t slots = sem.wait(RESTART_DELAY_MS);
TEST_ASSERT_EQUAL(0, slots);
stat = timer.stop();
TEST_ASSERT_EQUAL(osOK, stat);
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osOK, status);
slots = sem.wait(TEST_DELAY_MS + 1);
slots = sem.wait(DELAY_MS + DELTA_MS);
TEST_ASSERT_EQUAL(0, slots);
stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
}
/** Test timer started with infinite delay
*
* Given a one-shot timer
* Given a one-shot RtosTimer
* When the timer is started with @a osWaitForever delay
* Then @a start return status is @a osOK
*/
void test_wait_forever()
{
RtosTimer timer(mbed::callback(timer_callback, (void const *) NULL), osTimerOnce);
RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);
osStatus stat = timer.start(osWaitForever);
TEST_ASSERT_EQUAL(osOK, stat);
osStatus status = rtostimer.start(osWaitForever);
TEST_ASSERT_EQUAL(osOK, status);
stat = timer.stop();
TEST_ASSERT_EQUAL(osOK, stat);
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osOK, status);
}
/** Test timer started with zero delay
*
* Given a one-shot timer
* Given a one-shot RtosTimer
* When the timer is started with 0 delay
* Then @a start return status is @a osErrorParameter
*/
void test_no_wait()
{
RtosTimer timer(mbed::callback(timer_callback, (void const *) NULL), osTimerOnce);
RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);
osStatus stat = timer.start(0);
TEST_ASSERT_EQUAL(osErrorParameter, stat);
osStatus status = rtostimer.start(0);
TEST_ASSERT_EQUAL(osErrorParameter, status);
stat = timer.stop();
TEST_ASSERT_EQUAL(osErrorResource, stat);
status = rtostimer.stop();
TEST_ASSERT_EQUAL(osErrorResource, status);
}
void timer_isr_call(void const *arg)
void rtostimer_isr_call(RtosTimer *rtostimer)
{
RtosTimer *timer = (RtosTimer *) arg;
osStatus stat = timer->start(TEST_DELAY_MS);
TEST_ASSERT_EQUAL(osErrorISR, stat);
osStatus status = rtostimer->start(DELAY_MS);
TEST_ASSERT_EQUAL(osErrorISR, status);
stat = timer->stop();
TEST_ASSERT_EQUAL(osErrorISR, stat);
status = rtostimer->stop();
TEST_ASSERT_EQUAL(osErrorISR, status);
}
/** Test timer method calls from an ISR fail
*
* Given a one-shot timer
* Given a one-shot RtosTimer
* When a timer method is called from an ISR
* Then method return status is @a osErrorISR
*/
void test_isr_calls_fail()
{
RtosTimer timer(mbed::callback(timer_callback, (void const *) NULL), osTimerOnce);
RtosTimer rtostimer(mbed::callback(sem_callback, (Semaphore *) NULL), osTimerOnce);
Ticker ticker;
ticker.attach(mbed::callback(timer_isr_call, (void const *) &timer), (float) TEST_DELAY_MS / 1000.0);
ticker.attach(mbed::callback(rtostimer_isr_call, &rtostimer), (float) DELAY_MS / 1000.0);
wait_ms(TEST_DELAY_MS + 1);
wait_ms(DELAY_MS + DELTA_MS);
}
utest::v1::status_t test_setup(const size_t number_of_cases)
@ -347,16 +330,15 @@ utest::v1::status_t test_setup(const size_t number_of_cases)
}
Case cases[] = {
Case("Test one-shot not restarted when elapsed", test_oneshot_not_restarted),
Case("Test periodic repeats continuously", test_periodic_repeats),
Case("Test timer can be restarted while running", test_restart),
Case("Test stopped timer can be started again", test_start_again),
Case("Test restart changes timeout", test_restart_updates_delay),
Case("Test can be stopped", test_stop),
Case("Test timer is created in stopped state", test_created_stopped),
Case("Test timer started with infinite delay", test_wait_forever),
Case("Test timer started with zero delay", test_no_wait),
Case("Test calls from ISR fail", test_isr_calls_fail)
Case("One-shot not restarted when elapsed", test_oneshot_not_restarted),
Case("Periodic repeats continuously", test_periodic_repeats),
Case("Stopped timer can be started again", test_start_again),
Case("Restart changes timeout", test_restart_updates_delay),
Case("Timer can be stopped", test_stop),
Case("Timer is created in stopped state", test_created_stopped),
Case("Timer started with infinite delay", test_wait_forever),
Case("Timer started with zero delay", test_no_wait),
Case("Calls from ISR fail", test_isr_calls_fail)
};
Specification specification(test_setup, cases);

View File

@ -105,7 +105,7 @@ void prep_buffer() {
void test_socket_attach() {
// Dispatch event queue
Thread eventThread;
EventQueue queue;
EventQueue queue(4*EVENTS_EVENT_SIZE);
eventThread.start(callback(&queue, &EventQueue::dispatch_forever));
printf("TCP client IP Address is %s\r\n", net->get_ip_address());
@ -139,7 +139,7 @@ void cb_pass() {
void test_socket_detach() {
// Dispatch event queue
Thread eventThread;
EventQueue queue;
EventQueue queue(4*EVENTS_EVENT_SIZE);
eventThread.start(callback(&queue, &EventQueue::dispatch_forever));
printf("TCP client IP Address is %s\r\n", net->get_ip_address());
@ -166,7 +166,7 @@ void test_socket_detach() {
void test_socket_reattach() {
// Dispatch event queue
Thread eventThread;
EventQueue queue;
EventQueue queue(4*EVENTS_EVENT_SIZE);
eventThread.start(callback(&queue, &EventQueue::dispatch_forever));
printf("TCP client IP Address is %s\r\n", net->get_ip_address());

View File

@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = "My Project"
PROJECT_NAME = "Mbed OS Reference"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version

View File

@ -1,4 +1,5 @@
{
"PROJECT_NAME": "Mbed OS Reference",
"ENABLE_PREPROCESSING": "YES",
"MACRO_EXPANSION": "YES",
"EXPAND_ONLY_PREDEF": "NO",

View File

@ -39,6 +39,13 @@
namespace mbed {
/** \addtogroup drivers */
/** Class providing buffered UART communication functionality using separate circular buffer for send and receive channels
*
* @ingroup drivers
*/
class UARTSerial : private SerialBase, public FileHandle, private NonCopyable<UARTSerial> {
public:

View File

@ -14,64 +14,119 @@
* limitations under the License.
*/
#ifndef __BLE_BATTERY_SERVICE_H__
#define __BLE_BATTERY_SERVICE_H__
#ifndef MBED_BLE_BATTERY_SERVICE_H__
#define MBED_BLE_BATTERY_SERVICE_H__
#include "platform/mbed_assert.h"
#include "ble/BLE.h"
/**
* @class BatteryService
* @brief BLE Battery Service. This service displays the battery level from 0% to 100%, represented as an 8bit number.
* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.battery_service.xml
* Battery Level Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.battery_level.xml
*/
* BLE Battery service.
*
* @par purpose
*
* The battery service exposes the charge level of the battery of the device.
* This information is exposed as a percentage from 0% to 100%; a value of 0%
* represents a fully discharged battery, and a value of 100% represents a
* fully charged battery.
*
* Clients can read the current charge level and subscribe to server initiated
* updates of the charge level. The server delivers these updates to the subscribed
* client in a notification packet.
*
* The subscription mechanism is useful to save power; it avoids unecessary data
* traffic between the client and the server, which may be induced by polling the
* battery level characteristic value.
*
* @par usage
*
* When this class is instantiated, it adds a battery service in the GattServer.
*
* The application code can use the function updateBatteryLevel() to update the
* charge level that the service exposes and to notify the subscribed client that the
* value changed.
*
* @note You can find specification of the battery service here:
* https://www.bluetooth.com/specifications/gatt
*
* @important Multiple instances of this battery service are not supported.
*/
class BatteryService {
public:
/**
* @param[in] _ble
* BLE object for the underlying controller.
* @param[in] level
* 8bit batterly level. Usually used to represent percentage of batterly charge remaining.
* Instantiate a battery service.
*
* The construction of a BatteryService adds a GATT battery service in @p
* _ble GattServer and sets the initial charge level of the battery to @p
* level.
*
* @param[in] _ble BLE device which will host the battery service.
* @param[in] level Initial charge level of the battery. It is a percentage
* where 0% means that the battery is fully discharged and 100% means that
* the battery is fully charged.
*/
BatteryService(BLE &_ble, uint8_t level = 100) :
ble(_ble),
batteryLevel(level),
batteryLevelCharacteristic(GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, &batteryLevel, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {
GattCharacteristic *charTable[] = {&batteryLevelCharacteristic};
GattService batteryService(GattService::UUID_BATTERY_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
batteryLevelCharacteristic(
GattCharacteristic::UUID_BATTERY_LEVEL_CHAR,
&batteryLevel,
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY
)
{
MBED_ASSERT(level <= 100);
GattCharacteristic *charTable[] = { &batteryLevelCharacteristic };
GattService batteryService(
GattService::UUID_BATTERY_SERVICE,
charTable,
sizeof(charTable) / sizeof(GattCharacteristic *)
);
ble.addService(batteryService);
}
/**
* @brief Update the battery level with a new value. Valid values lie between 0 and 100,
* anything outside this range will be ignored.
* Update the battery charge level that the service exposes.
*
* @param newLevel
* Update to battery level.
* The server sends a notification of the new value to clients that have
* subscribed to the battery level characteristic updates, and clients
* reading the charge level after the update obtain the updated value.
*
* @param newLevel Charge level of the battery. It is a percentage of the
* remaining charge between 0% and 100%.
*
* @important This function must be called in the execution context of the
* BLE stack.
*/
void updateBatteryLevel(uint8_t newLevel) {
void updateBatteryLevel(uint8_t newLevel)
{
MBED_ASSERT(newLevel <= 100);
batteryLevel = newLevel;
ble.gattServer().write(batteryLevelCharacteristic.getValueHandle(), &batteryLevel, 1);
ble.gattServer().write(
batteryLevelCharacteristic.getValueHandle(),
&batteryLevel,
1
);
}
protected:
/**
* A reference to the underlying BLE instance that this object is attached to.
* The services and characteristics will be registered in this BLE instance.
* Reference to the underlying BLE instance that this object is attached to.
*
* The services and characteristics are registered in the GattServer of
* this BLE instance.
*/
BLE &ble;
/**
* The current battery level represented as an integer from 0% to 100%.
*/
uint8_t batteryLevel;
uint8_t batteryLevel;
/**
* A ReadOnlyGattCharacteristic that allows access to the peer device to the
* batteryLevel value through BLE.
* The GATT characteristic, which exposes the charge level.
*/
ReadOnlyGattCharacteristic<uint8_t> batteryLevelCharacteristic;
};
#endif /* #ifndef __BLE_BATTERY_SERVICE_H__*/
#endif /* #ifndef MBED_BLE_BATTERY_SERVICE_H__*/

View File

@ -153,7 +153,7 @@ struct lpc_enetdata {
# define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned))
# endif
#elif defined(TARGET_LPC17XX)
# if defined(TOOLCHAIN_GCC_ARM)
# if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_ARM)
# define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned))
# endif
#endif

View File

@ -0,0 +1,61 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "stm32f4xx_hal.h"
void _eth_config_mac(ETH_HandleTypeDef *heth)
{
ETH_MACInitTypeDef macconf =
{
.Watchdog = ETH_WATCHDOG_ENABLE,
.Jabber = ETH_JABBER_ENABLE,
.InterFrameGap = ETH_INTERFRAMEGAP_96BIT,
.CarrierSense = ETH_CARRIERSENCE_ENABLE,
.ReceiveOwn = ETH_RECEIVEOWN_ENABLE,
.LoopbackMode = ETH_LOOPBACKMODE_DISABLE,
.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE,
.RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE,
.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE,
.BackOffLimit = ETH_BACKOFFLIMIT_10,
.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE,
.ReceiveAll = ETH_RECEIVEAll_DISABLE,
.SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE,
.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL,
.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE,
.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL,
.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE,
.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter
.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT,
.HashTableHigh = 0x0U,
.HashTableLow = 0x0U,
.PauseTime = 0x0U,
.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE,
.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4,
.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE,
.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE,
.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE,
.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT,
.VLANTagIdentifier = 0x0U
};
if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) {
macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;
} else {
macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;
}
(void) HAL_ETH_ConfigMAC(heth, &macconf);
}

View File

@ -0,0 +1,143 @@
#include <string.h>
#include "stm32f4xx_hal.h"
#include "mbed_toolchain.h"
#define C029_OTP_START_ADDRESS (0x1FFF7800U)
#define C029_OTP_END_ADDRESS (C029_OTP_START_ADDRESS + (16*32))
#define C029_MAC_ETHERNET_ID (3)
typedef MBED_PACKED(struct) C029_OTP_Header {
uint8_t id;
uint8_t len;
uint8_t data[];
} C029_OTP_Header;
static int _macRetrieved = 0;
static char _macAddr[6] = { 0x02, 0x02, 0xF7, 0xF0, 0x00, 0x00 };
static C029_OTP_Header *increment(C029_OTP_Header *pTemp)
{
uint8_t len = 0;
uint8_t id = 0;
uint8_t *p = (uint8_t*)pTemp;
memcpy((void*)&id, (void*)pTemp, 1);
if (id == 0xFF){
p++;
} else {
p++;
memcpy((void*)&len, (void*)p++, 1);
p += len;
}
return (C029_OTP_Header*)p;
}
/**
* Override HAL Eth Init function
*/
void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
{
GPIO_InitTypeDef GPIO_InitStructure;
if (heth->Instance == ETH) {
/* Enable GPIOs clocks */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/** ETH GPIO Configuration
RMII_REF_CLK ----------------------> PA1
RMII_MDIO -------------------------> PA2
RMII_MDC --------------------------> PC1
RMII_MII_CRS_DV -------------------> PA7
RMII_MII_RXD0 ---------------------> PC4
RMII_MII_RXD1 ---------------------> PC5
RMII_MII_RXER ---------------------> PG2
RMII_MII_TX_EN --------------------> PB11
RMII_MII_TXD0 ---------------------> PB12
RMII_MII_TXD1 ---------------------> PB13
*/
/* Configure PA1, PA2 and PA7 */
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_7;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = GPIO_PIN_1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure PB13 */
GPIO_InitStructure.Pin = GPIO_PIN_13 | GPIO_PIN_11 | GPIO_PIN_12;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure PC1, PC4 and PC5 */
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Enable the Ethernet global Interrupt */
HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
HAL_NVIC_EnableIRQ(ETH_IRQn);
/* Enable ETHERNET clock */
__HAL_RCC_ETH_CLK_ENABLE();
}
}
/**
* Override HAL Eth DeInit function
*/
void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth)
{
if (heth->Instance == ETH) {
/* Peripheral clock disable */
__HAL_RCC_ETH_CLK_DISABLE();
/** ETH GPIO Configuration
RMII_REF_CLK ----------------------> PA1
RMII_MDIO -------------------------> PA2
RMII_MDC --------------------------> PC1
RMII_MII_CRS_DV -------------------> PA7
RMII_MII_RXD0 ---------------------> PC4
RMII_MII_RXD1 ---------------------> PC5
RMII_MII_RXER ---------------------> PG2
RMII_MII_TX_EN --------------------> PB11
RMII_MII_TXD0 ---------------------> PB12
RMII_MII_TXD1 ---------------------> PB13
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13 | GPIO_PIN_11 | GPIO_PIN_12);
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5);
/* Disable the Ethernet global Interrupt */
NVIC_DisableIRQ(ETH_IRQn);
}
}
uint8_t mbed_otp_mac_address(char *mac)
{
C029_OTP_Header *pFound = NULL;
C029_OTP_Header *pTemp = (C029_OTP_Header*)C029_OTP_START_ADDRESS;
C029_OTP_Header temp;
if (_macRetrieved == 0) {
while ((pTemp >= (C029_OTP_Header*)C029_OTP_START_ADDRESS) && (pTemp < (C029_OTP_Header*)C029_OTP_END_ADDRESS)){
memcpy((void*)&temp, (void*)pTemp, sizeof(temp));
if (temp.id == C029_MAC_ETHERNET_ID){
pFound = pTemp;
break;
}
pTemp = increment(pTemp);
}
if (pFound != NULL) {
memcpy(_macAddr, pFound->data, 6);
_macRetrieved = 1;
}
}
memcpy(mac, _macAddr, 6);
return 1;
}

View File

@ -19,7 +19,7 @@
void _eth_config_mac(ETH_HandleTypeDef *heth)
{
ETH_MACInitTypeDef macconf =
{
{
.Watchdog = ETH_WATCHDOG_ENABLE,
.Jabber = ETH_JABBER_ENABLE,
.InterFrameGap = ETH_INTERFRAMEGAP_96BIT,
@ -48,8 +48,8 @@ void _eth_config_mac(ETH_HandleTypeDef *heth)
.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE,
.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE,
.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT,
.VLANTagIdentifier = 0x0U,
};
.VLANTagIdentifier = 0x0U
};
if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) {
macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;

View File

@ -25,8 +25,7 @@ static C029_OTP_Header *increment(C029_OTP_Header *pTemp)
if (id == 0xFF){
p++;
}
else {
} else {
p++;
memcpy((void*)&len, (void*)p++, 1);
p += len;
@ -59,31 +58,30 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
RMII_MII_TXD0 ---------------------> PB12
RMII_MII_TXD1 ---------------------> PB13
*/
/* Configure PA1, PA2 and PA7 */
/* Configure PA1, PA2 and PA7 */
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_7;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = GPIO_PIN_1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure PB13 */
GPIO_InitStructure.Pin = GPIO_PIN_13 | GPIO_PIN_11 | GPIO_PIN_12;
GPIO_InitStructure.Pin = GPIO_PIN_13 | GPIO_PIN_11 | GPIO_PIN_12;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure PC1, PC4 and PC5 */
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Enable the Ethernet global Interrupt */
HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
HAL_NVIC_EnableIRQ(ETH_IRQn);
/* Enable ETHERNET clock */
__HAL_RCC_ETH_CLK_ENABLE();
}

View File

@ -46,7 +46,8 @@ static sys_mutex_t tx_lock_mutex;
/* function */
static void _eth_arch_rx_task(void *arg);
static void _eth_arch_phy_task(void *arg);
#if defined (TARGET_NUCLEO_F767ZI)
#if defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx)\
|| defined (STM32F779xx)
static void _rmii_watchdog(void *arg);
#endif
@ -375,9 +376,10 @@ static void _eth_arch_phy_task(void *arg)
}
}
#if defined (TARGET_NUCLEO_F767ZI)
#if defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx)\
|| defined (STM32F779xx)
/**
* workaround for the ETH RMII bug in STM32F769 Cut1.0
* workaround for the ETH RMII bug in STM32F76x and STM32F77x revA
*
* \param[in] netif the lwip network interface structure
*/
@ -497,7 +499,8 @@ err_t eth_arch_enetif_init(struct netif *netif)
/* initialize the hardware */
_eth_arch_low_level_init(netif);
#if defined (TARGET_NUCLEO_F767ZI)
#if defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx)\
|| defined (STM32F779xx)
sys_thread_new("stm32_rmii_watchdog", _rmii_watchdog, netif, DEFAULT_THREAD_STACKSIZE, osPriorityLow);
#endif

View File

@ -358,7 +358,6 @@ tcp_close_shutdown_fin(struct tcp_pcb *pcb)
default:
/* Has already been closed, do nothing. */
return ERR_OK;
break;
}
if (err == ERR_OK) {

View File

@ -293,7 +293,9 @@ static int get_ip_addr_type(const ip_addr_t *ip_addr)
return IPADDR_TYPE_V4;
}
#endif
#if LWIP_IPV6 && LWIP_IPV4
return IPADDR_TYPE_ANY;
#endif
}
void add_dns_addr(struct netif *lwip_netif)
@ -658,7 +660,7 @@ nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const cha
if (!netif_is_link_up(&lwip_netif)) {
if (sys_arch_sem_wait(&lwip_netif_linked, 15000) == SYS_ARCH_TIMEOUT) {
if (ppp) {
ppp_lwip_disconnect();
(void) ppp_lwip_disconnect();
}
return NSAPI_ERROR_NO_CONNECTION;
}
@ -686,7 +688,7 @@ nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const cha
if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) {
if (sys_arch_sem_wait(&lwip_netif_has_any_addr, DHCP_TIMEOUT * 1000) == SYS_ARCH_TIMEOUT) {
if (ppp) {
ppp_lwip_disconnect();
(void) ppp_lwip_disconnect();
}
return NSAPI_ERROR_DHCP_FAILURE;
}

View File

@ -0,0 +1,466 @@
/*
* Hardware-accelerated AES implementation for Silicon Labs devices
* containing an AES peripheral.
*
* Copyright 2017, Silicon Laboratories, Inc.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbedtls/aes.h"
#include "em_device.h"
#if defined(AES_PRESENT) && (AES_COUNT == 1)
#if defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_AES_ALT)
#include "em_aes.h"
#include "em_cmu.h"
#include "em_bus.h"
#include <string.h>
#if defined(MBEDTLS_THREADING_C)
#include "mbedtls/threading.h"
#include "em_core.h"
/* Mutex for protecting access to the AES instance */
static mbedtls_threading_mutex_t aes_mutex;
static volatile bool aes_mutex_inited = false;
#endif
static void aes_lock( void )
{
#if defined(MBEDTLS_THREADING_C)
if ( !aes_mutex_inited ) {
/* Turn off interrupts that can cause preemption */
CORE_irqState_t critical_irq_state = CORE_EnterCritical();
if ( !aes_mutex_inited ) {
mbedtls_mutex_init(&aes_mutex);
aes_mutex_inited = true;
}
CORE_ExitCritical(critical_irq_state);
}
mbedtls_mutex_lock(&aes_mutex);
#endif
BUS_RegBitWrite(&(CMU->HFCORECLKEN0), _CMU_HFCORECLKEN0_AES_SHIFT, 1);
return;
}
static void aes_unlock( void )
{
#if defined(MBEDTLS_THREADING_C)
if ( aes_mutex_inited ) {
mbedtls_mutex_unlock(&aes_mutex);
}
#endif
BUS_RegBitWrite(&(CMU->HFCORECLKEN0), _CMU_HFCORECLKEN0_AES_SHIFT, 0);
return;
}
/*
* Initialize AES context
*/
void mbedtls_aes_init( mbedtls_aes_context *ctx )
{
if( ctx == NULL )
return;
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
}
/*
* Clear AES context
*/
void mbedtls_aes_free( mbedtls_aes_context *ctx )
{
if( ctx == NULL )
return;
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
}
/*
* AES key schedule (encryption)
*/
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx,
const unsigned char *key,
unsigned int keybits )
{
if ( ( 128 != keybits ) && ( 256 != keybits ) )
{
/* Unsupported key size */
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
ctx->keybits = keybits;
memcpy( ctx->key, key, keybits/8 );
return 0;
}
/*
* AES key schedule (decryption)
*/
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx,
const unsigned char *key,
unsigned int keybits )
{
if ( ( 128 != keybits ) && ( 256 != keybits ) )
/* Unsupported key size */
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
ctx->keybits = keybits;
switch (keybits)
{
case 128:
aes_lock();
AES_DecryptKey128( ctx->key, key );
aes_unlock();
break;
case 256:
aes_lock();
AES_DecryptKey256( ctx->key, key );
aes_unlock();
break;
default:
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
return 0;
}
/*
* AES-ECB block encryption
*/
int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, input, output);
}
/*
* AES-ECB block decryption
*/
int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_DECRYPT, input, output);
}
/*
* AES-ECB block encryption/decryption
*/
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] )
{
switch ( ctx->keybits )
{
case 128:
aes_lock();
AES_ECB128( output,
input,
16,
ctx->key,
mode == MBEDTLS_AES_ENCRYPT ? true : false );
aes_unlock();
break;
case 256:
aes_lock();
AES_ECB256( output,
input,
16,
ctx->key,
mode == MBEDTLS_AES_ENCRYPT ? true : false );
aes_unlock();
break;
default:
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
}
return( 0 );
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/*
* AES-CBC buffer encryption/decryption
*/
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
uint8_t tmpIv[16];
if( length % 16 )
{
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
}
if ( mode == MBEDTLS_AES_DECRYPT )
{
if ( length >= 16 )
memcpy( tmpIv, &input[length-16], 16 );
}
switch ( ctx->keybits )
{
case 128:
aes_lock();
AES_CBC128( output,
input,
length,
ctx->key,
iv,
mode == MBEDTLS_AES_ENCRYPT ? true : false );
aes_unlock();
break;
case 256:
aes_lock();
AES_CBC256( output,
input,
length,
ctx->key,
iv,
mode == MBEDTLS_AES_ENCRYPT ? true : false );
aes_unlock();
break;
default:
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
}
if ( length >= 16 )
{
if ( mode == MBEDTLS_AES_ENCRYPT )
memcpy( iv, &output[length-16], 16 );
else
memcpy( iv, tmpIv, 16 );
}
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/*
* AES-CFB128 buffer encryption/decryption
*/
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
size_t n = ( iv_off != NULL ) ? *iv_off : 0;
if ( ( n > 0 ) || ( length & 0xf ) )
{
// IV offset or length not aligned to block size
int c;
if( mode == MBEDTLS_AES_DECRYPT )
{
while( length-- )
{
if( n == 0 )
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
c = *input++;
*output++ = (unsigned char)( c ^ iv[n] );
iv[n] = (unsigned char) c;
n = ( n + 1 ) & 0x0F;
}
}
else
{
while( length-- )
{
if( n == 0 )
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
n = ( n + 1 ) & 0x0F;
}
}
if (iv_off)
{
*iv_off = n;
}
return( 0 );
}
else
{
switch( ctx->keybits )
{
case 128:
aes_lock();
AES_CFB128(output,
input,
length,
ctx->key,
iv,
mode == MBEDTLS_AES_ENCRYPT ? true : false );
aes_unlock();
break;
case 256:
aes_lock();
AES_CFB256(output,
input,
length,
ctx->key,
iv,
mode == MBEDTLS_AES_ENCRYPT ? true : false );
aes_unlock();
break;
default:
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
return( 0 );
}
}
/*
* AES-CFB8 buffer encryption/decryption
*/
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
unsigned char c;
unsigned char ov[17];
while( length-- )
{
memcpy( ov, iv, 16 );
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
if( mode == MBEDTLS_AES_DECRYPT )
ov[16] = *input;
c = *output++ = (unsigned char)( iv[0] ^ *input++ );
if( mode == MBEDTLS_AES_ENCRYPT )
ov[16] = c;
memcpy( iv, ov + 1, 16 );
}
return( 0 );
}
#endif /*MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
* AES-CTR Nonce update function
*/
static void aes_ctr_update_nonce( uint8_t *nonce_counter )
{
for( size_t i = 16; i > 0; i-- )
if( ++nonce_counter[i - 1] != 0 )
break;
}
/*
* AES-CTR buffer encryption/decryption
*/
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output )
{
size_t n = ( nc_off != NULL ) ? *nc_off : 0;
if ( ( n > 0 ) || ( length & 0xf ) )
{
// IV offset or length not aligned to block size
int c, i;
while( length-- )
{
if( n == 0 )
{
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
for( i = 16; i > 0; i-- )
if( ++nonce_counter[i - 1] != 0 )
break;
}
c = *input++;
*output++ = (unsigned char)( c ^ stream_block[n] );
n = ( n + 1 ) & 0x0F;
}
if (nc_off)
{
*nc_off = n;
}
return( 0 );
}
else
{
switch( ctx->keybits )
{
case 128:
aes_lock();
AES_CTR128( output,
input,
length,
ctx->key,
nonce_counter,
&aes_ctr_update_nonce );
aes_unlock();
break;
case 256:
aes_lock();
AES_CTR256( output,
input,
length,
ctx->key,
nonce_counter,
&aes_ctr_update_nonce );
aes_unlock();
break;
default:
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
break;
}
return( 0 );
}
}
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#endif /* MBEDTLS_AES_ALT */
#endif /* MBEDTLS_AES_C */
#endif /* AES_PRESENT && (AES_COUNT == 1) */

View File

@ -0,0 +1,318 @@
/*
* AES block cipher
*
* Copyright (C) 2015-2017, Silicon Labs, http://www.silabs.com
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_AES_ALT_H
#define MBEDTLS_AES_ALT_H
/***************************************************************************//**
* \addtogroup sl_crypto
* \{
******************************************************************************/
/***************************************************************************//**
* \addtogroup sl_crypto_aes AES block cipher
* \brief Hardware accelerated AES block cipher.
* \{
******************************************************************************/
#if defined(MBEDTLS_AES_ALT)
/* SiliconLabs CRYPTO hardware acceleration implementation */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief AES context structure
*/
typedef struct
{
unsigned int keybits; /*!< size of key */
unsigned char key[32]; /*!< AES key 128 or 256 bits */
}
mbedtls_aes_context;
/**
* \brief Initialize AES context
*
* \param ctx AES context to be initialized
*/
void mbedtls_aes_init( mbedtls_aes_context *ctx );
/**
* \brief Clear AES context
*
* \param ctx AES context to be cleared
*/
void mbedtls_aes_free( mbedtls_aes_context *ctx );
/**
* \brief AES key schedule (encryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128 or 256
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits );
/**
* \brief AES key schedule (decryption)
*
* \param ctx AES context to be initialized
* \param key decryption key
* \param keybits must be 128 or 256
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits );
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] );
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/**
* \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block
* size (16 bytes)
*
* \note Upon exit, the content of the IV is updated so that you can
* call the same function again on the following block(s) of
* data and get the same result as if it was encrypted in one
* call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
*/
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/**
* \brief AES-CFB128 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief AES-CFB8 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#endif /*MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/**
* \brief AES-CTR buffer encryption/decryption
*
* Warning: You have to keep the maximum use of your counter in mind!
*
* Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \param ctx AES context
* \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to
* should be 0 at the start of a stream.
* \param nonce_counter The 128-bit nonce and counter.
* \param stream_block The saved stream-block for resuming. Is overwritten
* by the function.
* \param input The input data stream
* \param output The output data stream
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CTR */
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see MBEDTLS_AES_ENCRYPT_ALT)
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*
* \return 0 if successful
*/
int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief Internal AES block decryption function
* (Only exposed to allow overriding it,
* see MBEDTLS_AES_DECRYPT_ALT)
*
* \param ctx AES context
* \param input Ciphertext block
* \param output Output (plaintext) block
*
* \return 0 if successful
*/
int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] );
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see MBEDTLS_AES_ENCRYPT_ALT)
*
* \deprecated Superseded by mbedtls_aes_encrypt_ext() in 2.5.0
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*/
MBEDTLS_DEPRECATED static inline void mbedtls_aes_encrypt(
mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
mbedtls_internal_aes_encrypt( ctx, input, output );
}
/**
* \brief Internal AES block decryption function
* (Only exposed to allow overriding it,
* see MBEDTLS_AES_DECRYPT_ALT)
*
* \deprecated Superseded by mbedtls_aes_decrypt_ext() in 2.5.0
*
* \param ctx AES context
* \param input Ciphertext block
* \param output Output (plaintext) block
*/
MBEDTLS_DEPRECATED static inline void mbedtls_aes_decrypt(
mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
mbedtls_internal_aes_decrypt( ctx, input, output );
}
#undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_AES_ALT */
/** \} (end addtogroup sl_crypto_aes) */
/** \} (end addtogroup sl_crypto) */
#endif /* MBEDTLS_AES_ALT_H */

View File

@ -0,0 +1,557 @@
/*
* FIPS-197 compliant AES implementation
*
* Copyright (C) 2017, Silicon Labs, http://www.silabs.com
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This file includes alternative plugin implementations of various
* functions in aes.c using the CRYPTO hardware accelerator incorporated
* in MCU devices from Silicon Laboratories.
*/
/*
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
*
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
*/
#include "mbedtls/aes.h"
#include "em_device.h"
#if defined(CRYPTO_PRESENT)
#if defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_AES_ALT)
#include "crypto_management.h"
#include "em_crypto.h"
#include "em_core.h"
#include <string.h>
__STATIC_INLINE void CRYPTO_DataReadUnaligned(volatile uint32_t * reg,
uint8_t * const val)
{
/* Check data is 32bit aligned, if not, read into temporary buffer and
then move to user buffer. */
if ((uint32_t)val & 0x3)
{
uint32_t temp[4];
CRYPTO_DataRead(reg, temp);
memcpy(val, temp, 16);
}
else
{
CRYPTO_DataRead(reg, (uint32_t* const)val);
}
}
__STATIC_INLINE void CRYPTO_DataWriteUnaligned(volatile uint32_t * reg,
uint8_t * const val)
{
/* Check data is 32bit aligned, if not move to temporary buffer before
writing.*/
if ((uint32_t)val & 0x3)
{
uint32_t temp[4];
memcpy(temp, val, 16);
CRYPTO_DataWrite(reg, temp);
}
else
{
CRYPTO_DataWrite(reg, (uint32_t* const)val);
}
}
/*
* Initialize AES context
*/
void mbedtls_aes_init( mbedtls_aes_context *ctx )
{
if( ctx == NULL ) {
return;
}
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
}
/*
* Clear AES context
*/
void mbedtls_aes_free( mbedtls_aes_context *ctx )
{
if( ctx == NULL ) {
return;
}
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
}
/*
* AES key schedule (encryption)
*/
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx,
const unsigned char *key,
unsigned int keybits )
{
if( ctx == NULL || key == NULL ) {
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
}
if ( ( 128UL != keybits ) && ( 256UL != keybits ) ) {
/* Unsupported key size */
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
ctx->keybits = keybits;
memcpy(ctx->key, key, keybits/8);
return 0;
}
/*
* AES key schedule (decryption)
*/
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx,
const unsigned char *key,
unsigned int keybits )
{
CORE_DECLARE_IRQ_STATE;
if( ctx == NULL || key == NULL ) {
return ( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
}
if ( ( 128UL != keybits ) && ( 256UL != keybits ) ) {
/* Unsupported key size */
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
ctx->keybits = keybits;
CRYPTO_TypeDef *device = crypto_management_acquire();
device->WAC = 0;
device->CTRL = 0;
CORE_ENTER_CRITICAL();
CRYPTO_KeyBufWrite(device, (uint32_t*)key, (keybits == 128) ? cryptoKey128Bits : cryptoKey256Bits);
CORE_EXIT_CRITICAL();
/* Busy-wait here to allow context-switching to occur */
device->CMD = CRYPTO_CMD_INSTR_AESENC;
while ((device->STATUS & CRYPTO_STATUS_INSTRRUNNING) != 0);
CORE_ENTER_CRITICAL();
CRYPTO_KeyRead(device, (uint32_t*)ctx->key, (keybits == 128) ? cryptoKey128Bits : cryptoKey256Bits);
CORE_EXIT_CRITICAL();
crypto_management_release(device);
return 0;
}
/* TODO: underneath these, we should swap out the em_crypto-provided library
* functions with in-place implemented functions, to get much shorter
* critical sections */
/*
* AES-ECB block encryption
*/
int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, input, output);
}
/*
* AES-ECB block decryption
*/
int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_DECRYPT, input, output);
}
/*
* AES-ECB block encryption/decryption
*/
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] )
{
int ret = 0;
CORE_DECLARE_IRQ_STATE;
if( ctx == NULL || input == NULL || output == NULL ) {
return ( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
}
if ( ctx->keybits != 128UL && ctx->keybits != 256UL) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
CRYPTO_TypeDef *device = crypto_management_acquire();
device->WAC = 0;
device->CTRL = 0;
CORE_ENTER_CRITICAL();
CRYPTO_KeyBufWrite(device, (uint32_t*)ctx->key, (ctx->keybits == 128UL) ? cryptoKey128Bits : cryptoKey256Bits);
CRYPTO_DataWriteUnaligned(&device->DATA0, (uint8_t *)input);
CORE_EXIT_CRITICAL();
if ( mode == MBEDTLS_AES_ENCRYPT ) {
device->CMD = CRYPTO_CMD_INSTR_AESENC;
} else {
device->CMD = CRYPTO_CMD_INSTR_AESDEC;
}
while ((device->STATUS & CRYPTO_STATUS_INSTRRUNNING) != 0);
CORE_ENTER_CRITICAL();
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)output);
CORE_EXIT_CRITICAL();
crypto_management_release(device);
return ret;
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/*
* AES-CBC buffer encryption/decryption
*/
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int ret = 0;
CORE_DECLARE_IRQ_STATE;
size_t processed = 0;
if( ctx == NULL || input == NULL || output == NULL || iv == NULL ) {
return ( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
}
/* Input length must be a multiple of 16 bytes which is the AES block
length. */
if( length & 0xf ) {
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
}
if ( ctx->keybits != 128UL && ctx->keybits != 256UL) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
CRYPTO_TypeDef *device = crypto_management_acquire();
device->WAC = 0;
device->CTRL = 0;
CORE_ENTER_CRITICAL();
CRYPTO_KeyBufWrite(device, (uint32_t*)ctx->key, (ctx->keybits == 128UL) ? cryptoKey128Bits : cryptoKey256Bits);
if ( mode == MBEDTLS_AES_ENCRYPT ) {
CRYPTO_DataWriteUnaligned(&device->DATA0, (uint8_t *)iv);
} else {
CRYPTO_DataWriteUnaligned(&device->DATA2, (uint8_t *)iv);
}
CORE_EXIT_CRITICAL();
while ( processed < length ) {
if ( mode == MBEDTLS_AES_ENCRYPT ) {
CORE_ENTER_CRITICAL();
CRYPTO_DataWriteUnaligned(&device->DATA0XOR, (uint8_t *)(&input[processed]));
device->CMD = CRYPTO_CMD_INSTR_AESENC;
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)(&output[processed]));
CORE_EXIT_CRITICAL();
} else {
/* Decrypt input block, XOR IV to decrypted text, set ciphertext as next IV */
CORE_ENTER_CRITICAL();
CRYPTO_DataWriteUnaligned(&device->DATA0, (uint8_t *)(&input[processed]));
CRYPTO_EXECUTE_4( device,
CRYPTO_CMD_INSTR_DATA0TODATA1,
CRYPTO_CMD_INSTR_AESDEC,
CRYPTO_CMD_INSTR_DATA2TODATA0XOR,
CRYPTO_CMD_INSTR_DATA1TODATA2);
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)(&output[processed]));
CORE_EXIT_CRITICAL();
}
processed += 16;
}
if ( processed >= 16 ) {
if ( mode == MBEDTLS_AES_ENCRYPT ) {
memcpy(iv, &output[processed-16], 16);
} else {
CORE_ENTER_CRITICAL();
CRYPTO_DataReadUnaligned(&device->DATA2, (uint8_t *)(iv));
CORE_EXIT_CRITICAL();
}
}
crypto_management_release(device);
return ret;
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/*
* AES-CFB128 buffer encryption/decryption
*/
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
size_t n = iv_off ? *iv_off : 0;
size_t processed = 0;
int ret = 0;
CORE_DECLARE_IRQ_STATE;
if( ctx == NULL || input == NULL || output == NULL || iv == NULL ) {
return ( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
}
if ( ctx->keybits != 128UL && ctx->keybits != 256UL) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
while ( processed < length ) {
if ( n > 0 ) {
/* start by filling up the IV */
if( mode == MBEDTLS_AES_ENCRYPT ) {
iv[n] = output[processed] = (unsigned char)( iv[n] ^ input[processed] );
} else {
int c = input[processed];
output[processed] = (unsigned char)( c ^ iv[n] );
iv[n] = (unsigned char) c;
}
n = ( n + 1 ) & 0x0F;
processed++;
continue;
} else {
/* process one ore more blocks of data */
CRYPTO_TypeDef *device = crypto_management_acquire();
device->WAC = 0;
device->CTRL = 0;
CORE_ENTER_CRITICAL();
CRYPTO_KeyBufWrite(device, (uint32_t*)ctx->key, (ctx->keybits == 128UL) ? cryptoKey128Bits : cryptoKey256Bits);
CRYPTO_DataWriteUnaligned(&device->DATA0, (uint8_t *)iv);
CORE_EXIT_CRITICAL();
/* Encryption: encrypt IV, encIV xor input -> output and IV */
/* Decryption: encrypt IV, encIV xor input -> output, input -> IV */
size_t iterations = (length - processed) / 16;
for (size_t i = 0; i < iterations; i++ ) {
device->CMD = CRYPTO_CMD_INSTR_AESENC;
while ((device->STATUS & CRYPTO_STATUS_INSTRRUNNING) != 0);
CORE_ENTER_CRITICAL();
if ( mode == MBEDTLS_AES_ENCRYPT ) {
CRYPTO_DataWriteUnaligned(&device->DATA0XOR, (uint8_t *)(&input[processed]));
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)(&output[processed]));
} else {
CRYPTO_DataWriteUnaligned(&device->DATA1, (uint8_t *)(&input[processed]));
device->CMD = CRYPTO_CMD_INSTR_DATA1TODATA0XOR;
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)(&output[processed]));
device->CMD = CRYPTO_CMD_INSTR_DATA1TODATA0;
}
CORE_EXIT_CRITICAL();
processed += 16;
}
CORE_ENTER_CRITICAL();
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)iv);
CORE_EXIT_CRITICAL();
while ( length - processed > 0 ) {
if ( n == 0 ) {
device->CMD = CRYPTO_CMD_INSTR_AESENC;
while ((device->STATUS & CRYPTO_STATUS_INSTRRUNNING) != 0);
CORE_ENTER_CRITICAL();
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)iv);
CORE_EXIT_CRITICAL();
}
/* Save remainder to iv */
if( mode == MBEDTLS_AES_ENCRYPT ) {
iv[n] = output[processed] = (unsigned char)( iv[n] ^ input[processed] );
} else {
int c = input[processed];
output[processed] = (unsigned char)( c ^ iv[n] );
iv[n] = (unsigned char) c;
}
n = ( n + 1 ) & 0x0F;
processed++;
}
crypto_management_release(device);
}
}
if ( iv_off ) {
*iv_off = n;
}
return ret;
}
/*
* AES-CFB8 buffer encryption/decryption
*/
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
unsigned char c;
unsigned char ov[17];
int ret = 0;
if( ctx == NULL || input == NULL || output == NULL || iv == NULL ) {
return ( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
}
if ( ctx->keybits != 128UL && ctx->keybits != 256UL) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
while( length-- )
{
memcpy( ov, iv, 16 );
if ( (ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 ) {
return ret;
}
if( mode == MBEDTLS_AES_DECRYPT )
ov[16] = *input;
c = *output++ = (unsigned char)( iv[0] ^ *input++ );
if( mode == MBEDTLS_AES_ENCRYPT )
ov[16] = c;
memcpy( iv, ov + 1, 16 );
}
return ret;
}
#endif /*MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
* AES-CTR buffer encryption/decryption
*/
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output )
{
size_t n = nc_off ? *nc_off : 0;
size_t processed = 0;
int ret = 0;
CORE_DECLARE_IRQ_STATE;
if( ctx == NULL || input == NULL || output == NULL || nonce_counter == NULL || stream_block == NULL ) {
return ( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
}
if ( ctx->keybits != 128UL && ctx->keybits != 256UL) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
while ( processed < length ) {
if ( n > 0 ) {
/* start by filling up the IV */
output[processed] = (unsigned char)( input[processed] ^ stream_block[n] );
n = ( n + 1 ) & 0x0F;
processed++;
continue;
} else {
/* process one ore more blocks of data */
CRYPTO_TypeDef *device = crypto_management_acquire();
device->WAC = 0;
device->CTRL = CRYPTO_CTRL_INCWIDTH_INCWIDTH4;
CORE_ENTER_CRITICAL();
CRYPTO_KeyBufWrite(device, (uint32_t*)ctx->key, (ctx->keybits == 128UL) ? cryptoKey128Bits : cryptoKey256Bits);
CRYPTO_DataWriteUnaligned(&device->DATA1, (uint8_t *)nonce_counter);
CORE_EXIT_CRITICAL();
/* strategy: encrypt nonce, encNonce xor input -> output, inc(nonce) */
size_t iterations = (length - processed) / 16;
for (size_t i = 0; i < iterations; i++ ) {
device->CMD = CRYPTO_CMD_INSTR_DATA1TODATA0;
device->CMD = CRYPTO_CMD_INSTR_AESENC;
while ((device->STATUS & CRYPTO_STATUS_INSTRRUNNING) != 0);
device->CMD = CRYPTO_CMD_INSTR_DATA1INC;
CORE_ENTER_CRITICAL();
CRYPTO_DataWriteUnaligned(&device->DATA0XOR, (uint8_t *)(&input[processed]));
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)(&output[processed]));
CORE_EXIT_CRITICAL();
processed += 16;
}
while ( length - processed > 0 ) {
if ( n == 0 ) {
device->CMD = CRYPTO_CMD_INSTR_DATA1TODATA0;
device->CMD = CRYPTO_CMD_INSTR_AESENC;
while ((device->STATUS & CRYPTO_STATUS_INSTRRUNNING) != 0);
device->CMD = CRYPTO_CMD_INSTR_DATA1INC;
CORE_ENTER_CRITICAL();
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)stream_block);
CORE_EXIT_CRITICAL();
}
/* Save remainder to iv */
output[processed] = (unsigned char)( input[processed] ^ stream_block[n] );
n = ( n + 1 ) & 0x0F;
processed++;
}
CORE_ENTER_CRITICAL();
CRYPTO_DataReadUnaligned(&device->DATA1, (uint8_t *)nonce_counter);
CORE_EXIT_CRITICAL();
crypto_management_release(device);
}
}
if ( nc_off ) {
*nc_off = n;
}
return ret;
}
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#endif /* MBEDTLS_AES_ALT */
#endif /* MBEDTLS_AES_C */
#endif /* CRYPTO_PRESENT */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,403 @@
/*
* Silicon Labs CRYPTO device management interface.
*
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "crypto_management.h"
#include "em_core.h"
#include "em_bus.h"
#if defined( CRYPTO_PRESENT )
/* Conversion macro for compatibility with the 5.3.x release of the Gecko SDK */
#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION )
#warning "MBEDTLS_CRYPTO_DEVICE_PREEMPTION is deprecated, please define " \
"CRYPTO_DEVICE_PREEMPTION instead."
#endif
#if defined( MBEDTLS_THREADING_C )
#include "mbedtls/threading.h"
static mbedtls_threading_mutex_t crypto_locks[CRYPTO_COUNT];
static volatile bool crypto_locks_initialized = false;
static unsigned int acquire_count = 0U;
#endif /* MBEDTLS_THREADING_C */
#if defined( CRYPTO_DEVICE_PREEMPTION )
/** Preemptable context of CRYPTO hardware module. */
typedef struct
{
uint32_t CTRL; /*!< Control Register */
uint32_t WAC; /*!< Wide Arithmetic Configuration */
uint32_t SEQCTRL; /*!< Sequence Control */
uint32_t SEQCTRLB; /*!< Sequence Control B */
uint32_t IEN; /*!< Interrupt Enable Register */
uint32_t SEQ[5]; /*!< Instruction Sequence registers */
CRYPTO_Data260_TypeDef DDATA[5]; /*!< DDATA registers. Covers all data
registers
of CRYPTO, including DATA(128 bit),
DDATA (256bit/260bit),
QDATA (512bit) registers. */
uint32_t regmask; /*!< Bitmask for which registers to save */
uint32_t operands; /*!< Saving the currently selected operands */
bool carry; /*!< Saving the status of the carry flag */
} crypto_context_t;
static crypto_context_t preemption_context;
static bool is_preempted = false;
static CORE_DECLARE_IRQ_STATE;
#endif /* CRYPTO_DEVICE_PREEMPTION */
typedef enum
{
#if defined( CRYPTO0 )
CRYPTO0_ID = 0,
#elif defined( CRYPTO )
CRYPTO_ID = 0,
#endif
#if defined( CRYPTO1 )
CRYPTO1_ID = 1,
#endif
} crypto_instance_number_t;
typedef struct {
CRYPTO_TypeDef *device;
uint32_t clockMask;
} crypto_device_t;
static const crypto_device_t crypto_devices[CRYPTO_COUNT] =
{
#if defined( CRYPTO0 )
{
CRYPTO0,
_CMU_HFBUSCLKEN0_CRYPTO0_SHIFT
},
#elif defined( CRYPTO )
{
CRYPTO,
_CMU_HFBUSCLKEN0_CRYPTO_SHIFT
},
#endif
#if defined( CRYPTO1 )
{
CRYPTO1,
_CMU_HFBUSCLKEN0_CRYPTO1_SHIFT
},
#endif
};
static inline int crypto_management_index_by_device( CRYPTO_TypeDef *device )
{
#if defined( CRYPTO0 )
if ( device == CRYPTO0 ) return 0;
#elif defined( CRYPTO )
if ( device == CRYPTO ) return 0;
#endif
#if defined( CRYPTO1 )
if ( device == CRYPTO1 ) return 1;
#endif
return -1;
}
/* Use bitband for clock enable/disable operations, such that they are atomic */
#define CRYPTO_CLOCK_ENABLE(clk) BUS_RegBitWrite(&(CMU->HFBUSCLKEN0), (clk), 1)
#define CRYPTO_CLOCK_DISABLE(clk) BUS_RegBitWrite(&(CMU->HFBUSCLKEN0), (clk), 0)
#define CRYPTO_CLOCK_ENABLED(clk) BUS_RegBitRead(&(CMU->HFBUSCLKEN0), (clk))
/* Get ownership of an available crypto device */
CRYPTO_TypeDef *crypto_management_acquire( void )
{
CRYPTO_TypeDef *device = NULL;
#if defined( MBEDTLS_THREADING_C )
/* Initialize mutexes if that hasn't happened yet */
CORE_DECLARE_IRQ_STATE;
if ( !crypto_locks_initialized ) {
CORE_ENTER_CRITICAL();
if ( !crypto_locks_initialized ) {
for ( int i = 0; i < CRYPTO_COUNT; i++ ) {
mbedtls_mutex_init(&crypto_locks[i]);
}
crypto_locks_initialized = true;
}
CORE_EXIT_CRITICAL();
}
/* Wrapping this in SL_THREADING_ALT pending non-blocking mutex in official
* threading API. */
#if defined( SL_THREADING_ALT )
/* Try to take an available crypto instance */
unsigned int devno = 0;
for ( ; devno < CRYPTO_COUNT; devno++ ) {
if ( 0 == THREADING_TakeMutexNonBlocking(&crypto_locks[devno]) ) {
device = crypto_devices[devno].device;
break;
}
}
#endif // SL_THREADING_ALT
/* If no device immediately available, do naieve round-robin */
if ( device == NULL ) {
devno = acquire_count % CRYPTO_COUNT;
mbedtls_mutex_lock( &crypto_locks[devno] );
device = crypto_devices[devno].device;
}
/* Doing this outside of critical section is safe, since we own the lock
* and are using bitband to poke the clock enable bit */
CRYPTO_CLOCK_ENABLE( crypto_devices[devno].clockMask );
acquire_count++;
#else // !MBEDTLS_THREADING_C
device = crypto_devices[0].device;
CRYPTO_CLOCK_ENABLE( crypto_devices[0].clockMask );
#endif // MBEDTLS_THREADING_C
return device;
}
/* Get ownership of the default crypto device (CRYPTO0/CRYPTO) */
CRYPTO_TypeDef *crypto_management_acquire_default( void )
{
CRYPTO_TypeDef *device = NULL;
#if defined( MBEDTLS_THREADING_C )
/* Initialize mutexes if that hasn't happened yet */
CORE_DECLARE_IRQ_STATE;
if ( !crypto_locks_initialized ) {
CORE_ENTER_CRITICAL();
if ( !crypto_locks_initialized ) {
for ( int i = 0; i < CRYPTO_COUNT; i++ ) {
mbedtls_mutex_init(&crypto_locks[i]);
}
crypto_locks_initialized = true;
}
CORE_EXIT_CRITICAL();
}
mbedtls_mutex_lock( &crypto_locks[0] );
device = crypto_devices[0].device;
/* Doing this outside of critical section is safe, since we own the lock
* and are using bitband to poke the clock enable bit */
CRYPTO_CLOCK_ENABLE( crypto_devices[0].clockMask );
#else // !MBEDTLS_THREADING_C
device = crypto_devices[0].device;
CRYPTO_CLOCK_ENABLE( crypto_devices[0].clockMask );
#endif // MBEDTLS_THREADING_C
return device;
}
/* Release ownership of an available crypto device */
void crypto_management_release( CRYPTO_TypeDef *device )
{
int devno = crypto_management_index_by_device( device );
if ( devno < 0 ) {
return;
}
/* Doing this outside of critical section is safe, since we still own the lock
* and are using bitband to poke the clock enable bit */
CRYPTO_CLOCK_DISABLE( crypto_devices[devno].clockMask );
#if defined ( MBEDTLS_THREADING_C )
mbedtls_mutex_unlock( &crypto_locks[devno] );
#endif
}
/* Acquire a device with preemption. NOT thread-safe! */
CRYPTO_TypeDef *crypto_management_acquire_preemption( uint32_t regmask )
{
#if defined( CRYPTO_DEVICE_PREEMPTION )
CRYPTO_TypeDef *device = NULL;
/* Turn off interrupts */
CORE_ENTER_CRITICAL();
/* Check if there is an unused CRYPTO instance */
for ( int i = 0; i < CRYPTO_COUNT; i++ ) {
if ( !CRYPTO_CLOCK_ENABLED( crypto_devices[i].clockMask ) ) {
/* Found an unused device */
CRYPTO_CLOCK_ENABLE( crypto_devices[i].clockMask );
device = crypto_devices[i].device;
break;
}
}
/* If there is no unused instance, preempt the last one */
if ( device == NULL ) {
is_preempted = true;
device = crypto_devices[CRYPTO_COUNT - 1].device;
/* In case this instance is still working on anything */
CRYPTO_InstructionSequenceWait(device);
/* Store operational context */
preemption_context.regmask = regmask;
preemption_context.WAC = device->WAC;
preemption_context.CTRL = device->CTRL;
preemption_context.SEQCTRL = device->SEQCTRL;
preemption_context.SEQCTRLB = device->SEQCTRLB;
preemption_context.IEN = device->IEN;
preemption_context.operands = device->CSTATUS;
preemption_context.carry = (device->DSTATUS & CRYPTO_DSTATUS_CARRY) != 0;
if ( (preemption_context.WAC & _CRYPTO_WAC_RESULTWIDTH_MASK) == CRYPTO_WAC_RESULTWIDTH_260BIT)
{
CRYPTO_DData0Read260(device, preemption_context.DDATA[0]); /* Always save DDATA0 because it'll get clobbered in 260-bit mode*/
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA1) != 0 ) {
device->CMD = CRYPTO_CMD_INSTR_DDATA1TODDATA0; /* Move DDATA1 to DDATA0
in order to read. */
CRYPTO_DData0Read260(device, preemption_context.DDATA[1]);
}
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA2) != 0 ) {
device->CMD = CRYPTO_CMD_INSTR_DDATA2TODDATA0; /* Move DDATA2 to DDATA0
in order to read. */
CRYPTO_DData0Read260(device, preemption_context.DDATA[2]);
}
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA3) != 0 ) {
device->CMD = CRYPTO_CMD_INSTR_DDATA3TODDATA0; /* Move DDATA3 to DDATA0
in order to read. */
CRYPTO_DData0Read260(device, preemption_context.DDATA[3]);
}
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA4) != 0 ) {
device->CMD = CRYPTO_CMD_INSTR_DDATA4TODDATA0; /* Move DDATA4 to DDATA0
in order to read. */
CRYPTO_DData0Read260(device, preemption_context.DDATA[4]);
}
}
else
{
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA0) != 0 )
CRYPTO_DDataRead(&device->DDATA0, preemption_context.DDATA[0]);
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA1) != 0 )
CRYPTO_DDataRead(&device->DDATA1, preemption_context.DDATA[1]);
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA2) != 0 )
CRYPTO_DDataRead(&device->DDATA2, preemption_context.DDATA[2]);
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA3) != 0 )
CRYPTO_DDataRead(&device->DDATA3, preemption_context.DDATA[3]);
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA4) != 0 )
CRYPTO_DDataRead(&device->DDATA4, preemption_context.DDATA[4]);
}
/* Search for possible EXEC commands and replace with END. */
for ( size_t j = 0; j < (regmask & 0x7U)*sizeof(uint32_t); j++ ) {
if ( (j & 0x03) == 0 ) {
preemption_context.SEQ[j / sizeof(uint32_t)] = *((&device->SEQ0) + (j / sizeof(uint32_t)));
}
if ( ((uint8_t*)preemption_context.SEQ)[j] == CRYPTO_CMD_INSTR_EXEC ) {
((uint8_t*)preemption_context.SEQ)[j] = CRYPTO_CMD_INSTR_END;
}
}
}
return device;
#else
(void) regmask;
return crypto_management_acquire();
#endif
}
/* Release a device from preemption */
void crypto_management_release_preemption( CRYPTO_TypeDef *device )
{
if ( crypto_management_index_by_device( device ) < 0 ) {
return;
}
#if defined( CRYPTO_DEVICE_PREEMPTION )
if ( is_preempted ) {
/* If we preempted something, put their context back */
device->WAC = preemption_context.WAC;
device->CTRL = preemption_context.CTRL;
device->SEQCTRL = preemption_context.SEQCTRL;
device->SEQCTRLB = preemption_context.SEQCTRLB;
device->IEN = preemption_context.IEN;
if ( (preemption_context.WAC & _CRYPTO_WAC_RESULTWIDTH_MASK) == CRYPTO_WAC_RESULTWIDTH_260BIT)
{
/* Start by writing the DDATA1 value to DDATA0 and move to DDATA1. */
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA1) != 0 ) {
CRYPTO_DData0Write260(device, preemption_context.DDATA[1]);
device->CMD = CRYPTO_CMD_INSTR_DDATA0TODDATA1;
}
/* Write the DDATA2 value to DDATA0 and move to DDATA2. */
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA2) != 0 ) {
CRYPTO_DData0Write260(device, preemption_context.DDATA[2]);
device->CMD = CRYPTO_CMD_INSTR_DDATA0TODDATA2;
}
/* Write the DDATA3 value to DDATA0 and move to DDATA3. */
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA3) != 0 ) {
CRYPTO_DData0Write260(device, preemption_context.DDATA[3]);
device->CMD = CRYPTO_CMD_INSTR_DDATA0TODDATA3;
}
/* Write the DDATA4 value to DDATA0 and move to DDATA4. */
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA4) != 0 ) {
CRYPTO_DData0Write260(device, preemption_context.DDATA[4]);
device->CMD = CRYPTO_CMD_INSTR_DDATA0TODDATA4;
}
/* Finally write DDATA0 */
CRYPTO_DData0Write260(device, preemption_context.DDATA[0]);
}
else
{
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA0) != 0 )
CRYPTO_DDataWrite(&device->DDATA0, preemption_context.DDATA[0]);
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA1) != 0 )
CRYPTO_DDataWrite(&device->DDATA1, preemption_context.DDATA[1]);
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA2) != 0 )
CRYPTO_DDataWrite(&device->DDATA2, preemption_context.DDATA[2]);
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA3) != 0 )
CRYPTO_DDataWrite(&device->DDATA3, preemption_context.DDATA[3]);
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA4) != 0 )
CRYPTO_DDataWrite(&device->DDATA4, preemption_context.DDATA[4]);
}
if (preemption_context.carry) {
device->CMD = CRYPTO_CMD_INSTR_CSET;
} else {
device->CMD = CRYPTO_CMD_INSTR_CCLR;
}
device->CMD = (preemption_context.operands & 0x7U) |
(((preemption_context.operands >> 8) & 0x7U) << 3) |
0xC0;
for (size_t i = 0; i < (preemption_context.regmask & 0x7U); i++ ) {
*((&device->SEQ0) + i) = preemption_context.SEQ[i];
}
is_preempted = false;
} else {
/* If we didn't preempt anything, turn crypto clock back off */
CRYPTO_CLOCK_DISABLE( crypto_devices[crypto_management_index_by_device( device )].clockMask );
}
/* Turn interrupts back on */
CORE_EXIT_CRITICAL();
#else
crypto_management_release(device);
#endif
}
#endif /* CRYPTO_PRESENT */

View File

@ -0,0 +1,128 @@
/*
* Silicon Labs CRYPTO device management interface.
*
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CRYPTO_MANAGEMENT_H
#define CRYPTO_MANAGEMENT_H
/***************************************************************************//**
* \addtogroup sl_crypto
* \{
******************************************************************************/
/***************************************************************************//**
* \addtogroup sl_crypto_management CRYPTO peripheral instance management
* \brief Management functions for CRYPTO peripherals. These functions take care
* of not having two 'owners' simultaneously for the same peripheral,
* potentially messing up the internal state of said peripheral.
* \{
******************************************************************************/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stdlib.h>
#include "em_device.h"
#if defined( CRYPTO_PRESENT )
#include "em_crypto.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Save DDATA0 register when preempting */
#define CRYPTO_MANAGEMENT_SAVE_DDATA0 (0x1U << 3)
/** Save DDATA1 register when preempting */
#define CRYPTO_MANAGEMENT_SAVE_DDATA1 (0x1U << 4)
/** Save DDATA2 register when preempting */
#define CRYPTO_MANAGEMENT_SAVE_DDATA2 (0x1U << 5)
/** Save DDATA3 register when preempting */
#define CRYPTO_MANAGEMENT_SAVE_DDATA3 (0x1U << 6)
/** Save DDATA4 register when preempting */
#define CRYPTO_MANAGEMENT_SAVE_DDATA4 (0x1U << 7)
/** Save SEQ0 register when preempting */
#define CRYPTO_MANAGEMENT_SAVE_UPTO_SEQ0 (0x1U)
/** Save SEQ0 through SEQ1 register when preempting */
#define CRYPTO_MANAGEMENT_SAVE_UPTO_SEQ1 (0x2U)
/** Save SEQ0 through SEQ2 register when preempting */
#define CRYPTO_MANAGEMENT_SAVE_UPTO_SEQ2 (0x3U)
/** Save SEQ0 through SEQ3 register when preempting */
#define CRYPTO_MANAGEMENT_SAVE_UPTO_SEQ3 (0x4U)
/** Save SEQ0 through SEQ4 register when preempting */
#define CRYPTO_MANAGEMENT_SAVE_UPTO_SEQ4 (0x5U)
/**
* \brief Get ownership of a CRYPTO peripheral
*
* \return Handle of assigned CRYPTO peripheral
*/
CRYPTO_TypeDef *crypto_management_acquire( void );
/**
* \brief Get ownership of the default CRYPTO peripheral
*
* \return Handle of default CRYPTO peripheral
*/
CRYPTO_TypeDef *crypto_management_acquire_default( void );
/**
* \brief Release ownership of a CRYPTO peripheral
*
* \param device Handle of CRYPTO peripheral to be released
*/
void crypto_management_release( CRYPTO_TypeDef *device );
/**
* \brief Acquire preempting ownership of a CRYPTO peripheral.
* NOTE: this function is not meant for general use, it
* is not thread-safe, and must be called form the
* highest priority thread/interrupt allowed to use mbed TLS.
*
* \param regmask Bitmask of CRYPTO_MANAGEMENT_ defines instructing what
* parts of the device state will be clobbered during
* preemption.
*
* \return Handle of assigned CRYPTO peripheral
*/
CRYPTO_TypeDef *crypto_management_acquire_preemption( uint32_t regmask );
/**
* \brief Releasing preempting ownership of a CRYPTO peripheral.
* NOTE: this function is not meant for general use, it
* is not thread-safe, and must be called form the
* highest priority thread/interrupt allowed to use mbed TLS.
*
* \param device Handle of preempted CRYPTO peripheral to be released
*/
void crypto_management_release_preemption( CRYPTO_TypeDef *device );
#ifdef __cplusplus
}
#endif
#endif /* CRYPTO_PRESENT */
/** \} (end addtogroup sl_crypto_management) */
/** \} (end addtogroup sl_crypto) */
#endif /* CRYPTO_MANAGEMENT_H */

View File

@ -0,0 +1,467 @@
/*
* FIPS-180-2 compliant SHA-1 & SHA-256 implementation
*
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This file includes an alternative implementation of the standard
* mbedtls/libary/sha[1][256].c using the CRYPTO hardware accelerator incorporated
* in MCU devices from Silicon Laboratories.
*/
/*
* The SHA-1 standard was published by NIST in 1993.
*
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#if ( defined(MBEDTLS_SHA256_ALT) && defined(MBEDTLS_SHA256_C) ) || ( defined(MBEDTLS_SHA1_ALT) && defined (MBEDTLS_SHA1_C) )
#include "em_device.h"
#if defined(CRYPTO_PRESENT)
#include "em_crypto.h"
#include "em_core.h"
#include "crypto_management.h"
#include "em_assert.h"
#include <string.h>
#define CRYPTO_SHA_BLOCK_SIZE (64)
#if defined(MBEDTLS_SHA1_C)
static const uint32_t init_state_sha1[8] =
{
0x67452301UL,
0xEFCDAB89UL,
0x98BADCFEUL,
0x10325476UL,
0xC3D2E1F0UL,
0x0UL,
0x0UL,
0x0UL
};
#endif /* defined(MBEDTLS_SHA1_C) */
#if defined(MBEDTLS_SHA256_C)
static const uint32_t init_state_sha256[8] =
{
0x6A09E667UL,
0xBB67AE85UL,
0x3C6EF372UL,
0xA54FF53AUL,
0x510E527FUL,
0x9B05688CUL,
0x1F83D9ABUL,
0x5BE0CD19UL
};
static const uint32_t init_state_sha224[8] =
{
0xC1059ED8UL,
0x367CD507UL,
0x3070DD17UL,
0xF70E5939UL,
0xFFC00B31UL,
0x68581511UL,
0x64F98FA7UL,
0xBEFA4FA4UL
};
#endif /* defined(MBEDTLS_SHA256_C) */
static const unsigned char sha_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
typedef enum {
#if defined(MBEDTLS_SHA1_C)
CRYPTO_SHA1,
#endif /* defined(MBEDTLS_SHA1_C) */
#if defined(MBEDTLS_SHA256_C)
CRYPTO_SHA2
#endif /* defined(MBEDTLS_SHA256_C) */
} crypto_sha_mode_t;
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
do { \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
} while( 0 )
#endif
/**
* @brief unified SHA acceleration function.
*
* @param[inout] state State context for SHA hashing
* @param[in] data Input block(s). Must contain N blocks
* of SHA1/SHA256 block size (64 bytes)
* @param blocks Amount of blocks pointed to by data
* @param mode SHA operation mode
*/
static void crypto_sha_update_state( uint32_t state[8],
const unsigned char *data,
size_t blocks,
crypto_sha_mode_t mode )
{
CORE_DECLARE_IRQ_STATE;
CRYPTO_TypeDef *crypto = crypto_management_acquire();
switch ( mode ) {
#if defined(MBEDTLS_SHA1_C)
case CRYPTO_SHA1:
crypto->CTRL = CRYPTO_CTRL_SHA_SHA1;
break;
#endif /* defined(MBEDTLS_SHA1_C) */
#if defined(MBEDTLS_SHA256_C)
case CRYPTO_SHA2:
crypto->CTRL = CRYPTO_CTRL_SHA_SHA2;
break;
#endif /* defined(MBEDTLS_SHA256_C) */
}
crypto->WAC = 0;
crypto->IEN = 0;
/* Set result width of MADD32 operation. */
CRYPTO_ResultWidthSet(crypto, cryptoResult256Bits);
/* Clear sequence control registers */
crypto->SEQCTRL = 0;
crypto->SEQCTRLB = 0;
/* Put the state back */
CORE_ENTER_CRITICAL();
CRYPTO_DDataWrite(&crypto->DDATA1, state);
CORE_EXIT_CRITICAL();
CRYPTO_EXECUTE_3( crypto,
CRYPTO_CMD_INSTR_DDATA1TODDATA0,
CRYPTO_CMD_INSTR_DDATA1TODDATA2,
CRYPTO_CMD_INSTR_SELDDATA0DDATA1 );
/* Load the data block(s) */
for ( size_t i = 0; i < blocks; i++ ) {
if ((uint32_t)(&data[i*CRYPTO_SHA_BLOCK_SIZE]) & 0x3)
{
uint32_t temp[CRYPTO_SHA_BLOCK_SIZE/sizeof(uint32_t)];
memcpy(temp, &data[i*CRYPTO_SHA_BLOCK_SIZE], CRYPTO_SHA_BLOCK_SIZE);
CORE_ENTER_CRITICAL();
CRYPTO_QDataWrite(&crypto->QDATA1BIG, temp);
CORE_EXIT_CRITICAL();
}
else
{
CORE_ENTER_CRITICAL();
CRYPTO_QDataWrite(&crypto->QDATA1BIG,
(uint32_t*) &data[i*CRYPTO_SHA_BLOCK_SIZE]);
CORE_EXIT_CRITICAL();
}
/* Process the data block */
CRYPTO_EXECUTE_3( crypto,
CRYPTO_CMD_INSTR_SHA,
CRYPTO_CMD_INSTR_MADD32,
CRYPTO_CMD_INSTR_DDATA0TODDATA1 );
}
CORE_ENTER_CRITICAL();
CRYPTO_DDataRead(&crypto->DDATA0, state);
CORE_EXIT_CRITICAL();
crypto_management_release( crypto );
}
#if defined(MBEDTLS_SHA256_ALT) && defined(MBEDTLS_SHA256_C)
void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
{
if( ctx == NULL ) {
return;
}
memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
}
void mbedtls_sha256_free( mbedtls_sha256_context *ctx )
{
if( ctx == NULL ) {
return;
}
memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
}
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src )
{
if ( dst != NULL && src != NULL ) {
*dst = *src;
}
}
/*
* SHA-256 context setup
*/
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if ( is224 != 0 ) {
ctx->is224 = true;
memcpy(ctx->state, init_state_sha224, sizeof(ctx->state));
} else {
ctx->is224 = false;
memcpy(ctx->state, init_state_sha256, sizeof(ctx->state));
}
}
void mbedtls_sha256_process( mbedtls_sha256_context *ctx,
const unsigned char data[64] )
{
crypto_sha_update_state( ctx->state, data, 1, CRYPTO_SHA2 );
}
/*
* SHA-256 process buffer
*/
void mbedtls_sha256_update( mbedtls_sha256_context *ctx,
const unsigned char *input,
size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen == 0 ) {
return;
}
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen ) {
ctx->total[1]++;
}
if( left && ilen >= fill ) {
memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_sha256_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 ) {
size_t blocks = ilen / 64;
crypto_sha_update_state( ctx->state, input, blocks, CRYPTO_SHA2 );
input += blocks * 64;
ilen -= blocks * 64;
}
if( ilen > 0 ) {
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
}
/*
* SHA-256 final digest
*/
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx,
unsigned char output[32] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_sha256_update( ctx, sha_padding, padn );
mbedtls_sha256_update( ctx, msglen, 8 );
for ( size_t i = 0; i < (ctx->is224 ? 28 : 32); i+=4) {
*((uint32_t*)(&output[i])) = __REV(ctx->state[i >> 2]);
}
}
#endif /* #if defined(MBEDTLS_SHA256_ALT) && defined(MBEDTLS_SHA256_C) */
#if defined(MBEDTLS_SHA1_ALT) && defined(MBEDTLS_SHA1_C)
/**
* \brief Initialize SHA-1 context
*/
void mbedtls_sha1_init( mbedtls_sha1_context *ctx )
{
if( ctx == NULL ) {
return;
}
memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
}
/**
* \brief Clear SHA-1 context
*/
void mbedtls_sha1_free( mbedtls_sha1_context *ctx )
{
if( ctx == NULL ) {
return;
}
memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
}
/**
* \brief Clone (the state of) a SHA-1 context
*/
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
const mbedtls_sha1_context *src )
{
if ( dst != NULL && src != NULL ) {
*dst = *src;
}
}
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
memcpy(ctx->state, init_state_sha1, 32);
}
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
const unsigned char *input,
size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen == 0 ) {
return;
}
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen ) {
ctx->total[1]++;
}
if( left && ilen >= fill ) {
memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_sha1_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 ) {
size_t blocks = ilen / 64;
crypto_sha_update_state( ctx->state, input, blocks, CRYPTO_SHA1 );
input += blocks * 64;
ilen -= blocks * 64;
}
if( ilen > 0 ) {
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
}
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx,
unsigned char output[20] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_sha1_update( ctx, sha_padding, padn );
mbedtls_sha1_update( ctx, msglen, 8 );
for ( size_t i = 0; i < 20; i+=4) {
*((uint32_t*)(&output[i])) = __REV(ctx->state[i >> 2]);
}
}
/* Internal use */
void mbedtls_sha1_process( mbedtls_sha1_context *ctx,
const unsigned char data[64] )
{
crypto_sha_update_state( ctx->state, data, 1, CRYPTO_SHA1 );
}
#endif /* defined(MBEDTLS_SHA1_ALT) && defined(MBEDTLS_SHA1_C) */
#endif /* #if defined(CRYPTO_PRESENT) */
#endif /* #if ( defined(MBEDTLS_SHA256_ALT) && defined(MBEDTLS_SHA256_C) ) || ( defined(MBEDTLS_SHA1_ALT) && defined (MBEDTLS_SHA1_C) ) */

View File

@ -0,0 +1,42 @@
/*
* mbed OS configuration header for mbed TLS HW acceleration
*
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_DEVICE_H
#define MBEDTLS_DEVICE_H
#include "em_device.h"
#if defined ( AES_PRESENT )
#define MBEDTLS_AES_ALT
#endif
#if defined ( CRYPTO_PRESENT )
#define MBEDTLS_AES_ALT
#define MBEDTLS_ECP_INTERNAL_ALT
#define MBEDTLS_ECP_ADD_MIXED_ALT
#define MBEDTLS_ECP_DOUBLE_JAC_ALT
#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT
#define MBEDTLS_SHA1_ALT
#define MBEDTLS_SHA256_ALT
#endif
#endif /* MBEDTLS_DEVICE_H */

View File

@ -0,0 +1,113 @@
/**
* \file sha1_alt.h
*
* \brief SHA-1 cryptographic hash function
*
* Copyright (C) 2015-2016, Silicon Labs, http://www.silabs.com
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_SHA1_ALT_H
#define MBEDTLS_SHA1_ALT_H
/***************************************************************************//**
* \addtogroup sl_crypto
* \{
******************************************************************************/
/***************************************************************************//**
* \addtogroup sl_crypto_sha1 SHA-1 cryptographic hash function
* \brief CRYPTO hardware accelerated SHA-1 cryptographic hash function.
* \{
******************************************************************************/
#if defined(MBEDTLS_SHA1_ALT)
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-1 context structure
*/
typedef struct
{
uint32_t state[8]; /*!< intermediate digest state */
uint32_t total[2]; /*!< number of bytes processed */
unsigned char buffer[64]; /*!< data block being processed */
}
mbedtls_sha1_context;
/**
* \brief Initialize SHA-1 context
*
* \param ctx SHA-1 context to be initialized
*/
void mbedtls_sha1_init( mbedtls_sha1_context *ctx );
/**
* \brief Clear SHA-1 context
*
* \param ctx SHA-1 context to be cleared
*/
void mbedtls_sha1_free( mbedtls_sha1_context *ctx );
/**
* \brief Clone (the state of) a SHA-1 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
const mbedtls_sha1_context *src );
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*/
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx );
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*/
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] );
/* Internal use */
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] );
#ifdef __cplusplus
}
#endif
#endif /* #if defined(MBEDTLS_SHA1_ALT) */
/** \} (end addtogroup sl_crypto_sha1) */
/** \} (end addtogroup sl_crypto) */
#endif /* #ifndef MBEDTLS_SHA1_ALT_H */

View File

@ -0,0 +1,120 @@
/**
* \file sha256_alt.h
*
* \brief SHA-224 and SHA-256 cryptographic hash function
*
* Copyright (C) 2015-2016, Silicon Labs, http://www.silabs.com
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_SHA256_ALT_H
#define MBEDTLS_SHA256_ALT_H
/***************************************************************************//**
* \addtogroup sl_crypto
* \{
******************************************************************************/
/***************************************************************************//**
* \addtogroup sl_crypto_sha256 SHA-224 and SHA-256 cryptographic hash function
* \brief CRYPTO hardware accelerated SHA-224 and SHA-256 cryptographic hash function.
* \{
******************************************************************************/
#if defined(MBEDTLS_SHA256_ALT)
/* SiliconLabs CRYPTO hardware acceleration implementation */
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-256 context structure
*/
typedef struct
{
uint32_t state[8]; /*!< intermediate digest state */
uint32_t total[2]; /*!< number of bytes processed */
unsigned char buffer[64]; /*!< data block being processed */
bool is224; /*!< false => SHA-256, else SHA-224 */
}
mbedtls_sha256_context;
/**
* \brief Initialize SHA-256 context
*
* \param ctx SHA-256 context to be initialized
*/
void mbedtls_sha256_init( mbedtls_sha256_context *ctx );
/**
* \brief Clear SHA-256 context
*
* \param ctx SHA-256 context to be cleared
*/
void mbedtls_sha256_free( mbedtls_sha256_context *ctx );
/**
* \brief Clone (the state of) a SHA-256 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src );
/**
* \brief SHA-256 context setup
*
* \param ctx context to be initialized
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 );
/**
* \brief SHA-256 process buffer
*
* \param ctx SHA-256 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-256 final digest
*
* \param ctx SHA-256 context
* \param output SHA-224/256 checksum result
*/
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] );
/* Internal use */
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] );
#ifdef __cplusplus
}
#endif
#endif /* #if defined(MBEDTLS_SHA256_ALT) */
/** \} (end addtogroup sl_crypto_sha256) */
/** \} (end addtogroup sl_crypto) */
#endif /* #ifndef MBEDTLS_SHA256_ALT_H */

View File

@ -14,15 +14,66 @@
* limitations under the License.
*/
#include "NanostackRfPhyEfr32.h"
#include <string.h>
#include "mbed.h"
#include "ns_types.h"
#include "platform/arm_hal_interrupt.h"
#include "nanostack/platform/arm_hal_phy.h"
#include "mbed_toolchain.h"
#include <string.h>
#include "mbed-trace/mbed_trace.h"
#define TRACE_GROUP "SLRF"
/* Enable debug printing with SL_RADIO_DEBUG, override debug printer with SL_DEBUG_PRINT. */
#ifdef SL_RADIO_DEBUG
#ifndef SL_DEBUG_PRINT
#define SL_DEBUG_PRINT(...) tr_debug(__VA_ARGS__)
#endif
#else
#define SL_DEBUG_PRINT(...)
#endif
/* RF_THREAD_STACK_SIZE defines tack size for the RF adaptor thread */
#ifndef RF_THREAD_STACK_SIZE
#define RF_THREAD_STACK_SIZE 1024
#endif
/* RF_QUEUE_SIZE defines queue size for incoming messages */
#ifndef RF_QUEUE_SIZE
#define RF_QUEUE_SIZE 8
#endif
/* RFThreadSignal used to signal from interrupts to the adaptor thread */
enum RFThreadSignal {
SL_RX_DONE = (1 << 1),
SL_TX_DONE = (1 << 2),
SL_TX_ERR = (1 << 3),
SL_TX_TIMEOUT = (1 << 4),
SL_ACK_RECV = (1 << 5),
SL_ACK_TIMEOUT = (1 << 6),
SL_TXFIFO_ERR = (1 << 7),
SL_RXFIFO_ERR = (1 << 8),
SL_CAL_REQ = (1 << 9),
SL_RSSI_DONE = (1 << 10),
SL_QUEUE_FULL = (1 << 11),
// ACK pend flag can be signalled in addition to RX_DONE
SL_ACK_PEND = (1 << 31),
};
/* Adaptor thread definitions */
static void rf_thread_loop(const void *arg);
static osThreadDef(rf_thread_loop, osPriorityRealtime, RF_THREAD_STACK_SIZE);
static osThreadId rf_thread_id;
/* Queue for passing messages from interrupt to adaptor thread */
static volatile void* rx_queue[8];
static volatile size_t rx_queue_head;
static volatile size_t rx_queue_tail;
/* Silicon Labs headers */
extern "C" {
#include "rail/rail.h"
@ -64,10 +115,11 @@ typedef enum {
static const RAIL_CsmaConfig_t csma_config = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA;
#if defined(TARGET_EFR32MG1)
#if defined(TARGET_EFR32MG1) || defined(TARGET_EFR32FG1)
#include "ieee802154_subg_efr32xg1_configurator_out.h"
#include "ieee802154_efr32xg1_configurator_out.h"
#elif defined(TARGET_EFR32MG12)
#elif defined(TARGET_EFR32MG12) || defined(TARGET_EFR32FG12)
#include "ieee802154_efr32xg12_configurator_out.h"
#include "ieee802154_efr32xg12_configurator_out.h"
#else
#error "Not a valid target."
@ -152,6 +204,75 @@ static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_h
/* Local function prototypes */
static bool rail_checkAndSwitchChannel(uint8_t channel);
static void rf_thread_loop(const void *arg)
{
SL_DEBUG_PRINT("rf_thread_loop: starting (id: %d)\n", rf_thread_id);
for (;;) {
osEvent event = osSignalWait(0, osWaitForever);
if (event.status != osEventSignal) {
continue;
}
platform_enter_critical();
if (event.value.signals & SL_RX_DONE) {
while(rx_queue_tail != rx_queue_head) {
void* handle = (void*) rx_queue[rx_queue_tail];
RAIL_RxPacketInfo_t* info = (RAIL_RxPacketInfo_t*) memoryPtrFromHandle(handle);
device_driver.phy_rx_cb(
info->dataPtr + 1,
info->dataLength - 1,
info->appendedInfo.lqi,
info->appendedInfo.rssiLatch,
rf_radio_driver_id);
memoryFree(handle);
rx_queue[rx_queue_tail] = NULL;
rx_queue_tail = (rx_queue_tail + 1) % RF_QUEUE_SIZE;
}
} else if (event.value.signals & SL_TX_DONE) {
device_driver.phy_tx_done_cb(rf_radio_driver_id,
current_tx_handle,
PHY_LINK_TX_SUCCESS,
1,
1);
} else if (event.value.signals & SL_ACK_RECV) {
device_driver.phy_tx_done_cb( rf_radio_driver_id,
current_tx_handle,
(event.value.signals & SL_ACK_PEND) ? PHY_LINK_TX_DONE_PENDING : PHY_LINK_TX_DONE,
1,
1);
} else if (event.value.signals & SL_ACK_TIMEOUT) {
waiting_for_ack = false;
device_driver.phy_tx_done_cb(rf_radio_driver_id,
current_tx_handle,
PHY_LINK_TX_FAIL,
1,
1);
} else if(event.value.signals & SL_TX_ERR) {
device_driver.phy_tx_done_cb( rf_radio_driver_id,
current_tx_handle,
PHY_LINK_CCA_FAIL,
8,
1);
} else if(event.value.signals & SL_CAL_REQ) {
SL_DEBUG_PRINT("rf_thread_loop: SL_CAL_REQ signal received (unhandled)\n");
} else if(event.value.signals & SL_RXFIFO_ERR) {
SL_DEBUG_PRINT("rf_thread_loop: SL_RXFIFO_ERR signal received (unhandled)\n");
} else if(event.value.signals & SL_TXFIFO_ERR) {
SL_DEBUG_PRINT("rf_thread_loop: SL_TXFIFO_ERR signal received (unhandled)\n");
} else if(event.value.signals & SL_QUEUE_FULL) {
SL_DEBUG_PRINT("rf_thread_loop: SL_QUEUE_FULL signal received (packet dropped)\n");
} else {
SL_DEBUG_PRINT("rf_thread_loop unhandled event status: %d value: %d\n", event.status, event.value.signals);
}
platform_exit_critical();
}
}
/*============ CODE =========*/
/*
@ -168,6 +289,8 @@ static int8_t rf_device_register(void)
return -1;
}
SL_DEBUG_PRINT("rf_device_register: entry\n");
#if MBED_CONF_SL_RAIL_BAND == 2400
RADIO_PA_Init((RADIO_PAInit_t*)&paInit2p4);
#elif (MBED_CONF_SL_RAIL_BAND == 915) || (MBED_CONF_SL_RAIL_BAND == 868)
@ -254,6 +377,12 @@ static int8_t rf_device_register(void)
radio_state = RADIO_INITING;
}
#ifdef MBED_CONF_RTOS_PRESENT
rx_queue_head = 0;
rx_queue_tail = 0;
rf_thread_id = osThreadCreate(osThread(rf_thread_loop), NULL);
#endif
return rf_radio_driver_id;
}
@ -288,29 +417,31 @@ static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_h
switch(radio_state) {
case RADIO_UNINIT:
tr_debug("Radio uninit\n");
SL_DEBUG_PRINT("rf_start_cca: Radio uninit\n");
return -1;
case RADIO_INITING:
tr_debug("Radio initing\n");
SL_DEBUG_PRINT("rf_start_cca: Radio initing\n");
return -1;
case RADIO_CALIBRATION:
tr_debug("Radio calibrating\n");
SL_DEBUG_PRINT("rf_start_cca: Radio calibrating\n");
return -1;
case RADIO_TX:
tr_debug("Radio in TX mode\n");
SL_DEBUG_PRINT("rf_start_cca: Radio in TX mode\n");
return -1;
case RADIO_IDLE:
case RADIO_RX:
// If we're still waiting for an ACK, don't mess up the internal state
if(waiting_for_ack || RAIL_RfStateGet() == RAIL_RF_STATE_TX) {
if((RAIL_GetTime() - last_tx) < 30000) {
tr_debug("Still waiting on previous ACK\n");
SL_DEBUG_PRINT("rf_start_cca: Still waiting on previous ACK\n");
return -1;
} else {
tr_debug("TXerr\n");
SL_DEBUG_PRINT("rf_start_cca: TXerr\n");
}
}
platform_enter_critical();
data_ptr[0] = data_length + 2;
RAIL_RfIdleExt(RAIL_IDLE_ABORT , true);
RAIL_TxDataLoad(&txData);
@ -325,21 +456,24 @@ static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_h
txOpt.waitForAck = false;
}
//tr_debug("Called TX, len %d, chan %d, ack %d\n", data_length, channel, waiting_for_ack ? 1 : 0);
SL_DEBUG_PRINT("rf_start_cca: Called TX, len %d, chan %d, ack %d\n", data_length, channel, waiting_for_ack ? 1 : 0);
if(RAIL_TxStartWithOptions(channel, &txOpt, &RAIL_CcaCsma, (RAIL_CsmaConfig_t*) &csma_config) == 0) {
//Save packet number and sequence
current_tx_handle = tx_handle;
current_tx_sequence = data_ptr[3];
platform_exit_critical();
return 0;
} else {
RAIL_RfIdle();
RAIL_RxStart(channel);
radio_state = RADIO_RX;
platform_exit_critical();
return -1;
}
}
//Should never get here...
platform_exit_critical();
return -1;
}
@ -378,7 +512,7 @@ static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_
break;
/* Enable wireless interface ED scan mode */
case PHY_INTERFACE_RX_ENERGY_STATE:
tr_debug("Energy det req\n");
SL_DEBUG_PRINT("rf_interface_state_control: Energy det req\n");
// TODO: implement energy detection
break;
/* Enable RX in promiscuous mode (aka no address filtering) */
@ -435,12 +569,15 @@ static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_pt
/* Read status of the link */
case PHY_EXTENSION_READ_LINK_STATUS:
// TODO: return accurate value here
tr_debug("Trying to read link status\n");
SL_DEBUG_PRINT("rf_extension: Trying to read link status\n");
break;
/* Convert between LQI and RSSI */
case PHY_EXTENSION_CONVERT_SIGNAL_INFO:
// TODO: return accurate value here
tr_debug("Trying to read signal info\n");
SL_DEBUG_PRINT("rf_extension: Trying to read signal info\n");
break;
case PHY_EXTENSION_ACCEPT_ANY_BEACON:
SL_DEBUG_PRINT("rf_extension: Trying to accept any beacon\n");
break;
}
return 0;
@ -468,11 +605,11 @@ static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address
case PHY_MAC_64BIT:
/* Store MAC in MSB order */
memcpy(MAC_address, address_ptr, 8);
tr_debug("MACw ");
SL_DEBUG_PRINT("rf_address_write: MACw ");
for(unsigned int i = 0; i < sizeof(MAC_address); i ++) {
tr_debug("%02x:", MAC_address[i]);
SL_DEBUG_PRINT("%02x:", MAC_address[i]);
}
tr_debug("\n");
SL_DEBUG_PRINT("\n");
/* Pass MAC to the RF driver in LSB order */
uint8_t MAC_reversed[8];
for(unsigned int i = 0; i < sizeof(MAC_address); i ++) {
@ -483,13 +620,11 @@ static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address
/*Set 16-bit address*/
case PHY_MAC_16BIT:
short_address = address_ptr[0] << 8 | address_ptr[1];
tr_debug("Filter EUI16 %04x\n", short_address);
RAIL_IEEE802154_SetShortAddress(short_address);
break;
/*Set PAN Id*/
case PHY_MAC_PANID:
PAN_address = address_ptr[0] << 8 | address_ptr[1];
tr_debug("Filter PAN %04x\n", PAN_address);
RAIL_IEEE802154_SetPanId(PAN_address);
break;
}
@ -618,14 +753,19 @@ void RAILCb_TxRadioStatus(uint8_t status) {
status == RAIL_TX_CONFIG_TX_ABORTED ||
status == RAIL_TX_CONFIG_TX_BLOCKED) {
waiting_for_ack = false;
device_driver.phy_tx_done_cb( rf_radio_driver_id,
#ifdef MBED_CONF_RTOS_PRESENT
osSignalSet(rf_thread_id, SL_TX_ERR);
}
#else
device_driver.phy_tx_done_cb(rf_radio_driver_id,
current_tx_handle,
PHY_LINK_CCA_FAIL,
8,
1);
} else {
tr_debug("Packet TX error %d\n", status);
SL_DEBUG_PRINT("Packet TX error %d\n", status);
}
#endif
}
radio_state = RADIO_RX;
}
@ -648,7 +788,6 @@ void RAILCb_RxRadioStatus(uint8_t status) {
case RAIL_RX_CONFIG_ADDRESS_FILTERED:
break;
default:
tr_debug("RXE %d\n", status);
break;
}
}
@ -663,7 +802,11 @@ void RAILCb_RxRadioStatus(uint8_t status) {
*/
void RAILCb_CalNeeded(void) {
// TODO: Implement on-the-fly recalibration
tr_debug("!!!! Calling for calibration\n");
#ifdef MBED_CONF_RTOS_PRESENT
osSignalSet(rf_thread_id, SL_CAL_REQ);
#else
SL_DEBUG_PRINT("!!!! Calling for calibration\n");
#endif
}
/**
@ -691,6 +834,9 @@ void RAILCb_TimerExpired(void) {
* callback.
*/
void RAILCb_TxPacketSent(RAIL_TxPacketInfo_t *txPacketInfo) {
#ifdef MBED_CONF_RTOS_PRESENT
osSignalSet(rf_thread_id, SL_TX_DONE);
#else
if(device_driver.phy_tx_done_cb != NULL) {
device_driver.phy_tx_done_cb( rf_radio_driver_id,
current_tx_handle,
@ -700,6 +846,7 @@ void RAILCb_TxPacketSent(RAIL_TxPacketInfo_t *txPacketInfo) {
1,
1);
}
#endif
last_tx = RAIL_GetTime();
radio_state = RADIO_RX;
}
@ -731,12 +878,16 @@ void RAILCb_RxPacketReceived(void *rxPacketHandle) {
/* Save the pending bit */
last_ack_pending_bit = (rxPacketInfo->dataPtr[1] & (1 << 4)) != 0;
/* Tell the stack we got an ACK */
//tr_debug("rACK\n");
#ifdef MBED_CONF_RTOS_PRESENT
osSignalSet(rf_thread_id, SL_ACK_RECV | SL_ACK_PEND);
#else
SL_DEBUG_PRINT("rACK\n");
device_driver.phy_tx_done_cb( rf_radio_driver_id,
current_tx_handle,
last_ack_pending_bit ? PHY_LINK_TX_DONE_PENDING : PHY_LINK_TX_DONE,
1,
1);
#endif
} else {
/* Figure out whether we want to not ACK this packet */
@ -752,14 +903,24 @@ void RAILCb_RxPacketReceived(void *rxPacketHandle) {
RAIL_AutoAckCancelAck();
}
//tr_debug("rPKT %d\n", rxPacketInfo->dataLength);
/* Feed the received packet into the stack */
#ifdef MBED_CONF_RTOS_PRESENT
if (((rx_queue_head + 1) % RF_QUEUE_SIZE) != rx_queue_tail) {
memoryTakeReference(rxPacketHandle);
rx_queue[rx_queue_head] = rxPacketHandle;
rx_queue_head = (rx_queue_head + 1) % RF_QUEUE_SIZE;
osSignalSet(rf_thread_id, SL_RX_DONE);
} else {
osSignalSet(rf_thread_id, SL_QUEUE_FULL);
}
#else
SL_DEBUG_PRINT("rPKT %d\n", rxPacketInfo->dataLength);
device_driver.phy_rx_cb(rxPacketInfo->dataPtr + 1,
rxPacketInfo->dataLength - 1,
//TODO: take a new RAIL release that exposes LQI, or have LQI as function of RSSI
255,
rxPacketInfo->appendedInfo.lqi,
rxPacketInfo->appendedInfo.rssiLatch,
rf_radio_driver_id);
#endif
}
}
}
@ -792,13 +953,16 @@ void RAILCb_IEEE802154_DataRequestCommand(RAIL_IEEE802154_Address_t *address) {
*/
void RAILCb_RxAckTimeout(void) {
if(waiting_for_ack) {
tr_debug("nACK\n");
waiting_for_ack = false;
#ifdef MBED_CONF_RTOS_PRESENT
osSignalSet(rf_thread_id, SL_ACK_TIMEOUT);
#else
device_driver.phy_tx_done_cb( rf_radio_driver_id,
current_tx_handle,
PHY_LINK_TX_FAIL,
1,
1);
#endif
}
}
@ -849,7 +1013,11 @@ static bool rail_checkAndSwitchChannel(uint8_t newChannel) {
* time of the callback dispatch.
*/
void RAILCb_RxFifoAlmostFull(uint16_t bytesAvailable) {
tr_debug("RX near full (%d)\n", bytesAvailable);
#ifdef MBED_CONF_RTOS_PRESENT
osSignalSet(rf_thread_id, SL_RXFIFO_ERR);
#else
SL_DEBUG_PRINT("RX near full (%d)\n", bytesAvailable);
#endif
}
/**
@ -871,7 +1039,11 @@ void RAILCb_RxFifoAlmostFull(uint16_t bytesAvailable) {
* callback dispatch.
*/
void RAILCb_TxFifoAlmostEmpty(uint16_t spaceAvailable) {
tr_debug("TX near empty (%d)\n", spaceAvailable);
#ifdef MBED_CONF_RTOS_PRESENT
osSignalSet(rf_thread_id, SL_TXFIFO_ERR);
#else
SL_DEBUG_PRINT("TX near empty (%d)\n", spaceAvailable);
#endif
}
/**
@ -886,5 +1058,9 @@ void RAILCb_TxFifoAlmostEmpty(uint16_t spaceAvailable) {
* get the result.
*/
void RAILCb_RssiAverageDone(int16_t avgRssi) {
tr_debug("RSSI done (%d)\n", avgRssi);
#ifdef MBED_CONF_RTOS_PRESENT
osSignalSet(rf_thread_id, SL_RSSI_DONE);
#else
SL_DEBUG_PRINT("RSSI done (%d)\n", avgRssi);
#endif
}

4
mbed.h
View File

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

View File

@ -24,6 +24,15 @@
#include <cstdarg>
#include "Callback.h"
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_ATCmdParser ATCmdParser class
* @{
*/
/**
* Parser class for parsing AT commands
*
@ -43,8 +52,6 @@
* @endcode
*/
namespace mbed {
class ATCmdParser : private NonCopyable<ATCmdParser>
{
private:
@ -299,6 +306,11 @@ public:
*/
bool process_oob(void);
};
/**@}*/
/**@}*/
} //namespace mbed
#endif //MBED_ATCMDPARSER_H

View File

@ -1,6 +1,10 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_CThunk CThunk class
* @{
*/
/* General C++ Object Thunking class
*
* - allows direct callbacks to non-static C++ class functions
@ -73,13 +77,11 @@
/* IRQ/Exception compatible thunk entry function */
typedef void (*CThunkEntry)(void);
/** @}*/
/**
* Class for created a pointer with data bound to it
*
* @note Synchronization level: Not protected
* @ingroup platform
*/
template<class T>
class CThunk
@ -243,5 +245,9 @@ class CThunk
}
};
/**@}*/
/**@}*/
#endif/*__CTHUNK_H__*/

View File

@ -22,7 +22,17 @@
#include <string.h>
namespace mbed {
typedef Callback<void()> *pFunctionPointer_t;
class CallChainLink;
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_CallChain CallChain class
* @{
*/
/** Group one or more functions in an instance of a CallChain, then call them in
* sequence using CallChain::call(). Used mostly by the interrupt chaining code,
@ -60,12 +70,7 @@ namespace mbed {
* chain.call();
* }
* @endcode
* @ingroup platform
*/
typedef Callback<void()> *pFunctionPointer_t;
class CallChainLink;
class CallChain : private NonCopyable<CallChain> {
public:
/** Create an empty chain
@ -183,6 +188,10 @@ private:
CallChainLink *_chain;
};
/**@}*/
/**@}*/
} // namespace mbed
#endif

View File

@ -24,12 +24,15 @@
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_Callback Callback class
* @{
*/
/** Callback class based on template specialization
*
* @note Synchronization level: Not protected
* @ingroup platform
*/
template <typename F>
class Callback;
@ -67,7 +70,6 @@ namespace detail {
/** Callback class based on template specialization
*
* @note Synchronization level: Not protected
* @ingroup platform
*/
template <typename R>
class Callback<R()> {
@ -642,7 +644,6 @@ private:
/** Callback class based on template specialization
*
* @note Synchronization level: Not protected
* @ingroup platform
*/
template <typename R, typename A0>
class Callback<R(A0)> {
@ -1218,7 +1219,6 @@ private:
/** Callback class based on template specialization
*
* @note Synchronization level: Not protected
* @ingroup platform
*/
template <typename R, typename A0, typename A1>
class Callback<R(A0, A1)> {
@ -1795,7 +1795,6 @@ private:
/** Callback class based on template specialization
*
* @note Synchronization level: Not protected
* @ingroup platform
*/
template <typename R, typename A0, typename A1, typename A2>
class Callback<R(A0, A1, A2)> {
@ -2373,7 +2372,6 @@ private:
/** Callback class based on template specialization
*
* @note Synchronization level: Not protected
* @ingroup platform
*/
template <typename R, typename A0, typename A1, typename A2, typename A3>
class Callback<R(A0, A1, A2, A3)> {
@ -2952,7 +2950,6 @@ private:
/** Callback class based on template specialization
*
* @note Synchronization level: Not protected
* @ingroup platform
*/
template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
class Callback<R(A0, A1, A2, A3, A4)> {
@ -4546,6 +4543,9 @@ Callback<R(A0, A1, A2, A3, A4)> callback(const volatile U *obj, R (*func)(const
return Callback<R(A0, A1, A2, A3, A4)>(func, obj);
}
/**@}*/
/**@}*/
} // namespace mbed

View File

@ -20,11 +20,15 @@
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_CircularBuffer CircularBuffer functions
* @{
*/
/** Templated Circular buffer class
*
* @note Synchronization level: Interrupt safe
* @ingroup platform
*/
template<typename T, uint32_t BufferSize, typename CounterType = uint32_t>
class CircularBuffer {
@ -112,6 +116,10 @@ private:
volatile bool _full;
};
/**@}*/
/**@}*/
}
#endif

View File

@ -22,6 +22,13 @@
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_CriticalSectionLock CriticalSectionLock functions
* @{
*/
/** RAII object for disabling, then restoring, interrupt state
* Usage:
* @code
@ -65,6 +72,9 @@ public:
}
};
/**@}*/
/**@}*/
} // namespace mbed

View File

@ -22,6 +22,12 @@
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_DeepSleepLock DeepSleepLock functions
* @{
*/
/** RAII object for disabling, then restoring the deep sleep mode
* Usage:
@ -82,6 +88,11 @@ public:
}
};
/**@}*/
/**@}*/
}
#endif

View File

@ -23,6 +23,11 @@
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_DirHandle DirHandle functions
* @{
*/
/** Represents a directory stream. Objects of this type are returned
@ -40,7 +45,6 @@ namespace mbed {
*
* @note to create a directory, @see Dir
* @note Synchronization level: Set by subclass
* @ingroup platform
*/
class DirHandle : private NonCopyable<DirHandle> {
public:
@ -142,7 +146,9 @@ public:
virtual void seekdir(off_t location) { seek(location); }
};
/**@}*/
/**@}*/
} // namespace mbed
#endif /* MBED_DIRHANDLE_H */

View File

@ -27,19 +27,22 @@ typedef int FILEHANDLE;
#include "platform/NonCopyable.h"
namespace mbed {
/** \addtogroup platform */
/** @{*/
typedef enum {
FilePathType,
FileSystemPathType
} PathType;
/** @}*/
/** \addtogroup platform */
/** @{*/
/**
* @class FileBase
* @ingroup platform
* \defgroup platform_FileBase FileBase class
* @{
*/
/** Class FileBase
*
*/
class FileBase : private NonCopyable<FileBase> {
public:
FileBase(const char *name, PathType t);
@ -62,6 +65,10 @@ private:
const PathType _path_type;
};
/**@}*/
/**@}*/
} // namespace mbed
#endif

View File

@ -26,6 +26,11 @@ typedef int FILEHANDLE;
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_FileHandle FileHandle functions
* @{
*/
/** Class FileHandle
@ -36,7 +41,6 @@ namespace mbed {
*
* @note to create a file, @see File
* @note Synchronization level: Set by subclass
* @ingroup platform
*/
class FileHandle : private NonCopyable<FileHandle> {
public:
@ -254,6 +258,11 @@ public:
std::FILE *fdopen(FileHandle *fh, const char *mode);
/**@}*/
/**@}*/
} // namespace mbed
#endif

View File

@ -23,14 +23,17 @@
namespace mbed {
/** \addtogroup platform */
/* Class FileLike
/** @{*/
/**
* \defgroup platform_FileLike FileLike class
* @{
*/
/** Class FileLike
*
* A file-like object is one that can be opened with fopen by
* fopen("/name", mode).
*
* @note Synchronization level: Set by subclass
* @ingroup platform
*/
class FileLike : public FileHandle, public FileBase, private NonCopyable<FileLike> {
public:
@ -42,6 +45,9 @@ public:
virtual ~FileLike() {}
};
/**@}*/
/**@}*/
} // namespace mbed

View File

@ -23,15 +23,23 @@
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* @class FileSystem
* @ingroup platform
* \defgroup platform_FilePath FilePath class
* @{
*/
class FileSystem;
class FileSystem;
/** Class FilePath
*
*/
class FilePath {
public:
/** Constructor FilePath
*
* @param file_path The path of file.
*/
FilePath(const char* file_path);
const char* fileName(void);
@ -48,6 +56,10 @@ private:
FileBase* fb;
};
/**@}*/
/**@}*/
} // namespace mbed
#endif

View File

@ -26,6 +26,10 @@
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_FileSystemHandle FileSystemHandle functions
* @{
*/
/** A filesystem-like object is one that can be used to open file-like
@ -91,7 +95,9 @@ public:
*/
virtual int mkdir(const char *path, mode_t mode);
};
/**@}*/
/**@}*/
} // namespace mbed

View File

@ -25,6 +25,11 @@
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_FileSystemLike FileSystemLike functions
* @{
*/
/** A filesystem-like object is one that can be used to open file-like
@ -34,7 +39,6 @@ namespace mbed {
* of the rest of the functions just return error values).
*
* @note Synchronization level: Set by subclass
* @ingroup platform
*/
class FileSystemLike : public FileSystemHandle, public FileBase, private NonCopyable<FileSystemLike> {
public:
@ -79,6 +83,9 @@ public:
}
};
/**@}*/
/**@}*/
} // namespace mbed

View File

@ -23,13 +23,14 @@
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_FunctionPointer FunctionPointer class
* @{
*/
// Declarations for backwards compatibility
// To be foward compatible, code should adopt the Callback class
/**
* @ingroup platform
*/
template <typename R, typename A1>
class FunctionPointerArg1 : public Callback<R(A1)> {
public:
@ -61,9 +62,6 @@ public:
}
};
/**
* @ingroup platform
*/
template <typename R>
class FunctionPointerArg1<R, void> : public Callback<R()> {
public:
@ -97,6 +95,10 @@ public:
typedef FunctionPointerArg1<void, void> FunctionPointer;
/**@}*/
/**@}*/
} // namespace mbed

View File

@ -27,9 +27,12 @@
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_LocalFileSystem LocalFileSystem functions
* @{
*/
FILEHANDLE local_file_open(const char* name, int flags);
/** @}*/
/**
* @class LocalFileHandle
@ -112,6 +115,10 @@ public:
virtual int remove(const char *filename);
};
/**@}*/
/**@}*/
} // namespace mbed
#endif

View File

@ -1,5 +1,10 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_PlatformMutex PlatformMutex class
* @{
*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
@ -25,7 +30,6 @@
typedef rtos::Mutex PlatformMutex;
#else
/** A stub mutex for when an RTOS is not present
* @ingroup platform
*/
class PlatformMutex : private mbed::NonCopyable<PlatformMutex> {
public:
@ -50,3 +54,6 @@ public:
#endif
/**@}*/
/**@}*/

View File

@ -1,6 +1,10 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_SingletonPtr SingletonPtr class
* @{
*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
@ -55,7 +59,6 @@ inline static void singleton_unlock(void)
osMutexRelease (singleton_mutex_id);
#endif
}
/** @}*/
/** Utility class for creating an using a singleton
*
@ -68,7 +71,6 @@ inline static void singleton_unlock(void)
* @note: This class is lazily initialized on first use.
* This class is a POD type so if it is not used it will
* be garbage collected.
* @ingroup platform
*/
template <class T>
struct SingletonPtr {
@ -108,4 +110,6 @@ struct SingletonPtr {
};
#endif
/**@}*/
/**@}*/

View File

@ -26,16 +26,18 @@
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_Stream Stream class
* @{
*/
extern void mbed_set_unbuffered_stream(std::FILE *_file);
extern int mbed_getc(std::FILE *_file);
extern char* mbed_gets(char *s, int size, std::FILE *_file);
/** @}*/
/** File stream
*
* @note Synchronization level: Set by subclass
* @ingroup platform
*/
class Stream : public FileLike, private NonCopyable<Stream> {
@ -82,7 +84,9 @@ protected:
// Stub
}
};
/**@}*/
/**@}*/
} // namespace mbed
#endif

View File

@ -21,9 +21,13 @@
namespace mbed {
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_Transaction Transaction class
* @{
*/
/** Transaction structure
* @ingroup platform
*/
typedef struct {
void *tx_buffer; /**< Tx buffer */
@ -38,7 +42,6 @@ typedef struct {
/** Transaction class defines a transaction.
*
* @note Synchronization level: Not protected
* @ingroup platform
*/
template<typename Class>
class Transaction {
@ -72,7 +75,9 @@ private:
Class* _obj;
transaction_t _data;
};
/**@}*/
/**@}*/
}
#endif

View File

@ -1,6 +1,3 @@
/** \addtogroup platform */
/** @{*/
/* mbed Microcontroller Library
* Copyright (c) 2017-2017 ARM Limited
*
@ -16,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_APPLICATION_H
#define MBED_APPLICATION_H
@ -52,4 +50,3 @@ void mbed_start_application(uintptr_t address);
#endif
/** @}*/

View File

@ -1,6 +1,10 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_Assert Assert macros
* @{
*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
@ -39,6 +43,19 @@ void mbed_assert_internal(const char *expr, const char *file, int line);
}
#endif
/** MBED_ASSERT
* Declare runtime assertions: results in runtime error if condition is false
*
* @note
* Use of MBED_ASSERT is limited to Debug and Develop builds.
*
* @code
*
* int Configure(serial_t *obj) {
* MBED_ASSERT(obj);
* }
* @endcode
*/
#ifdef NDEBUG
#define MBED_ASSERT(expr) ((void)0)
@ -110,4 +127,7 @@ do { \
#endif
/** @}*/
/**@}*/
/**@}*/

View File

@ -1,6 +1,4 @@
/** \addtogroup platform */
/** @{*/
/*
* Copyright (c) 2015-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
@ -29,6 +27,12 @@
extern "C" {
#endif
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_critical critical section function
* @{
*/
/** Determine the current interrupts enabled state
*
@ -363,8 +367,11 @@ void *core_util_atomic_decr_ptr(void **valuePtr, ptrdiff_t delta);
#ifdef __cplusplus
} // extern "C"
#endif
/**@}*/
/**@}*/
#endif // __MBED_UTIL_CRITICAL_H__
/** @}*/

View File

@ -1,6 +1,11 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_debug Debug functions
* @{
*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
@ -68,4 +73,7 @@ static inline void debug_if(int condition, const char *format, ...) {
#endif
/** @}*/
/**@}*/
/**@}*/

View File

@ -1,6 +1,10 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_error Error functions
* @{
*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
@ -75,3 +79,4 @@ void error(const char* format, ...);
#endif
/** @}*/
/** @}*/

View File

@ -1,6 +1,11 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_interface Network interface and other utility functions
* @{
*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
@ -42,6 +47,11 @@ extern "C" {
#if DEVICE_SEMIHOST
/**
* \defgroup platform_interface interface functions
* @{
*/
/** Functions to control the mbed interface
*
* mbed Microcontrollers have a built-in interface to provide functionality such as
@ -137,6 +147,7 @@ void mbed_error_printf(const char* format, ...);
*
*/
void mbed_error_vfprintf(const char * format, va_list arg);
/** @}*/
#ifdef __cplusplus
}

View File

@ -1,6 +1,7 @@
/** \addtogroup platform */
/** @{*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
@ -35,6 +36,11 @@ enum {
MBED_MEM_TRACE_FREE
};
/**
* \defgroup platform_mem_trace mem_trace functions
* @{
*/
/* Prefix for the output of the default tracer */
#define MBED_MEM_DEFAULT_TRACER_PREFIX "#"
@ -133,6 +139,8 @@ void mbed_mem_trace_free(void *ptr, void *caller);
*/
void mbed_mem_trace_default_callback(uint8_t op, void *res, void *caller, ...);
/** @}*/
#ifdef __cplusplus
}
#endif

View File

@ -28,6 +28,11 @@
extern "C" {
#endif
/**
* \defgroup platform_mktime mktime functions
* @{
*/
/** Compute if a year is a leap year or not.
*
* @param year The year to test it shall be in the range [70:138]. Year 0 is
@ -89,6 +94,8 @@ time_t _rtc_mktime(const struct tm* calendar_time);
*/
bool _rtc_localtime(time_t timestamp, struct tm* calendar_time);
/** @}*/
#ifdef __cplusplus
}
#endif

View File

@ -27,7 +27,11 @@ namespace mbed {
class FileHandle;
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_poll poll functions
* @{
*/
struct pollfh {
FileHandle *fh;
@ -47,6 +51,10 @@ struct pollfh {
*/
int poll(pollfh fhs[], unsigned nfhs, int timeout);
/**@}*/
/**@}*/
} // namespace mbed
#endif //MBED_POLL_H

View File

@ -1,5 +1,10 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_preprocessor preprocessor macros
* @{
*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
@ -51,3 +56,4 @@
#endif
/** @}*/
/** @}*/

View File

@ -58,13 +58,21 @@ typedef unsigned int gid_t; ///< Group ID
#endif
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_retarget Retarget functions
* @{
*/
/* DIR declarations must also be here */
#if __cplusplus
namespace mbed {
class FileHandle;
class DirHandle;
std::FILE *mbed_fdopen(FileHandle *fh, const char *mode);
}
typedef mbed::DirHandle DIR;
#else
@ -438,4 +446,8 @@ enum {
DT_SOCK, ///< This is a UNIX domain socket.
};
/**@}*/
/**@}*/
#endif /* RETARGET_H */

View File

@ -1,6 +1,10 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_rtc_time rtc_time functions
* @{
*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
@ -90,3 +94,4 @@ void attach_rtc(time_t (*read_rtc)(void), void (*write_rtc)(time_t), void (*init
#endif
/** @}*/
/** @}*/

View File

@ -1,6 +1,4 @@
/** \addtogroup platform */
/** @{*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
@ -95,4 +93,4 @@ int semihost_disabledebug(void);
#endif
/** @}*/

View File

@ -1,6 +1,11 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_sleep Sleep functions
* @{
*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2017 ARM Limited
*
@ -169,3 +174,4 @@ __INLINE static void deepsleep(void)
#endif
/** @}*/
/** @}*/

View File

@ -1,6 +1,10 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_stats stats functions
* @{
*/
/* mbed Microcontroller Library
* Copyright (c) 2016-2016 ARM Limited
*
@ -25,6 +29,9 @@
extern "C" {
#endif
/**
* struct mbed_stats_heap_t definition
*/
typedef struct {
uint32_t current_size; /**< Bytes allocated currently. */
uint32_t max_size; /**< Max bytes allocated at a given time. */
@ -41,6 +48,9 @@ typedef struct {
*/
void mbed_stats_heap_get(mbed_stats_heap_t *stats);
/**
* struct mbed_stats_stack_t definition
*/
typedef struct {
uint32_t thread_id; /**< Identifier for thread that owns the stack or 0 if multiple threads. */
uint32_t max_size; /**< Maximum number of bytes used on the stack. */
@ -73,3 +83,5 @@ size_t mbed_stats_stack_get_each(mbed_stats_stack_t *stats, size_t count);
#endif
/** @}*/
/** @}*/

View File

@ -1,6 +1,11 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_toolchain Toolchain functions
* @{
*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
@ -382,3 +387,4 @@ typedef int FILEHANDLE;
#endif
/** @}*/
/** @}*/

View File

@ -1,6 +1,11 @@
/** \addtogroup platform */
/** @{*/
/**
* \defgroup platform_wait_api wait_api functions
* @{
*/
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
@ -70,3 +75,4 @@ void wait_us(int us);
#endif
/** @}*/
/** @}*/

View File

@ -39,11 +39,11 @@ EventFlags::EventFlags(const char *name)
void EventFlags::constructor(const char *name)
{
memset(&_obj_mem, 0, sizeof(_obj_mem));
memset(&_attr, 0, sizeof(_attr));
_attr.name = name ? name : "application_unnamed_event_flags";
_attr.cb_mem = &_obj_mem;
_attr.cb_size = sizeof(_obj_mem);
_id = osEventFlagsNew(&_attr);
osEventFlagsAttr_t attr;
attr.name = name ? name : "application_unnamed_event_flags";
attr.cb_mem = &_obj_mem;
attr.cb_size = sizeof(_obj_mem);
_id = osEventFlagsNew(&attr);
MBED_ASSERT(_id);
}

View File

@ -32,7 +32,11 @@
namespace rtos {
/** \addtogroup rtos */
/** @{*/
/**
* \defgroup rtos_EventFlags EventFlags class
* @{
*/
/** The EventFlags class is used to signal or wait for an arbitrary event or events.
@note
EventFlags support 31 flags so the MSB flag is ignored, it is used to return an error code (@a osFlagsError)
@ -90,11 +94,12 @@ private:
void constructor(const char *name = NULL);
uint32_t wait(uint32_t flags, uint32_t opt, uint32_t timeout, bool clear);
osEventFlagsId_t _id;
osEventFlagsAttr_t _attr;
mbed_rtos_storage_event_flags_t _obj_mem;
};
/** @}*/
/** @}*/
}
#endif
/** @}*/

View File

@ -38,7 +38,11 @@ using namespace rtos;
namespace rtos {
/** \addtogroup rtos */
/** @{*/
/**
* \defgroup rtos_Mail Mail class
* @{
*/
/** The Mail class allow to control, send, receive, or wait for mail.
A mail is a memory block that is send to a thread or interrupt service routine.
@tparam T data type of a single message element.
@ -103,9 +107,12 @@ private:
MemoryPool<T, queue_sz> _pool;
};
/** @}*/
/** @}*/
}
#endif
/** @}*/

View File

@ -33,7 +33,11 @@
namespace rtos {
/** \addtogroup rtos */
/** @{*/
/**
* \defgroup rtos_MemoryPool MemoryPool class
* @{
*/
/** Define and manage fixed-size memory pools of objects of a given type.
@tparam T data type of a single object (element).
@tparam queue_sz maximum number of objects (elements) in the memory pool.
@ -50,12 +54,12 @@ public:
MemoryPool() {
memset(_pool_mem, 0, sizeof(_pool_mem));
memset(&_obj_mem, 0, sizeof(_obj_mem));
memset(&_attr, 0, sizeof(_attr));
_attr.mp_mem = _pool_mem;
_attr.mp_size = sizeof(_pool_mem);
_attr.cb_mem = &_obj_mem;
_attr.cb_size = sizeof(_obj_mem);
_id = osMemoryPoolNew(pool_sz, sizeof(T), &_attr);
osMemoryPoolAttr_t attr = { 0 };
attr.mp_mem = _pool_mem;
attr.mp_size = sizeof(_pool_mem);
attr.cb_mem = &_obj_mem;
attr.cb_size = sizeof(_obj_mem);
_id = osMemoryPoolNew(pool_sz, sizeof(T), &attr);
MBED_ASSERT(_id);
}
@ -95,13 +99,14 @@ public:
private:
osMemoryPoolId_t _id;
osMemoryPoolAttr_t _attr;
/* osMemoryPoolNew requires that pool block size is a multiple of 4 bytes. */
char _pool_mem[((sizeof(T) + 3) & ~3) * pool_sz];
mbed_rtos_storage_mem_pool_t _obj_mem;
};
/** @}*/
/** @}*/
}
#endif
/** @}*/

View File

@ -40,12 +40,12 @@ Mutex::Mutex(const char *name)
void Mutex::constructor(const char *name)
{
memset(&_obj_mem, 0, sizeof(_obj_mem));
memset(&_attr, 0, sizeof(_attr));
_attr.name = name ? name : "aplication_unnamed_mutex";
_attr.cb_mem = &_obj_mem;
_attr.cb_size = sizeof(_obj_mem);
_attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
_id = osMutexNew(&_attr);
osMutexAttr_t attr = { 0 };
attr.name = name ? name : "aplication_unnamed_mutex";
attr.cb_mem = &_obj_mem;
attr.cb_size = sizeof(_obj_mem);
attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
_id = osMutexNew(&attr);
MBED_ASSERT(_id);
}

View File

@ -32,7 +32,11 @@
namespace rtos {
/** \addtogroup rtos */
/** @{*/
/**
* \defgroup rtos_Mutex Mutex class
* @{
*/
/** The Mutex class is used to synchronize the execution of threads.
This is for example used to protect access to a shared resource.
@ -82,11 +86,11 @@ private:
void constructor(const char *name = NULL);
osMutexId_t _id;
osMutexAttr_t _attr;
mbed_rtos_storage_mutex_t _obj_mem;
};
/** @}*/
/** @}*/
}
#endif
/** @}*/

View File

@ -34,7 +34,11 @@
namespace rtos {
/** \addtogroup rtos */
/** @{*/
/**
* \defgroup rtos_EventFlags EventFlags class
* @{
*/
/** The Queue class allow to control, send, receive, or wait for messages.
A message can be a integer or pointer value to a certain type T that is send
to a thread or interrupt service routine.
@ -51,12 +55,12 @@ public:
/** Create and initialize a message Queue. */
Queue() {
memset(&_obj_mem, 0, sizeof(_obj_mem));
memset(&_attr, 0, sizeof(_attr));
_attr.mq_mem = _queue_mem;
_attr.mq_size = sizeof(_queue_mem);
_attr.cb_mem = &_obj_mem;
_attr.cb_size = sizeof(_obj_mem);
_id = osMessageQueueNew(queue_sz, sizeof(T*), &_attr);
osMessageQueueAttr_t attr = { 0 };
attr.mq_mem = _queue_mem;
attr.mq_size = sizeof(_queue_mem);
attr.cb_mem = &_obj_mem;
attr.cb_size = sizeof(_obj_mem);
_id = osMessageQueueNew(queue_sz, sizeof(T*), &attr);
MBED_ASSERT(_id);
}
@ -115,12 +119,12 @@ public:
private:
osMessageQueueId_t _id;
osMessageQueueAttr_t _attr;
char _queue_mem[queue_sz * (sizeof(T*) + sizeof(mbed_rtos_storage_message_t))];
mbed_rtos_storage_msg_queue_t _obj_mem;
};
/** @}*/
/** @}*/
}
#endif
/** @}*/

View File

@ -31,10 +31,10 @@ namespace rtos {
void RtosTimer::constructor(mbed::Callback<void()> func, os_timer_type type) {
_function = func;
memset(&_obj_mem, 0, sizeof(_obj_mem));
memset(&_attr, 0, sizeof(_attr));
_attr.cb_mem = &_obj_mem;
_attr.cb_size = sizeof(_obj_mem);
_id = osTimerNew((void (*)(void *))Callback<void()>::thunk, type, &_function, &_attr);
osTimerAttr_t attr = { 0 };
attr.cb_mem = &_obj_mem;
attr.cb_size = sizeof(_obj_mem);
_id = osTimerNew((void (*)(void *))Callback<void()>::thunk, type, &_function, &attr);
MBED_ASSERT(_id);
}

View File

@ -33,7 +33,11 @@
namespace rtos {
/** \addtogroup rtos */
/** @{*/
/**
* \defgroup rtos_RtosTimer RtosTimer class
* @{
*/
/** The RtosTimer class allow creating and and controlling of timer functions in the system.
A timer function is called when a time period expires whereby both on-shot and
periodic timers are possible. A timer can be started, restarted, or stopped.
@ -157,13 +161,14 @@ private:
void constructor(mbed::Callback<void()> func, os_timer_type type);
osTimerId_t _id;
osTimerAttr_t _attr;
mbed_rtos_storage_timer_t _obj_mem;
mbed::Callback<void()> _function;
};
/** @}*/
/** @}*/
}
#endif
/** @}*/

View File

@ -36,10 +36,10 @@ Semaphore::Semaphore(int32_t count, uint16_t max_count) {
void Semaphore::constructor(int32_t count, uint16_t max_count) {
memset(&_obj_mem, 0, sizeof(_obj_mem));
memset(&_attr, 0, sizeof(_attr));
_attr.cb_mem = &_obj_mem;
_attr.cb_size = sizeof(_obj_mem);
_id = osSemaphoreNew(max_count, count, &_attr);
osSemaphoreAttr_t attr = { 0 };
attr.cb_mem = &_obj_mem;
attr.cb_size = sizeof(_obj_mem);
_id = osSemaphoreNew(max_count, count, &attr);
MBED_ASSERT(_id != NULL);
}

View File

@ -31,6 +31,10 @@
namespace rtos {
/** \addtogroup rtos */
/** @{*/
/**
* \defgroup rtos_Semaphore Semaphore class
* @{
*/
/** The Semaphore class is used to manage and protect access to a set of shared resources.
*
@ -71,11 +75,11 @@ private:
void constructor(int32_t count, uint16_t max_count);
osSemaphoreId_t _id;
osSemaphoreAttr_t _attr;
mbed_rtos_storage_semaphore_t _obj_mem;
};
/** @}*/
/** @}*/
}
#endif
/** @}*/

View File

@ -35,6 +35,10 @@
namespace rtos {
/** \addtogroup rtos */
/** @{*/
/**
* \defgroup rtos_Thread Thread class
* @{
*/
/** The Thread class allow defining, creating, and controlling thread functions in the system.
*
@ -370,8 +374,9 @@ private:
mbed_rtos_storage_thread_t _obj_mem;
bool _finished;
};
/** @}*/
/** @}*/
}
#endif
/** @}*/

View File

@ -31,7 +31,17 @@
extern "C" {
#endif
/**
* \defgroup rtos_Idle Idle hook function
* @{
*/
/**
@note
Sets the hook function called by idle task
@param fptr Hook function pointer.
*/
void rtos_attach_idle_hook(void (*fptr)(void));
/** @}*/
#ifdef __cplusplus
}
@ -40,3 +50,4 @@ void rtos_attach_idle_hook(void (*fptr)(void));
#endif
/** @}*/

View File

@ -0,0 +1,206 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#ifndef MBED_PINNAMES_H
#define MBED_PINNAMES_H
#include "cmsis.h"
#include "adi_gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PIN_INPUT,
PIN_OUTPUT
} PinDirection;
//update
#define GPIO_PORT_SHIFT 12
typedef enum {
P0_00 = (0 << GPIO_PORT_SHIFT | 0 ),
P0_01 = (0 << GPIO_PORT_SHIFT | 1 ),
P0_02 = (0 << GPIO_PORT_SHIFT | 2 ),
P0_03 = (0 << GPIO_PORT_SHIFT | 3 ),
P0_04 = (0 << GPIO_PORT_SHIFT | 4 ),
P0_05 = (0 << GPIO_PORT_SHIFT | 5 ),
P0_06 = (0 << GPIO_PORT_SHIFT | 6 ),
P0_07 = (0 << GPIO_PORT_SHIFT | 7 ),
P0_08 = (0 << GPIO_PORT_SHIFT | 8 ),
P0_09 = (0 << GPIO_PORT_SHIFT | 9 ),
P0_10 = (0 << GPIO_PORT_SHIFT | 10),
P0_11 = (0 << GPIO_PORT_SHIFT | 11),
P0_12 = (0 << GPIO_PORT_SHIFT | 12),
P0_13 = (0 << GPIO_PORT_SHIFT | 13),
P0_14 = (0 << GPIO_PORT_SHIFT | 14),
P0_15 = (0 << GPIO_PORT_SHIFT | 15),
P1_00 = (1 << GPIO_PORT_SHIFT | 0 ),
P1_01 = (1 << GPIO_PORT_SHIFT | 1 ),
P1_02 = (1 << GPIO_PORT_SHIFT | 2 ),
P1_03 = (1 << GPIO_PORT_SHIFT | 3 ),
P1_04 = (1 << GPIO_PORT_SHIFT | 4 ),
P1_05 = (1 << GPIO_PORT_SHIFT | 5 ),
P1_06 = (1 << GPIO_PORT_SHIFT | 6 ),
P1_07 = (1 << GPIO_PORT_SHIFT | 7 ),
P1_08 = (1 << GPIO_PORT_SHIFT | 8 ),
P1_09 = (1 << GPIO_PORT_SHIFT | 9 ),
P1_10 = (1 << GPIO_PORT_SHIFT | 10),
P1_11 = (1 << GPIO_PORT_SHIFT | 11),
P1_12 = (1 << GPIO_PORT_SHIFT | 12),
P1_13 = (1 << GPIO_PORT_SHIFT | 13),
P1_14 = (1 << GPIO_PORT_SHIFT | 14),
P1_15 = (1 << GPIO_PORT_SHIFT | 15),
P2_00 = (2 << GPIO_PORT_SHIFT | 0 ),
P2_01 = (2 << GPIO_PORT_SHIFT | 1 ),
P2_02 = (2 << GPIO_PORT_SHIFT | 2 ),
P2_03 = (2 << GPIO_PORT_SHIFT | 3 ),
P2_04 = (2 << GPIO_PORT_SHIFT | 4 ),
P2_05 = (2 << GPIO_PORT_SHIFT | 5 ),
P2_06 = (2 << GPIO_PORT_SHIFT | 6 ),
P2_07 = (2 << GPIO_PORT_SHIFT | 7 ),
P2_08 = (2 << GPIO_PORT_SHIFT | 8 ),
P2_09 = (2 << GPIO_PORT_SHIFT | 9 ),
P2_10 = (2 << GPIO_PORT_SHIFT | 10),
P2_11 = (2 << GPIO_PORT_SHIFT | 11),
// USB Pins
USBTX = P0_10,
USBRX = P0_11,
USBTX1 = P1_15,
USBRX1 = P2_00,
// mbed original LED naming
LED1 = P2_02,
LED2 = P2_10,
LED3 = LED2,
LED4 = LED1,
//Push buttons
PB0 = P1_00, // BTN1
PB1 = P0_09, // BTN2
BOOT = P1_01,
WAKE0 = P0_15, // JP15 to select
WAKE1 = P1_00, // JP8 (BTN1 jumper) to select
WAKE2 = P0_13, // JP4 to select
WAKE3 = P2_01, // JP15 to select
// SPI Pins
SPI0_SCLK = P0_00,
SPI0_MOSI = P0_01,
SPI0_MISO = P0_02,
SPI0_CS0 = P0_03,
SPI0_CS1 = P1_10,
SPI0_CS2 = P2_08,
SPI0_CS3 = P2_09,
SPI1_SCLK = P1_06,
SPI1_MOSI = P1_07,
SPI1_MISO = P1_08,
SPI1_CS0 = P1_09,
SPI1_CS1 = P2_11,
SPI1_CS2 = P2_02,
SPI1_CS3 = P1_10,
SPI2_SCLK = P1_02,
SPI2_MOSI = P1_03,
SPI2_MISO = P1_04,
SPI2_CS0 = P1_05,
SPI2_CS1 = P0_09,
SPI2_CS2 = P2_10,
SPI2_CS3 = P2_07,
// ADC Pins
ADC_VIN0 = P2_03,
ADC_VIN1 = P2_04,
ADC_VIN2 = P2_05,
ADC_VIN3 = P2_06,
ADC_VIN4 = P2_07,
ADC_VIN5 = P2_08,
ADC_VIN6 = P2_09,
ADC_VIN7 = P2_10,
// Arduino Headers
D0 = P0_10, // UART0_TXD
D1 = P0_11, // UART0_RXD
D2 = P0_15, // INT_WAKE0
D3 = P0_13, // EXT_INT_WAKE2
D4 = P0_09, // EXT_SPI2_CS1
D5 = P2_01, // INT_WAKE3 or EXT_RTC1_SS1 via JP8
D6 = P1_11, // GPIO_27
D7 = P0_12, // GPIO_08 or GPIO_12 via JP7
D8 = P1_12, // GPIO_28
D9 = P1_14, // GPIO_30
D10 = SPI0_CS2, // P2_08
D11 = SPI0_MOSI, // P0_01
D12 = SPI0_MISO, // P0_02
D13 = SPI0_SCLK, // P0_00
I2C_SCL = P0_04, // I2C_SCL
I2C_SDA = P0_05, // I2C_SDA
A0 = P2_03, // ADC0
A1 = P2_04, // EXT_ADC1
A2 = P2_05, // EXT_ADC2
A3 = P2_06, // ADC3
A4 = P2_07, // SPI2_CS3/ADC_VIN4
A5 = P2_10, // EXT_GPIO42/ADC_VIN7
// Not connected
NC = (int)0xFFFFFFFF
} PinName;
typedef enum {
PullNone = 0,
PullDown = 1,
PullUp = 2,
PullDefault = PullNone
} PinMode;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,272 @@
/*!
*****************************************************************************
* @file: startup_ADuCM3029.c
* @brief: Interrupt table and default handlers for ADuCM302x
* @version: $Revision: $
* @date: $Date: $
*-----------------------------------------------------------------------------
*
Copyright (c) 2010-2017 Analog Devices, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Modified versions of the software must be conspicuously marked as such.
- This software is licensed solely and exclusively for use with processors
manufactured by or for Analog Devices, Inc.
- This software may not be combined or merged with other code in any manner
that would cause the software to become subject to terms and conditions
which differ from those listed here.
- Neither the name of Analog Devices, Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
- The use of this software may or may not infringe the patent rights of one
or more patent holders. This license does not release you from the
requirement that you obtain separate licenses from these patent holders
to use this software.
THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF CLAIMS OF INTELLECTUAL
PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <stdint.h>
#ifdef __CC_ARM
#include <rt_misc.h>
#endif
#include <cmsis.h>
#include <startup_ADuCM3029.h>
#include <mbed_rtx.h>
/*----------------------------------------------------------------------------
External function Declaration
*----------------------------------------------------------------------------*/
extern void SramInit(void);
/*----------------------------------------------------------------------------
Checksum options
*----------------------------------------------------------------------------*/
#if defined (__CC_ARM)
__attribute__ ((at(0x000001A0u)))
#elif defined( __ICCARM__)
__root
#endif /* __ICCARM__ */
const uint32_t SECTION_PLACE(blank_checksum[],".checksum") =
{
BLANKX60,BLANKX600
};
/*----------------------------------------------------------------------------
Exception / Interrupt Handler
*----------------------------------------------------------------------------*/
WEAK_FUNCTION( NMI_Handler )
WEAK_FUNCTION( HardFault_Handler )
WEAK_FUNCTION( MemManage_Handler )
WEAK_FUNCTION( BusFault_Handler )
WEAK_FUNCTION( UsageFault_Handler )
WEAK_FUNCTION( SVC_Handler )
WEAK_FUNCTION( DebugMon_Handler )
WEAK_FUNCTION( PendSV_Handler )
WEAK_FUNCTION( SysTick_Handler )
WEAK_FUNCTION( RTC1_Int_Handler )
WEAK_FUNCTION( Ext_Int0_Handler )
WEAK_FUNCTION( Ext_Int1_Handler )
WEAK_FUNCTION( Ext_Int2_Handler )
WEAK_FUNCTION( Ext_Int3_Handler )
WEAK_FUNCTION( WDog_Tmr_Int_Handler )
WEAK_FUNCTION( Vreg_over_Int_Handler )
WEAK_FUNCTION( Battery_Voltage_Int_Handler )
WEAK_FUNCTION( RTC0_Int_Handler )
WEAK_FUNCTION( GPIO_A_Int_Handler )
WEAK_FUNCTION( GPIO_B_Int_Handler )
WEAK_FUNCTION( GP_Tmr0_Int_Handler )
WEAK_FUNCTION( GP_Tmr1_Int_Handler )
WEAK_FUNCTION( Flash0_Int_Handler )
WEAK_FUNCTION( UART_Int_Handler )
WEAK_FUNCTION( SPI0_Int_Handler )
WEAK_FUNCTION( SPI2_Int_Handler )
WEAK_FUNCTION( I2C0_Slave_Int_Handler )
WEAK_FUNCTION( I2C0_Master_Int_Handler )
WEAK_FUNCTION( DMA_Err_Int_Handler )
WEAK_FUNCTION( DMA_SPI2_TX_Int_Handler )
WEAK_FUNCTION( DMA_SPI2_RX_Int_Handler )
WEAK_FUNCTION( DMA_SPORT0A_Int_Handler )
WEAK_FUNCTION( DMA_SPORT0B_Int_Handler )
WEAK_FUNCTION( DMA_SPI0_TX_Int_Handler )
WEAK_FUNCTION( DMA_SPI0_RX_Int_Handler )
WEAK_FUNCTION( DMA_SPI1_TX_Int_Handler )
WEAK_FUNCTION( DMA_SPI1_RX_Int_Handler )
WEAK_FUNCTION( DMA_UART_TX_Int_Handler )
WEAK_FUNCTION( DMA_UART_RX_Int_Handler )
WEAK_FUNCTION( DMA_I2C0_STX_Int_Handler )
WEAK_FUNCTION( DMA_I2C0_SRX_Int_Handler )
WEAK_FUNCTION( DMA_I2C0_MX_Int_Handler )
WEAK_FUNCTION( DMA_AES0_IN_Int_Handler )
WEAK_FUNCTION( DMA_AES0_OUT_Int_Handler )
WEAK_FUNCTION( DMA_FLASH0_Int_Handler )
WEAK_FUNCTION( SPORT0A_Int_Handler )
WEAK_FUNCTION( SPORT0B_Int_Handler )
WEAK_FUNCTION( Crypto_Int_Handler )
WEAK_FUNCTION( DMA_ADC0_Int_Handler )
WEAK_FUNCTION( GP_Tmr2_Int_Handler )
WEAK_FUNCTION( Crystal_osc_Int_Handler )
WEAK_FUNCTION( SPI1_Int_Handler )
WEAK_FUNCTION( PLL_Int_Handler )
WEAK_FUNCTION( RNG_Int_Handler )
WEAK_FUNCTION( Beep_Int_Handler )
WEAK_FUNCTION( ADC_Int_Handler )
WEAK_FUNCTION( DMA_SIP0_Int_Handler )
WEAK_FUNCTION( DMA_SIP1_Int_Handler )
WEAK_FUNCTION( DMA_SIP2_Int_Handler )
WEAK_FUNCTION( DMA_SIP3_Int_Handler )
WEAK_FUNCTION( DMA_SIP4_Int_Handler )
WEAK_FUNCTION( DMA_SIP5_Int_Handler )
WEAK_FUNCTION( DMA_SIP6_Int_Handler )
WEAK_FUNCTION( DMA_SIP7_Int_Handler )
/*----------------------------------------------------------------------------
Exception / Interrupt Vector table
*----------------------------------------------------------------------------*/
const pFunc SECTION_PLACE(IVT_NAME[104],VECTOR_SECTION) =
{
(pFunc) INITIAL_SP, /* Initial Stack Pointer */
ADUCM3029_VECTORS
};
/*----------------------------------------------------------------------------
* Initialize .bss and .data for GNU
*----------------------------------------------------------------------------*/
#if defined( __GNUC__) && !defined (__CC_ARM)
void zero_bss(void)
{
uint32_t *pSrc, *pDest;
uint32_t *pTable __attribute__((unused));
#ifdef __STARTUP_COPY_MULTIPLE
/* Multiple sections scheme.
*
* Between symbol address __copy_table_start__ and __copy_table_end__,
* there are array of triplets, each of which specify:
* offset 0: LMA of start of a section to copy from
* offset 4: VMA of start of a section to copy to
* offset 8: size of the section to copy. Must be multiply of 4
*
* All addresses must be aligned to 4 bytes boundary.
*/
pTable = &__copy_table_start__;
for (; pTable < &__copy_table_end__; pTable = pTable + 3) {
pSrc = (uint32_t*)*(pTable + 0);
pDest = (uint32_t*)*(pTable + 1);
for (; pDest < (uint32_t*)(*(pTable + 1) + *(pTable + 2)) ; ) {
*pDest++ = *pSrc++;
}
}
#else
/* Single section scheme.
*
* The ranges of copy from/to are specified by following symbols
* __etext: LMA of start of the section to copy from. Usually end of text
* __data_start__: VMA of start of the section to copy to
* __data_end__: VMA of end of the section to copy to
*
* All addresses must be aligned to 4 bytes boundary.
*/
pSrc = (uint32_t*)(&__etext);
pDest = (uint32_t*)(&__data_start__);
for ( ; pDest < (uint32_t*)(&__data_end__) ; ) {
*pDest++ = *pSrc++;
}
#endif /*__STARTUP_COPY_MULTIPLE */
/* This part of work usually is done in C library startup code. Otherwise,
* define this macro to enable it in this startup.
*
* There are two schemes too. One can clear multiple BSS sections. Another
* can only clear one section. The former is more size expensive than the
* latter.
*
* Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
* Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later.
*/
#ifdef __STARTUP_CLEAR_BSS_MULTIPLE
/* Multiple sections scheme.
*
* Between symbol address __copy_table_start__ and __copy_table_end__,
* there are array of tuples specifying:
* offset 0: Start of a BSS section
* offset 4: Size of this BSS section. Must be multiply of 4
*/
pTable = (uint32_t*)(&__zero_table_start__);
for (; pTable < (uint32_t*)(&__zero_table_end__); pTable = pTable + 2) {
pDest = (uint32_t*)*(pTable + 0);
for (; pDest < (uint32_t*)(*(pTable + 0) + *(pTable + 1)) ; ) {
*pDest++ = 0;
}
}
#elif defined (__STARTUP_CLEAR_BSS)
/* Single BSS section scheme.
*
* The BSS section is specified by following symbols
* __bss_start__: start of the BSS section.
* __bss_end__: end of the BSS section.
*
* Both addresses must be aligned to 4 bytes boundary.
*/
pDest = &__bss_start__;
for ( ; pDest < &__bss_end__ ; ) {
*pDest++ = 0ul;
}
#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */
}
#endif
/*----------------------------------------------------------------------------
* Function : Reset_Handler (-15)
* Description : Reset event handler
*----------------------------------------------------------------------------*/
void Reset_Handler(void)
{
/* Configure the SRAM first. This is done first because the bss section
may reside in DSRAM bank B. */
SramInit();
#if defined(__GNUC__) && !defined (__CC_ARM)
/* Clear the bss section for GCC build only */
zero_bss();
#endif
/* initialize system */
SystemInit();
/* branch to other initialization routines before main */
RESET_EXCPT_HNDLR();
}
/*----------------------------------------------------------------------------
Default Handler for Exceptions / Interrupts
*----------------------------------------------------------------------------*/
#if defined(__CC_ARM) || defined (__GNUC__)
void Default_Handler(void)
{
while(1);
}
#endif

View File

@ -0,0 +1,210 @@
/*!
*****************************************************************************
* @file: startup_ADuCM3029.h
* @brief: CMSIS Cortex-M3 Core Peripheral Access Layer Header File for
* ADI ADuCxxx Device Series
* @version: $Revision: $
* @date: $Date: $
*-----------------------------------------------------------------------------
*
Copyright (c) 2010-2017 Analog Devices, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Modified versions of the software must be conspicuously marked as such.
- This software is licensed solely and exclusively for use with processors
manufactured by or for Analog Devices, Inc.
- This software may not be combined or merged with other code in any manner
that would cause the software to become subject to terms and conditions
which differ from those listed here.
- Neither the name of Analog Devices, Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
- The use of this software may or may not infringe the patent rights of one
or more patent holders. This license does not release you from the
requirement that you obtain separate licenses from these patent holders
to use this software.
THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF CLAIMS OF INTELLECTUAL
PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
/*
WEAK_FUNC(func)
If this is available for a compiler, apply whatever attributes are needed
to a function definition ("func") to flag that the function is a "weak" one.
VECTOR_SECTION
A particular setup may have a requirement that the vector table be placed
in a particular section. This specifies the name of that section
RESET_EXCPT_HNDLR
A particular setup may have a requirement for a different reset handler.
This specifies the name of that handler.
*/
#ifndef __STARTUP_H__
#define __STARTUP_H__
#define VECTOR_SECTION ".vectors"
#ifdef __CC_ARM
extern unsigned Image$$ADUCM_HEAP$$Base[];
extern unsigned Image$$ADUCM_HEAP$$ZI$$Limit[];
void Default_Handler(void);
#define SECTION_NAME(sectionname) __attribute__ ((section(sectionname)))
#define SECTION_PLACE(def,sectionname) def __attribute__ ((section(sectionname)))
#define IVT_NAME __Vectors
#define RESET_EXCPT_HNDLR __main
#define COMPILER_NAME "ARMCC"
#define WEAK_FUNCTION(x) void x (void) __attribute__ ((weak, alias("Default_Handler")));
#elif defined(__ICCARM__)
#pragma diag_suppress=Pm093,Pm140
#define SECTION_PLACE(def,sectionname) def @ sectionname
#define IVT_NAME __vector_table
#define WEAK_FUNC(func) __weak func
#define RESET_EXCPT_HNDLR __iar_program_start
#define COMPILER_NAME "ICCARM"
#define WEAK_FUNCTION(x) WEAK_FUNC ( void x (void)) { while(1){} }
#elif defined(__GNUC__)
extern unsigned __etext;
extern unsigned __data_start__;
extern unsigned __data_end__;
extern unsigned __copy_table_start__;
extern unsigned __copy_table_end__;
extern unsigned __zero_table_start__;
extern unsigned __zero_table_end__;
extern unsigned __bss_start__;
extern unsigned __bss_end__;
extern unsigned __StackTop;
void Default_Handler(void);
#ifndef __START
extern void _start(void) __attribute__((noreturn)); /* PreeMain (C library entry point) */
#define RESET_EXCPT_HNDLR _start
#else
extern int __START(void) __attribute__((noreturn)); /* main entry point */
#define RESET_EXCPT_HNDLR __START
#endif
#define SECTION_NAME(sectionname) __attribute__ ((section(sectionname)))
#define SECTION_PLACE(def,sectionname) def __attribute__ ((section(sectionname)))
#define IVT_NAME __Vectors
#define COMPILER_NAME "GNUC"
#define WEAK_FUNCTION(x) void x (void) __attribute__ ((weak, alias("Default_Handler")));
#define __STARTUP_CLEAR_BSS_MULTIPLE
#endif // __GNUC__
#define LASTCRCPAGE 0
#define BLANKX4 0xFFFFFFFF
#define BLANKX20 BLANKX4,BLANKX4,BLANKX4,BLANKX4,BLANKX4,BLANKX4,BLANKX4,BLANKX4
#define BLANKX100 BLANKX20,BLANKX20,BLANKX20,BLANKX20,BLANKX20,BLANKX20,BLANKX20,BLANKX20
#define BLANKX600 BLANKX100,BLANKX100,BLANKX100,BLANKX100,BLANKX100,BLANKX100
#define BLANKX60 BLANKX20,BLANKX20,BLANKX20
void RESET_EXCPT_HNDLR(void);
void Reset_Handler(void);
/* IVT typedefs. */
typedef void( *pFunc )( void );
#define ADUCM3029_VECTORS /* Cortex-M3 Exceptions Handler */ \
Reset_Handler, /* -15 */ \
NMI_Handler, /* -14 */ \
HardFault_Handler, /* -13 */ \
MemManage_Handler, /* -12 */ \
BusFault_Handler, /* -11 */ \
UsageFault_Handler, /* -10 */ \
0, /* -9 */ \
0, /* -8 */ \
0, /* -7 */ \
0, /* -6 */ \
SVC_Handler, /* -5 */ \
DebugMon_Handler, /* -4 */ \
0, /* -3 */ \
PendSV_Handler, /* -2 */ \
SysTick_Handler, /* -1 */ \
/* External interrupts */ \
RTC1_Int_Handler, /* 0 */ \
Ext_Int0_Handler, /* 1 */ \
Ext_Int1_Handler, /* 2 */ \
Ext_Int2_Handler, /* 3 */ \
Ext_Int3_Handler, /* 4 */ \
WDog_Tmr_Int_Handler, /* 5 */ \
Vreg_over_Int_Handler, /* 6 */ \
Battery_Voltage_Int_Handler, /* 7 */ \
RTC0_Int_Handler, /* 8 */ \
GPIO_A_Int_Handler, /* 9 */ \
GPIO_B_Int_Handler, /* 10 */ \
GP_Tmr0_Int_Handler, /* 11 */ \
GP_Tmr1_Int_Handler, /* 12 */ \
Flash0_Int_Handler, /* 13 */ \
UART_Int_Handler, /* 14 */ \
SPI0_Int_Handler, /* 15 */ \
SPI2_Int_Handler, /* 16 */ \
I2C0_Slave_Int_Handler, /* 17 */ \
I2C0_Master_Int_Handler, /* 18 */ \
DMA_Err_Int_Handler, /* 19 */ \
DMA_SPI2_TX_Int_Handler, /* 20 */ \
DMA_SPI2_RX_Int_Handler, /* 21 */ \
DMA_SPORT0A_Int_Handler, /* 22 */ \
DMA_SPORT0B_Int_Handler, /* 23 */ \
DMA_SPI0_TX_Int_Handler, /* 24 */ \
DMA_SPI0_RX_Int_Handler, /* 25 */ \
DMA_SPI1_TX_Int_Handler, /* 26 */ \
DMA_SPI1_RX_Int_Handler, /* 27 */ \
DMA_UART_TX_Int_Handler, /* 28 */ \
DMA_UART_RX_Int_Handler, /* 29 */ \
DMA_I2C0_STX_Int_Handler, /* 30 */ \
DMA_I2C0_SRX_Int_Handler, /* 31 */ \
DMA_I2C0_MX_Int_Handler, /* 32 */ \
DMA_AES0_IN_Int_Handler, /* 33 */ \
DMA_AES0_OUT_Int_Handler, /* 34 */ \
DMA_FLASH0_Int_Handler, /* 35 */ \
SPORT0A_Int_Handler, /* 36 */ \
SPORT0B_Int_Handler, /* 37 */ \
Crypto_Int_Handler, /* 38 */ \
DMA_ADC0_Int_Handler, /* 39 */ \
GP_Tmr2_Int_Handler, /* 40 */ \
Crystal_osc_Int_Handler, /* 41 */ \
SPI1_Int_Handler, /* 42 */ \
PLL_Int_Handler, /* 43 */ \
RNG_Int_Handler, /* 44 */ \
Beep_Int_Handler, /* 45 */ \
ADC_Int_Handler, /* 46 */ \
0, /* 47 */ \
0, /* 48 */ \
0, /* 49 */ \
0, /* 50 */ \
0, /* 51 */ \
0, /* 52 */ \
0, /* 53 */ \
0, /* 54 */ \
0, /* 55 */ \
DMA_SIP0_Int_Handler, /* 56 */ \
DMA_SIP1_Int_Handler, /* 57 */ \
DMA_SIP2_Int_Handler, /* 58 */ \
DMA_SIP3_Int_Handler, /* 59 */ \
DMA_SIP4_Int_Handler, /* 60 */ \
DMA_SIP5_Int_Handler, /* 61 */ \
DMA_SIP6_Int_Handler, /* 62 */ \
DMA_SIP7_Int_Handler, /* 63 */ \
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 64 - 79 */ \
(pFunc)BLANKX4, (pFunc)BLANKX4, /* security_options */ \
(pFunc)BLANKX4, (pFunc)BLANKX4, \
(pFunc)0xA79C3203u, (pFunc)LASTCRCPAGE, \
(pFunc)BLANKX4, (pFunc)BLANKX4 /* 80 - 87 */
#endif /* __STARTUP_H__ */

View File

@ -0,0 +1,286 @@
/******************************************************************************
* @file system_ADuCM3029.c
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer Source File for
* Device ADuCM3029
* @version V3.10
* @date 23. November 2012
*
******************************************************************************/
/* Copyright (c) 2012 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
*
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Portions Copyright (c) 2016 - 2017 Analog Devices, Inc.
---------------------------------------------------------------------------*/
#include <cmsis.h>
#include <adi_pwr.h>
#include <adi_gpio.h>
#include <startup_ADuCM3029.h>
/*----------------------------------------------------------------------------
Define clocks
*----------------------------------------------------------------------------*/
#ifdef ADI_DEBUG
/* only needed in debug mode */
uint32_t lfClock = 0u; /* "lf_clk" coming out of LF mux */
#endif
/*----------------------------------------------------------------------------
Clock Variable definitions
*----------------------------------------------------------------------------*/
/* Note that these variables will be re-initialized to the value set here by the
LIBC startup code, so if other clock values are required, make sure set them
here.
*/
uint32_t hfClock = __HFOSC; /* "root_clk" output of HF mux */
uint32_t gpioClock = 0; /* external GPIO clock */
uint32_t SystemCoreClock = __HFOSC; /*!< System Clock Frequency (Core Clock) */
/*----------------------------------------------------------------------------
Clock functions
*----------------------------------------------------------------------------*/
/*!
* Update the clock.
*
* @param none
* @return none
*
* @brief Updates the variable SystemCoreClock and must be called whenever
* the core clock is changed during program execution.
*/
void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */
{
uint32_t val;
uint16_t div2;
float mul2, nDivisor, nMulfactor;
#ifdef ADI_DEBUG
/* "lfclock" is only used during debug checks... */
/* LF clock is always 32k, whether osc or xtal */
lfClock = __LFCLK; /* for beep, wdt and lcd */
if( lfClock == 0 )
{
while( 1 );
}
#endif
/* Update Core Clock sources */
/* update the HF clock */
switch( pADI_CLKG0_CLK->CTL0 & BITM_CLKG_CLK_CTL0_CLKMUX ) {
case HFMUX_INTERNAL_OSC_VAL:
hfClock = __HFOSC;
break;
case HFMUX_EXTERNAL_XTAL_VAL:
hfClock = __HFXTAL;
break;
case HFMUX_SYSTEM_SPLL_VAL:
/* Calculate System PLL output frequency */
if( pADI_CLKG0_CLK->CTL0 & BITM_CLKG_CLK_CTL0_SPLLIPSEL )
{
/* PLL input from HFXTAL */
val = __HFXTAL;
}
else
{
/* PLL input from HFOSC */
val = __HFOSC;
}
/* PLL NSEL multiplier */
nMulfactor = ( ( pADI_CLKG0_CLK->CTL3 &BITM_CLKG_CLK_CTL3_SPLLNSEL ) >> BITP_CLKG_CLK_CTL3_SPLLNSEL );
/* PLL MSEL divider */
nDivisor = ( ( pADI_CLKG0_CLK->CTL3 & BITM_CLKG_CLK_CTL3_SPLLMSEL ) >> BITP_CLKG_CLK_CTL3_SPLLMSEL );
/* PLL NSEL multiplier */
div2 = ( ( pADI_CLKG0_CLK->CTL3 & BITM_CLKG_CLK_CTL3_SPLLDIV2 ) >> BITP_CLKG_CLK_CTL3_SPLLDIV2 );
/* PLL MSEL divider */
mul2 = ( ( pADI_CLKG0_CLK->CTL3 & BITM_CLKG_CLK_CTL3_SPLLMUL2 ) >> BITP_CLKG_CLK_CTL3_SPLLMUL2 );
val = ( ( (uint32_t)( ( nMulfactor * ( mul2 + 1.0 ) * (float) val ) / nDivisor ) ) >> div2 );
hfClock = val;
break;
case HFMUX_GPIO_VAL:
hfClock = gpioClock;
break;
default:
return;
} /* end switch */
SystemCoreClock = hfClock;
}
/*!
* Configure the SRAM banks
*
* @return none
*
* @brief Setup the SRAM banks.
* Initialize the SRAM configuration and retention.
*/
void SramInit(void)
{
/* SRAM Bank1 and Banck2 are hibernate-preserved */
adi_system_EnableRetention(ADI_SRAM_BANK_1, true);
adi_system_EnableRetention(ADI_SRAM_BANK_2, true);
/* To disable the instruction SRAM and entire 64K of SRAM is used as DSRAM */
adi_system_EnableISRAM(false);
/* To disable the instruction cache */
adi_system_EnableCache(false);
}
/*!
* Initialize the system
*
* @return none
*
* @brief Setup the microcontroller system.
* Initialize the System and update the relocate vector table.
*/
void SystemInit (void)
{
uint32_t IntStatus;
/* Turn off Tile 3029 LED */
pADI_GPIO1->OEN |= ADI_GPIO_PIN_10;
pADI_GPIO2->OEN |= ADI_GPIO_PIN_2;
pADI_GPIO1->SET = ADI_GPIO_PIN_10;
pADI_GPIO2->SET = ADI_GPIO_PIN_2;
IntStatus = __get_PRIMASK();
__disable_irq();
/* Set boot ROM IVT. */
SCB->VTOR = (uint32_t)NVIC_FLASH_VECTOR_ADDRESS;
/* Set all three (USGFAULTENA, BUSFAULTENA, and MEMFAULTENA) fault enable bits
* in the System Control Block, System Handler Control and State Register
* otherwise these faults are handled as hard faults.
*/
SCB->SHCSR = SCB_SHCSR_USGFAULTENA_Msk |
SCB_SHCSR_BUSFAULTENA_Msk |
SCB_SHCSR_MEMFAULTENA_Msk ;
adi_pwr_Init();
adi_pwr_SetClockDivider(ADI_CLOCK_HCLK,1);
adi_pwr_SetClockDivider(ADI_CLOCK_PCLK,1);
/* Set up the LF clock source */
adi_pwr_SetLFClockMux(ADI_CLOCK_MUX_LFCLK_LFXTAL);
adi_pwr_EnableClockSource(ADI_CLOCK_SOURCE_LFXTAL,true);
__set_PRIMASK(IntStatus);
}
/*!
* @brief This enables or disables the cache.
* \n @param bEnable : To specify whether to enable/disable cache.
* \n true : To enable cache.
* \n
* \n false : To disable cache.
* \n
* @return none
*
*/
void adi_system_EnableCache(bool bEnable)
{
pADI_FLCC0_CACHE->KEY = CACHE_CONTROLLER_KEY;
if(bEnable)
{
pADI_FLCC0_CACHE->SETUP |= BITM_FLCC_CACHE_SETUP_ICEN;
}
else
{
pADI_FLCC0_CACHE->SETUP &= ~BITM_FLCC_CACHE_SETUP_ICEN;
}
}
/*!
* @brief This enables or disables instruction SRAM
*
* @param bEnable: To enable/disable the instruction SRAM.
* \n true : To enable cache.
* \n
* \n false : To disable cache.
* \n
* @return none
* @note: Please note that respective linker file need to support the configuration.
*/
void adi_system_EnableISRAM(bool bEnable)
{
if(bEnable)
{
pADI_PMG0_TST->SRAM_CTL |= BITM_PMG_TST_SRAM_CTL_INSTREN;
}
else
{
pADI_PMG0_TST->SRAM_CTL &= ~BITM_PMG_TST_SRAM_CTL_INSTREN;
}
}
/*!
* @brief This enables/disable SRAM retention during the hibernation.
* @param eBank: Specify which SRAM bank. Only BANK1 and BANK2 are valid.
* @param bEnable: To enable/disable the retention for specified SRAM bank.
* \n true : To enable retention during the hibernation.
* \n
* \n false :To disable retention during the hibernation.
* \n
* @return : SUCCESS : Configured successfully.
* FAILURE : For invalid bank.
* @note: Please note that respective linker file need to support the configuration. Only BANK-1 and
BANK-2 of SRAM is valid.
*/
uint32_t adi_system_EnableRetention(ADI_SRAM_BANK eBank,bool bEnable)
{
#ifdef ADI_DEBUG
if((eBank != ADI_SRAM_BANK_1) && (eBank != ADI_SRAM_BANK_2))
{
return FAILURE;
}
#endif
pADI_PMG0->PWRKEY = PWRKEY_VALUE_KEY;
if(bEnable)
{
pADI_PMG0->SRAMRET |= (uint32_t)eBank>>1;
}
else
{
pADI_PMG0->SRAMRET &= ~((uint32_t)eBank >> 1);
}
return SUCCESS;
}

View File

@ -0,0 +1,65 @@
;******************************************************************************
; File: ADuCM3029.sct
; Scatter loading file for Analog Devices ADuCM3029 processor
;
; Copyright (c) 2011 - 2014 ARM LIMITED
; Copyright (c) 2016 - 2017 Analog Devices, Inc.
;
; All rights reserved.
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; - Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; - Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; - Neither the name of ARM nor the names of its contributors may be used
; to endorse or promote products derived from this software without
; specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
; POSSIBILITY OF SUCH DAMAGE.
;
; Portions Copyright (c) 2017 Analog Devices, Inc.
;
;******************************************************************************
LR_IROM1 0x00000000 0x00040000 {
ADUCM_IROM1 0x00000000 0x00040000 { ; romflash start address
*(.vectors, +First)
*(.checksum)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000200 { ; data section
.ANY (+RW)
}
ADUCM_HEAP AlignExpr(+0, 16) EMPTY
(0x20003000 - AlignExpr(ImageLimit(RW_IRAM1), 16)) { ; heap
}
ADUCM_STACK AlignExpr(+0, 16) EMPTY 0x1000 { ; stack
}
ADUCM_IRAM2 0x20004000 0x4000 { ; bss section
.ANY (+RW +ZI)
}
ADUCM_IRAM3 0x20040000 0x8000 { ; non-retainable memory region
.ANY (+RW +ZI)
}
}
ScatterAssert(ImageLimit(RW_IRAM1) <= 0x20002000)

View File

@ -0,0 +1,225 @@
/*
* Portions Copyright (c) 2016 - 2017 Analog Devices, Inc.
*
* Based on Device/ARM/ARMCM3/Source/GCC/gcc_arm.ld file in
* ARM.CMSIS.4.5.0.pack.
*/
/* Linker script to configure memory regions. */
MEMORY
{
/* Flash bank0 */
FLASH0 (rx) : ORIGIN = 0x00000000, LENGTH = 0x800
/* Flash bank0 - bank127*/
FLASH (rx) : ORIGIN = 0x00000800, LENGTH = 256k - 0x800
/* SRAM bank 0+1 */
DSRAM_V (rwx) : ORIGIN = 0x20000000, LENGTH = 0x200
DSRAM_A (rwx) : ORIGIN = 0x20000200, LENGTH = 16k - 0x200
DSRAM_C (rwx) : ORIGIN = 0x20004000, LENGTH = 16k
/* SRAM bank 3 */
DSRAM_B (rwx) : ORIGIN = 0x20040000, LENGTH = 32k
}
/* Library configurations */
GROUP(libgcc.a libc.a libm.a libnosys.a)
/* Custom stack and heap sizes */
__stack_size__ = 0x1000;
__heap_size__ = 0x2000;
/* select custom or default sizes for stack and heap */
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0400;
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x0C00;
/* Linker script to place sections and symbol values.
* It references the following symbols, which must be defined in code:
* Reset_Handler : Entry of reset handler
*
* It defines the following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
* __copy_table_start__
* __copy_table_end__
* __zero_table_start__
* __zero_table_end__
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __end__
* end
* __HeapLimit
* __StackLimit
* __StackTop
* __stack
* __Vectors_End
* __Vectors_Size
*/
ENTRY(Reset_Handler)
SECTIONS
{
.vectors :
{
KEEP(*(.vectors))
__Vectors_End = .;
__Vectors_Size = __Vectors_End - __Vectors;
__end__ = .;
KEEP(*(.checksum))
} > FLASH0
.text :
{
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
/* To copy multiple ROM to RAM sections,
* uncomment .copy.table section and,
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
/*
.copy.table :
{
. = ALIGN(4);
__copy_table_start__ = .;
LONG (__etext)
LONG (__data_start__)
LONG (__data_end__ - __data_start__)
LONG (__etext2)
LONG (__data2_start__)
LONG (__data2_end__ - __data2_start__)
__copy_table_end__ = .;
} > FLASH
*/
/* To clear multiple BSS sections,
* uncomment .zero.table section and,
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
.zero.table :
{
. = ALIGN(4);
__zero_table_start__ = .;
LONG (__bss_start__)
LONG (__bss_end__ - __bss_start__)
LONG (__bss2_start__)
LONG (__bss2_end__ - __bss2_start__)
__zero_table_end__ = .;
} > FLASH
__etext = .;
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
KEEP(*(.jcr*))
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > DSRAM_A
.bss :
{
. = ALIGN(4);
__bss_start__ = .;
KEEP(*(.bss.gChannelControlDataArray))
KEEP(*(.bss.thread_stack_main))
KEEP(*(.bss.UartDeviceMem))
KEEP(*(.bss.os_thread_def_stack_event_loop_thread))
*(COMMON)
*(.bss)
. = ALIGN(4);
__bss_end__ = .;
} > DSRAM_C
.bss2 :
{
. = ALIGN(4);
__bss2_start__ = .;
*(.bss*)
. = ALIGN(4);
__bss2_end__ = .;
} > DSRAM_B
.heap (COPY):
{
__HeapBase = .;
__end__ = .;
end = __end__;
. += HEAP_SIZE;
__HeapLimit = .;
} > DSRAM_A
/* Set stack top to end of DSRAM_A, and move stack limit down by
* size of stack_dummy section */
__StackTop = ORIGIN(DSRAM_C);
__StackLimit = __StackTop - STACK_SIZE;
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds DSRAM_A limit when they are both in DSRAM_A
ASSERT(__StackLimit >= __HeapLimit, "region DSRAM_A overflowed with stack") */
}

View File

@ -0,0 +1,49 @@
/******************************************************************************
* File: ADuCM3029.icf
* ILINK Configuration File for Analog Devices ADuCM3029 processor
*
* Copyright (c) 2011 - 2014 ARM LIMITED
* Copyright (c) 2016 - 2017 Analog Devices, Inc.
*
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
define memory mem with size = 4G;
define region ROM_PAGE0_INTVEC = mem:[from 0x00000000 size 0x000001A0];
define region ROM_PAGE0_CHECKSUM = mem:[from 0x000001A0 size 0x00000660];
define region ROM_REGION = mem:[from 0x00000800 size 254K];
define region RAM_bank1_region = mem:[from 0x20000200 size 0x00003E00];
define region RAM_bank2_region = mem:[from 0x20004000 size 0x00004000]
| mem:[from 0x20040000 size 0x00008000];
define block CSTACK with alignment = 16, size = 0x1000 { };
define block HEAP with alignment = 16, size = 0x2000 { };
do not initialize { section .noinit };
initialize by copy { rw };
place at start of ROM_PAGE0_INTVEC { ro section .vectors };
place in ROM_PAGE0_CHECKSUM { ro section .checksum };
place in ROM_REGION { ro };
place at end of RAM_bank1_region { block CSTACK };
place in RAM_bank1_region { rw section .data };
place in RAM_bank1_region { block HEAP };
place in RAM_bank2_region { rw };

View File

@ -0,0 +1,136 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#ifndef MBED_PERIPHERALNAMES_H
#define MBED_PERIPHERALNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
OSC32KCLK = 0,
} RTCName;
typedef enum {
UART_0 = 0,
UART_1 = 1,
UART_2 = 2,
UART_3 = 3,
UART_4 = 4,
} UARTName;
#define STDIO_UART_TX USBTX
#define STDIO_UART_RX USBRX
#define STDIO_UART UART_0
typedef enum {
I2C_0 = 0,
I2C_1 = 1,
I2C_2 = 2,
} I2CName;
#define TPM_SHIFT 8
typedef enum {
PWM_1 = (0 << TPM_SHIFT) | (0), // FTM0 CH0
PWM_2 = (0 << TPM_SHIFT) | (1), // FTM0 CH1
PWM_3 = (0 << TPM_SHIFT) | (2), // FTM0 CH2
PWM_4 = (0 << TPM_SHIFT) | (3), // FTM0 CH3
PWM_5 = (0 << TPM_SHIFT) | (4), // FTM0 CH4
PWM_6 = (0 << TPM_SHIFT) | (5), // FTM0 CH5
PWM_7 = (0 << TPM_SHIFT) | (6), // FTM0 CH6
PWM_8 = (0 << TPM_SHIFT) | (7), // FTM0 CH7
PWM_9 = (1 << TPM_SHIFT) | (0), // FTM1 CH0
PWM_10 = (1 << TPM_SHIFT) | (1), // FTM1 CH1
PWM_11 = (1 << TPM_SHIFT) | (2), // FTM1 CH2
PWM_12 = (1 << TPM_SHIFT) | (3), // FTM1 CH3
PWM_13 = (1 << TPM_SHIFT) | (4), // FTM1 CH4
PWM_14 = (1 << TPM_SHIFT) | (5), // FTM1 CH5
PWM_15 = (1 << TPM_SHIFT) | (6), // FTM1 CH6
PWM_16 = (1 << TPM_SHIFT) | (7), // FTM1 CH7
PWM_17 = (2 << TPM_SHIFT) | (0), // FTM2 CH0
PWM_18 = (2 << TPM_SHIFT) | (1), // FTM2 CH1
PWM_19 = (2 << TPM_SHIFT) | (2), // FTM2 CH2
PWM_20 = (2 << TPM_SHIFT) | (3), // FTM2 CH3
PWM_21 = (2 << TPM_SHIFT) | (4), // FTM2 CH4
PWM_22 = (2 << TPM_SHIFT) | (5), // FTM2 CH5
PWM_23 = (2 << TPM_SHIFT) | (6), // FTM2 CH6
PWM_24 = (2 << TPM_SHIFT) | (7), // FTM2 CH7
// could be 4 or could be 3... not sure what register
// this is for... too much abstraction
PWM_25 = (3 << TPM_SHIFT) | (0), // FTM3 CH0
PWM_26 = (3 << TPM_SHIFT) | (1), // FTM3 CH1
PWM_27 = (3 << TPM_SHIFT) | (2), // FTM3 CH2
PWM_28 = (3 << TPM_SHIFT) | (3), // FTM3 CH3
PWM_29 = (3 << TPM_SHIFT) | (4), // FTM3 CH4
PWM_30 = (3 << TPM_SHIFT) | (5), // FTM3 CH5
PWM_31 = (3 << TPM_SHIFT) | (6), // FTM3 CH6
PWM_32 = (3 << TPM_SHIFT) | (7), // FTM3 CH7
} PWMName;
typedef enum {
ADC0_VIN0 = 0,
ADC0_VIN1 = 1,
ADC0_VIN2 = 2,
ADC0_VIN3 = 3,
ADC0_VIN4 = 4,
ADC0_VIN5 = 5,
ADC0_VIN6 = 6,
ADC0_VIN7 = 7
} ADCName;
typedef enum {
DAC_0 = 0
} DACName;
typedef enum {
SPI_0 = 0,
SPI_1 = 1,
SPI_2 = 2,
} SPIName;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,111 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "PeripheralPins.h"
/************UART***************/
const PinMap PinMap_UART_TX[] = {
{P0_10, UART_0, 1},
{NC, NC, 0}
};
const PinMap PinMap_UART_RX[] = {
{P0_11, UART_0, 1},
{NC, NC, 0}
};
/************SPI***************/
const PinMap PinMap_SPI_SCLK[] = {
{P0_00, SPI_0, 1},
{P1_06, SPI_1, 1},
{P1_02, SPI_2, 1},
{NC, NC, 0}
};
const PinMap PinMap_SPI_MOSI[] = {
{P0_01, SPI_0, 1},
{P1_07, SPI_1, 1},
{P1_03, SPI_2, 1},
{NC, NC, 0}
};
const PinMap PinMap_SPI_MISO[] = {
{P0_02, SPI_0, 1},
{P1_08, SPI_1, 1},
{P1_04, SPI_2, 1},
{NC, NC, 0}
};
const PinMap PinMap_SPI_SSEL[] = {
{P0_03, SPI_0, 1},
{P1_09, SPI_1, 1},
{P2_10, SPI_2, 1},
{NC, NC, 0}
};
/************ADC***************/
const PinMap PinMap_ADC[] = {
{P2_03, ADC0_VIN0, 1},
{P2_04, ADC0_VIN1, 1},
{P2_05, ADC0_VIN2, 1},
{P2_06, ADC0_VIN3, 1},
{P2_07, ADC0_VIN4, 1},
{P2_08, ADC0_VIN5, 1},
{P2_09, ADC0_VIN6, 1},
{P2_10, ADC0_VIN7, 1},
{NC, NC, 0}
};
/************I2C***************/
const PinMap PinMap_I2C_SDA[] = {
{P0_05, I2C_0, 1},
{NC, NC, 0}
};
const PinMap PinMap_I2C_SCL[] = {
{P0_04, I2C_0, 1},
{NC, NC, 0}
};
/************RTC***************/
const PinMap PinMap_RTC[] = {
{NC, OSC32KCLK, 0},
};

View File

@ -0,0 +1,67 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#ifndef MBED_PERIPHERALPINS_H
#define MBED_PERIPHERALPINS_H
#include "pinmap.h"
#include "PeripheralNames.h"
/************RTC***************/
extern const PinMap PinMap_RTC[];
/************ADC***************/
extern const PinMap PinMap_ADC[];
/************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[];
/************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[];
#endif

View File

@ -0,0 +1,227 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "mbed_assert.h"
#include "analogin_api.h"
#if DEVICE_ANALOGIN
#include "adi_adc_def.h"
#include "pinmap.h"
#include "PeripheralPins.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ADC Device number */
#define ADC_DEV_NUM (0u)
/* Memory Required for adc driver */
static uint32_t DeviceMemory[(ADI_ADC_MEMORY_SIZE+3)/4];
/* Active channel */
static uint32_t adi_pin2channel(PinName pin);
/**
* \defgroup hal_analogin Analogin hal functions
* @{
*/
/** Initialize the analogin peripheral
*
* Configures the pin used by analogin.
* @param obj The analogin object to initialize
* @param pin The analogin pin name
*/
void analogin_init(analogin_t *obj, PinName pin)
{
ADI_ADC_HANDLE hDevice;
bool bCalibrationDone = false;
bool bReady = false;
ADCName peripheral;
uint32_t function, channel;
peripheral = (ADCName)pinmap_peripheral(pin, &PinMap_ADC[0]); // gives peripheral
MBED_ASSERT(peripheral != (ADCName)NC);
/* verify read function */
function = pinmap_function(pin, &PinMap_ADC[0]);
MBED_ASSERT(function == 1);
/* Configure PORT2_MUX registers */
pin_function(pin, function);
/* Configure active channel */
channel = adi_pin2channel(pin);
MBED_ASSERT(channel != 0xFFFFFFFF);
obj->UserBuffer.nChannels = channel;
/* Set ACLK to CCLK/16 */
adi_pwr_SetClockDivider(ADI_CLOCK_ACLK,16);
/* Set default values for conversion and delay cycles. This sets up a sampling rate of
16kHz. The sampling frequency is worked out from the following:
if delay time > 0:
Fs = ACLK / [((14 + sampling time) * oversample factor) + (delay time + 2)]
if delay time = 0:
Fs = ACLK / ((14 + sampling time) * oversample factor)
The sampling (or acquisition) and delay times are in number of ACLK clock cycles.
*/
obj->DelayCycles = 0;
obj->SampleCycles = 88;
/* Open the ADC device */
adi_adc_Open(ADC_DEV_NUM, DeviceMemory, sizeof(DeviceMemory), &hDevice);
obj->hDevice = hDevice;
/* Power up ADC */
adi_adc_PowerUp(hDevice, true);
/* Set ADC reference */
adi_adc_SetVrefSource(hDevice, ADI_ADC_VREF_SRC_INT_2_50_V);
/* Enable ADC sub system */
adi_adc_EnableADCSubSystem(hDevice, true);
/* Wait untilthe ADC is ready for sampling */
while(bReady == false) {
adi_adc_IsReady(hDevice, &bReady);
}
/* Start calibration */
adi_adc_StartCalibration(hDevice);
/* Wait until calibration is done */
while (!bCalibrationDone) {
adi_adc_IsCalibrationDone(hDevice, &bCalibrationDone);
}
/* Set the delay time */
adi_adc_SetDelayTime(hDevice, obj->DelayCycles);
/* Set the acquisition time. (Application need to change it based on the impedence) */
adi_adc_SetAcquisitionTime(hDevice, obj->SampleCycles);
}
/** Read the input voltage, represented as a float in the range [0.0, 1.0]
*
* @param obj The analogin object
* @return A floating value representing the current input voltage
*/
float analogin_read(analogin_t *obj)
{
float fl32 = (float)analogin_read_u16(obj)/(float)4095.0;
return(fl32);
}
/** Read the value from analogin pin, represented as an unsigned 16bit value
*
* @param obj The analogin object
* @return An unsigned 16bit value representing the current input voltage
*/
uint16_t analogin_read_u16(analogin_t *obj)
{
ADI_ADC_HANDLE hDevice = obj->hDevice;
ADI_ADC_BUFFER *pAdcBuffer;
/* Submit the buffer to the driver */
adi_adc_SubmitBuffer(hDevice, &obj->UserBuffer);
/* Enable the ADC */
adi_adc_Enable(hDevice, true);
adi_adc_GetBuffer(hDevice, &pAdcBuffer);
MBED_ASSERT(pAdcBuffer == &obj->UserBuffer);
return( (uint16_t)( ((uint16_t *)pAdcBuffer->pDataBuffer)[(pAdcBuffer->nNumConversionPasses) - 1]) );
}
/* Retrieve te active channel correspondoing to the input pin */
static uint32_t adi_pin2channel(PinName pin) {
uint32_t activech;
switch(pin) {
case ADC_VIN0:
activech = ADI_ADC_CHANNEL_0;
break;
case ADC_VIN1:
activech = ADI_ADC_CHANNEL_1;
break;
case ADC_VIN2:
activech = ADI_ADC_CHANNEL_2;
break;
case ADC_VIN3:
activech = ADI_ADC_CHANNEL_3;
break;
case ADC_VIN4:
activech = ADI_ADC_CHANNEL_4;
break;
case ADC_VIN5:
activech = ADI_ADC_CHANNEL_5;
break;
case ADC_VIN6:
activech = ADI_ADC_CHANNEL_6;
break;
case ADC_VIN7:
activech = ADI_ADC_CHANNEL_7;
break;
default:
activech = (uint32_t) 0xFFFFFFFF;
break;
}
return ((uint32_t)activech);
}
/**@}*/
#ifdef __cplusplus
}
#endif
#endif // #if DEVICE_ANALOGIN

View File

@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#ifndef MBED_CMSIS_H
#define MBED_CMSIS_H
#define __C
#include "adi_processor.h"
#include "cmsis_nvic.h"
#undef __C
#endif

View File

@ -0,0 +1,78 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#ifndef MBED_CMSIS_NVIC_H
#define MBED_CMSIS_NVIC_H
#include "cmsis.h"
#define NVIC_USER_IRQ_OFFSET 16
#define NVIC_USER_IRQ_NUMBER 64
#define NVIC_NUM_VECTORS (NVIC_USER_IRQ_OFFSET + NVIC_USER_IRQ_NUMBER)
#define NVIC_RAM_VECTOR_ADDRESS 0x20000000
#define NVIC_FLASH_VECTOR_ADDRESS 0x0
#ifdef __cplusplus
extern "C" {
#endif
/** Set the ISR for IRQn
*
* Sets an Interrupt Service Routine vector for IRQn; if the feature is available, the vector table is relocated to SRAM
* the first time this function is called
* @param[in] IRQn The Interrupt Request number for which a vector will be registered
* @param[in] vector The ISR vector to register for IRQn
*/
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector);
/** Get the ISR registered for IRQn
*
* Reads the Interrupt Service Routine currently registered for IRQn
* @param[in] IRQn The Interrupt Request number the vector of which will be read
* @return Returns the ISR registered for IRQn
*/
uint32_t NVIC_GetVector(IRQn_Type IRQn);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,48 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#ifndef MBED_DEVICE_H
#define MBED_DEVICE_H
#define DEVICE_ID_LENGTH 24
#include "objects.h"
#endif

View File

@ -0,0 +1,91 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#ifdef DEVICE_FLASH
#include "flash_api.h"
#include "flash_data.h"
#include "mbed_critical.h"
// This file is automagically generated
// This is a flash algo binary blob. It is PIC (position independent code) that should be stored in RAM
static unsigned FLASH_ALGO[] = {
0x2000B508,0x4A5B1E41,0x495B6011,0x21076211,0xBF006091,0x68094957,0x99009100,0x0104F001,
0xD0F72900,0xF0019900,0xB1010130,0x21002001,0x62114A50,0xB5F0BD08,0x460F4606,0x4D4D4614,
0x20013554,0x20007028,0x6048494A,0xD1072C01,0x6D004608,0x0001F000,0xF7FFB110,0xBDF0FFD1,
0xE7FC2000,0x20004601,0x62104A42,0xB5084770,0x20004601,0x4B3F1E42,0x461A601A,0x4A3E6191,
0x2206621A,0xBF00609A,0x68124A3A,0x9A009200,0x0204F002,0xD0F72A00,0xF0029A00,0xB1020230,
0x22002001,0x621A4B33,0xB5FEBD08,0x460B4604,0x46252600,0x48304611,0x62384F2E,0xF04FE052,
0x4F2C30FF,0x2B086038,0x6808D304,0x68486138,0xE02F6178,0x3CFFF04F,0xC000F8CD,0xC004F8CD,
0x2B084668,0xE8DFD21A,0x1619F003,0x0A0D1013,0x798F0407,0xBF007187,0x7147794F,0x790FBF00,
0xBF007107,0x70C778CF,0x788FBF00,0xBF007087,0x7047784F,0x780FBF00,0xE0007007,0xBF00BF00,
0xC050F8DF,0xF8CC9F00,0x9F017010,0x7014F8CC,0xBF002308,0x60C5480F,0x4F0E2004,0x463860B8,
0xF0006800,0xB1080030,0xE00D2601,0x4809BF00,0x90026800,0xF0009802,0x28000004,0x3B08D0F7,
0x35083108,0xD1AA2B00,0x2000BF00,0x62384F01,0xBDFE4630,0x40018000,0x676C7565,0
};
static const flash_algo_t flash_algo_config = {
.init = 0x00000037,
.uninit = 0x00000065,
.erase_sector = 0x0000006F,
.program_page = 0x000000AB,
.static_base = 0x0000017C,
.algo_blob = FLASH_ALGO
};
static const sector_info_t sectors_info[] = {
{0x0, 0x800},
};
static const flash_target_config_t flash_target_config = {
.page_size = 0x800,
.flash_start = 0x0,
.flash_size = 0x00040000,
.sectors = sectors_info,
.sector_info_count = sizeof(sectors_info) / sizeof(sector_info_t)
};
void flash_set_target_config(flash_t *obj)
{
obj->flash_algo = &flash_algo_config;
obj->target_config = &flash_target_config;
}
#endif

View File

@ -0,0 +1,147 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "mbed_assert.h"
#include "gpio_api.h"
#include "pinmap.h"
#include "adi_gpio.h"
#define MUX_FUNC_0 0x0
#define NUM_GPIO_PORTS 4
extern uint8_t gpioMemory[ADI_GPIO_MEMORY_SIZE];
extern uint8_t gpio_initialized;
static uint16_t gpio_oen[NUM_GPIO_PORTS] = {0};
static uint16_t gpio_output_val[NUM_GPIO_PORTS] = {0};
/******************************************************************************
Function definitions
*****************************************************************************/
uint32_t gpio_set(PinName pin)
{
MBED_ASSERT(pin != (PinName)NC);
uint32_t pin_num = pin & 0xFF;
pin_function(pin, MUX_FUNC_0);
return (1 << pin_num);
}
void gpio_init(gpio_t *obj, PinName pin)
{
obj->pin = pin;
if (pin == (PinName)NC) {
return;
}
// Initialize the GPIO driver. This function
// initializes the GPIO driver only once globally.
if (!gpio_initialized) {
adi_gpio_Init(gpioMemory, ADI_GPIO_MEMORY_SIZE);
}
pin_function(pin, MUX_FUNC_0);
}
void gpio_mode(gpio_t *obj, PinMode mode)
{
uint32_t pin = obj->pin;
pin_mode((PinName)pin, mode);
}
void gpio_dir(gpio_t *obj, PinDirection direction)
{
MBED_ASSERT(obj->pin != (PinName)NC);
uint32_t port = obj->pin >> GPIO_PORT_SHIFT;
uint32_t pin_num = obj->pin & 0xFF;
if (direction == PIN_OUTPUT) {
adi_gpio_OutputEnable(port, 1 << pin_num, true);
// save the input/output configuration
gpio_oen[port] |= (1 << pin_num);
} else {
adi_gpio_InputEnable(port, 1 << pin_num, true);
// save the input/output configuration
gpio_oen[port] &= (~(1 << pin_num));
}
}
void gpio_write(gpio_t *obj, int value)
{
MBED_ASSERT(obj->pin != (PinName)NC);
uint32_t port = obj->pin >> GPIO_PORT_SHIFT;
uint32_t pin_num = obj->pin & 0xFF;
if (value & 1) {
adi_gpio_SetHigh(port, (1 << pin_num));
// save the output port value
gpio_output_val[port] |= ((value & 1) << pin_num);
} else {
adi_gpio_SetLow(port, (1 << pin_num));
// save the output port value
gpio_output_val[port] &= (~(1 << pin_num));
}
}
int gpio_read(gpio_t *obj)
{
MBED_ASSERT(obj->pin != (PinName)NC);
uint32_t port = obj->pin >> GPIO_PORT_SHIFT;
uint32_t pin_num = obj->pin & 0xFF;
uint16_t Data;
// check whether the pin is configured as input or output
if ((gpio_oen[port] >> pin_num) & 1) {
Data = gpio_output_val[port] & (1 << pin_num);
} else {
// otherwise call GetData
adi_gpio_GetData(port, (1 << pin_num), &Data);
}
return ((((uint32_t)Data) >> pin_num) & 1);
}

View File

@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include <drivers/gpio/adi_gpio.h>
// ADI GPIO device driver state memory. Only one state memory is required globally.
uint8_t gpioMemory[ADI_GPIO_MEMORY_SIZE];
// Flag to indicate whether the GPIO driver has been initialized
uint8_t gpio_initialized = 0;

View File

@ -0,0 +1,327 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#include "gpio_irq_api.h"
#include "adi_gpio.h"
#include "adi_gpio_def.h"
#include "ADuCM302x_device.h"
#ifdef DEVICE_INTERRUPTIN
#define MAX_GPIO_LINES 16
#define MAX_GPIO_PORTS ADI_GPIO_NUM_PORTS
typedef struct {
unsigned int id;
gpio_irq_event event;
uint8_t int_enable;
} gpio_chan_info_t;
extern uint8_t gpioMemory[ADI_GPIO_MEMORY_SIZE];
extern uint8_t gpio_initialized;
static gpio_chan_info_t channel_ids[MAX_GPIO_PORTS][MAX_GPIO_LINES];
static gpio_irq_handler irq_handler = NULL;
/** Local interrupt callback routine.
*/
static void gpio_irq_callback(void *pCBParam, uint32_t Event, void *pArg)
{
uint16_t pin = *(ADI_GPIO_DATA*)pArg;
int index = 0;
// determine the index of the pin that caused the interrupt
while (pin) {
if (pin & 0x01) {
// call the user ISR. The argument Event is the port number of the GPIO line.
if (irq_handler != NULL)
irq_handler((uint32_t)channel_ids[Event][index].id, channel_ids[Event][index].event);
}
index++;
pin >>= 1;
}
}
/** Function to get the IENA and IENB register values.
* Added here temporarily until these are available in the BSP
*/
static ADI_GPIO_RESULT adi_gpio_GetGroupInterruptPins(const ADI_GPIO_PORT Port, const IRQn_Type eIrq,
const ADI_GPIO_DATA Pins, uint16_t* const pValue)
{
ADI_GPIO_TypeDef *pReg[MAX_GPIO_PORTS] = {pADI_GPIO0, pADI_GPIO1, pADI_GPIO2};
ADI_GPIO_TypeDef *pPort; /* pointer to port registers */
uint16_t Value = 0u;
pPort = pReg[Port];
switch (eIrq) {
case SYS_GPIO_INTA_IRQn:
Value = pPort->IENA;
break;
case SYS_GPIO_INTB_IRQn:
Value = pPort->IENB;
break;
default:
break; /* This shall never reach */
}
*pValue = (Value & Pins);
return (ADI_GPIO_SUCCESS);
}
/** Function to get the interrupt polarity register content.
* Added here temporarily until these are available in the BSP
*/
static ADI_GPIO_RESULT adi_gpio_GetGroupInterruptPolarity(const ADI_GPIO_PORT Port, const ADI_GPIO_DATA Pins,
uint16_t* const pValue)
{
ADI_GPIO_TypeDef *pPort; /* pointer to port registers */
ADI_GPIO_TypeDef *pReg[MAX_GPIO_PORTS] = {pADI_GPIO0, pADI_GPIO1, pADI_GPIO2};
pPort = pReg[Port];
*pValue = (pPort->POL & Pins);
return (ADI_GPIO_SUCCESS);
}
/** Function to clear the relevant interrupt enable bits in both the IENA and IENB registers
* for the given GPIO pin.
*/
static void disable_pin_interrupt(ADI_GPIO_PORT port, uint32_t pin_number)
{
uint16_t int_reg_val;
// Read the current content of the IENA register
adi_gpio_GetGroupInterruptPins(port, SYS_GPIO_INTA_IRQn, 1 << pin_number, &int_reg_val);
// clear the bit for the pin
int_reg_val &= ~(1 << pin_number);
// write the interrupt register
adi_gpio_SetGroupInterruptPins(port, SYS_GPIO_INTA_IRQn, int_reg_val);
// Do the same to IENB
adi_gpio_GetGroupInterruptPins(port, SYS_GPIO_INTB_IRQn, 1 << pin_number, &int_reg_val);
// clear the bit for the pin
int_reg_val &= ~(1 << pin_number);
// write the interrupt register
adi_gpio_SetGroupInterruptPins(port, SYS_GPIO_INTB_IRQn, int_reg_val);
}
/** Function to set the relevant interrupt enable bits in either the IENA and IENB registers
* for the given GPIO pin.
*/
static void enable_pin_interrupt(ADI_GPIO_PORT port, uint32_t pin_number, IRQn_Type eIrq)
{
uint16_t int_reg_val;
// Read the current interrupt enable register content
adi_gpio_GetGroupInterruptPins(port, eIrq, 1 << pin_number, &int_reg_val);
// set the bit for the pin
int_reg_val |= (1 << pin_number);
// write the interrupt register
adi_gpio_SetGroupInterruptPins(port, eIrq, int_reg_val);
}
/** Initialize the GPIO IRQ pin
*
* @param obj The GPIO object to initialize
* @param pin The GPIO pin name
* @param handler The handler to be attached to GPIO IRQ
* @param id The object ID (id != 0, 0 is reserved)
* @return -1 if pin is NC, 0 otherwise
*/
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
{
uint32_t port = pin >> GPIO_PORT_SHIFT;
uint32_t pin_num = pin & 0xFF;
// check for valid pin and ID
if ((pin == NC) || (id == 0)) {
return -1;
}
// make sure gpio driver has been initialized
if (!gpio_initialized) {
adi_gpio_Init(gpioMemory,ADI_GPIO_MEMORY_SIZE);
gpio_initialized = 1;
}
// save the handler
if (handler) {
irq_handler = handler;
}
// disable the interrupt for the given pin
disable_pin_interrupt((ADI_GPIO_PORT)port, pin_num);
// set the port pin as input
adi_gpio_InputEnable(port, 1 << pin_num, true);
// save the ID for future reference
channel_ids[port][pin_num].id = (uint32_t)id;
channel_ids[port][pin_num].event = IRQ_NONE;
channel_ids[port][pin_num].int_enable = 0;
obj->id = id;
obj->pinname = pin;
return 0;
}
/** Release the GPIO IRQ PIN
*
* @param obj The gpio object
*/
void gpio_irq_free(gpio_irq_t *obj)
{
uint32_t port = obj->pinname >> GPIO_PORT_SHIFT;
uint32_t pin_num = obj->pinname & 0xFF;
// disable interrupt for the given pin
gpio_irq_disable(obj);
// clear the status table
channel_ids[port][pin_num].id = (uint32_t)0;
channel_ids[port][pin_num].event = IRQ_NONE;
channel_ids[port][pin_num].int_enable = 0;
}
/** Enable/disable pin IRQ event
*
* @param obj The GPIO object
* @param event The GPIO IRQ event
* @param enable The enable flag
*/
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
{
uint16_t int_polarity_reg;
uint32_t port = obj->pinname >> GPIO_PORT_SHIFT;
uint32_t pin_num = obj->pinname & 0xFF;
if (event == IRQ_NONE) {
return;
}
// read the current polarity register
adi_gpio_GetGroupInterruptPolarity((ADI_GPIO_PORT)port, 1 << pin_num, &int_polarity_reg);
if (event == IRQ_RISE) {
int_polarity_reg |= (1 << pin_num);
} else {
int_polarity_reg &= ~(1 << pin_num);
}
// set the polarity register
adi_gpio_SetGroupInterruptPolarity((ADI_GPIO_PORT)port, int_polarity_reg);
channel_ids[port][pin_num].event = event;
// enable interrupt for this pin if enable flag is set
if (enable) {
gpio_irq_enable(obj);
} else {
gpio_irq_disable(obj);
}
}
/** Enable GPIO IRQ
*
* This is target dependent, as it might enable the entire port or just a pin
* @param obj The GPIO object
*/
void gpio_irq_enable(gpio_irq_t *obj)
{
uint32_t port = obj->pinname >> GPIO_PORT_SHIFT;
uint32_t pin_num = obj->pinname & 0xFF;
if (channel_ids[port][pin_num].event == IRQ_NONE) {
return;
}
// Group all RISE interrupts in INTA and FALL interrupts in INTB
if (channel_ids[port][pin_num].event == IRQ_RISE) {
// set the callback routine
adi_gpio_RegisterCallback(SYS_GPIO_INTA_IRQn, gpio_irq_callback, obj);
enable_pin_interrupt((ADI_GPIO_PORT)port, pin_num, SYS_GPIO_INTA_IRQn);
} else if (channel_ids[port][pin_num].event == IRQ_FALL) {
// set the callback routine
adi_gpio_RegisterCallback(SYS_GPIO_INTB_IRQn, gpio_irq_callback, obj);
enable_pin_interrupt((ADI_GPIO_PORT)port, pin_num, SYS_GPIO_INTB_IRQn);
}
channel_ids[port][pin_num].int_enable = 1;
}
/** Disable GPIO IRQ
*
* This is target dependent, as it might disable the entire port or just a pin
* @param obj The GPIO object
*/
void gpio_irq_disable(gpio_irq_t *obj)
{
uint32_t port = obj->pinname >> GPIO_PORT_SHIFT;
uint32_t pin_num = obj->pinname & 0xFF;
if (channel_ids[port][pin_num].event == IRQ_NONE) {
return;
}
// Group all RISE interrupts in INTA and FALL interrupts in INTB
if (channel_ids[port][pin_num].event == IRQ_RISE) {
disable_pin_interrupt((ADI_GPIO_PORT)port, pin_num);
}
else if (channel_ids[port][pin_num].event == IRQ_FALL) {
disable_pin_interrupt((ADI_GPIO_PORT)port, pin_num);
}
channel_ids[port][pin_num].int_enable = 0;
}
#endif // #ifdef DEVICE_INTERRUPTIN

View File

@ -0,0 +1,61 @@
/*******************************************************************************
* Copyright (c) 2010-2017 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with processors
* manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and conditions
* which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights of one
* or more patent holders. This license does not release you from the
* requirement that you obtain separate licenses from these patent holders
* to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-
* INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF
* CLAIMS OF INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
#ifndef MBED_GPIO_OBJECT_H
#define MBED_GPIO_OBJECT_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
PinName pin;
} gpio_t;
static inline int gpio_is_connected(const gpio_t *obj)
{
return obj->pin != (PinName)NC;
}
#ifdef __cplusplus
}
#endif
#endif

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