mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #5523 from ARMmbed/release-candidate
Release candidate for mbed-os-5.6.5pull/5540/head
commit
34b61d1612
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"PROJECT_NAME": "Mbed OS Reference",
|
||||
"ENABLE_PREPROCESSING": "YES",
|
||||
"MACRO_EXPANSION": "YES",
|
||||
"EXPAND_ONLY_PREDEF": "NO",
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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__*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
@ -72,13 +71,12 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
|
|||
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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) */
|
|
@ -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 */
|
|
@ -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
|
@ -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 */
|
|
@ -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 */
|
|
@ -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) ) */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
4
mbed.h
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__*/
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -23,15 +23,23 @@
|
|||
|
||||
namespace mbed {
|
||||
/** \addtogroup platform */
|
||||
|
||||
/** @{*/
|
||||
/**
|
||||
* @class FileSystem
|
||||
* @ingroup platform
|
||||
* \defgroup platform_FilePath FilePath class
|
||||
* @{
|
||||
*/
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**@}*/
|
||||
|
|
|
@ -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
|
||||
/**@}*/
|
||||
|
||||
/**@}*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
/**@}*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
||||
/** @}*/
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
/**@}*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
/** @}*/
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
/** @}*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
/** @}*/
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
|
||||
/** \addtogroup platform */
|
||||
/** @{*/
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
|
@ -95,4 +93,4 @@ int semihost_disabledebug(void);
|
|||
|
||||
#endif
|
||||
|
||||
/** @}*/
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
/** @}*/
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
|
||||
/** @}*/
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
/** @}*/
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
/** @}*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
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
|
||||
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
|
|
|
@ -38,6 +38,10 @@ 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.
|
||||
|
@ -103,9 +107,12 @@ private:
|
|||
MemoryPool<T, queue_sz> _pool;
|
||||
};
|
||||
|
||||
/** @}*/
|
||||
/** @}*/
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/** @}*/
|
||||
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
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).
|
||||
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
10
rtos/Mutex.h
10
rtos/Mutex.h
|
@ -32,6 +32,10 @@
|
|||
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
|
||||
|
||||
/** @}*/
|
||||
|
||||
|
|
20
rtos/Queue.h
20
rtos/Queue.h
|
@ -34,6 +34,10 @@
|
|||
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
|
||||
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
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
|
||||
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
/** @}*/
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
||||
|
|
@ -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") */
|
||||
}
|
|
@ -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 };
|
|
@ -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
|
|
@ -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},
|
||||
};
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue