Merge pull request #4824 from ARMmbed/release-candidate

Release candidate for mbed-os-5.5.4
pull/4909/merge mbed_lib_rev148
Jimmy Brisson 2017-08-02 15:45:49 -05:00 committed by GitHub
commit 4c256f0459
472 changed files with 100079 additions and 20398 deletions

View File

@ -37,8 +37,8 @@ before_install:
- python --version
- doxygen --version
install:
- sudo pip install -r requirements.txt
- sudo pip install pytest
- sudo pip install pylint
- sudo pip install hypothesis
- sudo pip install mock
- pip install -r requirements.txt
- pip install pytest
- pip install pylint
- pip install hypothesis
- pip install mock

View File

@ -148,7 +148,6 @@ void flash_mapping_alignment_test()
TEST_ASSERT_EQUAL(0, sector_start % sector_size);
// All address in a sector must return the same sector size
TEST_ASSERT_EQUAL(sector_size, end_sector_size);
}
// Make sure unmapped flash is reported correctly
@ -185,6 +184,7 @@ void flash_program_page_test()
uint32_t test_size = flash_get_page_size(&test_flash);
uint8_t *data = new uint8_t[test_size];
uint8_t *data_flashed = new uint8_t[test_size];
for (uint32_t i = 0; i < test_size; i++) {
data[i] = 0xCE;
}
@ -199,7 +199,9 @@ void flash_program_page_test()
ret = flash_program_page(&test_flash, address, data, test_size);
TEST_ASSERT_EQUAL_INT32(0, ret);
uint8_t *data_flashed = (uint8_t *)address;
ret = flash_read(&test_flash, address, data_flashed, test_size);
TEST_ASSERT_EQUAL_INT32(0, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, test_size);
// sector size might not be same as page size
@ -213,11 +215,15 @@ void flash_program_page_test()
}
ret = flash_program_page(&test_flash, address, data, test_size);
TEST_ASSERT_EQUAL_INT32(0, ret);
ret = flash_read(&test_flash, address, data_flashed, test_size);
TEST_ASSERT_EQUAL_INT32(0, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY(data, data_flashed, test_size);
ret = flash_free(&test_flash);
TEST_ASSERT_EQUAL_INT32(0, ret);
delete[] data;
delete[] data_flashed;
}
// make sure programming works with an unaligned data buffer
@ -230,6 +236,7 @@ void flash_buffer_alignment_test()
const uint32_t page_size = flash_get_page_size(&test_flash);
const uint32_t buf_size = page_size + 4;
uint8_t *data = new uint8_t[buf_size];
uint8_t *data_flashed = new uint8_t[buf_size];
for (uint32_t i = 0; i < buf_size; i++) {
data[i] = i & 0xFF;
}
@ -245,13 +252,16 @@ void flash_buffer_alignment_test()
const uint32_t addr = test_addr + i * page_size;
ret = flash_program_page(&test_flash, addr, data + i, page_size);
TEST_ASSERT_EQUAL_INT32(0, ret);
uint8_t *data_flashed = (uint8_t *)addr;
ret = flash_read(&test_flash, addr, data_flashed, page_size);
TEST_ASSERT_EQUAL_INT32(0, ret);
TEST_ASSERT_EQUAL_UINT8_ARRAY(data + i, data_flashed, page_size);
}
ret = flash_free(&test_flash);
TEST_ASSERT_EQUAL_INT32(0, ret);
delete[] data;
delete[] data_flashed;
}
// check the execution speed at the start and end of the test to make sure

View File

@ -12,12 +12,8 @@ using namespace utest::v1;
#define TEST_STACK_SIZE 512
#define TEST_ONE_SEC_MS (1000)
#define TEST_HALF_SEC_MS (500)
#define TEST_HALF_SEC_US (500000)
#define TEST_ONE_MS_US (1000)
#define THREAD_DELAY 50
#define TEST_LONG_DELAY 20
#define TEST_DELAY 10
#define SIGNALS_TO_EMIT 100
Mutex stdio_mutex;
@ -26,11 +22,14 @@ volatile int change_counter = 0;
volatile bool changing_counter = false;
volatile bool mutex_defect = false;
bool manipulate_protected_zone(const int thread_delay) {
bool manipulate_protected_zone(const int thread_delay)
{
bool result = true;
osStatus stat = stdio_mutex.lock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
core_util_critical_section_enter();
if (changing_counter == true) {
result = false;
mutex_defect = true;
@ -38,25 +37,37 @@ bool manipulate_protected_zone(const int thread_delay) {
changing_counter = true;
change_counter++;
core_util_critical_section_exit();
Thread::wait(thread_delay);
core_util_critical_section_enter();
changing_counter = false;
core_util_critical_section_exit();
stat = stdio_mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
return result;
}
void test_thread(int const *thread_delay) {
void test_thread(int const *thread_delay)
{
while (true) {
manipulate_protected_zone(*thread_delay);
}
}
/** Test multiple thread
Given 3 threads started with different delays and a section protected with a mutex
when each thread runs it tries to lock the mutex
then no more than one thread should be able to access protected region
*/
void test_multiple_threads(void)
{
const int t1_delay = THREAD_DELAY * 1;
const int t2_delay = THREAD_DELAY * 2;
const int t3_delay = THREAD_DELAY * 3;
const int t1_delay = TEST_DELAY * 1;
const int t2_delay = TEST_DELAY * 2;
const int t3_delay = TEST_DELAY * 3;
Thread t2(osPriorityNormal, TEST_STACK_SIZE);
Thread t3(osPriorityNormal, TEST_STACK_SIZE);
@ -69,34 +80,51 @@ void test_multiple_threads(void)
Thread::wait(t1_delay);
manipulate_protected_zone(t1_delay);
core_util_critical_section_enter();
if (change_counter >= SIGNALS_TO_EMIT or mutex_defect == true) {
core_util_critical_section_exit();
t2.terminate();
t3.terminate();
break;
}
core_util_critical_section_exit();
}
TEST_ASSERT_EQUAL(mutex_defect, false);
TEST_ASSERT_EQUAL(false, mutex_defect);
}
void test_dual_thread_nolock_lock_thread(Mutex *mutex)
{
bool stat_b = mutex->trylock();
TEST_ASSERT_EQUAL(stat_b, true);
osStatus stat = mutex->lock(osWaitForever);
TEST_ASSERT_EQUAL(osOK, stat);
osStatus stat = mutex->unlock();
TEST_ASSERT_EQUAL(stat, osOK);
stat = mutex->unlock();
TEST_ASSERT_EQUAL(osOK, stat);
}
void test_dual_thread_nolock_trylock_thread(Mutex *mutex)
{
bool stat_b = mutex->trylock();
TEST_ASSERT_EQUAL(stat_b, true);
TEST_ASSERT_EQUAL(true, stat_b);
osStatus stat = mutex->unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
}
/** Test dual thread no-lock
Test dual thread second thread lock
Given two threads A & B and a mutex
When thread A creates a mutex and starts thread B
and thread B calls @a lock and @a unlock
Then returned statuses are osOK
Test dual thread second thread trylock
Given two threads A & B and a mutex
When thread A creates a mutex and starts thread B
and thread B calls @a trylock and @a unlock
Then returned statuses are true and osOK
*/
template <void (*F)(Mutex *)>
void test_dual_thread_nolock(void)
{
@ -105,15 +133,24 @@ void test_dual_thread_nolock(void)
thread.start(callback(F, &mutex));
wait_us(TEST_HALF_SEC_MS);
wait_ms(TEST_DELAY);
}
void test_dual_thread_lock_unlock_thread(Mutex *mutex)
{
osStatus stat = mutex->lock(osWaitForever);
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
}
/** Test dual thread lock unlock
Given two threads and a lock
When thread A locks the lock and starts thread B
and thread B calls @a lock on the mutex
Then thread B waits for thread A to unlock the lock
When thread A calls @a unlock on the mutex
Then thread B acquires the lock
*/
void test_dual_thread_lock_unlock(void)
{
Mutex mutex;
@ -121,31 +158,45 @@ void test_dual_thread_lock_unlock(void)
Thread thread(osPriorityNormal, TEST_STACK_SIZE);
stat = mutex.lock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
thread.start(callback(test_dual_thread_lock_unlock_thread, &mutex));
stat = mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
wait_us(TEST_HALF_SEC_MS);
wait_ms(TEST_DELAY);
}
void test_dual_thread_lock_trylock_thread(Mutex *mutex)
{
bool stat = mutex->trylock();
TEST_ASSERT_EQUAL(stat, false);
TEST_ASSERT_EQUAL(false, stat);
}
void test_dual_thread_lock_lock_thread(Mutex *mutex)
{
uint32_t start = us_ticker_read();
osStatus stat = mutex->lock(TEST_HALF_SEC_MS);
TEST_ASSERT_EQUAL(stat, osErrorTimeout);
TEST_ASSERT_UINT32_WITHIN(TEST_ONE_MS_US, TEST_HALF_SEC_US, us_ticker_read() - start);
osStatus stat = mutex->lock(TEST_DELAY);
TEST_ASSERT_EQUAL(osErrorTimeout, stat);
TEST_ASSERT_UINT32_WITHIN(5000, TEST_DELAY*1000, us_ticker_read() - start);
}
/** Test dual thread lock
Test dual thread lock locked
Given a mutex and two threads A & B
When thread A calls @a lock and starts thread B
and thread B calls @a lock with 500ms timeout
Then thread B waits 500ms and timeouts
Test dual thread trylock locked
Given a mutex and two threads A & B
When thread A calls @a lock and starts thread B
Then thread B calls @a trylock
and thread B fails to acquire the lock
*/
template <void (*F)(Mutex *)>
void test_dual_thread_lock(void)
{
@ -154,59 +205,78 @@ void test_dual_thread_lock(void)
Thread thread(osPriorityNormal, TEST_STACK_SIZE);
stat = mutex.lock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
thread.start(callback(F, &mutex));
wait_us(TEST_ONE_SEC_MS);
wait_ms(TEST_LONG_DELAY);
stat = mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
}
/** Test single thread lock recursive
Given a mutex and a single running thread
When thread calls @a lock twice and @a unlock twice on the mutex
Then the returned statuses are osOK
*/
void test_single_thread_lock_recursive(void)
{
Mutex mutex;
osStatus stat;
stat = mutex.lock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
stat = mutex.lock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
stat = mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
stat = mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
}
/** Test single thread trylock
Given a mutex and a single running thread
When thread calls @a trylock and @a unlock on the mutex
Then the returned statuses are osOK
*/
void test_single_thread_trylock(void)
{
Mutex mutex;
bool stat_b = mutex.trylock();
TEST_ASSERT_EQUAL(stat_b, true);
TEST_ASSERT_EQUAL(true, stat_b);
osStatus stat = mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
}
/** Test single thread lock
Given a mutex and a single running thread
When thread calls @a lock and @a unlock on the mutex
Then the returned statuses are osOK
*/
void test_single_thread_lock(void)
{
Mutex mutex;
osStatus stat;
stat = mutex.lock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
stat = mutex.unlock();
TEST_ASSERT_EQUAL(stat, osOK);
TEST_ASSERT_EQUAL(osOK, stat);
}
utest::v1::status_t test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(15, "default_auto");
utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(10, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
@ -224,6 +294,7 @@ Case cases[] = {
Specification specification(test_setup, cases);
int main() {
int main()
{
return !Harness::run(specification);
}

View File

@ -1,14 +1,19 @@
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "rtos.h"
using namespace utest::v1;
#if defined(MBED_RTOS_SINGLE_THREAD)
#error [NOT_SUPPORTED] test not supported
#endif
#define THREAD_DELAY 75
#define THREAD_DELAY 30
#define SEMAPHORE_SLOTS 2
#define SEM_CHANGES 100
#define SHORT_WAIT 5
#define THREAD_STACK_SIZE 512
@ -18,7 +23,8 @@ volatile int change_counter = 0;
volatile int sem_counter = 0;
volatile bool sem_defect = false;
void test_thread(int const *delay) {
void test_thread(int const *delay)
{
const int thread_delay = *delay;
while (true) {
two_slots.wait();
@ -34,9 +40,14 @@ void test_thread(int const *delay) {
}
}
int main (void) {
GREENTEA_SETUP(20, "default_auto");
/* Test multiple threads
Given 3 threads started with different delays and a semaphore with 2 tokens
when each thread runs it tries to acquire a token
then no more than two threads should be able to access protected region
*/
void test_multi()
{
const int t1_delay = THREAD_DELAY * 1;
const int t2_delay = THREAD_DELAY * 2;
const int t3_delay = THREAD_DELAY * 3;
@ -57,7 +68,164 @@ int main (void) {
break;
}
}
GREENTEA_TESTSUITE_RESULT(!sem_defect);
return 0;
}
struct thread_data {
Semaphore *sem;
uint32_t data;
};
void single_thread(struct thread_data *data)
{
int32_t cnt = data->sem->wait();
TEST_ASSERT_EQUAL(1, cnt);
data->data++;
}
/** Test single thread
Given a two threads A & B and a semaphore (with count of 0) and a counter (equals to 0)
when thread B calls @a wait
then thread B waits for a token to become available
then the counter is equal to 0
when thread A calls @a release on the semaphore
then thread B acquires a token and increments the counter
then the counter equals to 1
*/
void test_single_thread()
{
Thread t(osPriorityNormal, THREAD_STACK_SIZE);
Semaphore sem(0);
struct thread_data data;
osStatus res;
data.sem = &sem;
data.data = 0;
res = t.start(callback(single_thread, &data));
TEST_ASSERT_EQUAL(osOK, res);
Thread::wait(SHORT_WAIT);
TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state());
TEST_ASSERT_EQUAL(0, data.data);
res = sem.release();
TEST_ASSERT_EQUAL(osOK, res);
Thread::wait(SHORT_WAIT);
TEST_ASSERT_EQUAL(1, data.data);
t.join();
}
void timeout_thread(Semaphore *sem)
{
int32_t cnt = sem->wait(30);
TEST_ASSERT_EQUAL(0, cnt);
}
/** Test timeout
Given thread and a semaphore with no tokens available
when thread calls @a wait on the semaphore with timeout of 10ms
then the thread waits for 10ms and timeouts after
*/
void test_timeout()
{
Thread t(osPriorityNormal, THREAD_STACK_SIZE);
Semaphore sem(0);
osStatus res;
uint32_t start = us_ticker_read();
res = t.start(callback(timeout_thread, &sem));
TEST_ASSERT_EQUAL(osOK, res);
Thread::wait(SHORT_WAIT);
TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state());
t.join();
TEST_ASSERT_UINT32_WITHIN(5000, 30000, us_ticker_read() - start);
}
/** Test no timeouts
Test 1 token no timeout
Given thread and a semaphore with one token available
when thread calls @a wait on the semaphore with timeout of 0ms
then the thread acquires the token immediately
Test 0 tokens no timeout
Given thread and a semaphore with no tokens available
when thread calls @a wait on the semaphore with timeout of 0ms
then the thread returns immediately without acquiring a token
*/
template<int T>
void test_no_timeout()
{
Semaphore sem(T);
uint32_t start = us_ticker_read();
int32_t cnt = sem.wait(0);
TEST_ASSERT_EQUAL(T, cnt);
TEST_ASSERT_UINT32_WITHIN(5000, 0, us_ticker_read() - start);
}
/** Test multiple tokens wait
Given a thread and a semaphore initialized with 5 tokens
when thread calls @a wait 6 times on the semaphore
then the token counts goes to zero
*/
void test_multiple_tokens_wait()
{
Semaphore sem(5);
for(int i = 5; i >= 0; i--) {
int32_t cnt = sem.wait(0);
TEST_ASSERT_EQUAL(i, cnt);
}
}
/** Test multiple tokens release
Given a thread and a semaphore initialized with zero tokens and max of 5
when thread calls @a release 6 times on the semaphore
then the token count should be equal to 5 and last release call should fail
*/
void test_multiple_tokens_release()
{
Semaphore sem(0, 5);
for(int i = 5; i > 0; i--) {
osStatus stat = sem.release();
TEST_ASSERT_EQUAL(osOK, stat);
}
osStatus stat = sem.release();
TEST_ASSERT_EQUAL(osErrorResource, stat);
}
utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(10, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("Test single thread", test_single_thread),
Case("Test timeout", test_timeout),
Case("Test 1 token no timeout", test_no_timeout<1>),
Case("Test 0 tokens no timeout", test_no_timeout<0>),
Case("Test multiple tokens wait", test_multiple_tokens_wait),
Case("Test multiple tokens release", test_multiple_tokens_release),
Case("Test multiple threads", test_multi)
};
Specification specification(test_setup, cases);
int main()
{
return !Harness::run(specification);
}

View File

@ -59,17 +59,76 @@ void self_terminate(Thread *self) {
}
// Tests that spawn tasks in different configurations
/** Template for tests: single thread, with yield, with wait, with child, with murder
Testing single thread
Given single thread is started
when the thread increments the counter
then the final value of the counter is equal to 1
Testing single thread with yield
Given single thread is started
when the thread yields and then increments the counter
then the final value of the counter is equal to 1
Testing single thread with wait
Given single thread is started
when the thread waits for 100ms and then increments the counter
then the final value of the counter is equal to 1
Testing single thread with child
Given single thread is started
when the thread spawns another thread that increments the counter
then the final value of the counter is equal to 1
Testing serial threads with murder
Given single thread is started
when the parent thread is holding a lock
and the parent thread spawns a child thread that waits for the lock before incrementing the counter
and the parent terminates the child before releasing the lock
and the parent increments the counter
then the final value of the counter is equal to 1
*/
template <void (*F)(counter_t *)>
void test_single_thread() {
const char tname[] = "Single Thread";
counter_t counter(0);
Thread thread(osPriorityNormal, THREAD_STACK_SIZE, NULL, tname);
Thread thread(osPriorityNormal, THREAD_STACK_SIZE);
thread.start(callback(F, &counter));
thread.join();
TEST_ASSERT_EQUAL(counter, 1);
TEST_ASSERT_EQUAL(strcmp(tname, thread.get_name()), 0);
}
/** Template for tests: parallel threads, with yield, with wait, with child, with murder
Testing parallel threads
Given multiple threads are started in parallel
when each of the threads increments the counter
then the final value of the counter is equal to number of threads
Testing parallel threads with yield
Given multiple threads are started in parallel
when each of the threads yields and then increments the counter
then the final value of the counter is equal to number of threads
Testing parallel threads with wait
Given multiple threads are started in parallel
when each of the threads waits for 100ms and then increments the counter
then the final value of the counter is equal to number of threads
Testing parallel threads with child
Given multiple threads are started in parallel
when each of the threads spawns another thread that increments the counter
then the final value of the counter is equal to number of parallel threads
Testing parallel threads with murder
Given multiple threads are started in parallel
when the parent thread is holding a lock
and the parent thread spawns a child thread that waits for the lock before incrementing the counter
and the parent terminates the child before releasing the lock
and the parent increments the counter
then the final value of the counter is equal to number of parallel threads
*/
template <int N, void (*F)(counter_t *)>
void test_parallel_threads() {
counter_t counter(0);
@ -88,6 +147,36 @@ void test_parallel_threads() {
TEST_ASSERT_EQUAL(counter, N);
}
/** Template for tests: serial threads, with yield, with wait, with child, with murder
Testing serial threads
Given multiple threads are started serially
when each of the threads increments the counter
then the final value of the counter is equal to number of threads
Testing serial threads with yield
Given multiple threads are started serially
when each of the threads yields and then increments the counter
then the final value of the counter is equal to number of threads
Testing serial threads with wait
Given multiple threads are started serially
when each of the threads waits for 100ms and then increments the counter
then the final value of the counter is equal to number of threads
Testing serial threads with child
Given multiple threads are started serially
when each of the threads spawns another thread that increments the counter
then the final value of the counter is equal to number of serial threads
Testing serial threads with murder
Given multiple threads are started serially
when the parent thread is holding a lock
and the parent thread spawns a child thread that waits for the lock before incrementing the counter
and the parent terminates the child before releasing the lock
and the parent increments the counter
then the final value of the counter is equal to number of serial threads
*/
template <int N, void (*F)(counter_t *)>
void test_serial_threads() {
counter_t counter(0);
@ -101,6 +190,12 @@ void test_serial_threads() {
TEST_ASSERT_EQUAL(counter, N);
}
/** Testing thread self terminate
Given the thread is running
when the thread calls @a terminate on its self
then the thread terminates execution cleanly
*/
void test_self_terminate() {
Thread *thread = new Thread(osPriorityNormal, THREAD_STACK_SIZE);
thread->start(callback(self_terminate, thread));
@ -108,34 +203,497 @@ void test_self_terminate() {
delete thread;
}
void signal_wait()
{
osEvent evt = Thread::signal_wait(0x1);
TEST_ASSERT_EQUAL(osEventSignal, evt.status);
TEST_ASSERT_EQUAL(0x1, evt.value.signals);
}
void signal_wait_tout()
{
osEvent evt = Thread::signal_wait(0x2, 50);
TEST_ASSERT_EQUAL(osEventTimeout, evt.status);
}
void signal_wait_multibit()
{
osEvent evt = Thread::signal_wait(0x1 | 0x2, 50);
TEST_ASSERT_EQUAL(osEventSignal, evt.status);
TEST_ASSERT_EQUAL(0x3, evt.value.signals);
}
void signal_wait_multibit_tout()
{
osEvent evt = Thread::signal_wait(0x1 | 0x2, 50);
TEST_ASSERT_EQUAL(osEventTimeout, evt.status);
}
/**
Testing thread signal: wait
Given two threads (A & B) are started
when thread A executes @a signal_wait(0x1)
and thread B execute @a signal_set(0x1)
then thread A exits the wait and continues execution
Testing thread signal: timeout
Given two threads (A & B) are started
when thread A executes @a signal_wait(0x1 | 0x2, 50) with a timeout of 50ms
and thread B execute @a signal_set(0x2)
then thread A keeps waiting for correct signal until it timeouts
Testing thread signal: multi-bit
Given two threads (A & B) are started
when thread A executes @a signal_wait(0x1 | 0x2)
and thread B execute @a signal_set(0x1 | 0x2)
then thread A exits the wait and continues execution
Testing thread signal: multi-bit timeout
Given two threads (A & B) are started
when thread A executes @a signal_wait(0x1, 50) with a timeout of 50ms
and thread B execute @a signal_set(0x2)
then thread A keeps waiting for correct signal until it timeouts
*/
template <int S, void (*F)()>
void test_thread_signal()
{
Thread t_wait;
t_wait.start(callback(F));
Thread::yield();
Thread::State state = t_wait.get_state();
TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, state);
int32_t res = t_wait.signal_set(S);
t_wait.join();
}
void signal_clr()
{
Thread::yield();
int32_t sig = Thread::signal_clr(0x1);
TEST_ASSERT_EQUAL(0x1, sig);
/* Signal cleared we should get timeout */
osEvent evt = Thread::signal_wait(0x1, 0);
TEST_ASSERT_EQUAL(osOK, evt.status);
}
/** Testing thread signals: signal clear
Given two threads (A & B) are started
when thread A executes @a signal_set(0x1)
and thread B execute @a signal_clr(0x1)
and thread B execute @a signal_wait(0x1, 0)
then thread B @a signal_wait status should be osOK indicating a timeout
*/
void test_thread_signal_clr()
{
Thread t_wait;
t_wait.start(callback(signal_clr));
int32_t res = t_wait.signal_set(0x1);
TEST_ASSERT_EQUAL(0x1, res);
t_wait.join();
}
void thread_wait_signal() {
Thread::signal_wait(0x1);
}
void stack_info() {
Thread::signal_wait(0x1);
thread_wait_signal();
Thread::signal_wait(0x1);
}
/** Testing thread stack info
Given the thread is running
when a function is called from the thread context
then the stack usage goes up
and the reported stack size is as requested in the constructor
and the sum of free and used stack sizes is equal to the total stack size
when the function returns
then the stack usage goes down
and the reported stack size is as requested in the constructor
and the sum of free and used stack sizes is equal to the total stack size
*/
void test_thread_stack_info() {
Thread t(osPriorityNormal, THREAD_STACK_SIZE);
t.start(callback(stack_info));
Thread::yield();
TEST_ASSERT_EQUAL(THREAD_STACK_SIZE, t.stack_size());
TEST_ASSERT_EQUAL(THREAD_STACK_SIZE, t.free_stack() + t.used_stack());
uint32_t last_stack = t.used_stack();
t.signal_set(0x1);
Thread::yield();
TEST_ASSERT_EQUAL(THREAD_STACK_SIZE, t.free_stack() + t.used_stack());
TEST_ASSERT(last_stack <= t.used_stack());
last_stack = t.used_stack();
t.signal_set(0x1);
Thread::yield();
TEST_ASSERT_EQUAL(THREAD_STACK_SIZE, t.free_stack() + t.used_stack());
TEST_ASSERT(last_stack >= t.used_stack());
t.signal_set(0x1);
t.join();
}
/** Testing thread wait aka delay
Given the thread is running
when the @a wait function is called
then the thread sleeps for given amount of time
*/
void test_thread_wait() {
uint32_t start = us_ticker_read();
Thread::wait(150);
TEST_ASSERT_UINT32_WITHIN(50000, 150000, us_ticker_read() - start);
}
/** Testing thread name
Given a thread is started with a specified name
when the name is queried using @a get_name
then the returned name is as set
*/
void test_thread_name() {
const char tname[] = "Amazing thread";
Thread t(osPriorityNormal, THREAD_STACK_SIZE, NULL, tname);
t.start(callback(thread_wait_signal));
TEST_ASSERT_EQUAL(strcmp(tname, t.get_name()), 0);
t.signal_set(0x1);
t.join();
}
void test_deleted_thread()
{
}
/** Testing thread states: deleted
Given the thread is not started
then its state, as reported by @a get_state, is @a Deleted
when the thread is started and finishes executing
then its state, as reported by @a get_state, is @a Deleted
*/
void test_deleted()
{
Thread t;
TEST_ASSERT_EQUAL(Thread::Deleted, t.get_state());
t.start(callback(test_deleted_thread));
t.join();
TEST_ASSERT_EQUAL(Thread::Deleted, t.get_state());
}
void test_delay_thread()
{
Thread::wait(50);
}
/** Testing thread states: wait delay
Given the thread is running
when thread calls @a wait
then its state, as reported by @a get_state, is @a WaitingDelay
*/
void test_delay()
{
Thread t;
t.start(callback(test_delay_thread));
Thread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingDelay, t.get_state());
t.join();
TEST_ASSERT_EQUAL(Thread::Deleted, t.get_state());
}
void test_signal_thread()
{
Thread::signal_wait(0x1);
}
/** Testing thread states: wait signal
Given the thread is running
when thread waits for a signal
then its state, as reported by @a get_state, is @a WaitingSignal
*/
void test_signal()
{
Thread t;
t.start(callback(test_signal_thread));
Thread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, t.get_state());
t.signal_set(0x1);
}
void test_evt_flag_thread(osEventFlagsId_t evtflg)
{
osEventFlagsWait(evtflg, 0x1, osFlagsWaitAny, osWaitForever);
}
/** Testing thread states: wait evt flag
Given the thread is running
when thread waits for an event flag
then its state, as reported by @a get_state, is @a WaitingEventFlag
*/
void test_evt_flag()
{
Thread t;
mbed_rtos_storage_event_flags_t evtflg_mem;
osEventFlagsAttr_t evtflg_attr;
osEventFlagsId_t evtflg;
evtflg_attr.cb_mem = &evtflg_mem;
evtflg_attr.cb_size = sizeof(evtflg_mem);
evtflg = osEventFlagsNew(&evtflg_attr);
TEST_ASSERT_NOT_EQUAL(NULL, evtflg);
t.start(callback(test_evt_flag_thread, evtflg));
Thread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingEventFlag, t.get_state());
osEventFlagsSet(evtflg, 0x1);
}
void test_mutex_thread(Mutex *mutex)
{
mutex->lock();
}
/** Testing thread states: wait mutex
Given the thread is running
when thread waits for a mutex
then its state, as reported by @a get_state, is @a WaitingMutex
*/
void test_mutex()
{
Thread t;
Mutex mutex;
mutex.lock();
t.start(callback(test_mutex_thread, &mutex));
Thread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingMutex, t.get_state());
mutex.unlock();
}
void test_semaphore_thread(Semaphore *sem)
{
sem->wait();
}
/** Testing thread states: wait semaphore
Given the thread is running
when thread waits for a semaphore
then its state, as reported by @a get_state, is @a WaitingSemaphore
*/
void test_semaphore()
{
Thread t;
Semaphore sem;
t.start(callback(test_semaphore_thread, &sem));
Thread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state());
sem.release();
}
void test_msg_get_thread(Queue<int32_t, 1> *queue)
{
queue->get();
}
/** Testing thread states: wait message get
Given the thread is running
when thread tries to get a message from an empty queue
then its state, as reported by @a get_state, is @a WaitingMessageGet
*/
void test_msg_get()
{
Thread t;
Queue<int32_t, 1> queue;
t.start(callback(test_msg_get_thread, &queue));
Thread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingMessageGet, t.get_state());
queue.put((int32_t *)0xE1EE7);
}
void test_msg_put_thread(Queue<int32_t, 1> *queue)
{
queue->put((int32_t *)0xDEADBEEF, osWaitForever);
}
/** Testing thread states: wait message put
Given the thread is running
when thread tries to put a message into a full queue
then its state, as reported by @a get_state, is @a WaitingMessagePut
*/
void test_msg_put()
{
Thread t;
Queue<int32_t, 1> queue;
queue.put((int32_t *)0xE1EE7);
t.start(callback(test_msg_put_thread, &queue));
Thread::yield();
TEST_ASSERT_EQUAL(Thread::WaitingMessagePut, t.get_state());
queue.get();
}
/** Utility function that places some date on the stack */
void use_some_stack () {
volatile uint32_t stack_filler[10] = {0xDEADBEEF};
}
/** Testing thread with external stack memory
Given external buffer is supplied as stack to a thread
when the thread executes
then the supplies buffer is used as a stack
*/
void test_thread_ext_stack() {
char stack[512];
Thread t(osPriorityNormal, sizeof(stack), (unsigned char*)stack);
memset(&stack, 0, sizeof(stack));
t.start(callback(use_some_stack));
t.join();
/* If buffer was used as a stack it was cleared with pattern and some data were placed in it */
for(unsigned i = 0; i < sizeof(stack); i++) {
if (stack[i] != 0)
return;
}
TEST_FAIL_MESSAGE("External stack was not used.");
}
/** Testing thread priority operations
Given thread running with osPriorityNormal
when new priority is set using @a set_priority
then priority is changed and can be retrieved using @a get_priority
*/
void test_thread_prio() {
Thread t(osPriorityNormal);
t.start(callback(thread_wait_signal));
TEST_ASSERT_EQUAL(osPriorityNormal, t.get_priority());
t.set_priority(osPriorityHigh);
TEST_ASSERT_EQUAL(osPriorityHigh, t.get_priority());
t.signal_set(0x1);
t.join();
}
utest::v1::status_t test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(40, "default_auto");
GREENTEA_SETUP(15, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
// Test cases
Case cases[] = {
Case("Testing single thread", test_single_thread<increment>),
Case("Testing parallel threads", test_parallel_threads<3, increment>),
Case("Testing serial threads", test_serial_threads<10, increment>),
#define DEFAULT_HANDLERS NULL,NULL,greentea_case_setup_handler,greentea_case_teardown_handler,greentea_case_failure_abort_handler
Case("Testing single thread with yield", test_single_thread<increment_with_yield>),
Case("Testing parallel threads with yield", test_parallel_threads<3, increment_with_yield>),
Case("Testing serial threads with yield", test_serial_threads<10, increment_with_yield>),
// Test cases. It's spelled out rather than constructed with macro because
// macros don't play nicely with the templates (extra comma).
static const case_t cases[] = {
{"Testing single thread", test_single_thread<increment>, DEFAULT_HANDLERS},
{"Testing parallel threads", test_parallel_threads<3, increment> , DEFAULT_HANDLERS},
{"Testing serial threads", test_serial_threads<10, increment> , DEFAULT_HANDLERS},
Case("Testing single thread with wait", test_single_thread<increment_with_wait>),
Case("Testing parallel threads with wait", test_parallel_threads<3, increment_with_wait>),
Case("Testing serial threads with wait", test_serial_threads<10, increment_with_wait>),
{"Testing single thread with yield", test_single_thread<increment_with_yield>, DEFAULT_HANDLERS},
{"Testing parallel threads with yield", test_parallel_threads<3, increment_with_yield>, DEFAULT_HANDLERS},
{"Testing serial threads with yield", test_serial_threads<10, increment_with_yield>, DEFAULT_HANDLERS},
Case("Testing single thread with child", test_single_thread<increment_with_child>),
Case("Testing parallel threads with child", test_parallel_threads<3, increment_with_child>),
Case("Testing serial threads with child", test_serial_threads<10, increment_with_child>),
{"Testing single thread with wait", test_single_thread<increment_with_wait>, DEFAULT_HANDLERS},
{"Testing parallel threads with wait", test_parallel_threads<3, increment_with_wait>, DEFAULT_HANDLERS},
{"Testing serial threads with wait", test_serial_threads<10, increment_with_wait>, DEFAULT_HANDLERS},
Case("Testing single thread with murder", test_single_thread<increment_with_murder>),
Case("Testing parallel threads with murder", test_parallel_threads<3, increment_with_murder>),
Case("Testing serial threads with murder", test_serial_threads<10, increment_with_murder>),
{"Testing single thread with child", test_single_thread<increment_with_child>, DEFAULT_HANDLERS},
{"Testing parallel threads with child", test_parallel_threads<3, increment_with_child>, DEFAULT_HANDLERS},
{"Testing serial threads with child", test_serial_threads<10, increment_with_child>, DEFAULT_HANDLERS},
Case("Testing thread self terminate", test_self_terminate),
{"Testing single thread with murder", test_single_thread<increment_with_murder>, DEFAULT_HANDLERS},
{"Testing parallel threads with murder", test_parallel_threads<3, increment_with_murder>, DEFAULT_HANDLERS},
{"Testing serial threads with murder", test_serial_threads<10, increment_with_murder>, DEFAULT_HANDLERS},
{"Testing thread self terminate", test_self_terminate, DEFAULT_HANDLERS},
{"Testing thread signals: wait", test_thread_signal<0x1, signal_wait>, DEFAULT_HANDLERS},
{"Testing thread signals: timeout", test_thread_signal<0x1, signal_wait_tout>, DEFAULT_HANDLERS},
{"Testing thread signals: multi-bit", test_thread_signal<0x3, signal_wait_multibit>, DEFAULT_HANDLERS},
{"Testing thread signals: multi-bit timeout", test_thread_signal<0x1, signal_wait_multibit_tout>, DEFAULT_HANDLERS},
{"Testing thread signals: signal clear", test_thread_signal_clr, DEFAULT_HANDLERS},
{"Testing thread stack info", test_thread_stack_info, DEFAULT_HANDLERS},
{"Testing thread wait", test_thread_wait, DEFAULT_HANDLERS},
{"Testing thread name", test_thread_name, DEFAULT_HANDLERS},
{"Testing thread states: deleted", test_deleted, DEFAULT_HANDLERS},
{"Testing thread states: wait delay", test_delay, DEFAULT_HANDLERS},
{"Testing thread states: wait signal", test_signal, DEFAULT_HANDLERS},
{"Testing thread states: wait event flag", test_evt_flag, DEFAULT_HANDLERS},
{"Testing thread states: wait mutex", test_mutex, DEFAULT_HANDLERS},
{"Testing thread states: wait semaphore", test_semaphore, DEFAULT_HANDLERS},
{"Testing thread states: wait message get", test_msg_get, DEFAULT_HANDLERS},
{"Testing thread states: wait message put", test_msg_put, DEFAULT_HANDLERS},
{"Testing thread with external stack memory", test_thread_ext_stack, DEFAULT_HANDLERS},
{"Testing thread priority ops", test_thread_prio, DEFAULT_HANDLERS}
};
Specification specification(test_setup, cases);

View File

@ -32,7 +32,8 @@ SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel) :
#endif
_bits(8),
_mode(0),
_hz(1000000) {
_hz(1000000),
_write_fill(SPI_FILL_CHAR) {
// No lock needed in the constructor
spi_init(&_spi, mosi, miso, sclk, ssel);
@ -102,7 +103,7 @@ int SPI::write(int value) {
int SPI::write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
lock();
_acquire();
int ret = spi_master_block_write(&_spi, tx_buffer, tx_length, rx_buffer, rx_length);
int ret = spi_master_block_write(&_spi, tx_buffer, tx_length, rx_buffer, rx_length, _write_fill);
unlock();
return ret;
}
@ -115,6 +116,12 @@ void SPI::unlock() {
_mutex->unlock();
}
void SPI::set_default_write_value(char data) {
lock();
_write_fill = data;
unlock();
}
#if DEVICE_SPI_ASYNCH
int SPI::transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t& callback, int event)

View File

@ -143,6 +143,15 @@ public:
*/
virtual void unlock(void);
/** Set default write data
* SPI requires the master to send some data during a read operation.
* Different devices may require different default byte values.
* For example: A SD Card requires default bytes to be 0xFF.
*
* @param data Default character to be transmitted while read operation
*/
void set_default_write_value(char data);
#if DEVICE_SPI_ASYNCH
/** Start non-blocking SPI transfer using 8bit buffers.
@ -271,6 +280,7 @@ protected:
int _bits;
int _mode;
int _hz;
char _write_fill;
private:
/* Private acquire function without locking/unlocking

View File

@ -43,6 +43,11 @@ void UARTSerial::dcd_irq()
wake();
}
void UARTSerial::set_baud(int baud)
{
SerialBase::baud(baud);
}
void UARTSerial::set_data_carrier_detect(PinName dcd_pin, bool active_high)
{
delete _dcd_irq;

View File

@ -152,6 +152,12 @@ public:
*/
void set_data_carrier_detect(PinName dcd_pin, bool active_high = false);
/** Set the baud rate
*
* @param baud The baud rate
*/
void set_baud(int baud);
private:
/** SerialBase lock override */

View File

@ -357,7 +357,20 @@ public:
* Where the first element is the length of the field.
*/
const uint8_t* findField(DataType_t type) const {
return findField(type);
/* Scan through advertisement data */
for (uint8_t idx = 0; idx < _payloadLen; ) {
uint8_t fieldType = _payload[idx + 1];
if (fieldType == type) {
return &_payload[idx];
}
/* Advance to next field */
idx += _payload[idx] + 1;
}
/* Field not found */
return NULL;
}
private:
@ -408,20 +421,7 @@ private:
* otherwise. Where the first element is the length of the field.
*/
uint8_t* findField(DataType_t type) {
/* Scan through advertisement data */
for (uint8_t idx = 0; idx < _payloadLen; ) {
uint8_t fieldType = _payload[idx + 1];
if (fieldType == type) {
return &_payload[idx];
}
/* Advance to next field */
idx += _payload[idx] + 1;
}
/* Field not found */
return NULL;
return const_cast<uint8_t*>(static_cast<const GapAdvertisingData*>(this)->findField(type));
}
/**

View File

@ -321,6 +321,11 @@ public:
* for the value attribute of a characteristic, then that particular
* characteristic may be considered optional and dropped while
* instantiating the service with the underlying BLE stack.
*
* @note A CCCD should not be allocated if either the notify or indicate
* flag is set, as it is handled by the underlying BLE stack. In such
* a case, the param descriptors could be empty and the param
* numDescriptors equal to zero.
*/
GattCharacteristic(const UUID &uuid,
uint8_t *valuePtr = NULL,
@ -584,6 +589,8 @@ private:
SecurityManager::SecurityMode_t _requiredSecurity;
/**
* The characteristic's descriptor attributes.
* This contains only CCCDs that has neither the notify nor the indicate
* flag set, as thoses are handled by the underlying BLE stack.
*/
GattAttribute **_descriptors;
/**

View File

@ -58,7 +58,7 @@ public:
valueBytes(hrmCounter),
hrmRate(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR, valueBytes.getPointer(),
valueBytes.getNumValueBytes(), HeartRateValueBytes::MAX_VALUE_BYTES,
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR, &location),
controlPoint(GattCharacteristic::UUID_HEART_RATE_CONTROL_POINT_CHAR, &controlPointValue) {
setupService();

View File

@ -36,3 +36,7 @@ build/
test_coverage/
**/*.info
**/*~
output/*
# Yotta files
.yotta.json

1
features/FEATURE_COMMON_PAL/mbed-trace/CMakeLists.txt Executable file → Normal file
View File

@ -7,6 +7,7 @@ project(mbedTrace)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mbed-trace/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../nanostack-libservice/mbed-client-libservice/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../nanostack-libservice/)

View File

@ -408,7 +408,7 @@ char* mbed_trace_array(const uint8_t* buf, uint16_t len);
#elif !defined(MBED_TRACE_DUMMIES_DEFINED)
// define dummies, hiding the real functions
#define MBED_TRACE_DUMMIES_DEFINED
#define mbed_trace_init(...) ((void) 0)
#define mbed_trace_init(...) ((int) 0)
#define mbed_trace_free(...) ((void) 0)
#define mbed_trace_buffer_sizes(...) ((void) 0)
#define mbed_trace_config_set(...) ((void) 0)

View File

@ -1,6 +1,6 @@
{
"name": "mbed-trace",
"version": "1.2.1",
"version": "1.3.0",
"description": "Trace library for mbed devices",
"keywords": [
"trace",

View File

@ -339,11 +339,6 @@ void mbed_vtracef(uint8_t dlevel, const char* grp, const char *fmt, va_list ap)
if (plain == true || dlevel == TRACE_LEVEL_CMD) {
//add trace data
retval = vsnprintf(ptr, bLeft, fmt, ap);
//convenience - trim off one trailing \n. Useful if trying to directly
//connect debug layers that do expect callers to pass \n to mbed_trace.
if (retval > 0 && retval < bLeft && ptr[retval - 1] == '\n') {
ptr[--retval] = '\0';
}
if (dlevel == TRACE_LEVEL_CMD && m_trace.cmd_printf) {
m_trace.cmd_printf(m_trace.line);
m_trace.cmd_printf("\n");
@ -446,12 +441,6 @@ void mbed_vtracef(uint8_t dlevel, const char* grp, const char *fmt, va_list ap)
if (retval > 0) {
ptr += retval;
bLeft -= retval;
//convenience - trim off one trailing \n. Useful if trying to directly
//connect debug layers that do expect callers to pass \n to mbed_trace.
if (ptr[-1] == '\n') {
*--ptr = '\0';
++bLeft;
}
}
}
@ -569,7 +558,7 @@ char *mbed_trace_array(const uint8_t *buf, uint16_t len)
int i, bLeft = tmp_data_left();
char *str, *wptr;
str = m_trace.tmp_data_ptr;
if (str == NULL || bLeft == 0) {
if (len == 0 || str == NULL || bLeft == 0) {
return "";
}
if (buf == NULL) {

View File

@ -91,6 +91,19 @@ TEST(trace, Array)
mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(longStr, 200) );
}
TEST(trace, Null0Array)
{
static const unsigned char array[2] = { 0x23, 0x45 };
mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(array, 2));
STRCMP_EQUAL("23:45", buf);
mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(array, 0));
STRCMP_EQUAL("", buf);
mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(NULL, 0));
STRCMP_EQUAL("", buf);
mbed_tracef(TRACE_LEVEL_DEBUG, "mygr", "%s", mbed_trace_array(NULL, 2));
STRCMP_EQUAL("<null>", buf);
}
TEST(trace, LongString)
{
char longStr[1000] = {0x36};

View File

@ -18,8 +18,11 @@
/**
* \file nsdynmemLIB.h
* \brief Dynamical Memory API for library model
*
* nsdynmemlib provides access to one default heap, along with the ability to use extra user heaps.
* ns_dyn_mem_alloc/free always access the default heap initialised by ns_dyn_mem_init.
* ns_mem_alloc/free access a user heap initialised by ns_mem_init. User heaps are identified by a book-keeping pointer.
*/
#ifndef NSDYNMEMLIB_H_
#define NSDYNMEMLIB_H_
#ifdef __cplusplus
@ -28,6 +31,12 @@ extern "C" {
#include "ns_types.h"
// Added to maintain backward compatibility with older implementation of ns_dyn_mem APIs
#define NSDYNMEMLIB_API_VERSION 2
typedef uint16_t ns_mem_block_size_t; //external interface unsigned heap block size type
typedef uint16_t ns_mem_heap_size_t; //total heap size type.
/*!
* \enum heap_fail_t
* \brief Dynamically heap system failure call back event types.
@ -47,14 +56,17 @@ typedef enum {
*/
typedef struct mem_stat_t {
/*Heap stats*/
int16_t heap_sector_size; /**< Heap total Sector len. */
int16_t heap_sector_alloc_cnt; /**< Reserved Heap sector cnt. */
int16_t heap_sector_allocated_bytes; /**< Reserved Heap data in bytes. */
int16_t heap_sector_allocated_bytes_max; /**< Reserved Heap data in bytes max value. */
ns_mem_heap_size_t heap_sector_size; /**< Heap total Sector len. */
ns_mem_heap_size_t heap_sector_alloc_cnt; /**< Reserved Heap sector cnt. */
ns_mem_heap_size_t heap_sector_allocated_bytes; /**< Reserved Heap data in bytes. */
ns_mem_heap_size_t heap_sector_allocated_bytes_max; /**< Reserved Heap data in bytes max value. */
uint32_t heap_alloc_total_bytes; /**< Total Heap allocated bytes. */
uint32_t heap_alloc_fail_cnt; /**< Counter for Heap allocation fail. */
} mem_stat_t;
typedef struct ns_mem_book ns_mem_book_t;
/**
* \brief Init and set Dynamical heap pointer and length.
*
@ -62,7 +74,7 @@ typedef struct mem_stat_t {
* \param heap_size size of the heap buffer
* \return None
*/
extern void ns_dyn_mem_init(uint8_t *heap, uint16_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr);
extern void ns_dyn_mem_init(void *heap, ns_mem_heap_size_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr);
/**
@ -84,7 +96,7 @@ extern void ns_dyn_mem_free(void *heap_ptr);
* \return 0, Allocate Fail
* \return >0, Pointer to allocated data sector.
*/
extern void *ns_dyn_mem_temporary_alloc(int16_t alloc_size);
extern void *ns_dyn_mem_temporary_alloc(ns_mem_block_size_t alloc_size);
/**
* \brief Allocate long period data.
*
@ -95,7 +107,7 @@ extern void *ns_dyn_mem_temporary_alloc(int16_t alloc_size);
* \return 0, Allocate Fail
* \return >0, Pointer to allocated data sector.
*/
extern void *ns_dyn_mem_alloc(int16_t alloc_size);
extern void *ns_dyn_mem_alloc(ns_mem_block_size_t alloc_size);
/**
* \brief Get pointer to the current mem_stat_t set via ns_dyn_mem_init.
@ -110,6 +122,65 @@ extern void *ns_dyn_mem_alloc(int16_t alloc_size);
*/
extern const mem_stat_t *ns_dyn_mem_get_mem_stat(void);
/**
* \brief Init and set Dynamical heap pointer and length.
*
* \param heap_ptr Pointer to dynamically heap buffer
* \param heap_size size of the heap buffer
* \return !=0, Pointer to ns_mem_book_t.
*/
extern ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr);
/**
* \brief Free allocated memory.
*
* \param book Address of book keeping structure
* \param heap_ptr Pointer to allocated memory
*
* \return 0, Free OK
* \return <0, Free Fail
*/
extern void ns_mem_free(ns_mem_book_t *book, void *heap_ptr);
/**
* \brief Allocate temporary data.
*
* Space allocate started from beginning of the heap sector
*
* \param book Address of book keeping structure
* \param alloc_size Allocated data size
*
* \return 0, Allocate Fail
* \return >0, Pointer to allocated data sector.
*/
extern void *ns_mem_temporary_alloc(ns_mem_book_t *book, ns_mem_block_size_t alloc_size);
/**
* \brief Allocate long period data.
*
* Space allocate started from end of the heap sector
*
* \param book Address of book keeping structure
* \param alloc_size Allocated data size
*
* \return 0, Allocate Fail
* \return >0, Pointer to allocated data sector.
*/
extern void *ns_mem_alloc(ns_mem_book_t *book, ns_mem_block_size_t alloc_size);
/**
* \brief Get pointer to the current mem_stat_t set via ns_mem_init.
*
* Get pointer to the statistics information, if one is set during the
* initialization. This may be useful for statistics collection purposes.
*
* Note: the caller may not modify the returned structure.
*
* \param book Address of book keeping structure
*
* \return NULL, no mem_stat_t was given on initialization
* \return !=0, Pointer to mem_stat_t.
*/
extern const mem_stat_t *ns_mem_get_mem_stat(ns_mem_book_t *book);
#ifdef __cplusplus
}
#endif

View File

@ -11,6 +11,8 @@
"extraIncludes": [
"mbed-client-libservice"
],
"dependencies": {},
"dependencies": {
"mbed-trace": "ARMmbed/mbed-trace"
},
"targetDependencies": {}
}

View File

@ -20,102 +20,128 @@
#include <stdlib.h>
#include "ns_list.h"
void (*heap_failure_callback)(heap_fail_t);
#ifndef STANDARD_MALLOC
static int *heap_main = 0;
static int *heap_main_end = 0;
static uint16_t heap_size = 0;
typedef enum mem_stat_update_t {
DEV_HEAP_ALLOC_OK,
DEV_HEAP_ALLOC_FAIL,
DEV_HEAP_FREE,
} mem_stat_update_t;
static mem_stat_t *mem_stat_info_ptr = 0;
typedef struct {
ns_list_link_t link;
} hole_t;
static NS_LIST_DEFINE(holes_list, hole_t, link);
typedef int ns_mem_word_size_t; // internal signed heap block size type
/* struct for book keeping variables */
struct ns_mem_book {
ns_mem_word_size_t *heap_main;
ns_mem_word_size_t *heap_main_end;
mem_stat_t *mem_stat_info_ptr;
void (*heap_failure_callback)(heap_fail_t);
NS_LIST_HEAD(hole_t, link) holes_list;
ns_mem_heap_size_t heap_size;
};
static ns_mem_book_t *default_book; // heap pointer for original "ns_" API use
// size of a hole_t in our word units
#define HOLE_T_SIZE ((sizeof(hole_t) + sizeof(int) - 1) / sizeof(int))
#define HOLE_T_SIZE ((sizeof(hole_t) + sizeof(ns_mem_word_size_t) - 1) / sizeof(ns_mem_word_size_t))
static NS_INLINE hole_t *hole_from_block_start(int *start)
static NS_INLINE hole_t *hole_from_block_start(ns_mem_word_size_t *start)
{
return (hole_t *)(start + 1);
}
static NS_INLINE int *block_start_from_hole(hole_t *start)
static NS_INLINE ns_mem_word_size_t *block_start_from_hole(hole_t *start)
{
return ((int *)start) - 1;
return ((ns_mem_word_size_t *)start) - 1;
}
static void heap_failure(heap_fail_t reason)
static void heap_failure(ns_mem_book_t *book, heap_fail_t reason)
{
if (heap_failure_callback) {
heap_failure_callback(reason);
if (book->heap_failure_callback) {
book->heap_failure_callback(reason);
}
}
#endif
void ns_dyn_mem_init(uint8_t *heap, uint16_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr)
void ns_dyn_mem_init(void *heap, ns_mem_heap_size_t h_size,
void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr)
{
#ifndef STANDARD_MALLOC
int *ptr;
int temp_int;
/* Do memory alignment */
temp_int = ((uintptr_t)heap % sizeof(int));
if (temp_int) {
heap += (sizeof(int) - temp_int);
h_size -= (sizeof(int) - temp_int);
}
/* Make correction for total length also */
temp_int = (h_size % sizeof(int));
if (temp_int) {
h_size -= (sizeof(int) - temp_int);
}
heap_main = (int *)heap; // SET Heap Pointer
heap_size = h_size; //Set Heap Size
temp_int = (h_size / sizeof(int));
temp_int -= 2;
ptr = heap_main;
*ptr = -(temp_int);
ptr += (temp_int + 1);
*ptr = -(temp_int);
heap_main_end = ptr;
ns_list_init(&holes_list);
ns_list_add_to_start(&holes_list, hole_from_block_start(heap_main));
//RESET Memory by Hea Len
if (info_ptr) {
mem_stat_info_ptr = info_ptr;
memset(mem_stat_info_ptr, 0, sizeof(mem_stat_t));
mem_stat_info_ptr->heap_sector_size = heap_size;
}
#endif
heap_failure_callback = passed_fptr;
default_book = ns_mem_init(heap, h_size, passed_fptr, info_ptr);
}
const mem_stat_t *ns_dyn_mem_get_mem_stat(void)
{
#ifndef STANDARD_MALLOC
return mem_stat_info_ptr;
return ns_mem_get_mem_stat(default_book);
#else
return NULL;
#endif
}
ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size,
void (*passed_fptr)(heap_fail_t),
mem_stat_t *info_ptr)
{
#ifndef STANDARD_MALLOC
ns_mem_book_t *book;
ns_mem_word_size_t *ptr;
ns_mem_word_size_t temp_int;
/* Do memory alignment */
temp_int = ((uintptr_t)heap % sizeof(ns_mem_word_size_t));
if (temp_int) {
heap = (uint8_t *) heap + (sizeof(ns_mem_word_size_t) - temp_int);
h_size -= (sizeof(ns_mem_word_size_t) - temp_int);
}
/* Make correction for total length also */
temp_int = (h_size % sizeof(ns_mem_word_size_t));
if (temp_int) {
h_size -= (sizeof(ns_mem_word_size_t) - temp_int);
}
book = heap;
book->heap_main = (ns_mem_word_size_t *)&(book[1]); // SET Heap Pointer
book->heap_size = h_size - sizeof(ns_mem_book_t); //Set Heap Size
temp_int = (book->heap_size / sizeof(ns_mem_word_size_t));
temp_int -= 2;
ptr = book->heap_main;
*ptr = -(temp_int);
ptr += (temp_int + 1);
*ptr = -(temp_int);
book->heap_main_end = ptr;
ns_list_init(&book->holes_list);
ns_list_add_to_start(&book->holes_list, hole_from_block_start(book->heap_main));
book->mem_stat_info_ptr = info_ptr;
//RESET Memory by Hea Len
if (info_ptr) {
memset(book->mem_stat_info_ptr, 0, sizeof(mem_stat_t));
book->mem_stat_info_ptr->heap_sector_size = book->heap_size;
}
#endif
//There really is no support to standard malloc in this library anymore
book->heap_failure_callback = passed_fptr;
return book;
}
const mem_stat_t *ns_mem_get_mem_stat(ns_mem_book_t *heap)
{
#ifndef STANDARD_MALLOC
return heap->mem_stat_info_ptr;
#else
return NULL;
#endif
}
#ifndef STANDARD_MALLOC
void dev_stat_update(mem_stat_update_t type, int16_t size)
static void dev_stat_update(mem_stat_t *mem_stat_info_ptr, mem_stat_update_t type, ns_mem_block_size_t size)
{
if (mem_stat_info_ptr) {
switch (type) {
@ -138,26 +164,27 @@ void dev_stat_update(mem_stat_update_t type, int16_t size)
}
}
static int convert_allocation_size(int16_t requested_bytes)
static ns_mem_word_size_t convert_allocation_size(ns_mem_book_t *book, ns_mem_block_size_t requested_bytes)
{
if (heap_main == 0) {
heap_failure(NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED);
if (book->heap_main == 0) {
heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED);
} else if (requested_bytes < 1) {
heap_failure(NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID);
} else if ((size_t)requested_bytes > (heap_size - 2 * sizeof(int)) ) {
heap_failure(NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID);
heap_failure(book, NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID);
} else if (requested_bytes > (book->heap_size - 2 * sizeof(ns_mem_word_size_t)) ) {
heap_failure(book, NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID);
}
return (requested_bytes + sizeof(int) - 1) / sizeof(int);
return (requested_bytes + sizeof(ns_mem_word_size_t) - 1) / sizeof(ns_mem_word_size_t);
}
// Checks that block length indicators are valid
// Block has format: Size of data area [1 word] | data area [abs(size) words]| Size of data area [1 word]
// If Size is negative it means area is unallocated
static int8_t ns_block_validate(int *block_start)
// For direction, use 1 for direction up and -1 for down
static int8_t ns_mem_block_validate(ns_mem_word_size_t *block_start, int direction)
{
int8_t ret_val = -1;
int *end = block_start;
int size_start = *end;
ns_mem_word_size_t *end = block_start;
ns_mem_word_size_t size_start = *end;
end += (1 + abs(size_start));
if (size_start != 0 && size_start == *end) {
ret_val = 0;
@ -167,29 +194,35 @@ static int8_t ns_block_validate(int *block_start)
#endif
// For direction, use 1 for direction up and -1 for down
static void *ns_dyn_mem_internal_alloc(const int16_t alloc_size, int direction)
static void *ns_mem_internal_alloc(ns_mem_book_t *book, const ns_mem_block_size_t alloc_size, int direction)
{
#ifndef STANDARD_MALLOC
int *block_ptr = NULL;
if (!book) {
/* We can not do anything except return NULL because we can't find book
keeping block */
return NULL;
}
ns_mem_word_size_t *block_ptr = NULL;
platform_enter_critical();
int data_size = convert_allocation_size(alloc_size);
ns_mem_word_size_t data_size = convert_allocation_size(book, alloc_size);
if (!data_size) {
goto done;
}
// ns_list_foreach, either forwards or backwards, result to ptr
for (hole_t *cur_hole = direction > 0 ? ns_list_get_first(&holes_list)
: ns_list_get_last(&holes_list);
for (hole_t *cur_hole = direction > 0 ? ns_list_get_first(&book->holes_list)
: ns_list_get_last(&book->holes_list);
cur_hole;
cur_hole = direction > 0 ? ns_list_get_next(&holes_list, cur_hole)
: ns_list_get_previous(&holes_list, cur_hole)
cur_hole = direction > 0 ? ns_list_get_next(&book->holes_list, cur_hole)
: ns_list_get_previous(&book->holes_list, cur_hole)
) {
int *p = block_start_from_hole(cur_hole);
if (ns_block_validate(p) != 0 || *p >= 0) {
ns_mem_word_size_t *p = block_start_from_hole(cur_hole);
if (ns_mem_block_validate(p, direction) != 0 || *p >= 0) {
//Validation failed, or this supposed hole has positive (allocated) size
heap_failure(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
break;
}
if (-*p >= data_size) {
@ -203,10 +236,10 @@ static void *ns_dyn_mem_internal_alloc(const int16_t alloc_size, int direction)
goto done;
}
size_t block_data_size = -*block_ptr;
ns_mem_word_size_t block_data_size = -*block_ptr;
if (block_data_size >= (data_size + 2 + HOLE_T_SIZE)) {
int hole_size = block_data_size - data_size - 2;
int *hole_ptr;
ns_mem_word_size_t hole_size = block_data_size - data_size - 2;
ns_mem_word_size_t *hole_ptr;
//There is enough room for a new hole so create it first
if ( direction > 0 ) {
hole_ptr = block_ptr + 1 + data_size + 1;
@ -214,12 +247,12 @@ static void *ns_dyn_mem_internal_alloc(const int16_t alloc_size, int direction)
// Would like to just replace this block_ptr with new descriptor, but
// they could overlap, so ns_list_replace might fail
//ns_list_replace(&holes_list, block_ptr, hole_from_block_start(hole_ptr));
hole_t *before = ns_list_get_previous(&holes_list, hole_from_block_start(block_ptr));
ns_list_remove(&holes_list, hole_from_block_start(block_ptr));
hole_t *before = ns_list_get_previous(&book->holes_list, hole_from_block_start(block_ptr));
ns_list_remove(&book->holes_list, hole_from_block_start(block_ptr));
if (before) {
ns_list_add_after(&holes_list, before, hole_from_block_start(hole_ptr));
ns_list_add_after(&book->holes_list, before, hole_from_block_start(hole_ptr));
} else {
ns_list_add_to_start(&holes_list, hole_from_block_start(hole_ptr));
ns_list_add_to_start(&book->holes_list, hole_from_block_start(hole_ptr));
}
} else {
hole_ptr = block_ptr;
@ -232,20 +265,20 @@ static void *ns_dyn_mem_internal_alloc(const int16_t alloc_size, int direction)
} else {
// Not enough room for a left-over hole, so use the whole block
data_size = block_data_size;
ns_list_remove(&holes_list, hole_from_block_start(block_ptr));
ns_list_remove(&book->holes_list, hole_from_block_start(block_ptr));
}
block_ptr[0] = data_size;
block_ptr[1 + data_size] = data_size;
done:
if (mem_stat_info_ptr) {
if (book->mem_stat_info_ptr) {
if (block_ptr) {
//Update Allocate OK
dev_stat_update(DEV_HEAP_ALLOC_OK, (data_size + 2) * sizeof(int));
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_OK, (data_size + 2) * sizeof(ns_mem_word_size_t));
} else {
//Update Allocate Fail, second parameter is not used for stats
dev_stat_update(DEV_HEAP_ALLOC_FAIL, 0);
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0);
}
}
platform_exit_critical();
@ -262,18 +295,28 @@ static void *ns_dyn_mem_internal_alloc(const int16_t alloc_size, int direction)
#endif
}
void *ns_dyn_mem_alloc(int16_t alloc_size)
void *ns_mem_alloc(ns_mem_book_t *heap, ns_mem_block_size_t alloc_size)
{
return ns_dyn_mem_internal_alloc(alloc_size, -1);
return ns_mem_internal_alloc(heap, alloc_size, -1);
}
void *ns_dyn_mem_temporary_alloc(int16_t alloc_size)
void *ns_mem_temporary_alloc(ns_mem_book_t *heap, ns_mem_block_size_t alloc_size)
{
return ns_dyn_mem_internal_alloc(alloc_size, 1);
return ns_mem_internal_alloc(heap, alloc_size, 1);
}
void *ns_dyn_mem_alloc(ns_mem_block_size_t alloc_size)
{
return ns_mem_alloc(default_book, alloc_size);
}
void *ns_dyn_mem_temporary_alloc(ns_mem_block_size_t alloc_size)
{
return ns_mem_temporary_alloc(default_book, alloc_size);
}
#ifndef STANDARD_MALLOC
static void ns_free_and_merge_with_adjacent_blocks(int * const cur_block, int data_size)
static void ns_mem_free_and_merge_with_adjacent_blocks(ns_mem_book_t *book, ns_mem_word_size_t *cur_block, ns_mem_word_size_t data_size)
{
// Theory of operation: Block is always in form | Len | Data | Len |
// So we need to check length of previous (if current not heap start)
@ -282,21 +325,21 @@ static void ns_free_and_merge_with_adjacent_blocks(int * const cur_block, int da
hole_t *existing_start = NULL;
hole_t *existing_end = NULL;
int *start = cur_block;
int *end = cur_block + data_size + 1;
ns_mem_word_size_t *start = cur_block;
ns_mem_word_size_t *end = cur_block + data_size + 1;
//invalidate current block
*start = -data_size;
*end = -data_size;
size_t merged_data_size = data_size;
ns_mem_word_size_t merged_data_size = data_size;
if (start != heap_main) {
if (start != book->heap_main) {
if (*(start - 1) < 0) {
int *block_end = start - 1;
size_t block_size = 1 + (-*block_end) + 1;
merged_data_size += block_size;
start -= block_size;
if (*start != *block_end) {
heap_failure(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
}
if (block_size >= 1 + HOLE_T_SIZE + 1) {
existing_start = hole_from_block_start(start);
@ -304,14 +347,14 @@ static void ns_free_and_merge_with_adjacent_blocks(int * const cur_block, int da
}
}
if (end != heap_main_end) {
if (end != book->heap_main_end) {
if (*(end + 1) < 0) {
int *block_start = end + 1;
size_t block_size = 1 + (-*block_start) + 1;
merged_data_size += block_size;
end += block_size;
if (*end != *block_start) {
heap_failure(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
}
if (block_size >= 1 + HOLE_T_SIZE + 1) {
existing_end = hole_from_block_start(block_start);
@ -326,8 +369,8 @@ static void ns_free_and_merge_with_adjacent_blocks(int * const cur_block, int da
// Will replace with descriptor at bottom of merged block.
// (Can't use ns_list_replace, because of danger of overlap)
// Optimisation - note our position for insertion below.
before = ns_list_get_next(&holes_list, existing_end);
ns_list_remove(&holes_list, existing_end);
before = ns_list_get_next(&book->holes_list, existing_end);
ns_list_remove(&book->holes_list, existing_end);
}
if (existing_start) {
// Extending hole described by "existing_start" upwards.
@ -340,7 +383,7 @@ static void ns_free_and_merge_with_adjacent_blocks(int * const cur_block, int da
// Locate hole position in list, if we don't already know
// from merging with the block above.
if (!existing_end) {
ns_list_foreach(hole_t, ptr, &holes_list) {
ns_list_foreach(hole_t, ptr, &book->holes_list) {
if (ptr > to_add) {
before = ptr;
break;
@ -348,9 +391,9 @@ static void ns_free_and_merge_with_adjacent_blocks(int * const cur_block, int da
}
}
if (before) {
ns_list_add_before(&holes_list, before, to_add);
ns_list_add_before(&book->holes_list, before, to_add);
} else {
ns_list_add_to_end(&holes_list, to_add);
ns_list_add_to_end(&book->holes_list, to_add);
}
}
@ -360,39 +403,35 @@ static void ns_free_and_merge_with_adjacent_blocks(int * const cur_block, int da
}
#endif
void ns_dyn_mem_free(void *block)
void ns_mem_free(ns_mem_book_t *book, void *block)
{
#ifndef STANDARD_MALLOC
int *ptr = block;
int size;
if (!block) {
return;
}
if (!heap_main) {
heap_failure(NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED);
return;
}
ns_mem_word_size_t *ptr = block;
ns_mem_word_size_t size;
platform_enter_critical();
ptr --;
//Read Current Size
size = *ptr;
if (size < 0) {
heap_failure(NS_DYN_MEM_DOUBLE_FREE);
} else if (ptr < heap_main || ptr >= heap_main_end) {
heap_failure(NS_DYN_MEM_POINTER_NOT_VALID);
} else if ((ptr + size) >= heap_main_end) {
heap_failure(NS_DYN_MEM_POINTER_NOT_VALID);
if (ptr < book->heap_main || ptr >= book->heap_main_end) {
heap_failure(book, NS_DYN_MEM_POINTER_NOT_VALID);
} else if ((ptr + size) >= book->heap_main_end) {
heap_failure(book, NS_DYN_MEM_POINTER_NOT_VALID);
} else if (size < 0) {
heap_failure(book, NS_DYN_MEM_DOUBLE_FREE);
} else {
if (ns_block_validate(ptr) != 0) {
heap_failure(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
if (ns_mem_block_validate(ptr, 1) != 0) {
heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
} else {
ns_free_and_merge_with_adjacent_blocks(ptr, size);
if (mem_stat_info_ptr) {
ns_mem_free_and_merge_with_adjacent_blocks(book, ptr, size);
if (book->mem_stat_info_ptr) {
//Update Free Counter
dev_stat_update(DEV_HEAP_FREE, (size + 2) * sizeof(int));
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_FREE, (size + 2) * sizeof(ns_mem_word_size_t));
}
}
}
@ -403,3 +442,8 @@ void ns_dyn_mem_free(void *block)
platform_exit_critical();
#endif
}
void ns_dyn_mem_free(void *block)
{
ns_mem_free(default_book, block);
}

View File

@ -37,7 +37,7 @@ TEST(dynmem, init)
mem_stat_t info;
reset_heap_error();
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
CHECK(info.heap_sector_size >= (size-4));
CHECK(info.heap_sector_size >= (size-64));
CHECK(!heap_have_failed());
CHECK(ns_dyn_mem_get_mem_stat() == &info);
free(heap);
@ -50,7 +50,7 @@ TEST(dynmem, different_sizes)
mem_stat_t info;
uint8_t *heap = (uint8_t*)malloc(size);
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
CHECK(info.heap_sector_size >= (size-4));
CHECK(info.heap_sector_size >= (size-64));
CHECK(!heap_have_failed());
CHECK(ns_dyn_mem_alloc(10));
free(heap);
@ -68,7 +68,7 @@ TEST(dynmem, diff_alignment)
for (int i=0; i<16; i++) {
ptr++; size--;
ns_dyn_mem_init(ptr, size, &heap_fail_callback, &info);
CHECK(info.heap_sector_size >= (size-4));
CHECK(info.heap_sector_size >= (size-64));
CHECK(!heap_have_failed());
}
free(heap);
@ -137,7 +137,7 @@ TEST(dynmem, ns_dyn_mem_temporary_alloc)
}
TEST(dynmem, test_both_allocs_with_hole_usage) {
uint16_t size = 48;
uint16_t size = 112;
mem_stat_t info;
void *p[size];
uint8_t *heap = (uint8_t*)malloc(size);
@ -273,7 +273,7 @@ TEST(dynmem, diff_sizes)
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
CHECK(!heap_have_failed());
int i;
for (i=1; i<(size-8); i++) {
for (i=1; i<(size-64); i++) {
p = ns_dyn_mem_temporary_alloc(i);
CHECK(p);
ns_dyn_mem_free(p);
@ -413,7 +413,7 @@ TEST(dynmem, not_negative_stats)
}
TEST(dynmem, test_invalid_pointer_freed) {
uint16_t size = 28;
uint16_t size = 92;
uint8_t *heap = (uint8_t*)malloc(size);
CHECK(NULL != heap);
reset_heap_error();
@ -472,7 +472,7 @@ TEST(dynmem, test_free_corrupted_next_block) {
//NOTE! This test must be last!
TEST(dynmem, uninitialized_test){
ns_dyn_mem_alloc(4);
uint8_t buf[1];
ns_dyn_mem_free(&buf);
void *p = ns_dyn_mem_alloc(4);
ns_dyn_mem_free(p);
CHECK(p == NULL);
}

View File

@ -1,7 +1,7 @@
597 Alessandro Angelino
600 Alessandro Angelino
592 Milosch Meriac
144 Jaeden Amero
80 Niklas Hauser
155 Jaeden Amero
89 Niklas Hauser
5 Irit Arkin
3 JaredCJR
3 AnotherButler
@ -12,5 +12,6 @@
2 Jan Jongboom
2 Nathan Chong
2 Vincenzo Frascino
1 ccli8
1 Aksel Skauge Mellbye
1 ccli8
1 Michael Schwarcz

View File

@ -198,6 +198,7 @@ typedef struct {
/* ACLs list for the secure box: Timer (PIT). */
static const UvisorBoxAclItem g_private_button_acls[] = {
{PORTC, sizeof(*PORTC), UVISOR_TACLDEF_PERIPH}, /* Private peripheral */
{(void *) PORTC_IRQn, 0, UVISOR_TACL_IRQ}, /* Private IRQ */
};
static void private_button_main_thread(const void *);
@ -257,8 +258,9 @@ static void private_button_main_thread(const void *)
{
/* Allocate serial port to ensure that code in this secure box
* won't touch handle in the default security context when printing */
if (!(uvisor_ctx->pc = new RawSerial(USBTX, USBRX)))
if (!(uvisor_ctx->pc = new RawSerial(USBTX, USBRX))) {
return;
}
/* Create the buffer and cache its pointer to the private static memory. */
uvisor_ctx->buffer = (uint32_t *) malloc(PRIVATE_BUTTON_BUFFER_COUNT * sizeof(uint32_t));
@ -286,7 +288,7 @@ A few things to note in the code above:
- If code runs in the context of `private_button`, then any object instantiated inside that code belongs to the `private_button` heap and stack. This means that in the example above, the `InterruptIn` object is private to the `private_button` box. The same applies to the dynamically allocated buffer `uvisor_ctx->buffer`.
- You can access the content of the private memory `PrivateButtonStaticMemory` using the `void * const __uvisor_ctx` pointer, which uVisor maintains. You need to cast this pointer to your own context type. In this example we used a pre-processor symbol to improve readability.
- The `InterruptIn` object triggers the registration of an interrupt slot. Because that code runs in the context of the `private_button` box, the push-button IRQ belongs to that box. If you want to use the IRQ APIs directly, read the [NVIC APIs section](#the-nvic-apis) below.
- The `InterruptIn` object triggers the registration of an interrupt slot using the NVIC APIs. If you want to use the IRQ APIs directly, read the [NVIC APIs section](#the-nvic-apis) below. We registered the push-button IRQ to the `private_button` box through an IRQ ACL, and hence only code from this box can access it. Changing the push-button IRQ state from the public box causes a uVisor fault.
- Even if the `private_button_on_press` function runs in the context of `private_button`, you can still use the `printf` function, which accesses the `UART0` peripheral, owned by the public box. This is because all ACLs declared in the public box are by default shared with all the other secure boxes. This also means that the messages we are printing on the serial port are not secure because other boxes have access to that peripheral.
> **Warning**: Instantiating an object in the `secure_box.cpp` global scope automatically maps it to the public box context, not the `private_button` one. If you want an object to be private to a box, you need to instantiate it inside the code that runs in the context of that box (such as the `InterruptIn` object), or alternatively statically initialize it in the box private static memory (such as the `buffer`, `index` and `counter` variables in `PrivateButtonStaticMemory`).
@ -422,26 +424,12 @@ When the uVisor is enabled, all NVIC APIs are rerouted to the corresponding uVis
- The uVisor owns the interrupt vector table.
- All ISRs are relocated to SRAM.
- Code in a box can only change the state of an IRQ (enable it, change its priority, etc.) if the box registered that IRQ with uVisor at runtime, using the `NVIC_SetVector` API.
- Code in a box can only change the state of an IRQ (enable it, change its priority and so on) if the box registered that IRQ with uVisor through an IRQ ACL.
- An IRQ that belongs to a box can only be modified when that box context is active.
Although this behavior is different from that of the original NVIC, it is backward compatible. Legacy code (such as a device HAL) still works after uVisor is enabled. The general use case is the following:
Although this behavior is different from that of the original NVIC, it is backward compatible. Legacy code (such as a device HAL) still works after uVisor is enabled.
```C
#define MY_IRQ 42
/* Set the ISR for MY_IRQ at runtime.
* Without uVisor: Relocate the interrupt vector table to SRAM and set my_isr as
the ISR for MY_IRQ.
* With uVisor: Register MY_IRQ for the current box with my_isr as ISR. */
NVIC_SetVector(MY_IRQ, &my_isr);
/* Change the IRQ state. */
NVIC_SetPriority(MY_IRQ, 3);
NVIC_EnableIRQ(MY_IRQ);
```
> **Note**: In this model, a call to `NVIC_SetVector` must happen before an IRQ state changes. In platforms that don't relocate the interrupt vector table, such a call might be absent and must be added to work with uVisor.
All IRQ slots that are not listed in any box ACL list are considered unclaimed. Boxes can gain exclusive ownership of unclaimed IRQs on a first-come first-served basis through the use of the NVIC APIs.
## The *public box* ACLs

View File

@ -1 +1 @@
v0.28.1
v0.29.0

View File

@ -111,6 +111,8 @@ publish: TARGET_M3 TARGET_M4
#
# Updated list of authors, sorted by contributions
git -C $(UVISOR_DIR) shortlog -s -n > $(TARGET_PREFIX)AUTHORS.txt
# Updated version of uvisor-tests
cp $(UVISOR_DIR)/tools/uvisor-tests.txt $(TARGET_PREFIX)uvisor-tests.txt
uvisor-compile: $(UVISOR_GIT_CFG)
make -C $(UVISOR_DIR)

View File

@ -58,6 +58,7 @@ typedef struct {
int (*page_free)(const UvisorPageTable * const table);
int (*box_namespace)(int box_id, char *box_namespace, size_t length);
int (*box_id_for_namespace)(int * const box_id, const char * const box_namespace);
void (*debug_init)(const TUvisorDebugDriver * const driver);
void (*error)(THaltUserError reason);

View File

@ -40,6 +40,11 @@ static UVISOR_FORCEINLINE int uvisor_box_namespace(int box_id, char *box_namespa
return uvisor_api.box_namespace(box_id, box_namespace, length);
}
static UVISOR_FORCEINLINE int uvisor_box_id_for_namespace(int * const box_id, const char * const box_namespace)
{
return uvisor_api.box_id_for_namespace(box_id, box_namespace);
}
UVISOR_EXTERN_C_END
#endif /* __UVISOR_API_BOX_ID_H__ */

View File

@ -46,15 +46,15 @@ typedef enum uvisor_ipc_io_state {
UVISOR_IPC_IO_STATE_VALID, /* uVisor has copied the message */
} uvisor_ipc_io_state_t;
/* IPC Descriptor Structure */
/* When sending:
/* IPC Descriptor Structure
* When sending:
* @param[in] box_id the ID of the destination box
* @param[in] port the port to send the message to
* @param[in] len the length of the message
* @param[out] token a token that can be used to wait at a later time for
* the send to complete
*/
/* When receiving before a message has been received:
*
* When receiving before a message has been received:
* @param[in] box_id an ID of a box that is allowed to send to this box, or
* UVISOR_BOX_ID_ANY to allow messages from any box
* @param[in] port the port to listen for messages on

View File

@ -0,0 +1 @@
209b261bb6d34b657fb699eb22669eb5c9055219

View File

@ -159,6 +159,18 @@ namespace v1 {
);
}
Specification(const test_setup_handler_t setup_handler,
const Case *cases,
const size_t length,
const test_teardown_handler_t teardown_handler,
const test_failure_handler_t failure_handler,
const handlers_t defaults = default_handlers) :
setup_handler(setup_handler), teardown_handler(teardown_handler), failure_handler(failure_handler),
cases(cases), length(length),
defaults(defaults)
{
}
private:
const test_setup_handler_t setup_handler;
const test_teardown_handler_t teardown_handler;

View File

@ -0,0 +1,26 @@
/*
* mbedtls_device.h
*******************************************************************************
* Copyright (c) 2017, STMicroelectronics
* 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
#define MBEDTLS_AES_ALT
#endif /* MBEDTLS_DEVICE_H */

View File

@ -34,9 +34,9 @@ public:
LoWPANNDInterface(NanostackRfPhy *phy) : MeshInterfaceNanostack(phy) { }
nsapi_error_t initialize(NanostackRfPhy *phy);
int connect();
int disconnect();
bool getOwnIpAddress(char *address, int8_t len);
virtual int connect();
virtual int disconnect();
virtual bool getOwnIpAddress(char *address, int8_t len);
bool getRouterIpAddress(char *address, int8_t len);
private:
mesh_error_t init();

View File

@ -32,7 +32,7 @@ public:
*
* @return 0 on success, negative on failure
*/
virtual nsapi_error_t initialize(NanostackPhy *phy);
nsapi_error_t initialize(NanostackPhy *phy);
/** Start the interface
*

View File

@ -27,9 +27,9 @@ public:
NanostackEthernetInterface(NanostackEthernetPhy *phy) : MeshInterfaceNanostack(phy) { }
nsapi_error_t initialize(NanostackEthernetPhy *phy);
int connect();
int disconnect();
bool getOwnIpAddress(char *address, int8_t len);
virtual int connect();
virtual int disconnect();
virtual bool getOwnIpAddress(char *address, int8_t len);
bool getRouterIpAddress(char *address, int8_t len);
};

View File

@ -34,8 +34,8 @@ public:
ThreadInterface(NanostackRfPhy *phy) : MeshInterfaceNanostack(phy) { }
nsapi_error_t initialize(NanostackRfPhy *phy);
int connect();
int disconnect();
virtual int connect();
virtual int disconnect();
private:
/*
* \brief Initialization of the interface.
@ -69,7 +69,7 @@ private:
* \param len is the length of the address buffer, must be at least 40 bytes
* \return true if address is read successfully, false otherwise
*/
bool getOwnIpAddress(char *address, int8_t len);
virtual bool getOwnIpAddress(char *address, int8_t len);
};
#endif // THREADINTERFACE_H

View File

@ -27,12 +27,12 @@ public:
* @return Device driver ID or a negative error
* code on failure
*/
int8_t phy_register() { return rf_register();}
virtual int8_t phy_register() { return rf_register();}
/** Unregister this physical interface
*
*/
void unregister() { rf_unregister(); }
virtual void unregister() { rf_unregister(); }
};
#endif /* NANOSTACK_RF_PHY_H_ */

View File

@ -33,6 +33,7 @@
#define SPI_EVENT_INTERNAL_TRANSFER_COMPLETE (1 << 30) // Internal flag to report that an event occurred
#define SPI_FILL_WORD (0xFFFF)
#define SPI_FILL_CHAR (0xFF)
#if DEVICE_SPI_ASYNCH
/** Asynch SPI HAL structure
@ -127,11 +128,12 @@ int spi_master_write(spi_t *obj, int value);
* @param[in] tx_length Number of bytes to write, may be zero
* @param[in] rx_buffer Pointer to the byte-array of data to read from the device
* @param[in] rx_length Number of bytes to read, may be zero
* @param[in] write_fill Default data transmitted while performing a read
* @returns
* The number of bytes written and read from the device. This is
* maximum of tx_length and rx_length.
*/
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length);
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill);
/** Check if a value is available to read
*

4
mbed.h
View File

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

View File

@ -29,7 +29,8 @@
*
* Here are some examples:
* @code
* ATCmdParser at = ATCmdParser(serial, "\r\n");
* UARTSerial serial = UARTSerial(D1, D0);
* ATCmdParser at = ATCmdParser(&serial, "\r\n");
* int value;
* char buffer[100];
*

View File

@ -21,7 +21,12 @@
#include<stdint.h>
#define MBED_APPLICATION_SUPPORT defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__CORTEX_M7)
#if defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__CORTEX_M7)
#define MBED_APPLICATION_SUPPORT 1
#else
#define MBED_APPLICATION_SUPPORT 0
#endif
#if MBED_APPLICATION_SUPPORT
#ifdef __cplusplus
extern "C" {

View File

@ -23,7 +23,11 @@
#include "platform/mbed_assert.h"
#include "platform/mbed_toolchain.h"
#define EXCLUSIVE_ACCESS (!defined (__CORTEX_M0) && !defined (__CORTEX_M0PLUS))
#if !defined (__CORTEX_M0) && !defined (__CORTEX_M0PLUS)
#define EXCLUSIVE_ACCESS 1
#else
#define EXCLUSIVE_ACCESS 0
#endif
static volatile uint32_t interrupt_enable_counter = 0;
static volatile bool critical_interrupts_disabled = false;

View File

@ -42,22 +42,22 @@ typedef struct {
void mbed_stats_heap_get(mbed_stats_heap_t *stats);
typedef struct {
uint32_t thread_id; /**< Identifier for thread that owns the stack. */
uint32_t max_size; /**< Sum of the maximum number of bytes used in each stack. */
uint32_t reserved_size; /**< Current number of bytes allocated for all stacks. */
uint32_t stack_cnt; /**< Number of stacks currently allocated. */
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. */
uint32_t reserved_size; /**< Current number of bytes allocated for the stack. */
uint32_t stack_cnt; /**< Number of stacks stats accumulated in the structure. */
} mbed_stats_stack_t;
/**
* Fill the passed in structure with stack stats.
* Fill the passed in structure with stack stats accumulated for all threads. The thread_id will be 0
* and stack_cnt will represent number of threads.
*
* @param stats A pointer to the mbed_stats_stack_t structure to fill
*/
void mbed_stats_stack_get(mbed_stats_stack_t *stats);
/**
* Fill the passed array of stat structures with the stack stats
* for each available stack.
* Fill the passed array of stat structures with the stack stats for each available thread.
*
* @param stats A pointer to an array of mbed_stats_stack_t structures to fill
* @param count The number of mbed_stats_stack_t structures in the provided array

View File

@ -96,7 +96,13 @@
* Mark a function as being weak.
*
* @note
* weak functions are not friendly to making code re-usable, as they can only
* Functions should only be marked as weak in the source file. The header file
* should contain a regular function declaration to insure the function is emitted.
* A function marked weak will not be emitted if an alternative non-weak
* implementation is defined.
*
* @note
* Weak functions are not friendly to making code re-usable, as they can only
* be overridden once (and if they are multiply overridden the linker will emit
* no warning). You should not normally use weak symbols as part of the API to
* re-usable modules.

View File

@ -53,7 +53,12 @@ public:
/** Wait until a Mutex becomes available.
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever)
@return status code that indicates the execution status of the function.
@return status code that indicates the execution status of the function:
@a osOK the mutex has been obtained.
@a osErrorTimeout the mutex could not be obtained in the given time.
@a osErrorParameter internal error.
@a osErrorResource the mutex could not be obtained when no timeout was specified.
@a osErrorISR this function cannot be called from the interrupt service routine.
*/
osStatus lock(uint32_t millisec=osWaitForever);
@ -63,7 +68,11 @@ public:
bool trylock();
/** Unlock the mutex that has previously been locked by the same thread
@return status code that indicates the execution status of the function.
@return status code that indicates the execution status of the function:
@a osOK the mutex has been released.
@a osErrorParameter internal error.
@a osErrorResource the mutex was not locked or the current thread wasn't the owner.
@a osErrorISR this function cannot be called from the interrupt service routine.
*/
osStatus unlock();

View File

@ -53,12 +53,15 @@ public:
/** Wait until a Semaphore resource becomes available.
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever).
@return number of available tokens, or -1 in case of incorrect parameters
@return number of available tokens, before taking one; or -1 in case of incorrect parameters
*/
int32_t wait(uint32_t millisec=osWaitForever);
/** Release a Semaphore resource that was obtain with Semaphore::wait.
@return status code that indicates the execution status of the function.
@return status code that indicates the execution status of the function:
@a osOK the token has been correctly released.
@a osErrorResource the maximum token count has been reached.
@a osErrorParameter internal error.
*/
osStatus release(void);

View File

@ -162,10 +162,6 @@ int32_t Thread::signal_set(int32_t flags) {
return osThreadFlagsSet(_tid, flags);
}
int32_t Thread::signal_clr(int32_t flags) {
return osThreadFlagsClear(flags);
}
Thread::State Thread::get_state() {
uint8_t state = osThreadTerminated;
@ -244,7 +240,7 @@ uint32_t Thread::free_stack() {
if (_tid != NULL) {
os_thread_t *thread = (os_thread_t *)_tid;
size = (uint32_t)thread->stack_mem - thread->sp;
size = (uint32_t)thread->sp - (uint32_t)thread->stack_mem;
}
_mutex.unlock();
@ -284,6 +280,10 @@ const char *Thread::get_name() {
return _attr.name;
}
int32_t Thread::signal_clr(int32_t flags) {
return osThreadFlagsClear(flags);
}
osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) {
uint32_t res;
osEvent evt;
@ -309,9 +309,10 @@ osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) {
evt.status = (osStatus)osErrorValue;
break;
}
}
} else {
evt.status = (osStatus)osEventSignal;
evt.value.signals = res;
}
return evt;
}

View File

@ -245,25 +245,19 @@ public:
*/
osPriority get_priority();
/** Set the specified Signal Flags of an active thread.
/** Set the specified Thread Flags for the thread.
@param signals specifies the signal flags of the thread that should be set.
@return previous signal flags of the specified thread or osFlagsError in case of incorrect parameters.
*/
int32_t signal_set(int32_t signals);
/** Clears the specified Signal Flags of an active thread.
@param signals specifies the signal flags of the thread that should be cleared.
@return resultant signal flags of the specified thread or osFlagsError in case of incorrect parameters.
*/
int32_t signal_clr(int32_t signals);
/** State of the Thread */
enum State {
Inactive, /**< Not created */
Inactive, /**< NOT USED */
Ready, /**< Ready to run */
Running, /**< Running */
WaitingDelay, /**< Waiting for a delay to occur */
WaitingJoin, /**< Waiting for thread to join */
WaitingJoin, /**< Waiting for thread to join. Only happens when using RTX directly. */
WaitingThreadFlag, /**< Waiting for a thread flag to be set */
WaitingEventFlag, /**< Waiting for a event flag to be set */
WaitingMutex, /**< Waiting for a mutex event to occur */
@ -271,13 +265,13 @@ public:
WaitingMemoryPool, /**< Waiting for a memory pool */
WaitingMessageGet, /**< Waiting for message to arrive */
WaitingMessagePut, /**< Waiting for message to be send */
WaitingInterval, /**< Waiting for an interval to occur */
WaitingOr, /**< Waiting for one event in a set to occur */
WaitingAnd, /**< Waiting for multiple events in a set to occur */
WaitingMailbox, /**< Waiting for a mailbox event to occur */
WaitingInterval, /**< NOT USED */
WaitingOr, /**< NOT USED */
WaitingAnd, /**< NOT USED */
WaitingMailbox, /**< NOT USED (Mail is implemented as MemoryPool and Queue) */
/* Not in sync with RTX below here */
Deleted, /**< The task has been deleted */
Deleted, /**< The task has been deleted or not started */
};
/** State of this Thread
@ -310,10 +304,16 @@ public:
*/
const char *get_name();
/** Wait for one or more Signal Flags to become signaled for the current RUNNING thread.
/** Clears the specified Thread Flags of the currently running thread.
@param signals specifies the signal flags of the thread that should be cleared.
@return resultant signal flags of the specified thread or osFlagsError in case of incorrect parameters.
*/
static int32_t signal_clr(int32_t signals);
/** Wait for one or more Thread Flags to become signaled for the current RUNNING thread.
@param signals wait until all specified signal flags are set or 0 for any single signal flag.
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever).
@return event flag information or error code.
@return event flag information or error code. @note if @a millisec is set to 0 and flag is no set the event carries osOK value.
@note not callable from interrupt
*/
static osEvent signal_wait(int32_t signals, uint32_t millisec=osWaitForever);

View File

@ -160,6 +160,8 @@
*
*/
#include <stdlib.h>
#include "cmsis.h"
#include "mbed_rtx.h"
#include "mbed_rtos_storage.h"
@ -413,6 +415,47 @@ void __rt_entry (void) {
mbed_start_main();
}
typedef void *mutex;
/* ARM toolchain requires dynamically created mutexes to enforce thread safety. There's
up to 8 static mutexes, protecting atexit, signalinit, stdin, stdout, stderr, stream_list,
fp_trap_init and the heap. Additionally for each call to fopen one extra mutex will be
created.
mbed OS provides a RTX pool for 8 mutexes, to satisfy the static requirements. All
additional mutexes will be allocated on the heap. We can't use the heap allocation for
all the required mutexes, as the heap operations also require a mutex. We don't need to
worry about freeing the allocated memory as library mutexes are only freed when the
application finishes executing.
*/
int _mutex_initialize(mutex *m)
{
osMutexAttr_t attr;
memset(&attr, 0, sizeof(attr));
attr.name = "ARM toolchain mutex";
attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust;
*m = osMutexNew(&attr);
if (*m != NULL) {
return 1;
}
/* Mutex pool exhausted, try using HEAP */
attr.cb_size = sizeof(mbed_rtos_storage_mutex_t);
attr.cb_mem = (void*)malloc(attr.cb_size);
if (attr.cb_mem == NULL) {
osRtxErrorNotify(osRtxErrorClibSpace, m);
return 0;
}
*m = osMutexNew(&attr);
if (*m == NULL) {
osRtxErrorNotify(osRtxErrorClibMutex, m);
return 0;
}
return 1;
}
#endif /* ARMC */
#elif defined (__GNUC__) /******************** GCC ********************/

View File

@ -597,7 +597,7 @@ typedef void *mutex;
// Initialize mutex
__USED
int _mutex_initialize(mutex *m);
int _mutex_initialize(mutex *m) {
__WEAK int _mutex_initialize(mutex *m) {
*m = osMutexNew(NULL);
if (*m == NULL) {
osRtxErrorNotify(osRtxErrorClibMutex, m);
@ -609,7 +609,7 @@ int _mutex_initialize(mutex *m) {
// Acquire mutex
__USED
void _mutex_acquire(mutex *m);
void _mutex_acquire(mutex *m) {
__WEAK void _mutex_acquire(mutex *m) {
if (os_kernel_is_active()) {
osMutexAcquire(*m, osWaitForever);
}
@ -618,7 +618,7 @@ void _mutex_acquire(mutex *m) {
// Release mutex
__USED
void _mutex_release(mutex *m);
void _mutex_release(mutex *m) {
__WEAK void _mutex_release(mutex *m) {
if (os_kernel_is_active()) {
osMutexRelease(*m);
}
@ -627,7 +627,7 @@ void _mutex_release(mutex *m) {
// Free mutex
__USED
void _mutex_free(mutex *m);
void _mutex_free(mutex *m) {
__WEAK void _mutex_free(mutex *m) {
osMutexDelete(*m);
}

View File

@ -39,6 +39,7 @@
#define OS_DYNAMIC_MEM_SIZE 0
#if defined(__CC_ARM)
/* ARM toolchain uses up to 8 static mutexes, any further mutexes will be allocated on the heap. */
#define OS_MUTEX_OBJ_MEM 1
#define OS_MUTEX_NUM 8
#endif

View File

@ -262,11 +262,12 @@ int spi_master_write(spi_t *obj, int value) {
return data;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -256,13 +256,13 @@ int spi_master_write(spi_t *obj, int value)
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length)
char *rx_buffer, int rx_length, char write_fill)
{
int total = (tx_length > rx_length) ? tx_length : rx_length;
char out, in;
for (int i = 0; i < total; i++) {
out = (i < tx_length) ? tx_buffer[i] : 0xff;
out = (i < tx_length) ? tx_buffer[i] : write_fill;
in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -268,11 +268,12 @@ int spi_master_write(spi_t *obj, int value) {
return (ssp_read(obj));
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -268,11 +268,12 @@ int spi_master_write(spi_t *obj, int value) {
return (ssp_read(obj));
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -555,11 +555,12 @@ int spi_master_write(spi_t *obj, int value)
return rx_data;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -296,11 +296,12 @@ int spi_master_write(spi_t *obj, int value)
return 0;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char _write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : _write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -140,11 +140,12 @@ int spi_master_write(spi_t *obj, int value) {
return obj->spi->POPR;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -141,11 +141,12 @@ int spi_master_write(spi_t *obj, int value) {
return obj->spi->D & 0xff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -120,11 +120,12 @@ int spi_master_write(spi_t *obj, int value) {
return obj->spi->D & 0xff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -199,11 +199,12 @@ int spi_master_write(spi_t *obj, int value) {
return ret;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -199,11 +199,12 @@ int spi_master_write(spi_t *obj, int value) {
return ret;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -118,11 +118,12 @@ int spi_master_write(spi_t *obj, int value)
return rx_data & 0xffff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -118,11 +118,12 @@ int spi_master_write(spi_t *obj, int value)
return rx_data & 0xffff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -115,11 +115,12 @@ int spi_master_write(spi_t *obj, int value)
return rx_data & 0xffff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -115,11 +115,12 @@ int spi_master_write(spi_t *obj, int value)
return rx_data & 0xffff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -117,11 +117,12 @@ int spi_master_write(spi_t *obj, int value)
return rx_data & 0xffff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -117,11 +117,12 @@ int spi_master_write(spi_t *obj, int value)
return rx_data & 0xffff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -117,11 +117,12 @@ int spi_master_write(spi_t *obj, int value)
return rx_data & 0xffff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -117,11 +117,12 @@ int spi_master_write(spi_t *obj, int value)
return rx_data & 0xffff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -127,11 +127,12 @@ int spi_master_write(spi_t *obj, int value)
return rx_data & 0xffff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -127,17 +127,17 @@ int spi_master_write(spi_t *obj, int value)
return rx_data & 0xffff;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
DSPI_MasterTransferBlocking(spi_address[obj->spi.instance], &(dspi_transfer_t){
.txData = (uint8_t *)tx_buffer,
.rxData = (uint8_t *)rx_buffer,
.dataSize = total,
.configFlags = kDSPI_MasterCtar0 | kDSPI_MasterPcs0 | kDSPI_MasterPcsContinuous,
});
DSPI_ClearStatusFlags(spi_address[obj->spi.instance], kDSPI_RxFifoDrainRequestFlag | kDSPI_EndOfQueueFlag);
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;
}
}
return total;
}

View File

@ -179,11 +179,12 @@ int spi_master_write(spi_t *obj, int value)
return result;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -179,11 +179,12 @@ int spi_master_write(spi_t *obj, int value)
return result;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -231,11 +231,12 @@ int spi_master_write(spi_t *obj, int value)
return spi_master_transaction(obj, value, MXC_S_SPI_FIFO_DIR_BOTH);
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -167,11 +167,12 @@ int spi_master_write(spi_t *obj, int value)
return *req.rx_data;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -100,26 +100,26 @@ const PinMap PinMap_UART_RX[] = {
};
const PinMap PinMap_UART_CTS[] = {
{ P0_2, UART_0, (int)&((pin_function_t){&MXC_IOMAN->uart0_req, &MXC_IOMAN->uart0_ack, ((uint32_t)IOMAN_MAP_A | MXC_F_IOMAN_UART0_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART0_ACK_CTS_MAP | MXC_F_IOMAN_UART0_ACK_CTS_IO_ACK)}) },
{ P2_2, UART_1, (int)&((pin_function_t){&MXC_IOMAN->uart1_req, &MXC_IOMAN->uart1_ack, ((uint32_t)IOMAN_MAP_A | MXC_F_IOMAN_UART1_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART1_ACK_CTS_MAP | MXC_F_IOMAN_UART1_ACK_CTS_IO_ACK)}) },
{ P3_2, UART_2, (int)&((pin_function_t){&MXC_IOMAN->uart2_req, &MXC_IOMAN->uart2_ack, ((uint32_t)IOMAN_MAP_A | MXC_F_IOMAN_UART2_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART2_ACK_CTS_MAP | MXC_F_IOMAN_UART2_ACK_CTS_IO_ACK)}) },
{ P5_5, UART_3, (int)&((pin_function_t){&MXC_IOMAN->uart3_req, &MXC_IOMAN->uart3_ack, ((uint32_t)IOMAN_MAP_A | MXC_F_IOMAN_UART3_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART3_ACK_CTS_MAP | MXC_F_IOMAN_UART3_ACK_CTS_IO_ACK)}) },
{ P0_3, UART_0, (int)&((pin_function_t){&MXC_IOMAN->uart0_req, &MXC_IOMAN->uart0_ack, ((uint32_t)IOMAN_MAP_B | MXC_F_IOMAN_UART0_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART0_ACK_CTS_MAP | MXC_F_IOMAN_UART0_ACK_CTS_IO_ACK)}) },
{ P2_3, UART_1, (int)&((pin_function_t){&MXC_IOMAN->uart1_req, &MXC_IOMAN->uart1_ack, ((uint32_t)IOMAN_MAP_B | MXC_F_IOMAN_UART1_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART1_ACK_CTS_MAP | MXC_F_IOMAN_UART1_ACK_CTS_IO_ACK)}) },
{ P3_3, UART_2, (int)&((pin_function_t){&MXC_IOMAN->uart2_req, &MXC_IOMAN->uart2_ack, ((uint32_t)IOMAN_MAP_B | MXC_F_IOMAN_UART2_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART2_ACK_CTS_MAP | MXC_F_IOMAN_UART2_ACK_CTS_IO_ACK)}) },
{ P5_6, UART_3, (int)&((pin_function_t){&MXC_IOMAN->uart3_req, &MXC_IOMAN->uart3_ack, ((uint32_t)IOMAN_MAP_B | MXC_F_IOMAN_UART3_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART3_ACK_CTS_MAP | MXC_F_IOMAN_UART3_ACK_CTS_IO_ACK)}) },
{ P0_2, UART_0, (int)&((pin_function_t){&MXC_IOMAN->uart0_req, &MXC_IOMAN->uart0_ack, ((uint32_t)(IOMAN_MAP_A << MXC_F_IOMAN_UART0_REQ_CTS_MAP_POS) | MXC_F_IOMAN_UART0_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART0_ACK_CTS_MAP | MXC_F_IOMAN_UART0_ACK_CTS_IO_ACK)}) },
{ P2_2, UART_1, (int)&((pin_function_t){&MXC_IOMAN->uart1_req, &MXC_IOMAN->uart1_ack, ((uint32_t)(IOMAN_MAP_A << MXC_F_IOMAN_UART1_REQ_CTS_MAP_POS) | MXC_F_IOMAN_UART1_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART1_ACK_CTS_MAP | MXC_F_IOMAN_UART1_ACK_CTS_IO_ACK)}) },
{ P3_2, UART_2, (int)&((pin_function_t){&MXC_IOMAN->uart2_req, &MXC_IOMAN->uart2_ack, ((uint32_t)(IOMAN_MAP_A << MXC_F_IOMAN_UART2_REQ_CTS_MAP_POS) | MXC_F_IOMAN_UART2_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART2_ACK_CTS_MAP | MXC_F_IOMAN_UART2_ACK_CTS_IO_ACK)}) },
{ P5_5, UART_3, (int)&((pin_function_t){&MXC_IOMAN->uart3_req, &MXC_IOMAN->uart3_ack, ((uint32_t)(IOMAN_MAP_A << MXC_F_IOMAN_UART3_REQ_CTS_MAP_POS) | MXC_F_IOMAN_UART3_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART3_ACK_CTS_MAP | MXC_F_IOMAN_UART3_ACK_CTS_IO_ACK)}) },
{ P0_3, UART_0, (int)&((pin_function_t){&MXC_IOMAN->uart0_req, &MXC_IOMAN->uart0_ack, ((uint32_t)(IOMAN_MAP_B << MXC_F_IOMAN_UART0_REQ_CTS_MAP_POS) | MXC_F_IOMAN_UART0_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART0_ACK_CTS_MAP | MXC_F_IOMAN_UART0_ACK_CTS_IO_ACK)}) },
{ P2_3, UART_1, (int)&((pin_function_t){&MXC_IOMAN->uart1_req, &MXC_IOMAN->uart1_ack, ((uint32_t)(IOMAN_MAP_B << MXC_F_IOMAN_UART1_REQ_CTS_MAP_POS) | MXC_F_IOMAN_UART1_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART1_ACK_CTS_MAP | MXC_F_IOMAN_UART1_ACK_CTS_IO_ACK)}) },
{ P3_3, UART_2, (int)&((pin_function_t){&MXC_IOMAN->uart2_req, &MXC_IOMAN->uart2_ack, ((uint32_t)(IOMAN_MAP_B << MXC_F_IOMAN_UART2_REQ_CTS_MAP_POS) | MXC_F_IOMAN_UART2_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART2_ACK_CTS_MAP | MXC_F_IOMAN_UART2_ACK_CTS_IO_ACK)}) },
{ P5_6, UART_3, (int)&((pin_function_t){&MXC_IOMAN->uart3_req, &MXC_IOMAN->uart3_ack, ((uint32_t)(IOMAN_MAP_B << MXC_F_IOMAN_UART3_REQ_CTS_MAP_POS) | MXC_F_IOMAN_UART3_REQ_CTS_IO_REQ), (MXC_F_IOMAN_UART3_ACK_CTS_MAP | MXC_F_IOMAN_UART3_ACK_CTS_IO_ACK)}) },
{ NC, NC, 0 }
};
const PinMap PinMap_UART_RTS[] = {
{ P0_3, UART_0, (int)&((pin_function_t){&MXC_IOMAN->uart0_req, &MXC_IOMAN->uart0_ack, ((uint32_t)IOMAN_MAP_A | MXC_F_IOMAN_UART0_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART0_ACK_RTS_MAP | MXC_F_IOMAN_UART0_ACK_RTS_IO_ACK)}) },
{ P2_3, UART_1, (int)&((pin_function_t){&MXC_IOMAN->uart1_req, &MXC_IOMAN->uart1_ack, ((uint32_t)IOMAN_MAP_A | MXC_F_IOMAN_UART1_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART1_ACK_RTS_MAP | MXC_F_IOMAN_UART1_ACK_RTS_IO_ACK)}) },
{ P3_3, UART_2, (int)&((pin_function_t){&MXC_IOMAN->uart2_req, &MXC_IOMAN->uart2_ack, ((uint32_t)IOMAN_MAP_A | MXC_F_IOMAN_UART2_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART2_ACK_RTS_MAP | MXC_F_IOMAN_UART2_ACK_RTS_IO_ACK)}) },
{ P5_6, UART_3, (int)&((pin_function_t){&MXC_IOMAN->uart3_req, &MXC_IOMAN->uart3_ack, ((uint32_t)IOMAN_MAP_A | MXC_F_IOMAN_UART3_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART3_ACK_RTS_MAP | MXC_F_IOMAN_UART3_ACK_RTS_IO_ACK)}) },
{ P0_2, UART_0, (int)&((pin_function_t){&MXC_IOMAN->uart0_req, &MXC_IOMAN->uart0_ack, ((uint32_t)IOMAN_MAP_B | MXC_F_IOMAN_UART0_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART0_ACK_RTS_MAP | MXC_F_IOMAN_UART0_ACK_RTS_IO_ACK)}) },
{ P2_2, UART_1, (int)&((pin_function_t){&MXC_IOMAN->uart1_req, &MXC_IOMAN->uart1_ack, ((uint32_t)IOMAN_MAP_B | MXC_F_IOMAN_UART1_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART1_ACK_RTS_MAP | MXC_F_IOMAN_UART1_ACK_RTS_IO_ACK)}) },
{ P3_2, UART_2, (int)&((pin_function_t){&MXC_IOMAN->uart2_req, &MXC_IOMAN->uart2_ack, ((uint32_t)IOMAN_MAP_B | MXC_F_IOMAN_UART2_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART2_ACK_RTS_MAP | MXC_F_IOMAN_UART2_ACK_RTS_IO_ACK)}) },
{ P5_5, UART_3, (int)&((pin_function_t){&MXC_IOMAN->uart3_req, &MXC_IOMAN->uart3_ack, ((uint32_t)IOMAN_MAP_B | MXC_F_IOMAN_UART3_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART3_ACK_RTS_MAP | MXC_F_IOMAN_UART3_ACK_RTS_IO_ACK)}) },
{ P0_3, UART_0, (int)&((pin_function_t){&MXC_IOMAN->uart0_req, &MXC_IOMAN->uart0_ack, ((uint32_t)(IOMAN_MAP_A << MXC_F_IOMAN_UART0_REQ_RTS_MAP_POS) | MXC_F_IOMAN_UART0_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART0_ACK_RTS_MAP | MXC_F_IOMAN_UART0_ACK_RTS_IO_ACK)}) },
{ P2_3, UART_1, (int)&((pin_function_t){&MXC_IOMAN->uart1_req, &MXC_IOMAN->uart1_ack, ((uint32_t)(IOMAN_MAP_A << MXC_F_IOMAN_UART1_REQ_RTS_MAP_POS) | MXC_F_IOMAN_UART1_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART1_ACK_RTS_MAP | MXC_F_IOMAN_UART1_ACK_RTS_IO_ACK)}) },
{ P3_3, UART_2, (int)&((pin_function_t){&MXC_IOMAN->uart2_req, &MXC_IOMAN->uart2_ack, ((uint32_t)(IOMAN_MAP_A << MXC_F_IOMAN_UART2_REQ_RTS_MAP_POS) | MXC_F_IOMAN_UART2_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART2_ACK_RTS_MAP | MXC_F_IOMAN_UART2_ACK_RTS_IO_ACK)}) },
{ P5_6, UART_3, (int)&((pin_function_t){&MXC_IOMAN->uart3_req, &MXC_IOMAN->uart3_ack, ((uint32_t)(IOMAN_MAP_A << MXC_F_IOMAN_UART3_REQ_RTS_MAP_POS) | MXC_F_IOMAN_UART3_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART3_ACK_RTS_MAP | MXC_F_IOMAN_UART3_ACK_RTS_IO_ACK)}) },
{ P0_2, UART_0, (int)&((pin_function_t){&MXC_IOMAN->uart0_req, &MXC_IOMAN->uart0_ack, ((uint32_t)(IOMAN_MAP_B << MXC_F_IOMAN_UART0_REQ_RTS_MAP_POS) | MXC_F_IOMAN_UART0_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART0_ACK_RTS_MAP | MXC_F_IOMAN_UART0_ACK_RTS_IO_ACK)}) },
{ P2_2, UART_1, (int)&((pin_function_t){&MXC_IOMAN->uart1_req, &MXC_IOMAN->uart1_ack, ((uint32_t)(IOMAN_MAP_B << MXC_F_IOMAN_UART1_REQ_RTS_MAP_POS) | MXC_F_IOMAN_UART1_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART1_ACK_RTS_MAP | MXC_F_IOMAN_UART1_ACK_RTS_IO_ACK)}) },
{ P3_2, UART_2, (int)&((pin_function_t){&MXC_IOMAN->uart2_req, &MXC_IOMAN->uart2_ack, ((uint32_t)(IOMAN_MAP_B << MXC_F_IOMAN_UART2_REQ_RTS_MAP_POS) | MXC_F_IOMAN_UART2_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART2_ACK_RTS_MAP | MXC_F_IOMAN_UART2_ACK_RTS_IO_ACK)}) },
{ P5_5, UART_3, (int)&((pin_function_t){&MXC_IOMAN->uart3_req, &MXC_IOMAN->uart3_ack, ((uint32_t)(IOMAN_MAP_B << MXC_F_IOMAN_UART3_REQ_RTS_MAP_POS) | MXC_F_IOMAN_UART3_REQ_RTS_IO_REQ), (MXC_F_IOMAN_UART3_ACK_RTS_MAP | MXC_F_IOMAN_UART3_ACK_RTS_IO_ACK)}) },
{ NC, NC, 0 }
};

View File

@ -180,6 +180,10 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
//******************************************************************************
void uart_handler(serial_t *obj)
{
// clear interrupts
volatile uint32_t flags = obj->uart->intfl;
obj->uart->intfl = flags;
if (obj && obj->id) {
irq_handler(obj->id, RxIrq);
}
@ -200,6 +204,9 @@ void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
//******************************************************************************
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
{
MBED_ASSERT(obj->index < MXC_CFG_UART_INSTANCES);
objs[obj->index] = obj;
switch (obj->index) {
case 0:
NVIC_SetVector(UART0_IRQn, (uint32_t)uart0_handler);

View File

@ -167,11 +167,12 @@ int spi_master_write(spi_t *obj, int value)
return *req.rx_data;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -263,11 +263,12 @@ int spi_master_write(spi_t *obj, int value)
return spi_read(obj);
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -0,0 +1,253 @@
/*
* Copyright (c) 2017 VNG IoT Lab, Vietnam
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
* integrated circuit in a product or a software update for such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific prior
* written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* 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 THE COPYRIGHT HOLDER OR 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.
*
*/
/*
* PinNames for the VBLUno52 board
*/
#ifndef MBED_PINNAMES_H
#define MBED_PINNAMES_H
#include "cmsis.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
PIN_INPUT,
PIN_OUTPUT
} PinDirection;
#define PORT_SHIFT 3
typedef enum {
p0 = 0,
p1 = 1,
p2 = 2,
p3 = 3,
p4 = 4,
p5 = 5,
p6 = 6,
p7 = 7,
p8 = 8,
p9 = 9,
p10 = 10,
p11 = 11,
p12 = 12,
p13 = 13,
p14 = 14,
p15 = 15,
p16 = 16,
p17 = 17,
p18 = 18,
p19 = 19,
p20 = 20,
p21 = 21,
p22 = 22,
p23 = 23,
p24 = 24,
p25 = 25,
p26 = 26,
p27 = 27,
p28 = 28,
p29 = 29,
p30 = 30,
p31 = 31,
P0_0 = p0,
P0_1 = p1,
P0_2 = p2,
P0_3 = p3,
P0_4 = p4,
P0_5 = p5,
P0_6 = p6,
P0_7 = p7,
P0_8 = p8,
P0_9 = p9,
P0_10 = p10,
P0_11 = p11,
P0_12 = p12,
P0_13 = p13,
P0_14 = p14,
P0_15 = p15,
P0_16 = p16,
P0_17 = p17,
P0_18 = p18,
P0_19 = p19,
P0_20 = p20,
P0_21 = p21,
P0_22 = p22,
P0_23 = p23,
P0_24 = p24,
P0_25 = p25,
P0_26 = p26,
P0_27 = p27,
P0_28 = p28,
P0_29 = p29,
P0_30 = p30,
P0_31 = p31,
//only for mbed test suite
LED1 = p12,
LED2 = p18,
LED3 = p19,
LED4 = p20,
//only for mbed test suite
BUTTON1 = p17,
BUTTON2 = p3,
BUTTON3 = p4,
BUTTON4 = p28,
RX_PIN_NUMBER = p8,
TX_PIN_NUMBER = p6,
CTS_PIN_NUMBER = p7, //not on Header
RTS_PIN_NUMBER = p5, //not on Header
// mBed interface Pins
USBTX = TX_PIN_NUMBER,
USBRX = RX_PIN_NUMBER,
SPI_PSELMOSI0 = p13,
SPI_PSELMISO0 = p14,
SPI_PSELSS0 = p11,
SPI_PSELSCK0 = p15,
SPI_PSELMOSI1 = p13,
SPI_PSELMISO1 = p14,
SPI_PSELSS1 = p11,
SPI_PSELSCK1 = p15,
SPIS_PSELMOSI = p13,
SPIS_PSELMISO = p14,
SPIS_PSELSS = p11,
SPIS_PSELSCK = p15,
I2C_SDA = p26,
I2C_SCL = p27,
I2C_SDA0 = p26,
I2C_SCL0 = p27,
I2C_SDA1 = p30,
I2C_SCL1 = p31,
RESET = p21,
NFC1 = p9,
NFC2 = p10,
//Adruino interface pins
D0 = p8,
D1 = p6,
D2 = p24,
D3 = p23,
D4 = p22,
D5 = p18,
D6 = p19,
D7 = p20,
D8 = p9,
D9 = p10,
D10 = p11,
D11 = p13,
D12 = p14,
D13 = p15,
D14 = p3,
D15 = p4,
D16 = p28,
D17 = p29,
D18 = p30,
D19 = p31,
D20 = p26,
D21 = p27,
D22 = p12,
D23 = p17,
D24 = p5,
D25 = p7,
A0 = D14,
A1 = D15,
A2 = D16,
A3 = D17,
A4 = D18,
A5 = D19,
SS = D10,
MOSI = D11,
MISO = D12,
SCK = D13,
SDA0 = D20,
SCL0 = D21,
SDA1 = D18,
SCL1 = D19,
SDA = SDA0,
SCL = SCL0,
RX = D0,
TX = D1,
RTS = D24, //not on Header
CTS = D25, //not on Header
LED = D22, //not on Header
BUT = D23, //not on Header
// Not connected
NC = (int)0xFFFFFFFF
} PinName;
typedef enum {
PullNone = 0,
PullDown = 1,
PullUp = 3,
PullDefault = PullUp
} PinMode;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,23 @@
// The 'features' section in 'target.json' is now used to create the device's hardware preprocessor switches.
// Check the 'features' section of the target description in 'targets.json' for more details.
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_DEVICE_H
#define MBED_DEVICE_H
#include "objects.h"
#endif

View File

@ -487,11 +487,12 @@ int spi_master_write(spi_t *obj, int value)
return p_spi_info->rx_buf;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -241,11 +241,12 @@ int spi_master_write(spi_t *obj, int value)
return value2;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -244,11 +244,12 @@ int spi_master_write(spi_t *obj, int value)
return value2;
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -190,11 +190,12 @@ int spi_master_write(spi_t *obj, int value) {
return ssp_read(obj);
}
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length) {
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
char *rx_buffer, int rx_length, char write_fill) {
int total = (tx_length > rx_length) ? tx_length : rx_length;
for (int i = 0; i < total; i++) {
char out = (i < tx_length) ? tx_buffer[i] : 0xff;
char out = (i < tx_length) ? tx_buffer[i] : write_fill;
char in = spi_master_write(obj, out);
if (i < rx_length) {
rx_buffer[i] = in;

View File

@ -1,17 +0,0 @@
LR_IROM1 0x00000000 0xC000 { ; load region size_region (48k)
ER_IROM1 0x00000000 0xC000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
; 8_byte_aligned(48 vect * 4 bytes) = 8_byte_aligned(0xC0) = 0xC0
; 8KB - 0xC0 = 0x1F40
RW_IRAM1 0x100000C0 0x1F40 {
.ANY (+RW +ZI)
}
RW_IRAM2 0x20004000 0x800 { ; RW data, USB RAM
.ANY (USBRAM)
}
}

View File

@ -1,325 +0,0 @@
;/*****************************************************************************
; * @file: startup_LPC11xx.s
; * @purpose: CMSIS Cortex-M0 Core Device Startup File
; * for the NXP LPC11xx Device Series
; * @version: V1.0
; * @date: 25. Nov. 2008
; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------
; *
; * Copyright (C) 2008 ARM Limited. All rights reserved.
; * ARM Limited (ARM) is supplying this software for use with Cortex-M0
; * processor based microcontrollers. This file can be freely distributed
; * within development tools that are supporting such ARM based processors.
; *
; * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
; * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
; * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
; * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
; * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
; *
; *****************************************************************************/
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3
EXPORT __initial_sp
Stack_Mem SPACE Stack_Size
__initial_sp EQU 0x10002000 ; Top of RAM from LPC11U
Heap_Size EQU 0x00000000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
EXPORT __heap_base
EXPORT __heap_limit
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
PRESERVE8
THUMB
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
; for LPC11Uxx (With USB)
DCD FLEX_INT0_IRQHandler ; All GPIO pin can be routed to FLEX_INTx
DCD FLEX_INT1_IRQHandler
DCD FLEX_INT2_IRQHandler
DCD FLEX_INT3_IRQHandler
DCD FLEX_INT4_IRQHandler
DCD FLEX_INT5_IRQHandler
DCD FLEX_INT6_IRQHandler
DCD FLEX_INT7_IRQHandler
DCD GINT0_IRQHandler
DCD GINT1_IRQHandler ; PIO0 (0:7)
DCD Reserved_IRQHandler ; Reserved
DCD Reserved_IRQHandler
DCD Reserved_IRQHandler
DCD Reserved_IRQHandler
DCD SSP1_IRQHandler ; SSP1
DCD I2C_IRQHandler ; I2C
DCD TIMER16_0_IRQHandler ; 16-bit Timer0
DCD TIMER16_1_IRQHandler ; 16-bit Timer1
DCD TIMER32_0_IRQHandler ; 32-bit Timer0
DCD TIMER32_1_IRQHandler ; 32-bit Timer1
DCD SSP0_IRQHandler ; SSP0
DCD UART_IRQHandler ; UART
DCD USB_IRQHandler ; USB IRQ
DCD USB_FIQHandler ; USB FIQ
DCD ADC_IRQHandler ; A/D Converter
DCD WDT_IRQHandler ; Watchdog timer
DCD BOD_IRQHandler ; Brown Out Detect
DCD FMC_IRQHandler ; IP2111 Flash Memory Controller
DCD Reserved_IRQHandler ; Reserved
DCD Reserved_IRQHandler ; Reserved
DCD USBWakeup_IRQHandler ; USB wake up
DCD Reserved_IRQHandler ; Reserved
;; 48 vector entries. We pad to 128 to fill the 0x0 - 0x1FF REMAP address space
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
IF :LNOT::DEF:NO_CRP
AREA |.ARM.__at_0x02FC|, CODE, READONLY
CRP_Key DCD 0xFFFFFFFF
ENDIF
AREA |.text|, CODE, READONLY
; Reset Handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
; Dummy Exception Handlers (infinite loops which can be modified)
; now, under COMMON NMI.c and NMI.h, a real NMI handler is created if NMI is enabled
; for particular peripheral.
;NMI_Handler PROC
; EXPORT NMI_Handler [WEAK]
; B .
; ENDP
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
MemManage_Handler\
PROC
EXPORT MemManage_Handler [WEAK]
B .
ENDP
BusFault_Handler\
PROC
EXPORT BusFault_Handler [WEAK]
B .
ENDP
UsageFault_Handler\
PROC
EXPORT UsageFault_Handler [WEAK]
B .
ENDP
SVC_Handler PROC
EXPORT SVC_Handler [WEAK]
B .
ENDP
DebugMon_Handler\
PROC
EXPORT DebugMon_Handler [WEAK]
B .
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK]
B .
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP
Reserved_IRQHandler PROC
EXPORT Reserved_IRQHandler [WEAK]
B .
ENDP
Default_Handler PROC
; for LPC11Uxx (With USB)
EXPORT NMI_Handler [WEAK]
EXPORT FLEX_INT0_IRQHandler [WEAK]
EXPORT FLEX_INT1_IRQHandler [WEAK]
EXPORT FLEX_INT2_IRQHandler [WEAK]
EXPORT FLEX_INT3_IRQHandler [WEAK]
EXPORT FLEX_INT4_IRQHandler [WEAK]
EXPORT FLEX_INT5_IRQHandler [WEAK]
EXPORT FLEX_INT6_IRQHandler [WEAK]
EXPORT FLEX_INT7_IRQHandler [WEAK]
EXPORT GINT0_IRQHandler [WEAK]
EXPORT GINT1_IRQHandler [WEAK]
EXPORT SSP1_IRQHandler [WEAK]
EXPORT I2C_IRQHandler [WEAK]
EXPORT TIMER16_0_IRQHandler [WEAK]
EXPORT TIMER16_1_IRQHandler [WEAK]
EXPORT TIMER32_0_IRQHandler [WEAK]
EXPORT TIMER32_1_IRQHandler [WEAK]
EXPORT SSP0_IRQHandler [WEAK]
EXPORT UART_IRQHandler [WEAK]
EXPORT USB_IRQHandler [WEAK]
EXPORT USB_FIQHandler [WEAK]
EXPORT ADC_IRQHandler [WEAK]
EXPORT WDT_IRQHandler [WEAK]
EXPORT BOD_IRQHandler [WEAK]
EXPORT FMC_IRQHandler [WEAK]
EXPORT USBWakeup_IRQHandler [WEAK]
NMI_Handler
FLEX_INT0_IRQHandler
FLEX_INT1_IRQHandler
FLEX_INT2_IRQHandler
FLEX_INT3_IRQHandler
FLEX_INT4_IRQHandler
FLEX_INT5_IRQHandler
FLEX_INT6_IRQHandler
FLEX_INT7_IRQHandler
GINT0_IRQHandler
GINT1_IRQHandler
SSP1_IRQHandler
I2C_IRQHandler
TIMER16_0_IRQHandler
TIMER16_1_IRQHandler
TIMER32_0_IRQHandler
TIMER32_1_IRQHandler
SSP0_IRQHandler
UART_IRQHandler
USB_IRQHandler
USB_FIQHandler
ADC_IRQHandler
WDT_IRQHandler
BOD_IRQHandler
FMC_IRQHandler
USBWakeup_IRQHandler
B .
ENDP
ALIGN
END

View File

@ -1,17 +0,0 @@
LR_IROM1 0x00000000 0xC000 { ; load region size_region (48k)
ER_IROM1 0x00000000 0xC000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
; 8_byte_aligned(48 vect * 4 bytes) = 8_byte_aligned(0xC0) = 0xC0
; 8KB - 0xC0 = 0x1F40
RW_IRAM1 0x100000C0 0x1F40 {
.ANY (+RW +ZI)
}
RW_IRAM2 0x20004000 0x800 { ; RW data, USB RAM
.ANY (USBRAM)
}
}

View File

@ -1,308 +0,0 @@
;/*****************************************************************************
; * @file: startup_LPC11xx.s
; * @purpose: CMSIS Cortex-M0 Core Device Startup File
; * for the NXP LPC11xx Device Series
; * @version: V1.0
; * @date: 25. Nov. 2008
; *------- <<< Use Configuration Wizard in Context Menu >>> ------------------
; *
; * Copyright (C) 2008 ARM Limited. All rights reserved.
; * ARM Limited (ARM) is supplying this software for use with Cortex-M0
; * processor based microcontrollers. This file can be freely distributed
; * within development tools that are supporting such ARM based processors.
; *
; * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
; * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
; * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
; * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
; * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
; *
; *****************************************************************************/
__initial_sp EQU 0x10002000 ; Top of RAM from LPC11U
PRESERVE8
THUMB
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
; for LPC11Uxx (With USB)
DCD FLEX_INT0_IRQHandler ; All GPIO pin can be routed to FLEX_INTx
DCD FLEX_INT1_IRQHandler
DCD FLEX_INT2_IRQHandler
DCD FLEX_INT3_IRQHandler
DCD FLEX_INT4_IRQHandler
DCD FLEX_INT5_IRQHandler
DCD FLEX_INT6_IRQHandler
DCD FLEX_INT7_IRQHandler
DCD GINT0_IRQHandler
DCD GINT1_IRQHandler ; PIO0 (0:7)
DCD Reserved_IRQHandler ; Reserved
DCD Reserved_IRQHandler
DCD Reserved_IRQHandler
DCD Reserved_IRQHandler
DCD SSP1_IRQHandler ; SSP1
DCD I2C_IRQHandler ; I2C
DCD TIMER16_0_IRQHandler ; 16-bit Timer0
DCD TIMER16_1_IRQHandler ; 16-bit Timer1
DCD TIMER32_0_IRQHandler ; 32-bit Timer0
DCD TIMER32_1_IRQHandler ; 32-bit Timer1
DCD SSP0_IRQHandler ; SSP0
DCD UART_IRQHandler ; UART
DCD USB_IRQHandler ; USB IRQ
DCD USB_FIQHandler ; USB FIQ
DCD ADC_IRQHandler ; A/D Converter
DCD WDT_IRQHandler ; Watchdog timer
DCD BOD_IRQHandler ; Brown Out Detect
DCD FMC_IRQHandler ; IP2111 Flash Memory Controller
DCD Reserved_IRQHandler ; Reserved
DCD Reserved_IRQHandler ; Reserved
DCD USBWakeup_IRQHandler ; USB wake up
DCD Reserved_IRQHandler ; Reserved
;; 48 vector entries. We pad to 128 to fill the 0x0 - 0x1FF REMAP address space
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
DCD 0xFFFFFFFF ; Datafill
IF :LNOT::DEF:NO_CRP
AREA |.ARM.__at_0x02FC|, CODE, READONLY
CRP_Key DCD 0xFFFFFFFF
ENDIF
AREA |.text|, CODE, READONLY
; Reset Handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
; Dummy Exception Handlers (infinite loops which can be modified)
; now, under COMMON NMI.c and NMI.h, a real NMI handler is created if NMI is enabled
; for particular peripheral.
;NMI_Handler PROC
; EXPORT NMI_Handler [WEAK]
; B .
; ENDP
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
MemManage_Handler\
PROC
EXPORT MemManage_Handler [WEAK]
B .
ENDP
BusFault_Handler\
PROC
EXPORT BusFault_Handler [WEAK]
B .
ENDP
UsageFault_Handler\
PROC
EXPORT UsageFault_Handler [WEAK]
B .
ENDP
SVC_Handler PROC
EXPORT SVC_Handler [WEAK]
B .
ENDP
DebugMon_Handler\
PROC
EXPORT DebugMon_Handler [WEAK]
B .
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK]
B .
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP
Reserved_IRQHandler PROC
EXPORT Reserved_IRQHandler [WEAK]
B .
ENDP
Default_Handler PROC
; for LPC11Uxx (With USB)
EXPORT NMI_Handler [WEAK]
EXPORT FLEX_INT0_IRQHandler [WEAK]
EXPORT FLEX_INT1_IRQHandler [WEAK]
EXPORT FLEX_INT2_IRQHandler [WEAK]
EXPORT FLEX_INT3_IRQHandler [WEAK]
EXPORT FLEX_INT4_IRQHandler [WEAK]
EXPORT FLEX_INT5_IRQHandler [WEAK]
EXPORT FLEX_INT6_IRQHandler [WEAK]
EXPORT FLEX_INT7_IRQHandler [WEAK]
EXPORT GINT0_IRQHandler [WEAK]
EXPORT GINT1_IRQHandler [WEAK]
EXPORT SSP1_IRQHandler [WEAK]
EXPORT I2C_IRQHandler [WEAK]
EXPORT TIMER16_0_IRQHandler [WEAK]
EXPORT TIMER16_1_IRQHandler [WEAK]
EXPORT TIMER32_0_IRQHandler [WEAK]
EXPORT TIMER32_1_IRQHandler [WEAK]
EXPORT SSP0_IRQHandler [WEAK]
EXPORT UART_IRQHandler [WEAK]
EXPORT USB_IRQHandler [WEAK]
EXPORT USB_FIQHandler [WEAK]
EXPORT ADC_IRQHandler [WEAK]
EXPORT WDT_IRQHandler [WEAK]
EXPORT BOD_IRQHandler [WEAK]
EXPORT FMC_IRQHandler [WEAK]
EXPORT USBWakeup_IRQHandler [WEAK]
NMI_Handler
FLEX_INT0_IRQHandler
FLEX_INT1_IRQHandler
FLEX_INT2_IRQHandler
FLEX_INT3_IRQHandler
FLEX_INT4_IRQHandler
FLEX_INT5_IRQHandler
FLEX_INT6_IRQHandler
FLEX_INT7_IRQHandler
GINT0_IRQHandler
GINT1_IRQHandler
SSP1_IRQHandler
I2C_IRQHandler
TIMER16_0_IRQHandler
TIMER16_1_IRQHandler
TIMER32_0_IRQHandler
TIMER32_1_IRQHandler
SSP0_IRQHandler
UART_IRQHandler
USB_IRQHandler
USB_FIQHandler
ADC_IRQHandler
WDT_IRQHandler
BOD_IRQHandler
FMC_IRQHandler
USBWakeup_IRQHandler
B .
ENDP
ALIGN
END

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