mirror of https://github.com/ARMmbed/mbed-os.git
Merge branch 'master' of https://github.com/ARMmbed/mbed-os into pr-sm
commit
e568aa47ba
|
@ -0,0 +1,219 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
#include "drivers/TimerEvent.h"
|
||||
#include "hal/ticker_api.h"
|
||||
#include "rtos.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
#define TEST_DELAY_US 50000ULL
|
||||
|
||||
class TestTimerEvent: public TimerEvent {
|
||||
private:
|
||||
Semaphore sem;
|
||||
virtual void handler() {
|
||||
sem.release();
|
||||
}
|
||||
|
||||
public:
|
||||
TestTimerEvent() :
|
||||
TimerEvent(), sem(0, 1) {
|
||||
}
|
||||
|
||||
TestTimerEvent(const ticker_data_t *data) :
|
||||
TimerEvent(data), sem(0, 1) {
|
||||
}
|
||||
|
||||
virtual ~TestTimerEvent() {
|
||||
}
|
||||
|
||||
// Make these methods publicly accessible
|
||||
using TimerEvent::insert;
|
||||
using TimerEvent::insert_absolute;
|
||||
using TimerEvent::remove;
|
||||
|
||||
int32_t sem_wait(uint32_t millisec) {
|
||||
return sem.wait(millisec);
|
||||
}
|
||||
};
|
||||
|
||||
class TestTimerEventRelative: public TestTimerEvent {
|
||||
public:
|
||||
static const int32_t SEM_SLOTS_AFTER_PAST_TS_INSERTED = 0;
|
||||
TestTimerEventRelative() :
|
||||
TestTimerEvent() {
|
||||
}
|
||||
|
||||
TestTimerEventRelative(const ticker_data_t *data) :
|
||||
TestTimerEvent(data) {
|
||||
}
|
||||
|
||||
// Set relative timestamp of internal event to present_time + ts
|
||||
void set_future_timestamp(timestamp_t ts) {
|
||||
insert(::ticker_read(_ticker_data) + ts);
|
||||
}
|
||||
|
||||
void set_past_timestamp(void) {
|
||||
insert(::ticker_read(_ticker_data) - 1UL);
|
||||
}
|
||||
};
|
||||
|
||||
class TestTimerEventAbsolute: public TestTimerEvent {
|
||||
public:
|
||||
static const int32_t SEM_SLOTS_AFTER_PAST_TS_INSERTED = 1;
|
||||
TestTimerEventAbsolute() :
|
||||
TestTimerEvent() {
|
||||
}
|
||||
|
||||
TestTimerEventAbsolute(const ticker_data_t *data) :
|
||||
TestTimerEvent(data) {
|
||||
}
|
||||
|
||||
// Set absolute timestamp of internal event to present_time + ts
|
||||
void set_future_timestamp(us_timestamp_t ts) {
|
||||
insert_absolute(::ticker_read_us(_ticker_data) + ts);
|
||||
}
|
||||
|
||||
void set_past_timestamp(void) {
|
||||
insert_absolute(::ticker_read_us(_ticker_data) - 1ULL);
|
||||
}
|
||||
};
|
||||
|
||||
/** Template for tests: insert, insert_absolute
|
||||
*
|
||||
* Test insert
|
||||
* Given an instance of @a TimerEvent subclass
|
||||
* When a tiestamp is set with @a insert()
|
||||
* and given time elapses
|
||||
* Then an event handler is called
|
||||
*
|
||||
* Test insert_absolute
|
||||
* Given an instance of @a TimerEvent subclass
|
||||
* When a tiestamp is set with @a insert_absolute()
|
||||
* and given time elapses
|
||||
* Then an event handler is called
|
||||
*/
|
||||
template<typename T>
|
||||
void test_insert(void) {
|
||||
T tte;
|
||||
|
||||
tte.set_future_timestamp(TEST_DELAY_US);
|
||||
int32_t sem_slots = tte.sem_wait(0);
|
||||
TEST_ASSERT_EQUAL(0, sem_slots);
|
||||
|
||||
sem_slots = tte.sem_wait(TEST_DELAY_US / 1000 + 1);
|
||||
TEST_ASSERT_EQUAL(1, sem_slots);
|
||||
|
||||
tte.remove();
|
||||
}
|
||||
|
||||
/** Template for tests: remove
|
||||
*
|
||||
* Test remove after insert
|
||||
* Given an instance of @a TimerEvent subclass
|
||||
* When a tiestamp is set with @a insert()
|
||||
* and timestamp is removed before being reached
|
||||
* Then the event handler is never called
|
||||
*
|
||||
* Test remove after insert_absolute
|
||||
* Given an instance of @a TimerEvent subclass
|
||||
* When a tiestamp is set with @a insert_absolute()
|
||||
* and timestamp is removed before being reached
|
||||
* Then the event handler is never called
|
||||
*/
|
||||
template<typename T>
|
||||
void test_remove(void) {
|
||||
T tte;
|
||||
|
||||
tte.set_future_timestamp(TEST_DELAY_US * 2);
|
||||
int32_t sem_slots = tte.sem_wait(TEST_DELAY_US / 1000);
|
||||
TEST_ASSERT_EQUAL(0, sem_slots);
|
||||
tte.remove();
|
||||
|
||||
sem_slots = tte.sem_wait(TEST_DELAY_US * 2 / 1000 + 1);
|
||||
TEST_ASSERT_EQUAL(0, sem_slots);
|
||||
}
|
||||
|
||||
/** Test insert_absolute zero
|
||||
* Given an instance of @a TimerEvent subclass
|
||||
* When a timestamp of 0 us is set with @a insert_absolute()
|
||||
* Then an event handler is called instantly
|
||||
*/
|
||||
void test_insert_zero(void) {
|
||||
TestTimerEvent tte;
|
||||
|
||||
tte.insert_absolute(0ULL);
|
||||
int32_t sem_slots = tte.sem_wait(0);
|
||||
TEST_ASSERT_EQUAL(1, sem_slots);
|
||||
|
||||
tte.remove();
|
||||
}
|
||||
|
||||
/** Template for tests: insert, insert_absolute past timestamp
|
||||
*
|
||||
* Test insert timestamp from the past
|
||||
* Given an instance of @a TimerEvent subclass
|
||||
* When a timestamp of X us is set with @a insert()
|
||||
* and X is less than present_time
|
||||
* Then an event handler is **not** called instantly
|
||||
* (the event is scheduled after the ticker's overflow)
|
||||
*
|
||||
* Test insert_absolute timestamp from the past
|
||||
* Given an instance of @a TimerEvent subclass
|
||||
* When a timestamp of X us is set with @a insert_absolute()
|
||||
* and X is less than present_time
|
||||
* Then an event handler is called instantly
|
||||
*/
|
||||
template<typename T>
|
||||
void test_insert_past(void) {
|
||||
T tte;
|
||||
|
||||
tte.set_past_timestamp();
|
||||
int32_t sem_slots = tte.sem_wait(0);
|
||||
TEST_ASSERT_EQUAL(tte.SEM_SLOTS_AFTER_PAST_TS_INSERTED, sem_slots);
|
||||
|
||||
tte.remove();
|
||||
}
|
||||
|
||||
utest::v1::status_t test_setup(const size_t number_of_cases)
|
||||
{
|
||||
GREENTEA_SETUP(5, "default_auto");
|
||||
return verbose_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("Test insert", test_insert<TestTimerEventRelative>),
|
||||
Case("Test insert_absolute", test_insert<TestTimerEventAbsolute>),
|
||||
|
||||
Case("Test remove after insert", test_remove<TestTimerEventRelative>),
|
||||
Case("Test remove after insert_absolute", test_remove<TestTimerEventAbsolute>),
|
||||
|
||||
Case("Test insert_absolute zero", test_insert_zero),
|
||||
|
||||
Case("Test insert timestamp from the past", test_insert_past<TestTimerEventRelative>),
|
||||
Case("Test insert_absolute timestamp from the past", test_insert_past<TestTimerEventAbsolute>),
|
||||
};
|
||||
|
||||
Specification specification(test_setup, cases);
|
||||
|
||||
int main()
|
||||
{
|
||||
return !Harness::run(specification);
|
||||
}
|
|
@ -90,17 +90,15 @@ void test_fwrite_fread()
|
|||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
|
||||
TEST_ASSERT_EQUAL_INT(str1_size, write_ret);
|
||||
|
||||
#ifndef __ICCARM__ // prevents IAR infinite loop
|
||||
// write 3; expected written 2
|
||||
TestFile<FS>::resetFunctionCallHistory();
|
||||
write_ret = std::fwrite(str2, 1, str2_size, file);
|
||||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
|
||||
TEST_ASSERT_TRUE(std::ferror(file) != 0);
|
||||
std::clearerr(file); // for ARMCC
|
||||
#ifndef __ARMCC_VERSION
|
||||
// ARMCC returns 0 here instead of number of elements successfully written
|
||||
TEST_ASSERT_EQUAL_INT(str2_size - 1, write_ret);
|
||||
#endif
|
||||
std::clearerr(file);
|
||||
|
||||
// ARMCC/IAR returns 0 here instead of number of elements successfully written !!!
|
||||
TEST_ASSERT_TRUE(write_ret >= 0 && write_ret <= (str2_size - 1));
|
||||
|
||||
// write 3; expected written 0
|
||||
TestFile<FS>::resetFunctionCallHistory();
|
||||
|
@ -108,7 +106,6 @@ void test_fwrite_fread()
|
|||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
|
||||
TEST_ASSERT_TRUE(std::ferror(file) != 0);
|
||||
TEST_ASSERT_EQUAL_INT(0, write_ret);
|
||||
#endif
|
||||
|
||||
std::rewind(file);
|
||||
|
||||
|
@ -119,13 +116,12 @@ void test_fwrite_fread()
|
|||
TEST_ASSERT_EQUAL_INT(str1_size, read_ret);
|
||||
TEST_ASSERT_EQUAL_INT(0, strncmp(str1, read_buf, str1_size));
|
||||
|
||||
#ifndef __ICCARM__
|
||||
// read 3; expected read 2
|
||||
TestFile<FS>::resetFunctionCallHistory();
|
||||
read_ret = std::fread(read_buf, 1, str2_size, file);
|
||||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
|
||||
TEST_ASSERT_TRUE(std::feof(file) != 0);
|
||||
std::clearerr(file); // for ARMCC
|
||||
std::clearerr(file);
|
||||
TEST_ASSERT_EQUAL_INT(str2_size - 1, read_ret);
|
||||
TEST_ASSERT_EQUAL_INT(0, strncmp(str2, read_buf, str2_size - 1));
|
||||
|
||||
|
@ -135,11 +131,12 @@ void test_fwrite_fread()
|
|||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
|
||||
TEST_ASSERT_TRUE(std::feof(file) != 0);
|
||||
TEST_ASSERT_EQUAL_INT(0, read_ret);
|
||||
#endif
|
||||
|
||||
std::fclose(file);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Test fputc and fgetc
|
||||
*
|
||||
* Given already opened file
|
||||
|
@ -168,7 +165,6 @@ void test_fputc_fgetc()
|
|||
TEST_ASSERT_NOT_NULL(file);
|
||||
std::setbuf(file, NULL);
|
||||
|
||||
|
||||
// write 1; expected written 1
|
||||
TestFile<FS>::resetFunctionCallHistory();
|
||||
ret = std::fputc(char_buf[0], file);
|
||||
|
@ -187,14 +183,12 @@ void test_fputc_fgetc()
|
|||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
|
||||
TEST_ASSERT_EQUAL_INT(char_buf[2], ret);
|
||||
|
||||
#ifndef __ICCARM__ // prevents IAR infinite loop
|
||||
// write 1; expected written 0
|
||||
TestFile<FS>::resetFunctionCallHistory();
|
||||
ret = std::fputc(char_buf[0], file);
|
||||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
|
||||
TEST_ASSERT_TRUE(std::ferror(file) != 0);
|
||||
TEST_ASSERT_EQUAL_INT(EOF, ret);
|
||||
#endif
|
||||
|
||||
std::rewind(file);
|
||||
|
||||
|
@ -207,29 +201,19 @@ void test_fputc_fgetc()
|
|||
// read 1; expected read 1
|
||||
TestFile<FS>::resetFunctionCallHistory();
|
||||
ret = std::fgetc(file);
|
||||
#ifndef __ICCARM__
|
||||
// IAR optimize reads
|
||||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
|
||||
#endif
|
||||
TEST_ASSERT_EQUAL_INT(char_buf[1], ret);
|
||||
|
||||
// read 1; expected read 1
|
||||
TestFile<FS>::resetFunctionCallHistory();
|
||||
ret = std::fgetc(file);
|
||||
#ifndef __ICCARM__
|
||||
// IAR optimize reads
|
||||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
|
||||
#endif
|
||||
TEST_ASSERT_EQUAL_INT(char_buf[2], ret);
|
||||
|
||||
#ifndef __ICCARM__
|
||||
// read 1; expected read 0
|
||||
TestFile<FS>::resetFunctionCallHistory();
|
||||
ret = std::fgetc(file);
|
||||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
|
||||
TEST_ASSERT_TRUE(std::feof(file) != 0);
|
||||
TEST_ASSERT_EQUAL_INT(EOF, ret);
|
||||
#endif
|
||||
|
||||
std::fclose(file);
|
||||
}
|
||||
|
@ -273,13 +257,12 @@ void test_fputs_fgets()
|
|||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
|
||||
TEST_ASSERT_TRUE(fputs_ret >= 0);
|
||||
|
||||
#ifndef __ICCARM__ // prevents IAR infinite loop
|
||||
// write 3; expected written 2
|
||||
TestFile<FS>::resetFunctionCallHistory();
|
||||
fputs_ret = std::fputs(str2, file);
|
||||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
|
||||
TEST_ASSERT_TRUE(std::ferror(file) != 0);
|
||||
std::clearerr(file); // for ARMCC
|
||||
std::clearerr(file);
|
||||
TEST_ASSERT_EQUAL_INT(EOF, fputs_ret);
|
||||
|
||||
// write 3; expected written 0
|
||||
|
@ -288,7 +271,6 @@ void test_fputs_fgets()
|
|||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
|
||||
TEST_ASSERT_TRUE(std::ferror(file) != 0);
|
||||
TEST_ASSERT_EQUAL_INT(EOF, fputs_ret);
|
||||
#endif
|
||||
|
||||
std::rewind(file);
|
||||
|
||||
|
@ -299,13 +281,12 @@ void test_fputs_fgets()
|
|||
TEST_ASSERT_EQUAL_INT(read_buf, fgets_ret);
|
||||
TEST_ASSERT_EQUAL_INT(0, strncmp(read_buf, str1, str1_size));
|
||||
|
||||
#ifndef __ICCARM__
|
||||
// read 3; expected read 2
|
||||
TestFile<FS>::resetFunctionCallHistory();
|
||||
fgets_ret = std::fgets(read_buf, str2_size + 1, file);
|
||||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
|
||||
TEST_ASSERT_TRUE(std::feof(file) != 0);
|
||||
std::clearerr(file); // for ARMCC
|
||||
std::clearerr(file);
|
||||
TEST_ASSERT_EQUAL_INT(read_buf, fgets_ret);
|
||||
TEST_ASSERT_EQUAL_INT(0, strncmp(read_buf, str2, str2_size - 2));
|
||||
|
||||
|
@ -315,7 +296,6 @@ void test_fputs_fgets()
|
|||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
|
||||
TEST_ASSERT_TRUE(std::feof(file) != 0);
|
||||
TEST_ASSERT_EQUAL_INT(NULL, fgets_ret);
|
||||
#endif
|
||||
|
||||
std::fclose(file);
|
||||
}
|
||||
|
@ -359,13 +339,12 @@ void test_fprintf_fscanf()
|
|||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
|
||||
TEST_ASSERT_EQUAL_INT(str1_size, fprintf_ret);
|
||||
|
||||
#ifndef __ICCARM__ // prevents IAR infinite loop
|
||||
// write 3; expected written 2
|
||||
TestFile<FS>::resetFunctionCallHistory();
|
||||
fprintf_ret = fprintf(file, "%s", str2);
|
||||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
|
||||
TEST_ASSERT_TRUE(std::ferror(file) != 0);
|
||||
std::clearerr(file); // for ARMCC
|
||||
std::clearerr(file);
|
||||
TEST_ASSERT_TRUE(fprintf_ret < 0);
|
||||
|
||||
// write 3; expected written 0
|
||||
|
@ -374,7 +353,6 @@ void test_fprintf_fscanf()
|
|||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnWrite));
|
||||
TEST_ASSERT_TRUE(std::ferror(file) != 0);
|
||||
TEST_ASSERT_TRUE(fprintf_ret < 0);
|
||||
#endif
|
||||
|
||||
std::rewind(file);
|
||||
|
||||
|
@ -385,13 +363,12 @@ void test_fprintf_fscanf()
|
|||
TEST_ASSERT_EQUAL_INT(1, fscanf_ret);
|
||||
TEST_ASSERT_EQUAL_INT(0, strncmp(read_buf, str1, str1_size));
|
||||
|
||||
#ifndef __ICCARM__
|
||||
// read 3; expected read 2
|
||||
TestFile<FS>::resetFunctionCallHistory();
|
||||
fscanf_ret = fscanf(file, "%3s", read_buf);
|
||||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
|
||||
TEST_ASSERT_TRUE(std::feof(file) != 0);
|
||||
std::clearerr(file); // for ARMCC
|
||||
std::clearerr(file);
|
||||
TEST_ASSERT_EQUAL_INT(1, fscanf_ret);
|
||||
TEST_ASSERT_EQUAL_INT(0, strncmp(read_buf, str2, str2_size - 1));
|
||||
|
||||
|
@ -401,7 +378,6 @@ void test_fprintf_fscanf()
|
|||
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnRead));
|
||||
TEST_ASSERT_TRUE(std::feof(file) != 0);
|
||||
TEST_ASSERT_EQUAL_INT(EOF, fscanf_ret);
|
||||
#endif
|
||||
|
||||
std::fclose(file);
|
||||
}
|
||||
|
|
|
@ -47,13 +47,31 @@ protected:
|
|||
// The handler called to service the timer event of the derived class
|
||||
virtual void handler() = 0;
|
||||
|
||||
// insert relative timestamp in to linked list
|
||||
/** Set relative timestamp of the internal event.
|
||||
* @param timestamp event's us timestamp
|
||||
*
|
||||
* @warning
|
||||
* Do not insert more than one timestamp.
|
||||
* The same @a event object is used for every @a insert/insert_absolute call.
|
||||
*
|
||||
* @warning
|
||||
* Ticker's present timestamp is used for reference. For timestamps
|
||||
* from the past the event is scheduled after ticker's overflow.
|
||||
* For reference @see convert_timestamp
|
||||
*/
|
||||
void insert(timestamp_t timestamp);
|
||||
|
||||
// insert absolute timestamp into linked list
|
||||
/** Set absolute timestamp of the internal event.
|
||||
* @param timestamp event's us timestamp
|
||||
*
|
||||
* @warning
|
||||
* Do not insert more than one timestamp.
|
||||
* The same @a event object is used for every @a insert/insert_absolute call.
|
||||
*/
|
||||
void insert_absolute(us_timestamp_t timestamp);
|
||||
|
||||
// remove from linked list, if in it
|
||||
/** Remove timestamp.
|
||||
*/
|
||||
void remove();
|
||||
|
||||
ticker_event_t event;
|
||||
|
|
|
@ -9,5 +9,10 @@
|
|||
"help": "Define event-loop thread stack size.",
|
||||
"value": 6144
|
||||
}
|
||||
,
|
||||
"event-loop-dispatch-from-application": {
|
||||
"help": "Application is responsible of message dispatch loop. Else launch a separate thread for event-loop.",
|
||||
"value": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,19 @@
|
|||
|
||||
#define TRACE_GROUP "evlp"
|
||||
|
||||
|
||||
#if MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
|
||||
|
||||
static mbed_rtos_storage_event_flags_t event_flag_cb;
|
||||
static const osEventFlagsAttr_t event_flags_attr = {
|
||||
.name = "nanostack_event_flags",
|
||||
.cb_mem = &event_flag_cb,
|
||||
.cb_size = sizeof event_flag_cb
|
||||
};
|
||||
static osEventFlagsId_t event_flag_id;
|
||||
|
||||
#else
|
||||
|
||||
static void event_loop_thread(void *arg);
|
||||
|
||||
static uint64_t event_thread_stk[MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_THREAD_STACK_SIZE/8];
|
||||
|
@ -26,6 +39,8 @@ static const osThreadAttr_t event_thread_attr = {
|
|||
.cb_mem = &event_thread_tcb,
|
||||
.cb_size = sizeof event_thread_tcb,
|
||||
};
|
||||
#endif
|
||||
|
||||
static osThreadId_t event_thread_id;
|
||||
static mbed_rtos_storage_mutex_t event_mutex;
|
||||
static const osMutexAttr_t event_mutex_attr = {
|
||||
|
@ -66,7 +81,11 @@ void eventOS_scheduler_signal(void)
|
|||
// XXX why does signal set lock if called with irqs disabled?
|
||||
//__enable_irq();
|
||||
//tr_debug("signal %p", (void*)event_thread_id);
|
||||
#if MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
|
||||
osEventFlagsSet(event_flag_id, 1);
|
||||
#else
|
||||
osThreadFlagsSet(event_thread_id, 1);
|
||||
#endif
|
||||
//tr_debug("signalled %p", (void*)event_thread_id);
|
||||
}
|
||||
|
||||
|
@ -74,22 +93,45 @@ void eventOS_scheduler_idle(void)
|
|||
{
|
||||
//tr_debug("idle");
|
||||
eventOS_scheduler_mutex_release();
|
||||
|
||||
#if MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
|
||||
osEventFlagsWait(event_flag_id, 1, osFlagsWaitAny, osWaitForever);
|
||||
#else
|
||||
osThreadFlagsWait(1, 0, osWaitForever);
|
||||
#endif
|
||||
|
||||
eventOS_scheduler_mutex_wait();
|
||||
}
|
||||
|
||||
#if !MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
|
||||
static void event_loop_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
eventOS_scheduler_mutex_wait();
|
||||
eventOS_scheduler_run(); //Does not return
|
||||
}
|
||||
#endif
|
||||
|
||||
void ns_event_loop_thread_create(void)
|
||||
// This is used to initialize the lock used by event loop even
|
||||
// if it is not ran in a separate thread.
|
||||
void ns_event_loop_init(void)
|
||||
{
|
||||
event_mutex_id = osMutexNew(&event_mutex_attr);
|
||||
MBED_ASSERT(event_mutex_id != NULL);
|
||||
|
||||
// If a separate event loop thread is not used, the signaling
|
||||
// happens via event flags instead of thread flags. This allows one to
|
||||
// perform the initialization from any thread and removes need to know the id
|
||||
// of event loop dispatch thread.
|
||||
#if MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
|
||||
event_flag_id = osEventFlagsNew(&event_flags_attr);
|
||||
MBED_ASSERT(event_flag_id != NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
|
||||
void ns_event_loop_thread_create(void)
|
||||
{
|
||||
event_thread_id = osThreadNew(event_loop_thread, NULL, &event_thread_attr);
|
||||
MBED_ASSERT(event_thread_id != NULL);
|
||||
}
|
||||
|
@ -97,3 +139,4 @@ void ns_event_loop_thread_create(void)
|
|||
void ns_event_loop_thread_start(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ns_event_loop_init(void);
|
||||
void ns_event_loop_thread_create(void);
|
||||
void ns_event_loop_thread_start(void);
|
||||
|
||||
|
|
|
@ -32,10 +32,19 @@ void ns_hal_init(void *heap, size_t h_size, void (*passed_fptr)(heap_fail_t), me
|
|||
ns_dyn_mem_init(heap, h_size, passed_fptr, info_ptr);
|
||||
platform_timer_enable();
|
||||
eventOS_scheduler_init();
|
||||
|
||||
// We do not initialise randlib, as it should be done after
|
||||
// RF driver has started, to get MAC address and RF noise as seed.
|
||||
// We do not initialise trace - left to application.
|
||||
|
||||
// Prepare the event loop lock which is used even if the loop
|
||||
// is not ran in a separate thread.
|
||||
ns_event_loop_init();
|
||||
|
||||
#if !MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION
|
||||
ns_event_loop_thread_create();
|
||||
ns_event_loop_thread_start();
|
||||
#endif
|
||||
|
||||
initted = true;
|
||||
}
|
||||
|
|
|
@ -35,39 +35,48 @@
|
|||
static int fat_error_remap(FRESULT res)
|
||||
{
|
||||
switch(res) {
|
||||
case FR_OK: /* (0) Succeeded */
|
||||
return 0; /* no error */
|
||||
case FR_DISK_ERR: /* (1) A hard error occurred in the low level disk I/O layer */
|
||||
case FR_NOT_READY: /* (3) The physical drive cannot work */
|
||||
return -EIO; /* I/O error */
|
||||
case FR_NO_FILE: /* (4) Could not find the file */
|
||||
case FR_NO_PATH: /* (5) Could not find the path */
|
||||
case FR_INVALID_NAME: /* (6) The path name format is invalid */
|
||||
case FR_INVALID_DRIVE: /* (11) The logical drive number is invalid */
|
||||
case FR_NO_FILESYSTEM: /* (13) There is no valid FAT volume */
|
||||
return -ENOENT; /* No such file or directory */
|
||||
case FR_DENIED: /* (7) Access denied due to prohibited access or directory full */
|
||||
return -EACCES; /* Permission denied */
|
||||
case FR_EXIST: /* (8) Access denied due to prohibited access */
|
||||
return -EEXIST; /* File exists */
|
||||
case FR_WRITE_PROTECTED: /* (10) The physical drive is write protected */
|
||||
case FR_LOCKED: /* (16) The operation is rejected according to the file sharing policy */
|
||||
return -EACCES; /* Permission denied */
|
||||
case FR_INVALID_OBJECT: /* (9) The file/directory object is invalid */
|
||||
return -EFAULT; /* Bad address */
|
||||
case FR_NOT_ENABLED: /* (12) The volume has no work area */
|
||||
return -ENXIO; /* No such device or address */
|
||||
case FR_NOT_ENOUGH_CORE: /* (17) LFN working buffer could not be allocated */
|
||||
return -ENOMEM; /* Not enough space */
|
||||
case FR_TOO_MANY_OPEN_FILES: /* (18) Number of open files > _FS_LOCK */
|
||||
return -ENFILE; /* Too many open files in system */
|
||||
case FR_INVALID_PARAMETER: /* (19) Given parameter is invalid */
|
||||
return -ENOEXEC; /* Exec format error */
|
||||
case FR_INT_ERR: /* (2) Assertion failed */
|
||||
case FR_MKFS_ABORTED: /* (14) The f_mkfs() aborted due to any parameter error */
|
||||
case FR_TIMEOUT: /* (15) Could not get a grant to access the volume within defined period */
|
||||
default: /* Bad file number */
|
||||
case FR_OK: // (0) Succeeded
|
||||
return 0;
|
||||
case FR_DISK_ERR: // (1) A hard error occurred in the low level disk I/O layer
|
||||
return -EIO;
|
||||
case FR_INT_ERR: // (2) Assertion failed
|
||||
return -1;
|
||||
case FR_NOT_READY: // (3) The physical drive cannot work
|
||||
return -EIO;
|
||||
case FR_NO_FILE: // (4) Could not find the file
|
||||
return -ENOENT;
|
||||
case FR_NO_PATH: // (5) Could not find the path
|
||||
return -ENOTDIR;
|
||||
case FR_INVALID_NAME: // (6) The path name format is invalid
|
||||
return -EINVAL;
|
||||
case FR_DENIED: // (7) Access denied due to prohibited access or directory full
|
||||
return -EACCES;
|
||||
case FR_EXIST: // (8) Access denied due to prohibited access
|
||||
return -EEXIST;
|
||||
case FR_INVALID_OBJECT: // (9) The file/directory object is invalid
|
||||
return -EBADF;
|
||||
case FR_WRITE_PROTECTED: // (10) The physical drive is write protected
|
||||
return -EACCES;
|
||||
case FR_INVALID_DRIVE: // (11) The logical drive number is invalid
|
||||
return -ENODEV;
|
||||
case FR_NOT_ENABLED: // (12) The volume has no work area
|
||||
return -ENODEV;
|
||||
case FR_NO_FILESYSTEM: // (13) There is no valid FAT volume
|
||||
return -EINVAL;
|
||||
case FR_MKFS_ABORTED: // (14) The f_mkfs() aborted due to any problem
|
||||
return -EIO;
|
||||
case FR_TIMEOUT: // (15) Could not get a grant to access the volume within defined period
|
||||
return -ETIMEDOUT;
|
||||
case FR_LOCKED: // (16) The operation is rejected according to the file sharing policy
|
||||
return -EBUSY;
|
||||
case FR_NOT_ENOUGH_CORE: // (17) LFN working buffer could not be allocated
|
||||
return -ENOMEM;
|
||||
case FR_TOO_MANY_OPEN_FILES: // (18) Number of open files > FF_FS_LOCK
|
||||
return -ENFILE;
|
||||
case FR_INVALID_PARAMETER: // (19) Given parameter is invalid
|
||||
return -EINVAL;
|
||||
default:
|
||||
return -res;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -724,6 +724,19 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
|
|||
pathname += strspn(pathname, "/");
|
||||
pathlen = strcspn(pathname, "/");
|
||||
|
||||
// special case for root dir
|
||||
if (pathname[0] == '\0') {
|
||||
*entry = (lfs_entry_t){
|
||||
.d.type = LFS_TYPE_DIR,
|
||||
.d.elen = sizeof(entry->d) - 4,
|
||||
.d.alen = 0,
|
||||
.d.nlen = 0,
|
||||
.d.u.dir[0] = lfs->root[0],
|
||||
.d.u.dir[1] = lfs->root[1],
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
// skip '.' and root '..'
|
||||
if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) ||
|
||||
(pathlen == 2 && memcmp(pathname, "..", 2) == 0)) {
|
||||
|
@ -880,15 +893,6 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
|
|||
return err;
|
||||
}
|
||||
|
||||
// check for root, can only be something like '/././../.'
|
||||
if (strspn(path, "/.") == strlen(path)) {
|
||||
dir->head[0] = dir->pair[0];
|
||||
dir->head[1] = dir->pair[1];
|
||||
dir->pos = sizeof(dir->d) - 2;
|
||||
dir->off = sizeof(dir->d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lfs_entry_t entry;
|
||||
err = lfs_dir_find(lfs, dir, &entry, &path);
|
||||
if (err) {
|
||||
|
@ -1671,14 +1675,6 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
|
|||
|
||||
/// General fs oprations ///
|
||||
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
|
||||
// check for root, can only be something like '/././../.'
|
||||
if (strspn(path, "/.") == strlen(path)) {
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->type = LFS_TYPE_DIR;
|
||||
strcpy(info->name, "/");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lfs_dir_t cwd;
|
||||
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
|
||||
if (err) {
|
||||
|
@ -1697,11 +1693,15 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
|
|||
info->size = entry.d.u.file.size;
|
||||
}
|
||||
|
||||
err = lfs_bd_read(lfs, cwd.pair[0],
|
||||
entry.off + 4+entry.d.elen+entry.d.alen,
|
||||
info->name, entry.d.nlen);
|
||||
if (err) {
|
||||
return err;
|
||||
if (lfs_paircmp(entry.d.u.dir, lfs->root) == 0) {
|
||||
strcpy(info->name, "/");
|
||||
} else {
|
||||
err = lfs_bd_read(lfs, cwd.pair[0],
|
||||
entry.off + 4+entry.d.elen+entry.d.alen,
|
||||
info->name, entry.d.nlen);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -108,6 +108,10 @@ tests/test.py << TEST
|
|||
lfs_stat(&lfs, "/", &info) => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
strcmp(info.name, "/") => 0;
|
||||
|
||||
lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST;
|
||||
lfs_file_open(&lfs, &file[0], "/", LFS_O_WRONLY | LFS_O_CREAT)
|
||||
=> LFS_ERR_ISDIR;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
TEST
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ void us_ticker_set_interrupt(timestamp_t timestamp) {
|
|||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
uint32_t us_ticker_irqn1 = Timer_GetIRQn(TIMER1);
|
||||
uint32_t us_ticker_irqn1 = Timer_GetIRQn(TIMER0);
|
||||
NVIC_SetPendingIRQ((IRQn_Type)us_ticker_irqn1);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -23,11 +23,11 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
typedef enum {
|
||||
UART_0 = (int)CMSDK_UART0_BASE, /* MCC UART */
|
||||
UART_1 = (int)CMSDK_UART1_BASE, /* MPS2+ UART */
|
||||
UART_2 = (int)CMSDK_UART2_BASE, /* Shield 0 UART */
|
||||
UART_3 = (int)CMSDK_UART3_BASE, /* Shield 1 UART */
|
||||
UART_4 = (int)CMSDK_UART4_BASE /* Shield BT UART */
|
||||
UART_0 = 0, /* MCC UART */
|
||||
UART_1, /* MPS2+ UART */
|
||||
UART_2, /* Shield 0 UART */
|
||||
UART_3, /* Shield 1 UART */
|
||||
UART_4 /* Shield BT UART */
|
||||
} UARTName;
|
||||
|
||||
typedef enum {
|
||||
|
@ -53,11 +53,12 @@ typedef enum {
|
|||
} ADCName;
|
||||
|
||||
typedef enum {
|
||||
SPI_0 = (int)MPS2_SSP0_BASE,
|
||||
SPI_1 = (int)MPS2_SSP1_BASE,
|
||||
SPI_2 = (int)MPS2_SSP2_BASE,
|
||||
SPI_3 = (int)MPS2_SSP3_BASE,
|
||||
SPI_4 = (int)MPS2_SSP4_BASE
|
||||
SPI_0 = 0,
|
||||
SPI_1,
|
||||
SPI_2,
|
||||
SPI_3,
|
||||
SPI_4,
|
||||
SPI_NC = (SPI_4 + 1)
|
||||
} SPIName;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2018 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file cmsdk_ticker.c
|
||||
* Two abstracted functionalities for CMSDK APB Timers
|
||||
* 1. Measure elapsed time
|
||||
* 2. Timer interval interrupt
|
||||
*
|
||||
* Passed \ref tick_drv_data_t should be initialized by the caller
|
||||
* for using these services accordingly.
|
||||
* See details \ref tick_cfg_t and \ref tick_data_t.
|
||||
*/
|
||||
|
||||
#include "cmsdk_ticker.h"
|
||||
|
||||
void cmsdk_ticker_init(const struct tick_drv_data_t* timer_data)
|
||||
{
|
||||
if (!timer_data->data->is_initialized) {
|
||||
timer_cmsdk_init(timer_data->cfg->timer_driver);
|
||||
timer_cmsdk_set_reload_value(timer_data->cfg->timer_driver,
|
||||
TIMER_CMSDK_MAX_RELOAD);
|
||||
timer_cmsdk_enable_interrupt(timer_data->cfg->timer_driver);
|
||||
NVIC_EnableIRQ(timer_data->cfg->irq_n);
|
||||
|
||||
timer_data->data->max_interval_time =
|
||||
timer_data->cfg->convert_tick_to_time(TIMER_CMSDK_MAX_RELOAD);
|
||||
timer_data->data->reload_time = timer_data->data->max_interval_time;
|
||||
timer_data->data->is_initialized = true;
|
||||
timer_cmsdk_enable(timer_data->cfg->timer_driver);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t cmsdk_ticker_read(const struct tick_drv_data_t* timer_data)
|
||||
{
|
||||
uint32_t current_elapsed = 0;
|
||||
|
||||
if (!timer_data->data->is_initialized) {
|
||||
cmsdk_ticker_init(timer_data);
|
||||
}
|
||||
current_elapsed = timer_cmsdk_get_elapsed_value(timer_data->cfg->timer_driver);
|
||||
/*
|
||||
* If for the same reload cycle (ie. cumulated_time is the same) the
|
||||
* current elapsed time is lower than the previous one, it means that the
|
||||
* timer has wrapped around without the system logging it. To ensure that
|
||||
* we are always returning an increasing time in those condition, we return
|
||||
* the time perviously read.
|
||||
*/
|
||||
if ((timer_data->data->previous_cumulated_time ==
|
||||
timer_data->data->cumulated_time) &&
|
||||
(current_elapsed < timer_data->data->previous_elapsed)) {
|
||||
current_elapsed = timer_data->data->previous_elapsed;
|
||||
}
|
||||
|
||||
timer_data->data->previous_elapsed = current_elapsed;
|
||||
timer_data->data->previous_cumulated_time =
|
||||
timer_data->data->cumulated_time;
|
||||
|
||||
return (timer_data->data->cumulated_time +
|
||||
timer_data->cfg->convert_tick_to_time(current_elapsed));
|
||||
}
|
||||
|
||||
void cmsdk_ticker_set_interrupt(const struct tick_drv_data_t* timer_data,
|
||||
uint32_t timestamp)
|
||||
{
|
||||
uint32_t interval = 0;
|
||||
uint32_t interval_reload_tick = 0;
|
||||
|
||||
/* Stop before read to avoid race condition with IRQ. */
|
||||
timer_cmsdk_disable(timer_data->cfg->timer_driver);
|
||||
uint32_t current_time = cmsdk_ticker_read(timer_data);
|
||||
|
||||
timer_data->data->interval_callback_enabled = true;
|
||||
|
||||
/*
|
||||
* We always assume that the event is in the future, even if this
|
||||
* substraction underflows it is still corect.
|
||||
*/
|
||||
interval = (timestamp - current_time);
|
||||
|
||||
if (interval >= timer_data->data->max_interval_time) {
|
||||
/* Event will be in the future but the time is too big: set max */
|
||||
interval_reload_tick = TIMER_CMSDK_MAX_RELOAD;
|
||||
timer_data->data->reload_time = timer_data->data->max_interval_time;
|
||||
} else {
|
||||
/* Event will be in the future in a time that can be set */
|
||||
interval_reload_tick =
|
||||
timer_data->cfg->convert_time_to_tick(interval);
|
||||
timer_data->data->reload_time = interval;
|
||||
}
|
||||
|
||||
/* Store the current elapsed time, before reset the timer */
|
||||
timer_data->data->cumulated_time = current_time;
|
||||
/* Reset the timer with new reload value */
|
||||
timer_cmsdk_set_reload_value(timer_data->cfg->timer_driver,
|
||||
interval_reload_tick);
|
||||
timer_cmsdk_reset(timer_data->cfg->timer_driver);
|
||||
|
||||
timer_cmsdk_enable(timer_data->cfg->timer_driver);
|
||||
}
|
||||
|
||||
void cmsdk_ticker_disable_interrupt(const struct tick_drv_data_t* timer_data)
|
||||
{
|
||||
if (!timer_data->data->is_initialized) {
|
||||
cmsdk_ticker_init(timer_data);
|
||||
}
|
||||
|
||||
timer_data->data->interval_callback_enabled = false;
|
||||
|
||||
/* Stop before read to avoid race condition with IRQ. */
|
||||
timer_cmsdk_disable(timer_data->cfg->timer_driver);
|
||||
/* If interval interrupt is disabled, restore the default max interval,
|
||||
* but save the current elapsed time before changing the timer. */
|
||||
timer_data->data->cumulated_time = cmsdk_ticker_read(timer_data);
|
||||
/* Reset the timer with default reload value */
|
||||
timer_cmsdk_set_reload_value(timer_data->cfg->timer_driver,
|
||||
TIMER_CMSDK_MAX_RELOAD);
|
||||
timer_data->data->reload_time = timer_data->data->max_interval_time;
|
||||
|
||||
timer_cmsdk_reset(timer_data->cfg->timer_driver);
|
||||
timer_cmsdk_enable(timer_data->cfg->timer_driver);
|
||||
}
|
||||
|
||||
void cmsdk_ticker_clear_interrupt(const struct tick_drv_data_t* timer_data)
|
||||
{
|
||||
timer_cmsdk_clear_interrupt(timer_data->cfg->timer_driver);
|
||||
}
|
||||
|
||||
void cmsdk_ticker_fire_interrupt(const struct tick_drv_data_t* timer_data)
|
||||
{
|
||||
NVIC_SetPendingIRQ(timer_data->cfg->irq_n);
|
||||
}
|
||||
|
||||
void cmsdk_ticker_irq_handler(const struct tick_drv_data_t* timer_data)
|
||||
{
|
||||
uint32_t reload_val = 0;
|
||||
/* If timer's internal interrupt status is not active, then not overflow,
|
||||
* but explicit interrupt request was fired by cmsdk_ticker_fire_interrupt.
|
||||
*/
|
||||
if (timer_cmsdk_is_interrupt_active(timer_data->cfg->timer_driver)) {
|
||||
/* 1. Calculate cumulated time by overflow */
|
||||
timer_cmsdk_clear_interrupt(timer_data->cfg->timer_driver);
|
||||
reload_val = timer_cmsdk_get_reload_value(timer_data->cfg->timer_driver);
|
||||
timer_data->data->cumulated_time +=
|
||||
timer_data->cfg->convert_tick_to_time(reload_val);
|
||||
}
|
||||
|
||||
/* 2. Call mbed interval interrupt handler if it's required */
|
||||
if (timer_data->data->interval_callback_enabled) {
|
||||
cmsdk_ticker_disable_interrupt(timer_data);
|
||||
timer_data->cfg->interval_callback();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright (c) 2018 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file cmsdk_ticker.h
|
||||
* CMSDK Ticker implements the functionalities of mbed tickers:
|
||||
* 1. Elapsed time measurement
|
||||
* 2. Interval interrupt request
|
||||
*
|
||||
* This ticker service is based on CMSDK APB Timers, abstracting
|
||||
* the HAL logic, the timer driver and interrupt number.
|
||||
* These parameters should be passed to the functions by
|
||||
* an initialized \ref tick_drv_data_t pointer.
|
||||
*/
|
||||
|
||||
#ifndef CMSDK_TICKER_H
|
||||
#define CMSDK_TICKER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "CMSDK_CM3DS.h"
|
||||
#include "timer_cmsdk_drv.h"
|
||||
|
||||
#define SEC_TO_USEC_MULTIPLIER 1000000U
|
||||
|
||||
/**
|
||||
* brief Encapsulating struct for config data \ref tick_cfg_t and
|
||||
* the current status \ref tick_data_t.
|
||||
*/
|
||||
struct tick_drv_data_t {
|
||||
const struct tick_cfg_t* const cfg;
|
||||
struct tick_data_t* const data;
|
||||
};
|
||||
|
||||
/**
|
||||
* brief Configuration data of the CMSDK ticker
|
||||
*/
|
||||
struct tick_cfg_t {
|
||||
/** Pointer to the used CMSDK Timer's device structure */
|
||||
struct timer_cmsdk_dev_t* const timer_driver;
|
||||
/** IRQ number of the used CMSDK Timer */
|
||||
const IRQn_Type irq_n;
|
||||
/** Interval callback of mbed*/
|
||||
void (*const interval_callback)();
|
||||
/** Function pointers to call for conversions of clock ticks and defined
|
||||
* time unit.
|
||||
* These conversions define the unit of the measured time.
|
||||
*/
|
||||
uint32_t (*const convert_tick_to_time)(uint32_t tick);
|
||||
uint32_t (*const convert_time_to_tick)(uint32_t time);
|
||||
};
|
||||
|
||||
/**
|
||||
* brief Current state data of the CMSDK ticker
|
||||
*/
|
||||
struct tick_data_t {
|
||||
/** True if initialized the ticker, false otherwise */
|
||||
bool is_initialized;
|
||||
/** Measured elapsed time in the defined unit by
|
||||
* \ref convert_tick_to_time and \ref convert_time_to_tick */
|
||||
uint32_t cumulated_time;
|
||||
/** Max interval time possible to set, in the defined unit by
|
||||
* \ref convert_tick_to_time and \ref convert_time_to_tick */
|
||||
uint32_t max_interval_time;
|
||||
/** Current reload time in the defined unit by
|
||||
* \ref convert_tick_to_time and \ref convert_time_to_tick */
|
||||
uint32_t reload_time;
|
||||
/** Interval IRQ callback is requested */
|
||||
bool interval_callback_enabled;
|
||||
/** Previous cumulated time calculated for this ticker. Used in the
|
||||
* cmsdk_ticker_read function to detect that the timer has wrapped. */
|
||||
uint32_t previous_cumulated_time;
|
||||
/** Previous elapsed value for this ticker. Used in the
|
||||
* cmsdk_ticker_read function to detect that the timer has wrapped. */
|
||||
uint32_t previous_elapsed;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Init the CMSDK Ticker
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
*/
|
||||
void cmsdk_ticker_init(const struct tick_drv_data_t* timer_data);
|
||||
|
||||
/**
|
||||
* \brief Read elapsed time by CMSDK Ticker
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
*
|
||||
* \return Elapsed time in the unit defined by \ref convert_tick_to_time
|
||||
*/
|
||||
|
||||
uint32_t cmsdk_ticker_read(const struct tick_drv_data_t* timer_data);
|
||||
|
||||
/**
|
||||
* \brief Request interval interrupt by time stamp \ref timestamp_t
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
* \param[in] timestamp Absolute time \ref timestamp_t value when the interval
|
||||
* is requested. Unit of the timestamp is defined by
|
||||
* \ref convert_tick_to_time and \ref convert_time_to_tick
|
||||
*/
|
||||
void cmsdk_ticker_set_interrupt(const struct tick_drv_data_t* timer_data,
|
||||
uint32_t timestamp);
|
||||
|
||||
/**
|
||||
* \brief Disable interval interrupt
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
*/
|
||||
void cmsdk_ticker_disable_interrupt(const struct tick_drv_data_t* timer_data);
|
||||
|
||||
/**
|
||||
* \brief Clear interval interrupt
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
*/
|
||||
void cmsdk_ticker_clear_interrupt(const struct tick_drv_data_t* timer_data);
|
||||
|
||||
/**
|
||||
* \brief Set pending interrupt that should be fired right away.
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
*/
|
||||
void cmsdk_ticker_fire_interrupt(const struct tick_drv_data_t* timer_data);
|
||||
|
||||
/**
|
||||
* \brief Interrupt handler of the given CMSDK Timer
|
||||
*
|
||||
* \warning This function may be called from multiple interrupt handlers,
|
||||
* so extra care must be taken for re-entrancy!
|
||||
*
|
||||
* \param[in] timer_data Pointer to the used CMSDK Timer's device structure
|
||||
*/
|
||||
void cmsdk_ticker_irq_handler(const struct tick_drv_data_t* timer_data);
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2017 ARM Limited. All rights reserved.
|
||||
* Copyright (c) 2009-2018 ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
|
@ -135,420 +135,6 @@ typedef enum IRQn
|
|||
#warning Not supported compiler type
|
||||
#endif
|
||||
|
||||
/*------------- Universal Asynchronous Receiver Transmitter (UART) -----------*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t DATA; /* Offset: 0x000 (R/W) Data Register */
|
||||
__IO uint32_t STATE; /* Offset: 0x004 (R/W) Status Register */
|
||||
__IO uint32_t CTRL; /* Offset: 0x008 (R/W) Control Register */
|
||||
union {
|
||||
__I uint32_t INTSTATUS; /* Offset: 0x00C (R/ ) Interrupt Status Register */
|
||||
__O uint32_t INTCLEAR; /* Offset: 0x00C ( /W) Interrupt Clear Register */
|
||||
};
|
||||
__IO uint32_t BAUDDIV; /* Offset: 0x010 (R/W) Baudrate Divider Register */
|
||||
|
||||
} CMSDK_UART_TypeDef;
|
||||
|
||||
/* CMSDK_UART DATA Register Definitions */
|
||||
|
||||
#define CMSDK_UART_DATA_Pos 0 /* CMSDK_UART_DATA_Pos: DATA Position */
|
||||
#define CMSDK_UART_DATA_Msk (0xFFul << CMSDK_UART_DATA_Pos) /* CMSDK_UART DATA: DATA Mask */
|
||||
|
||||
#define CMSDK_UART_STATE_RXOR_Pos 3 /* CMSDK_UART STATE: RXOR Position */
|
||||
#define CMSDK_UART_STATE_RXOR_Msk (0x1ul << CMSDK_UART_STATE_RXOR_Pos) /* CMSDK_UART STATE: RXOR Mask */
|
||||
|
||||
#define CMSDK_UART_STATE_TXOR_Pos 2 /* CMSDK_UART STATE: TXOR Position */
|
||||
#define CMSDK_UART_STATE_TXOR_Msk (0x1ul << CMSDK_UART_STATE_TXOR_Pos) /* CMSDK_UART STATE: TXOR Mask */
|
||||
|
||||
#define CMSDK_UART_STATE_RXBF_Pos 1 /* CMSDK_UART STATE: RXBF Position */
|
||||
#define CMSDK_UART_STATE_RXBF_Msk (0x1ul << CMSDK_UART_STATE_RXBF_Pos) /* CMSDK_UART STATE: RXBF Mask */
|
||||
|
||||
#define CMSDK_UART_STATE_TXBF_Pos 0 /* CMSDK_UART STATE: TXBF Position */
|
||||
#define CMSDK_UART_STATE_TXBF_Msk (0x1ul << CMSDK_UART_STATE_TXBF_Pos ) /* CMSDK_UART STATE: TXBF Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_HSTM_Pos 6 /* CMSDK_UART CTRL: HSTM Position */
|
||||
#define CMSDK_UART_CTRL_HSTM_Msk (0x01ul << CMSDK_UART_CTRL_HSTM_Pos) /* CMSDK_UART CTRL: HSTM Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_RXORIRQEN_Pos 5 /* CMSDK_UART CTRL: RXORIRQEN Position */
|
||||
#define CMSDK_UART_CTRL_RXORIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_RXORIRQEN_Pos) /* CMSDK_UART CTRL: RXORIRQEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_TXORIRQEN_Pos 4 /* CMSDK_UART CTRL: TXORIRQEN Position */
|
||||
#define CMSDK_UART_CTRL_TXORIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_TXORIRQEN_Pos) /* CMSDK_UART CTRL: TXORIRQEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_RXIRQEN_Pos 3 /* CMSDK_UART CTRL: RXIRQEN Position */
|
||||
#define CMSDK_UART_CTRL_RXIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_RXIRQEN_Pos) /* CMSDK_UART CTRL: RXIRQEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_TXIRQEN_Pos 2 /* CMSDK_UART CTRL: TXIRQEN Position */
|
||||
#define CMSDK_UART_CTRL_TXIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_TXIRQEN_Pos) /* CMSDK_UART CTRL: TXIRQEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_RXEN_Pos 1 /* CMSDK_UART CTRL: RXEN Position */
|
||||
#define CMSDK_UART_CTRL_RXEN_Msk (0x01ul << CMSDK_UART_CTRL_RXEN_Pos) /* CMSDK_UART CTRL: RXEN Mask */
|
||||
|
||||
#define CMSDK_UART_CTRL_TXEN_Pos 0 /* CMSDK_UART CTRL: TXEN Position */
|
||||
#define CMSDK_UART_CTRL_TXEN_Msk (0x01ul << CMSDK_UART_CTRL_TXEN_Pos) /* CMSDK_UART CTRL: TXEN Mask */
|
||||
|
||||
#define CMSDK_UART_INTSTATUS_RXORIRQ_Pos 3 /* CMSDK_UART CTRL: RXORIRQ Position */
|
||||
#define CMSDK_UART_INTSTATUS_RXORIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_RXORIRQ_Pos) /* CMSDK_UART CTRL: RXORIRQ Mask */
|
||||
|
||||
#define CMSDK_UART_INTSTATUS_TXORIRQ_Pos 2 /* CMSDK_UART CTRL: TXORIRQ Position */
|
||||
#define CMSDK_UART_INTSTATUS_TXORIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_TXORIRQ_Pos) /* CMSDK_UART CTRL: TXORIRQ Mask */
|
||||
|
||||
#define CMSDK_UART_INTSTATUS_RXIRQ_Pos 1 /* CMSDK_UART CTRL: RXIRQ Position */
|
||||
#define CMSDK_UART_INTSTATUS_RXIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_RXIRQ_Pos) /* CMSDK_UART CTRL: RXIRQ Mask */
|
||||
|
||||
#define CMSDK_UART_INTSTATUS_TXIRQ_Pos 0 /* CMSDK_UART CTRL: TXIRQ Position */
|
||||
#define CMSDK_UART_INTSTATUS_TXIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_TXIRQ_Pos) /* CMSDK_UART CTRL: TXIRQ Mask */
|
||||
|
||||
#define CMSDK_UART_BAUDDIV_Pos 0 /* CMSDK_UART BAUDDIV: BAUDDIV Position */
|
||||
#define CMSDK_UART_BAUDDIV_Msk (0xFFFFFul << CMSDK_UART_BAUDDIV_Pos) /* CMSDK_UART BAUDDIV: BAUDDIV Mask */
|
||||
|
||||
|
||||
/*----------------------------- Timer (TIMER) -------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t CTRL; /* Offset: 0x000 (R/W) Control Register */
|
||||
__IO uint32_t VALUE; /* Offset: 0x004 (R/W) Current Value Register */
|
||||
__IO uint32_t RELOAD; /* Offset: 0x008 (R/W) Reload Value Register */
|
||||
union {
|
||||
__I uint32_t INTSTATUS; /* Offset: 0x00C (R/ ) Interrupt Status Register */
|
||||
__O uint32_t INTCLEAR; /* Offset: 0x00C ( /W) Interrupt Clear Register */
|
||||
};
|
||||
|
||||
} CMSDK_TIMER_TypeDef;
|
||||
|
||||
/* CMSDK_TIMER CTRL Register Definitions */
|
||||
|
||||
#define CMSDK_TIMER_CTRL_IRQEN_Pos 3 /* CMSDK_TIMER CTRL: IRQEN Position */
|
||||
#define CMSDK_TIMER_CTRL_IRQEN_Msk (0x01ul << CMSDK_TIMER_CTRL_IRQEN_Pos) /* CMSDK_TIMER CTRL: IRQEN Mask */
|
||||
|
||||
#define CMSDK_TIMER_CTRL_SELEXTCLK_Pos 2 /* CMSDK_TIMER CTRL: SELEXTCLK Position */
|
||||
#define CMSDK_TIMER_CTRL_SELEXTCLK_Msk (0x01ul << CMSDK_TIMER_CTRL_SELEXTCLK_Pos) /* CMSDK_TIMER CTRL: SELEXTCLK Mask */
|
||||
|
||||
#define CMSDK_TIMER_CTRL_SELEXTEN_Pos 1 /* CMSDK_TIMER CTRL: SELEXTEN Position */
|
||||
#define CMSDK_TIMER_CTRL_SELEXTEN_Msk (0x01ul << CMSDK_TIMER_CTRL_SELEXTEN_Pos) /* CMSDK_TIMER CTRL: SELEXTEN Mask */
|
||||
|
||||
#define CMSDK_TIMER_CTRL_EN_Pos 0 /* CMSDK_TIMER CTRL: EN Position */
|
||||
#define CMSDK_TIMER_CTRL_EN_Msk (0x01ul << CMSDK_TIMER_CTRL_EN_Pos) /* CMSDK_TIMER CTRL: EN Mask */
|
||||
|
||||
#define CMSDK_TIMER_VAL_CURRENT_Pos 0 /* CMSDK_TIMER VALUE: CURRENT Position */
|
||||
#define CMSDK_TIMER_VAL_CURRENT_Msk (0xFFFFFFFFul << CMSDK_TIMER_VAL_CURRENT_Pos) /* CMSDK_TIMER VALUE: CURRENT Mask */
|
||||
|
||||
#define CMSDK_TIMER_RELOAD_VAL_Pos 0 /* CMSDK_TIMER RELOAD: RELOAD Position */
|
||||
#define CMSDK_TIMER_RELOAD_VAL_Msk (0xFFFFFFFFul << CMSDK_TIMER_RELOAD_VAL_Pos) /* CMSDK_TIMER RELOAD: RELOAD Mask */
|
||||
|
||||
#define CMSDK_TIMER_INTSTATUS_Pos 0 /* CMSDK_TIMER INTSTATUS: INTSTATUSPosition */
|
||||
#define CMSDK_TIMER_INTSTATUS_Msk (0x01ul << CMSDK_TIMER_INTSTATUS_Pos) /* CMSDK_TIMER INTSTATUS: INTSTATUSMask */
|
||||
|
||||
#define CMSDK_TIMER_INTCLEAR_Pos 0 /* CMSDK_TIMER INTCLEAR: INTCLEAR Position */
|
||||
#define CMSDK_TIMER_INTCLEAR_Msk (0x01ul << CMSDK_TIMER_INTCLEAR_Pos) /* CMSDK_TIMER INTCLEAR: INTCLEAR Mask */
|
||||
|
||||
|
||||
/*------------- Timer (TIM) --------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t Timer1Load; /* Offset: 0x000 (R/W) Timer 1 Load */
|
||||
__I uint32_t Timer1Value; /* Offset: 0x004 (R/ ) Timer 1 Counter Current Value */
|
||||
__IO uint32_t Timer1Control; /* Offset: 0x008 (R/W) Timer 1 Control */
|
||||
__O uint32_t Timer1IntClr; /* Offset: 0x00C ( /W) Timer 1 Interrupt Clear */
|
||||
__I uint32_t Timer1RIS; /* Offset: 0x010 (R/ ) Timer 1 Raw Interrupt Status */
|
||||
__I uint32_t Timer1MIS; /* Offset: 0x014 (R/ ) Timer 1 Masked Interrupt Status */
|
||||
__IO uint32_t Timer1BGLoad; /* Offset: 0x018 (R/W) Background Load Register */
|
||||
uint32_t RESERVED0;
|
||||
__IO uint32_t Timer2Load; /* Offset: 0x020 (R/W) Timer 2 Load */
|
||||
__I uint32_t Timer2Value; /* Offset: 0x024 (R/ ) Timer 2 Counter Current Value */
|
||||
__IO uint32_t Timer2Control; /* Offset: 0x028 (R/W) Timer 2 Control */
|
||||
__O uint32_t Timer2IntClr; /* Offset: 0x02C ( /W) Timer 2 Interrupt Clear */
|
||||
__I uint32_t Timer2RIS; /* Offset: 0x030 (R/ ) Timer 2 Raw Interrupt Status */
|
||||
__I uint32_t Timer2MIS; /* Offset: 0x034 (R/ ) Timer 2 Masked Interrupt Status */
|
||||
__IO uint32_t Timer2BGLoad; /* Offset: 0x038 (R/W) Background Load Register */
|
||||
uint32_t RESERVED1[945];
|
||||
__IO uint32_t ITCR; /* Offset: 0xF00 (R/W) Integration Test Control Register */
|
||||
__O uint32_t ITOP; /* Offset: 0xF04 ( /W) Integration Test Output Set Register */
|
||||
} CMSDK_DUALTIMER_BOTH_TypeDef;
|
||||
|
||||
#define CMSDK_DUALTIMER1_LOAD_Pos 0 /* CMSDK_DUALTIMER1 LOAD: LOAD Position */
|
||||
#define CMSDK_DUALTIMER1_LOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER1_LOAD_Pos) /* CMSDK_DUALTIMER1 LOAD: LOAD Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_VALUE_Pos 0 /* CMSDK_DUALTIMER1 VALUE: VALUE Position */
|
||||
#define CMSDK_DUALTIMER1_VALUE_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER1_VALUE_Pos) /* CMSDK_DUALTIMER1 VALUE: VALUE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_CTRL_EN_Pos 7 /* CMSDK_DUALTIMER1 CTRL_EN: CTRL Enable Position */
|
||||
#define CMSDK_DUALTIMER1_CTRL_EN_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_EN_Pos) /* CMSDK_DUALTIMER1 CTRL_EN: CTRL Enable Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_CTRL_MODE_Pos 6 /* CMSDK_DUALTIMER1 CTRL_MODE: CTRL MODE Position */
|
||||
#define CMSDK_DUALTIMER1_CTRL_MODE_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_MODE_Pos) /* CMSDK_DUALTIMER1 CTRL_MODE: CTRL MODE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_CTRL_INTEN_Pos 5 /* CMSDK_DUALTIMER1 CTRL_INTEN: CTRL Int Enable Position */
|
||||
#define CMSDK_DUALTIMER1_CTRL_INTEN_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_INTEN_Pos) /* CMSDK_DUALTIMER1 CTRL_INTEN: CTRL Int Enable Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_CTRL_PRESCALE_Pos 2 /* CMSDK_DUALTIMER1 CTRL_PRESCALE: CTRL PRESCALE Position */
|
||||
#define CMSDK_DUALTIMER1_CTRL_PRESCALE_Msk (0x3ul << CMSDK_DUALTIMER1_CTRL_PRESCALE_Pos) /* CMSDK_DUALTIMER1 CTRL_PRESCALE: CTRL PRESCALE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_CTRL_SIZE_Pos 1 /* CMSDK_DUALTIMER1 CTRL_SIZE: CTRL SIZE Position */
|
||||
#define CMSDK_DUALTIMER1_CTRL_SIZE_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_SIZE_Pos) /* CMSDK_DUALTIMER1 CTRL_SIZE: CTRL SIZE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_CTRL_ONESHOOT_Pos 0 /* CMSDK_DUALTIMER1 CTRL_ONESHOOT: CTRL ONESHOOT Position */
|
||||
#define CMSDK_DUALTIMER1_CTRL_ONESHOOT_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_ONESHOOT_Pos) /* CMSDK_DUALTIMER1 CTRL_ONESHOOT: CTRL ONESHOOT Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_INTCLR_Pos 0 /* CMSDK_DUALTIMER1 INTCLR: INT Clear Position */
|
||||
#define CMSDK_DUALTIMER1_INTCLR_Msk (0x1ul << CMSDK_DUALTIMER1_INTCLR_Pos) /* CMSDK_DUALTIMER1 INTCLR: INT Clear Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_RAWINTSTAT_Pos 0 /* CMSDK_DUALTIMER1 RAWINTSTAT: Raw Int Status Position */
|
||||
#define CMSDK_DUALTIMER1_RAWINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER1_RAWINTSTAT_Pos) /* CMSDK_DUALTIMER1 RAWINTSTAT: Raw Int Status Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_MASKINTSTAT_Pos 0 /* CMSDK_DUALTIMER1 MASKINTSTAT: Mask Int Status Position */
|
||||
#define CMSDK_DUALTIMER1_MASKINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER1_MASKINTSTAT_Pos) /* CMSDK_DUALTIMER1 MASKINTSTAT: Mask Int Status Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER1_BGLOAD_Pos 0 /* CMSDK_DUALTIMER1 BGLOAD: Background Load Position */
|
||||
#define CMSDK_DUALTIMER1_BGLOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER1_BGLOAD_Pos) /* CMSDK_DUALTIMER1 BGLOAD: Background Load Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_LOAD_Pos 0 /* CMSDK_DUALTIMER2 LOAD: LOAD Position */
|
||||
#define CMSDK_DUALTIMER2_LOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER2_LOAD_Pos) /* CMSDK_DUALTIMER2 LOAD: LOAD Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_VALUE_Pos 0 /* CMSDK_DUALTIMER2 VALUE: VALUE Position */
|
||||
#define CMSDK_DUALTIMER2_VALUE_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER2_VALUE_Pos) /* CMSDK_DUALTIMER2 VALUE: VALUE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_CTRL_EN_Pos 7 /* CMSDK_DUALTIMER2 CTRL_EN: CTRL Enable Position */
|
||||
#define CMSDK_DUALTIMER2_CTRL_EN_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_EN_Pos) /* CMSDK_DUALTIMER2 CTRL_EN: CTRL Enable Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_CTRL_MODE_Pos 6 /* CMSDK_DUALTIMER2 CTRL_MODE: CTRL MODE Position */
|
||||
#define CMSDK_DUALTIMER2_CTRL_MODE_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_MODE_Pos) /* CMSDK_DUALTIMER2 CTRL_MODE: CTRL MODE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_CTRL_INTEN_Pos 5 /* CMSDK_DUALTIMER2 CTRL_INTEN: CTRL Int Enable Position */
|
||||
#define CMSDK_DUALTIMER2_CTRL_INTEN_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_INTEN_Pos) /* CMSDK_DUALTIMER2 CTRL_INTEN: CTRL Int Enable Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_CTRL_PRESCALE_Pos 2 /* CMSDK_DUALTIMER2 CTRL_PRESCALE: CTRL PRESCALE Position */
|
||||
#define CMSDK_DUALTIMER2_CTRL_PRESCALE_Msk (0x3ul << CMSDK_DUALTIMER2_CTRL_PRESCALE_Pos) /* CMSDK_DUALTIMER2 CTRL_PRESCALE: CTRL PRESCALE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_CTRL_SIZE_Pos 1 /* CMSDK_DUALTIMER2 CTRL_SIZE: CTRL SIZE Position */
|
||||
#define CMSDK_DUALTIMER2_CTRL_SIZE_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_SIZE_Pos) /* CMSDK_DUALTIMER2 CTRL_SIZE: CTRL SIZE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_CTRL_ONESHOOT_Pos 0 /* CMSDK_DUALTIMER2 CTRL_ONESHOOT: CTRL ONESHOOT Position */
|
||||
#define CMSDK_DUALTIMER2_CTRL_ONESHOOT_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_ONESHOOT_Pos) /* CMSDK_DUALTIMER2 CTRL_ONESHOOT: CTRL ONESHOOT Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_INTCLR_Pos 0 /* CMSDK_DUALTIMER2 INTCLR: INT Clear Position */
|
||||
#define CMSDK_DUALTIMER2_INTCLR_Msk (0x1ul << CMSDK_DUALTIMER2_INTCLR_Pos) /* CMSDK_DUALTIMER2 INTCLR: INT Clear Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_RAWINTSTAT_Pos 0 /* CMSDK_DUALTIMER2 RAWINTSTAT: Raw Int Status Position */
|
||||
#define CMSDK_DUALTIMER2_RAWINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER2_RAWINTSTAT_Pos) /* CMSDK_DUALTIMER2 RAWINTSTAT: Raw Int Status Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_MASKINTSTAT_Pos 0 /* CMSDK_DUALTIMER2 MASKINTSTAT: Mask Int Status Position */
|
||||
#define CMSDK_DUALTIMER2_MASKINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER2_MASKINTSTAT_Pos) /* CMSDK_DUALTIMER2 MASKINTSTAT: Mask Int Status Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER2_BGLOAD_Pos 0 /* CMSDK_DUALTIMER2 BGLOAD: Background Load Position */
|
||||
#define CMSDK_DUALTIMER2_BGLOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER2_BGLOAD_Pos) /* CMSDK_DUALTIMER2 BGLOAD: Background Load Mask */
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t TimerLoad; /* Offset: 0x000 (R/W) Timer Load */
|
||||
__I uint32_t TimerValue; /* Offset: 0x000 (R/W) Timer Counter Current Value */
|
||||
__IO uint32_t TimerControl; /* Offset: 0x000 (R/W) Timer Control */
|
||||
__O uint32_t TimerIntClr; /* Offset: 0x000 (R/W) Timer Interrupt Clear */
|
||||
__I uint32_t TimerRIS; /* Offset: 0x000 (R/W) Timer Raw Interrupt Status */
|
||||
__I uint32_t TimerMIS; /* Offset: 0x000 (R/W) Timer Masked Interrupt Status */
|
||||
__IO uint32_t TimerBGLoad; /* Offset: 0x000 (R/W) Background Load Register */
|
||||
} CMSDK_DUALTIMER_SINGLE_TypeDef;
|
||||
|
||||
#define CMSDK_DUALTIMER_LOAD_Pos 0 /* CMSDK_DUALTIMER LOAD: LOAD Position */
|
||||
#define CMSDK_DUALTIMER_LOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER_LOAD_Pos) /* CMSDK_DUALTIMER LOAD: LOAD Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_VALUE_Pos 0 /* CMSDK_DUALTIMER VALUE: VALUE Position */
|
||||
#define CMSDK_DUALTIMER_VALUE_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER_VALUE_Pos) /* CMSDK_DUALTIMER VALUE: VALUE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_CTRL_EN_Pos 7 /* CMSDK_DUALTIMER CTRL_EN: CTRL Enable Position */
|
||||
#define CMSDK_DUALTIMER_CTRL_EN_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_EN_Pos) /* CMSDK_DUALTIMER CTRL_EN: CTRL Enable Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_CTRL_MODE_Pos 6 /* CMSDK_DUALTIMER CTRL_MODE: CTRL MODE Position */
|
||||
#define CMSDK_DUALTIMER_CTRL_MODE_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_MODE_Pos) /* CMSDK_DUALTIMER CTRL_MODE: CTRL MODE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_CTRL_INTEN_Pos 5 /* CMSDK_DUALTIMER CTRL_INTEN: CTRL Int Enable Position */
|
||||
#define CMSDK_DUALTIMER_CTRL_INTEN_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_INTEN_Pos) /* CMSDK_DUALTIMER CTRL_INTEN: CTRL Int Enable Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_CTRL_PRESCALE_Pos 2 /* CMSDK_DUALTIMER CTRL_PRESCALE: CTRL PRESCALE Position */
|
||||
#define CMSDK_DUALTIMER_CTRL_PRESCALE_Msk (0x3ul << CMSDK_DUALTIMER_CTRL_PRESCALE_Pos) /* CMSDK_DUALTIMER CTRL_PRESCALE: CTRL PRESCALE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_CTRL_SIZE_Pos 1 /* CMSDK_DUALTIMER CTRL_SIZE: CTRL SIZE Position */
|
||||
#define CMSDK_DUALTIMER_CTRL_SIZE_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_SIZE_Pos) /* CMSDK_DUALTIMER CTRL_SIZE: CTRL SIZE Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_CTRL_ONESHOOT_Pos 0 /* CMSDK_DUALTIMER CTRL_ONESHOOT: CTRL ONESHOOT Position */
|
||||
#define CMSDK_DUALTIMER_CTRL_ONESHOOT_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_ONESHOOT_Pos) /* CMSDK_DUALTIMER CTRL_ONESHOOT: CTRL ONESHOOT Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_INTCLR_Pos 0 /* CMSDK_DUALTIMER INTCLR: INT Clear Position */
|
||||
#define CMSDK_DUALTIMER_INTCLR_Msk (0x1ul << CMSDK_DUALTIMER_INTCLR_Pos) /* CMSDK_DUALTIMER INTCLR: INT Clear Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_RAWINTSTAT_Pos 0 /* CMSDK_DUALTIMER RAWINTSTAT: Raw Int Status Position */
|
||||
#define CMSDK_DUALTIMER_RAWINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER_RAWINTSTAT_Pos) /* CMSDK_DUALTIMER RAWINTSTAT: Raw Int Status Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_MASKINTSTAT_Pos 0 /* CMSDK_DUALTIMER MASKINTSTAT: Mask Int Status Position */
|
||||
#define CMSDK_DUALTIMER_MASKINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER_MASKINTSTAT_Pos) /* CMSDK_DUALTIMER MASKINTSTAT: Mask Int Status Mask */
|
||||
|
||||
#define CMSDK_DUALTIMER_BGLOAD_Pos 0 /* CMSDK_DUALTIMER BGLOAD: Background Load Position */
|
||||
#define CMSDK_DUALTIMER_BGLOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER_BGLOAD_Pos) /* CMSDK_DUALTIMER BGLOAD: Background Load Mask */
|
||||
|
||||
|
||||
/*-------------------- General Purpose Input Output (GPIO) -------------------*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t DATA; /* Offset: 0x000 (R/W) DATA Register */
|
||||
__IO uint32_t DATAOUT; /* Offset: 0x004 (R/W) Data Output Latch Register */
|
||||
uint32_t RESERVED0[2];
|
||||
__IO uint32_t OUTENABLESET; /* Offset: 0x010 (R/W) Output Enable Set Register */
|
||||
__IO uint32_t OUTENABLECLR; /* Offset: 0x014 (R/W) Output Enable Clear Register */
|
||||
__IO uint32_t ALTFUNCSET; /* Offset: 0x018 (R/W) Alternate Function Set Register */
|
||||
__IO uint32_t ALTFUNCCLR; /* Offset: 0x01C (R/W) Alternate Function Clear Register */
|
||||
__IO uint32_t INTENSET; /* Offset: 0x020 (R/W) Interrupt Enable Set Register */
|
||||
__IO uint32_t INTENCLR; /* Offset: 0x024 (R/W) Interrupt Enable Clear Register */
|
||||
__IO uint32_t INTTYPESET; /* Offset: 0x028 (R/W) Interrupt Type Set Register */
|
||||
__IO uint32_t INTTYPECLR; /* Offset: 0x02C (R/W) Interrupt Type Clear Register */
|
||||
__IO uint32_t INTPOLSET; /* Offset: 0x030 (R/W) Interrupt Polarity Set Register */
|
||||
__IO uint32_t INTPOLCLR; /* Offset: 0x034 (R/W) Interrupt Polarity Clear Register */
|
||||
union {
|
||||
__I uint32_t INTSTATUS; /* Offset: 0x038 (R/ ) Interrupt Status Register */
|
||||
__O uint32_t INTCLEAR; /* Offset: 0x038 ( /W) Interrupt Clear Register */
|
||||
};
|
||||
uint32_t RESERVED1[241];
|
||||
__IO uint32_t LB_MASKED[256]; /* Offset: 0x400 - 0x7FC Lower byte Masked Access Register (R/W) */
|
||||
__IO uint32_t UB_MASKED[256]; /* Offset: 0x800 - 0xBFC Upper byte Masked Access Register (R/W) */
|
||||
} CMSDK_GPIO_TypeDef;
|
||||
|
||||
#define CMSDK_GPIO_DATA_Pos 0 /* CMSDK_GPIO DATA: DATA Position */
|
||||
#define CMSDK_GPIO_DATA_Msk (0xFFFFul << CMSDK_GPIO_DATA_Pos) /* CMSDK_GPIO DATA: DATA Mask */
|
||||
|
||||
#define CMSDK_GPIO_DATAOUT_Pos 0 /* CMSDK_GPIO DATAOUT: DATAOUT Position */
|
||||
#define CMSDK_GPIO_DATAOUT_Msk (0xFFFFul << CMSDK_GPIO_DATAOUT_Pos) /* CMSDK_GPIO DATAOUT: DATAOUT Mask */
|
||||
|
||||
#define CMSDK_GPIO_OUTENSET_Pos 0 /* CMSDK_GPIO OUTEN: OUTEN Position */
|
||||
#define CMSDK_GPIO_OUTENSET_Msk (0xFFFFul << CMSDK_GPIO_OUTEN_Pos) /* CMSDK_GPIO OUTEN: OUTEN Mask */
|
||||
|
||||
#define CMSDK_GPIO_OUTENCLR_Pos 0 /* CMSDK_GPIO OUTEN: OUTEN Position */
|
||||
#define CMSDK_GPIO_OUTENCLR_Msk (0xFFFFul << CMSDK_GPIO_OUTEN_Pos) /* CMSDK_GPIO OUTEN: OUTEN Mask */
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNCSET_Pos 0 /* CMSDK_GPIO ALTFUNC: ALTFUNC Position */
|
||||
#define CMSDK_GPIO_ALTFUNCSET_Msk (0xFFFFul << CMSDK_GPIO_ALTFUNC_Pos) /* CMSDK_GPIO ALTFUNC: ALTFUNC Mask */
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNCCLR_Pos 0 /* CMSDK_GPIO ALTFUNC: ALTFUNC Position */
|
||||
#define CMSDK_GPIO_ALTFUNCCLR_Msk (0xFFFFul << CMSDK_GPIO_ALTFUNC_Pos) /* CMSDK_GPIO ALTFUNC: ALTFUNC Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTENSET_Pos 0 /* CMSDK_GPIO INTEN: INTEN Position */
|
||||
#define CMSDK_GPIO_INTENSET_Msk (0xFFFFul << CMSDK_GPIO_INTEN_Pos) /* CMSDK_GPIO INTEN: INTEN Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTENCLR_Pos 0 /* CMSDK_GPIO INTEN: INTEN Position */
|
||||
#define CMSDK_GPIO_INTENCLR_Msk (0xFFFFul << CMSDK_GPIO_INTEN_Pos) /* CMSDK_GPIO INTEN: INTEN Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTTYPESET_Pos 0 /* CMSDK_GPIO INTTYPE: INTTYPE Position */
|
||||
#define CMSDK_GPIO_INTTYPESET_Msk (0xFFFFul << CMSDK_GPIO_INTTYPE_Pos) /* CMSDK_GPIO INTTYPE: INTTYPE Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTTYPECLR_Pos 0 /* CMSDK_GPIO INTTYPE: INTTYPE Position */
|
||||
#define CMSDK_GPIO_INTTYPECLR_Msk (0xFFFFul << CMSDK_GPIO_INTTYPE_Pos) /* CMSDK_GPIO INTTYPE: INTTYPE Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTPOLSET_Pos 0 /* CMSDK_GPIO INTPOL: INTPOL Position */
|
||||
#define CMSDK_GPIO_INTPOLSET_Msk (0xFFFFul << CMSDK_GPIO_INTPOL_Pos) /* CMSDK_GPIO INTPOL: INTPOL Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTPOLCLR_Pos 0 /* CMSDK_GPIO INTPOL: INTPOL Position */
|
||||
#define CMSDK_GPIO_INTPOLCLR_Msk (0xFFFFul << CMSDK_GPIO_INTPOL_Pos) /* CMSDK_GPIO INTPOL: INTPOL Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTSTATUS_Pos 0 /* CMSDK_GPIO INTSTATUS: INTSTATUS Position */
|
||||
#define CMSDK_GPIO_INTSTATUS_Msk (0xFFul << CMSDK_GPIO_INTSTATUS_Pos) /* CMSDK_GPIO INTSTATUS: INTSTATUS Mask */
|
||||
|
||||
#define CMSDK_GPIO_INTCLEAR_Pos 0 /* CMSDK_GPIO INTCLEAR: INTCLEAR Position */
|
||||
#define CMSDK_GPIO_INTCLEAR_Msk (0xFFul << CMSDK_GPIO_INTCLEAR_Pos) /* CMSDK_GPIO INTCLEAR: INTCLEAR Mask */
|
||||
|
||||
#define CMSDK_GPIO_MASKLOWBYTE_Pos 0 /* CMSDK_GPIO MASKLOWBYTE: MASKLOWBYTE Position */
|
||||
#define CMSDK_GPIO_MASKLOWBYTE_Msk (0x00FFul << CMSDK_GPIO_MASKLOWBYTE_Pos) /* CMSDK_GPIO MASKLOWBYTE: MASKLOWBYTE Mask */
|
||||
|
||||
#define CMSDK_GPIO_MASKHIGHBYTE_Pos 0 /* CMSDK_GPIO MASKHIGHBYTE: MASKHIGHBYTE Position */
|
||||
#define CMSDK_GPIO_MASKHIGHBYTE_Msk (0xFF00ul << CMSDK_GPIO_MASKHIGHBYTE_Pos) /* CMSDK_GPIO MASKHIGHBYTE: MASKHIGHBYTE Mask */
|
||||
|
||||
/* GPIO Alternate function pin numbers */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_UART2_RX 0 /* Shield 0 UART 2 Rx */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_UART2_RX_SET (CMSDK_GPIO_ALTFUNC_SH0_UART2_RX % 16)
|
||||
#define CMSDK_GPIO_SH0_UART2_RX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_UART2_RX / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_UART2_TX 4 /* Shield 0 UART 2 Tx */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_UART2_TX_SET (CMSDK_GPIO_ALTFUNC_SH0_UART2_TX % 16)
|
||||
#define CMSDK_GPIO_SH0_UART2_TX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_UART2_TX / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_UART3_RX 26 /* Shield 1 UART 3 Rx */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_UART3_RX_SET (CMSDK_GPIO_ALTFUNC_SH1_UART3_RX % 16)
|
||||
#define CMSDK_GPIO_SH1_UART3_RX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_UART3_RX / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_UART3_TX 30 /* Shield 1 UART 3 Tx */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_UART3_TX_SET (CMSDK_GPIO_ALTFUNC_SH1_UART3_TX % 16)
|
||||
#define CMSDK_GPIO_SH1_UART3_TX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_UART3_TX / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_UART4_RX 23 /* UART 4 Rx */
|
||||
#define CMSDK_GPIO_ALTFUNC_UART4_RX_SET (CMSDK_GPIO_ALTFUNC_UART4_RX % 16)
|
||||
#define CMSDK_GPIO_UART4_RX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_UART4_RX / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_UART4_TX 24 /* UART 4 Tx */
|
||||
#define CMSDK_GPIO_ALTFUNC_UART4_TX_SET (CMSDK_GPIO_ALTFUNC_UART4_TX % 16)
|
||||
#define CMSDK_GPIO_UART4_TX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_UART4_TX / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_SCL_I2C 5 /* Shield 0 SCL I2S */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_SCL_I2C_SET (CMSDK_GPIO_ALTFUNC_SH0_SCL_I2C % 16)
|
||||
#define CMSDK_GPIO_SH0_SCL_I2C_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_SCL_I2C / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_SDA_I2C 15 /* Shield 0 SDA I2S */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_SDA_I2C_SET (CMSDK_GPIO_ALTFUNC_SH0_SDA_I2C % 16)
|
||||
#define CMSDK_GPIO_SH0_SDA_I2C_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_SDA_I2C / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_SCL_I2C 31 /* Shield 1 SCL I2S */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_SCL_I2C_SET (CMSDK_GPIO_ALTFUNC_SH1_SCL_I2C % 16)
|
||||
#define CMSDK_GPIO_SH1_SCL_I2C_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_SCL_I2C / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_SDA_I2C 41 /* Shield 1 SDA I2S */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_SDA_I2C_SET (CMSDK_GPIO_ALTFUNC_SH1_SDA_I2C % 16)
|
||||
#define CMSDK_GPIO_SH1_SDA_I2C_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_SDA_I2C / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_SCK_SPI 11 /* Shield 0 SCK SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_SCK_SPI_SET (CMSDK_GPIO_ALTFUNC_SH0_SCK_SPI % 16)
|
||||
#define CMSDK_GPIO_SH0_SCK_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_SCK_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_CS_SPI 12 /* Shield 0 CS SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_CS_SPI_SET (CMSDK_GPIO_ALTFUNC_SH0_CS_SPI % 16)
|
||||
#define CMSDK_GPIO_SH0_CS_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_CS_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_MOSI_SPI 13 /* Shield 0 MOSI SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_MOSI_SPI_SET (CMSDK_GPIO_ALTFUNC_SH0_MOSI_SPI % 16)
|
||||
#define CMSDK_GPIO_SH0_MOSI_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_MOSI_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_MISO_SPI 14 /* Shield 0 MISO SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH0_MISO_SPI_SET (CMSDK_GPIO_ALTFUNC_SH0_MISO_SPI % 16)
|
||||
#define CMSDK_GPIO_SH0_MISO_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_MISO_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_SCK_SPI 44 /* Shield 1 SCK SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_SCK_SPI_SET (CMSDK_GPIO_ALTFUNC_SH1_SCK_SPI % 16)
|
||||
#define CMSDK_GPIO_SH1_SCK_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_SCK_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_CS_SPI 38 /* Shield 1 CS SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_CS_SPI_SET (CMSDK_GPIO_ALTFUNC_SH1_CS_SPI % 16)
|
||||
#define CMSDK_GPIO_SH1_CS_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_CS_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_MOSI_SPI 39 /* Shield 1 MOSI SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_MOSI_SPI_SET (CMSDK_GPIO_ALTFUNC_SH1_MOSI_SPI % 16)
|
||||
#define CMSDK_GPIO_SH1_MOSI_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_MOSI_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_MISO_SPI 40 /* Shield 1 MISO SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_SH1_MISO_SPI_SET (CMSDK_GPIO_ALTFUNC_SH1_MISO_SPI % 16)
|
||||
#define CMSDK_GPIO_SH1_MISO_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_MISO_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_SCK_SPI 19 /* Shield ADC SCK SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_SCK_SPI_SET (CMSDK_GPIO_ALTFUNC_ADC_SCK_SPI % 16)
|
||||
#define CMSDK_GPIO_ADC_SCK_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_ADC_SCK_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_CS_SPI 16 /* Shield ADC CS SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_CS_SPI_SET (CMSDK_GPIO_ALTFUNC_ADC_CS_SPI % 16)
|
||||
#define CMSDK_GPIO_ADC_CS_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_ADC_CS_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_MOSI_SPI 18 /* Shield ADC MOSI SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_MOSI_SPI_SET (CMSDK_GPIO_ALTFUNC_ADC_MOSI_SPI % 16)
|
||||
#define CMSDK_GPIO_ADC_MOSI_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_ADC_MOSI_SPI / 16)
|
||||
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_MISO_SPI 17 /* Shield ADC MISO SPI */
|
||||
#define CMSDK_GPIO_ALTFUNC_ADC_MISO_SPI_SET (CMSDK_GPIO_ALTFUNC_ADC_MISO_SPI % 16)
|
||||
#define CMSDK_GPIO_ADC_MISO_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_ADC_MISO_SPI / 16)
|
||||
|
||||
/*------------- System Control (SYSCON) --------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
|
@ -755,28 +341,12 @@ typedef struct
|
|||
/* ================ Peripheral declaration ================ */
|
||||
/* ================================================================================ */
|
||||
|
||||
#define CMSDK_UART0 ((CMSDK_UART_TypeDef *) CMSDK_UART0_BASE )
|
||||
#define CMSDK_UART1 ((CMSDK_UART_TypeDef *) CMSDK_UART1_BASE )
|
||||
#define CMSDK_UART2 ((CMSDK_UART_TypeDef *) CMSDK_UART2_BASE )
|
||||
#define CMSDK_UART3 ((CMSDK_UART_TypeDef *) CMSDK_UART3_BASE )
|
||||
#define CMSDK_UART4 ((CMSDK_UART_TypeDef *) CMSDK_UART4_BASE )
|
||||
#define CMSDK_TIMER0 ((CMSDK_TIMER_TypeDef *) CMSDK_TIMER0_BASE )
|
||||
#define CMSDK_TIMER1 ((CMSDK_TIMER_TypeDef *) CMSDK_TIMER1_BASE )
|
||||
#define CMSDK_DUALTIMER ((CMSDK_DUALTIMER_BOTH_TypeDef *) CMSDK_DUALTIMER_BASE )
|
||||
#define CMSDK_DUALTIMER1 ((CMSDK_DUALTIMER_SINGLE_TypeDef *) CMSDK_DUALTIMER_1_BASE )
|
||||
#define CMSDK_DUALTIMER2 ((CMSDK_DUALTIMER_SINGLE_TypeDef *) CMSDK_DUALTIMER_2_BASE )
|
||||
#define CMSDK_RTC ((CMSDK_RTC_TypeDef *) CMSDK_RTC_BASE )
|
||||
#define CMSDK_WATCHDOG ((CMSDK_WATCHDOG_TypeDef *) CMSDK_WATCHDOG_BASE )
|
||||
#define CMSDK_GPIO0 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO0_BASE )
|
||||
#define CMSDK_GPIO1 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO1_BASE )
|
||||
#define CMSDK_GPIO2 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO2_BASE )
|
||||
#define CMSDK_GPIO3 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO3_BASE )
|
||||
#define CMSDK_GPIO4 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO4_BASE )
|
||||
#define CMSDK_GPIO5 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO5_BASE )
|
||||
#define CMSDK_SYSCON ((CMSDK_SYSCON_TypeDef *) CMSDK_SYSCTRL_BASE )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CMSDK_BEETLE_H */
|
||||
#endif /* CMSDK_CM3DS_H */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* MPS2 CMSIS Library
|
||||
*
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -153,154 +153,6 @@ typedef struct //
|
|||
} MPS2_SCC_TypeDef;
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* SSP Peripheral declaration */
|
||||
/******************************************************************************/
|
||||
|
||||
typedef struct // Document DDI0194G_ssp_pl022_r1p3_trm.pdf
|
||||
{
|
||||
__IO uint32_t CR0; // Offset: 0x000 (R/W) Control register 0
|
||||
// [31:16] : Reserved
|
||||
// [15:8] : Serial clock rate
|
||||
// [7] : SSPCLKOUT phase, applicable to Motorola SPI frame format only
|
||||
// [6] : SSPCLKOUT polarity, applicable to Motorola SPI frame format only
|
||||
// [5:4] : Frame format
|
||||
// [3:0] : Data Size Select
|
||||
__IO uint32_t CR1; // Offset: 0x004 (R/W) Control register 1
|
||||
// [31:4] : Reserved
|
||||
// [3] : Slave-mode output disable
|
||||
// [2] : Master or slave mode select
|
||||
// [1] : Synchronous serial port enable
|
||||
// [0] : Loop back mode
|
||||
__IO uint32_t DR; // Offset: 0x008 (R/W) Data register
|
||||
// [31:16] : Reserved
|
||||
// [15:0] : Transmit/Receive FIFO
|
||||
__I uint32_t SR; // Offset: 0x00C (R/ ) Status register
|
||||
// [31:5] : Reserved
|
||||
// [4] : PrimeCell SSP busy flag
|
||||
// [3] : Receive FIFO full
|
||||
// [2] : Receive FIFO not empty
|
||||
// [1] : Transmit FIFO not full
|
||||
// [0] : Transmit FIFO empty
|
||||
__IO uint32_t CPSR; // Offset: 0x010 (R/W) Clock prescale register
|
||||
// [31:8] : Reserved
|
||||
// [8:0] : Clock prescale divisor
|
||||
__IO uint32_t IMSC; // Offset: 0x014 (R/W) Interrupt mask set or clear register
|
||||
// [31:4] : Reserved
|
||||
// [3] : Transmit FIFO interrupt mask
|
||||
// [2] : Receive FIFO interrupt mask
|
||||
// [1] : Receive timeout interrupt mask
|
||||
// [0] : Receive overrun interrupt mask
|
||||
__I uint32_t RIS; // Offset: 0x018 (R/ ) Raw interrupt status register
|
||||
// [31:4] : Reserved
|
||||
// [3] : raw interrupt state, prior to masking, of the SSPTXINTR interrupt
|
||||
// [2] : raw interrupt state, prior to masking, of the SSPRXINTR interrupt
|
||||
// [1] : raw interrupt state, prior to masking, of the SSPRTINTR interrupt
|
||||
// [0] : raw interrupt state, prior to masking, of the SSPRORINTR interrupt
|
||||
__I uint32_t MIS; // Offset: 0x01C (R/ ) Masked interrupt status register
|
||||
// [31:4] : Reserved
|
||||
// [3] : transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt
|
||||
// [2] : receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt
|
||||
// [1] : receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt
|
||||
// [0] : receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt
|
||||
__O uint32_t ICR; // Offset: 0x020 ( /W) Interrupt clear register
|
||||
// [31:2] : Reserved
|
||||
// [1] : Clears the SSPRTINTR interrupt
|
||||
// [0] : Clears the SSPRORINTR interrupt
|
||||
__IO uint32_t DMACR; // Offset: 0x024 (R/W) DMA control register
|
||||
// [31:2] : Reserved
|
||||
// [1] : Transmit DMA Enable
|
||||
// [0] : Receive DMA Enable
|
||||
} MPS2_SSP_TypeDef;
|
||||
|
||||
|
||||
// SSP_CR0 Control register 0
|
||||
#define SSP_CR0_DSS_Pos 0 // Data Size Select
|
||||
#define SSP_CR0_DSS_Msk (0xF<<SSP_CR0_DSS_Pos)
|
||||
#define SSP_CR0_FRF_Pos 4 // Frame Format Select
|
||||
#define SSP_CR0_FRF_Msk (3UL<<SSP_CR0_FRM_Pos)
|
||||
#define SSP_CR0_SPO_Pos 6 // SSPCLKOUT polarity
|
||||
#define SSP_CR0_SPO_Msk (1UL<<SSP_CR0_SPO_Pos)
|
||||
#define SSP_CR0_SPH_Pos 7 // SSPCLKOUT phase
|
||||
#define SSP_CR0_SPH_Msk (1UL<<SSP_CR0_SPH_Pos)
|
||||
#define SSP_CR0_SCR_Pos 8 // Serial Clock Rate (divide)
|
||||
#define SSP_CR0_SCR_Msk (0xFF<<SSP_CR0_SCR_Pos)
|
||||
|
||||
#define SSP_CR0_SCR_DFLT 0x0300 // Serial Clock Rate (divide), default set at 3
|
||||
#define SSP_CR0_FRF_MOT 0x0000 // Frame format, Motorola
|
||||
#define SSP_CR0_DSS_8 0x0007 // Data packet size, 8bits
|
||||
#define SSP_CR0_DSS_16 0x000F // Data packet size, 16bits
|
||||
|
||||
// SSP_CR1 Control register 1
|
||||
#define SSP_CR1_LBM_Pos 0 // Loop Back Mode
|
||||
#define SSP_CR1_LBM_Msk (1UL<<SSP_CR1_LBM_Pos)
|
||||
#define SSP_CR1_SSE_Pos 1 // Serial port enable
|
||||
#define SSP_CR1_SSE_Msk (1UL<<SSP_CR1_SSE_Pos)
|
||||
#define SSP_CR1_MS_Pos 2 // Master or Slave mode
|
||||
#define SSP_CR1_MS_Msk (1UL<<SSP_CR1_MS_Pos)
|
||||
#define SSP_CR1_SOD_Pos 3 // Slave Output mode Disable
|
||||
#define SSP_CR1_SOD_Msk (1UL<<SSP_CR1_SOD_Pos)
|
||||
|
||||
// SSP_SR Status register
|
||||
#define SSP_SR_TFE_Pos 0 // Transmit FIFO empty
|
||||
#define SSP_SR_TFE_Msk (1UL<<SSP_SR_TFE_Pos)
|
||||
#define SSP_SR_TNF_Pos 1 // Transmit FIFO not full
|
||||
#define SSP_SR_TNF_Msk (1UL<<SSP_SR_TNF_Pos)
|
||||
#define SSP_SR_RNE_Pos 2 // Receive FIFO not empty
|
||||
#define SSP_SR_RNE_Msk (1UL<<SSP_SR_RNE_Pos)
|
||||
#define SSP_SR_RFF_Pos 3 // Receive FIFO full
|
||||
#define SSP_SR_RFF_Msk (1UL<<SSP_SR_RFF_Pos)
|
||||
#define SSP_SR_BSY_Pos 4 // Busy
|
||||
#define SSP_SR_BSY_Msk (1UL<<SSP_SR_BSY_Pos)
|
||||
|
||||
// SSP_CPSR Clock prescale register
|
||||
#define SSP_CPSR_CPD_Pos 0 // Clock prescale divisor
|
||||
#define SSP_CPSR_CPD_Msk (0xFF<<SSP_CPSR_CDP_Pos)
|
||||
|
||||
#define SSP_CPSR_DFLT 0x0008 // Clock prescale (use with SCR), default set at 8
|
||||
|
||||
// SSPIMSC Interrupt mask set and clear register
|
||||
#define SSP_IMSC_RORIM_Pos 0 // Receive overrun not Masked
|
||||
#define SSP_IMSC_RORIM_Msk (1UL<<SSP_IMSC_RORIM_Pos)
|
||||
#define SSP_IMSC_RTIM_Pos 1 // Receive timeout not Masked
|
||||
#define SSP_IMSC_RTIM_Msk (1UL<<SSP_IMSC_RTIM_Pos)
|
||||
#define SSP_IMSC_RXIM_Pos 2 // Receive FIFO not Masked
|
||||
#define SSP_IMSC_RXIM_Msk (1UL<<SSP_IMSC_RXIM_Pos)
|
||||
#define SSP_IMSC_TXIM_Pos 3 // Transmit FIFO not Masked
|
||||
#define SSP_IMSC_TXIM_Msk (1UL<<SSP_IMSC_TXIM_Pos)
|
||||
|
||||
// SSPRIS Raw interrupt status register
|
||||
#define SSP_RIS_RORRIS_Pos 0 // Raw Overrun interrupt flag
|
||||
#define SSP_RIS_RORRIS_Msk (1UL<<SSP_RIS_RORRIS_Pos)
|
||||
#define SSP_RIS_RTRIS_Pos 1 // Raw Timemout interrupt flag
|
||||
#define SSP_RIS_RTRIS_Msk (1UL<<SSP_RIS_RTRIS_Pos)
|
||||
#define SSP_RIS_RXRIS_Pos 2 // Raw Receive interrupt flag
|
||||
#define SSP_RIS_RXRIS_Msk (1UL<<SSP_RIS_RXRIS_Pos)
|
||||
#define SSP_RIS_TXRIS_Pos 3 // Raw Transmit interrupt flag
|
||||
#define SSP_RIS_TXRIS_Msk (1UL<<SSP_RIS_TXRIS_Pos)
|
||||
|
||||
// SSPMIS Masked interrupt status register
|
||||
#define SSP_MIS_RORMIS_Pos 0 // Masked Overrun interrupt flag
|
||||
#define SSP_MIS_RORMIS_Msk (1UL<<SSP_MIS_RORMIS_Pos)
|
||||
#define SSP_MIS_RTMIS_Pos 1 // Masked Timemout interrupt flag
|
||||
#define SSP_MIS_RTMIS_Msk (1UL<<SSP_MIS_RTMIS_Pos)
|
||||
#define SSP_MIS_RXMIS_Pos 2 // Masked Receive interrupt flag
|
||||
#define SSP_MIS_RXMIS_Msk (1UL<<SSP_MIS_RXMIS_Pos)
|
||||
#define SSP_MIS_TXMIS_Pos 3 // Masked Transmit interrupt flag
|
||||
#define SSP_MIS_TXMIS_Msk (1UL<<SSP_MIS_TXMIS_Pos)
|
||||
|
||||
// SSPICR Interrupt clear register
|
||||
#define SSP_ICR_RORIC_Pos 0 // Clears Overrun interrupt flag
|
||||
#define SSP_ICR_RORIC_Msk (1UL<<SSP_ICR_RORIC_Pos)
|
||||
#define SSP_ICR_RTIC_Pos 1 // Clears Timemout interrupt flag
|
||||
#define SSP_ICR_RTIC_Msk (1UL<<SSP_ICR_RTIC_Pos)
|
||||
|
||||
// SSPDMACR DMA control register
|
||||
#define SSP_DMACR_RXDMAE_Pos 0 // Enable Receive FIFO DMA
|
||||
#define SSP_DMACR_RXDMAE_Msk (1UL<<SSP_DMACR_RXDMAE_Pos)
|
||||
#define SSP_DMACR_TXDMAE_Pos 1 // Enable Transmit FIFO DMA
|
||||
#define SSP_DMACR_TXDMAE_Msk (1UL<<SSP_DMACR_TXDMAE_Pos)
|
||||
|
||||
/******************************************************************************/
|
||||
/* Audio and Touch Screen (I2C) Peripheral declaration */
|
||||
/******************************************************************************/
|
||||
|
@ -577,11 +429,6 @@ __IO uint32_t E2P_DATA; // EEPROM Data (offset 0xB4)
|
|||
#define MPS2_AAIC_I2S ((MPS2_I2S_TypeDef *) MPS2_AAIC_I2S_BASE )
|
||||
#define MPS2_FPGAIO ((MPS2_FPGAIO_TypeDef *) MPS2_FPGAIO_BASE )
|
||||
#define MPS2_SCC ((MPS2_SCC_TypeDef *) MPS2_SCC_BASE )
|
||||
#define MPS2_SSP0 ((MPS2_SSP_TypeDef *) MPS2_SSP0_BASE )
|
||||
#define MPS2_SSP1 ((MPS2_SSP_TypeDef *) MPS2_SSP1_BASE )
|
||||
#define MPS2_SSP2 ((MPS2_SSP_TypeDef *) MPS2_SSP2_BASE )
|
||||
#define MPS2_SSP3 ((MPS2_SSP_TypeDef *) MPS2_SSP3_BASE )
|
||||
#define MPS2_SSP4 ((MPS2_SSP_TypeDef *) MPS2_SSP4_BASE )
|
||||
|
||||
/******************************************************************************/
|
||||
/* General Function Definitions */
|
||||
|
|
|
@ -1,265 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2016 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "cmsis.h"
|
||||
#include "apb_timer.h"
|
||||
|
||||
/* Timer Private Data */
|
||||
typedef struct {
|
||||
/* Timer Definition */
|
||||
CMSDK_TIMER_TypeDef *timerN;
|
||||
/* Timer IRQn */
|
||||
uint32_t timerIRQn;
|
||||
/* Timer Reload Value */
|
||||
uint32_t timerReload;
|
||||
/* Timer state */
|
||||
uint32_t state;
|
||||
} apb_timer_t;
|
||||
|
||||
/* Timer state definitions */
|
||||
#define TIMER_INITIALIZED (1)
|
||||
#define TIMER_ENABLED (1 << 1)
|
||||
|
||||
/*
|
||||
* This Timer is written for MBED OS and keeps count
|
||||
* of the ticks. All the elaboration logic is demanded
|
||||
* to the upper layers.
|
||||
*/
|
||||
#define TIMER_MAX_VALUE 0xFFFFFFFF
|
||||
#define TIMER_TICKS_US (SystemCoreClock/1000000)
|
||||
|
||||
/* Timers Array */
|
||||
static apb_timer_t Timers[NUM_TIMERS];
|
||||
|
||||
void Timer_Index_Init(uint32_t timer, uint32_t reload,
|
||||
CMSDK_TIMER_TypeDef *TimerN, uint32_t IRQn)
|
||||
{
|
||||
Timers[timer].timerN = TimerN;
|
||||
Timers[timer].timerIRQn = IRQn;
|
||||
Timers[timer].timerReload = reload;
|
||||
Timers[timer].state = TIMER_INITIALIZED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_Initialize(): Initializes an hardware timer
|
||||
* timer: timer to be Initialized
|
||||
* time_us: timer reload value in us - 0 to reload to timer max value
|
||||
* time_us = tick_value / TIMER_TICKS_US
|
||||
*/
|
||||
#define TIMER_INIT(index, reload) Timer_Index_Init(index, reload, CMSDK_TIMER##index, TIMER##index##_IRQn)
|
||||
void Timer_Initialize(uint32_t timer, uint32_t time_us)
|
||||
{
|
||||
uint32_t reload = 0;
|
||||
|
||||
if (timer < NUM_TIMERS) {
|
||||
if (time_us == 0) {
|
||||
reload = TIMER_MAX_VALUE;
|
||||
} else {
|
||||
reload = (time_us) * TIMER_TICKS_US;
|
||||
}
|
||||
switch (timer) {
|
||||
case 0:
|
||||
TIMER_INIT(0, reload);
|
||||
break;
|
||||
case 1:
|
||||
TIMER_INIT(1, reload);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_Enable(): Enables a hardware timer
|
||||
* timer: timer to be enabled
|
||||
*/
|
||||
void Timer_Enable(uint32_t timer)
|
||||
{
|
||||
/* The timer has to be contained in a valid range */
|
||||
if (timer < NUM_TIMERS) {
|
||||
/* Timer has to be already initialized */
|
||||
if (Timers[timer].state == TIMER_INITIALIZED) {
|
||||
/* Disable Timer */
|
||||
(Timers[timer].timerN)->CTRL = 0x0;
|
||||
/* Reload Value */
|
||||
(Timers[timer].timerN)->RELOAD = Timers[timer].timerReload;
|
||||
/* Enable Interrupt */
|
||||
(Timers[timer].timerN)->CTRL = CMSDK_TIMER_CTRL_IRQEN_Msk;
|
||||
/* Enable Counter */
|
||||
(Timers[timer].timerN)->CTRL |= CMSDK_TIMER_CTRL_EN_Msk;
|
||||
/* Change timer state */
|
||||
Timers[timer].state |= TIMER_ENABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_Disable(): Disables a hardware timer
|
||||
* timer: timer to be disabled
|
||||
*/
|
||||
void Timer_Disable(uint32_t timer)
|
||||
{
|
||||
/* The timer has to be contained in a valid range */
|
||||
if (timer < NUM_TIMERS) {
|
||||
/* Timer has to be already initialized and enabled */
|
||||
if (Timers[timer].state == (TIMER_INITIALIZED | TIMER_ENABLED)) {
|
||||
/* Disable Timer */
|
||||
(Timers[timer].timerN)->CTRL = 0x0;
|
||||
/* Change timer state */
|
||||
Timers[timer].state = TIMER_INITIALIZED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_isEnabled(): verifies if a timer is enabled
|
||||
* timer: timer to be verified
|
||||
* @return: 0 disabled - 1 enabled
|
||||
*/
|
||||
uint32_t Timer_isEnabled(uint32_t timer)
|
||||
{
|
||||
/* The timer has to be contained in a valid range */
|
||||
if (timer < NUM_TIMERS) {
|
||||
/* Timer has to be already initialized and enabled */
|
||||
if (Timers[timer].state == (TIMER_INITIALIZED | TIMER_ENABLED)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_Read(): provides timer VALUE
|
||||
* timer: timer to be read
|
||||
* @return: timer VALUE us
|
||||
*/
|
||||
uint32_t Timer_Read(uint32_t timer)
|
||||
{
|
||||
uint32_t return_value = 0;
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
return_value = (Timers[timer].timerReload
|
||||
- (Timers[timer].timerN)->VALUE) / TIMER_TICKS_US;
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_SetInterrupt(): sets timer Interrupt
|
||||
* timer: timer on which interrupt is set
|
||||
* time_us: reloading time in us
|
||||
*/
|
||||
void Timer_SetInterrupt(uint32_t timer, uint32_t time_us)
|
||||
{
|
||||
uint32_t load_time_us = 0;
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
/* Disable Timer */
|
||||
Timer_Disable(timer);
|
||||
/* Enable Interrupt */
|
||||
(Timers[timer].timerN)->CTRL = CMSDK_TIMER_CTRL_IRQEN_Msk;
|
||||
|
||||
/* Check time us condition */
|
||||
if (time_us == TIMER_DEFAULT_RELOAD) {
|
||||
load_time_us = TIMER_MAX_VALUE;
|
||||
} else {
|
||||
load_time_us = time_us * TIMER_TICKS_US;
|
||||
}
|
||||
|
||||
/* Initialize Timer Value */
|
||||
Timers[timer].timerReload = load_time_us;
|
||||
(Timers[timer].timerN)->RELOAD = Timers[timer].timerReload;
|
||||
(Timers[timer].timerN)->VALUE = Timers[timer].timerReload;
|
||||
/* Enable Counter */
|
||||
(Timers[timer].timerN)->CTRL |= CMSDK_TIMER_CTRL_EN_Msk;
|
||||
/* Change timer state */
|
||||
Timers[timer].state |= TIMER_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_DisableInterrupt(): disables timer interrupt
|
||||
* timer: timer on which interrupt is disabled
|
||||
*/
|
||||
void Timer_DisableInterrupt(uint32_t timer)
|
||||
{
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
/* Disable Interrupt */
|
||||
(Timers[timer].timerN)->CTRL &= CMSDK_TIMER_CTRL_EN_Msk;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_ClearInterrupt(): clear timer interrupt
|
||||
* timer: timer on which interrupt needs to be cleared
|
||||
*/
|
||||
void Timer_ClearInterrupt(uint32_t timer)
|
||||
{
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
/* Clear Interrupt */
|
||||
(Timers[timer].timerN)->INTCLEAR = CMSDK_TIMER_INTCLEAR_Msk;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_GetIRQn(): returns IRQn of a Timer
|
||||
* timer: timer on which IRQn is defined - 0 if it is not defined
|
||||
*/
|
||||
uint32_t Timer_GetIRQn(uint32_t timer)
|
||||
{
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
return Timers[timer].timerIRQn;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_GetTicksUS(): returns the number of Ticks per us
|
||||
* timer: timer associated with the Ticks per us
|
||||
* @return: Ticks per us - 0 if the timer is disables
|
||||
*/
|
||||
uint32_t Timer_GetTicksUS(uint32_t timer)
|
||||
{
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
return TIMER_TICKS_US;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer_GetReloadValue(): returns the load value of the selected
|
||||
* timer.
|
||||
* timer: timer associated with the Ticks per us
|
||||
* @return: reload value of the selected singletimer
|
||||
*/
|
||||
uint32_t Timer_GetReloadValue(uint32_t timer)
|
||||
{
|
||||
/* Verify if the Timer is enabled */
|
||||
if (Timer_isEnabled(timer) == 1) {
|
||||
if (timer == TIMER1) {
|
||||
return Timers[timer].timerReload / TIMER_TICKS_US;
|
||||
} else {
|
||||
return Timers[timer].timerReload / TIMER_TICKS_US;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2016 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.
|
||||
*/
|
||||
|
||||
/* This file is derivative of apb_timer.h from BEETLE */
|
||||
|
||||
#ifndef _APB_TIMER_DRV_H
|
||||
#define _APB_TIMER_DRV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Supported Number of Timers */
|
||||
#define NUM_TIMERS 2
|
||||
#define TIMER0 0
|
||||
#define TIMER1 1
|
||||
|
||||
/* Default reload */
|
||||
#define TIMER_DEFAULT_RELOAD 0xFFFFFFFF
|
||||
|
||||
/*
|
||||
* Timer_Initialize(): Initializes an hardware timer
|
||||
* timer: timer to be Initialized
|
||||
* time_us: timer reload value in us - 0 to reload to timer max value
|
||||
* time_us = tick_value / TIMER_TICK_US
|
||||
*/
|
||||
void Timer_Initialize(uint32_t timer, uint32_t time_us);
|
||||
|
||||
/*
|
||||
* Timer_Enable(): Enables an hardware timer
|
||||
* timer: timer to be enabled
|
||||
*/
|
||||
void Timer_Enable(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_Disable(): Disables an hardware timer
|
||||
* timer: timer to be disabled
|
||||
*/
|
||||
void Timer_Disable(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_isEnabled(): verifies if a timer is enabled
|
||||
* timer: timer to be verified
|
||||
* @return: 0 disabled - 1 enabled
|
||||
*/
|
||||
uint32_t Timer_isEnabled(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_Read(): provides timer VALUE
|
||||
* timer: timer to be read
|
||||
* @return: timer VALUE
|
||||
*/
|
||||
uint32_t Timer_Read(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_SetInterrupt(): sets timer Interrupt
|
||||
* timer: timer on which interrupt is set
|
||||
* time_us: reloading time in us
|
||||
*/
|
||||
void Timer_SetInterrupt(uint32_t timer, uint32_t time_us);
|
||||
|
||||
/*
|
||||
* Timer_DisableInterrupt(): disables timer interrupt
|
||||
* timer: timer on which interrupt is disabled
|
||||
*/
|
||||
void Timer_DisableInterrupt(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_ClearInterrupt(): clear timer interrupt
|
||||
* timer: timer on which interrupt needs to be cleared
|
||||
*/
|
||||
void Timer_ClearInterrupt(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_GetIRQn(): returns IRQn of a Timer
|
||||
* timer: timer on which IRQn is defined - 0 if it is not defined
|
||||
*/
|
||||
uint32_t Timer_GetIRQn(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_GetTicksUS(): returns the number of Ticks per us
|
||||
* timer: timer associated with the Ticks per us
|
||||
* @return: Ticks per us - 0 if the timer is disables
|
||||
*/
|
||||
uint32_t Timer_GetTicksUS(uint32_t timer);
|
||||
|
||||
/*
|
||||
* Timer_GetReloadValue(): returns the load value of the selected
|
||||
* timer.
|
||||
* timer: timer associated with the Ticks per us
|
||||
* @return: reload value of the selected singletimer
|
||||
*/
|
||||
uint32_t Timer_GetReloadValue(uint32_t timer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _APB_TIMER_DRV_H */
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2015-2017 ARM Limited
|
||||
* Copyright (c) 2015-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -25,7 +25,5 @@
|
|||
#include "SMM_MPS2.h"
|
||||
/* NVIC Driver */
|
||||
#include "cmsis_nvic.h"
|
||||
/* APB Timer */
|
||||
#include "apb_timer.h"
|
||||
|
||||
#endif /* MBED_CMSIS_H */
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2018 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 __ARM_LTD_DEVICE_CFG_H__
|
||||
#define __ARM_LTD_DEVICE_CFG_H__
|
||||
|
||||
/**
|
||||
* \file device_cfg.h
|
||||
* \brief
|
||||
* This is the default device configuration file with all peripherals
|
||||
* defined and configured to be used via the non-secure base address.
|
||||
* This file is an example of how to define your own configuration file
|
||||
* with the peripherals required for your application.
|
||||
*/
|
||||
|
||||
/* CMSDK Timers */
|
||||
#define ARM_CMSDK_TIMER0
|
||||
#define ARM_CMSDK_TIMER1
|
||||
|
||||
/* ARM GPIO */
|
||||
#define ARM_GPIO0
|
||||
#define ARM_GPIO1
|
||||
#define ARM_GPIO2
|
||||
#define ARM_GPIO3
|
||||
|
||||
/* ARM MPS2 IO FPGAIO */
|
||||
#define ARM_MPS2_IO_FPGAIO
|
||||
|
||||
/* ARM MPS2 IO SCC */
|
||||
#define ARM_MPS2_IO_SCC
|
||||
|
||||
/* ARM SPI PL022 */
|
||||
#define DEFAULT_SPI_SPEED_HZ 4000000U /* 4MHz */
|
||||
#define ARM_SPI0
|
||||
#define ARM_SPI1
|
||||
#define ARM_SPI2
|
||||
#define ARM_SPI3
|
||||
#define ARM_SPI4
|
||||
|
||||
/* ARM UART */
|
||||
#define DEFAULT_UART_BAUDRATE 9600
|
||||
#define ARM_UART0
|
||||
#define ARM_UART1
|
||||
#define ARM_UART2
|
||||
#define ARM_UART3
|
||||
#define ARM_UART4
|
||||
|
||||
#endif /* __ARM_LTD_DEVICE_CFG_H__ */
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "arm_gpio_drv.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* GPIO state definitions */
|
||||
#define ARM_GPIO_INITIALIZED (1 << 0)
|
||||
|
||||
#define MAX_PIN_NBR 16
|
||||
|
||||
/* GPIO register map structure */
|
||||
struct arm_gpio_reg_map_t {
|
||||
volatile uint32_t data; /* Offset: 0x000 (R/W) Data register */
|
||||
volatile uint32_t dataout; /* Offset: 0x004 (R/W) Data output
|
||||
* latch register */
|
||||
volatile uint32_t reserved0[2];
|
||||
volatile uint32_t outenableset; /* Offset: 0x010 (R/W) Output enable
|
||||
* set register */
|
||||
volatile uint32_t outenableclr; /* Offset: 0x014 (R/W) Output enable
|
||||
* clear register */
|
||||
volatile uint32_t altfuncset; /* Offset: 0x018 (R/W) Alternate function
|
||||
* set register */
|
||||
volatile uint32_t altfuncclr; /* Offset: 0x01C (R/W) Alternate function
|
||||
* clear register */
|
||||
volatile uint32_t intenset; /* Offset: 0x020 (R/W) Interrupt enable
|
||||
* set register */
|
||||
volatile uint32_t intenclr; /* Offset: 0x024 (R/W) Interrupt enable
|
||||
* clear register */
|
||||
volatile uint32_t inttypeset; /* Offset: 0x028 (R/W) Interrupt type
|
||||
* set register */
|
||||
volatile uint32_t inttypeclr; /* Offset: 0x02C (R/W) Interrupt type
|
||||
* clear register */
|
||||
volatile uint32_t intpolset; /* Offset: 0x030 (R/W) Interrupt polarity
|
||||
* set register */
|
||||
volatile uint32_t intpolclr; /* Offset: 0x034 (R/W) Interrupt polarity
|
||||
* clear register */
|
||||
union {
|
||||
volatile uint32_t intstatus; /* Offset: 0x038 (R/ ) Interrupt status
|
||||
* register */
|
||||
volatile uint32_t intclear; /* Offset: 0x038 ( /W) Interrupt clear
|
||||
* register */
|
||||
}intreg;
|
||||
volatile uint32_t reserved1[241];
|
||||
volatile uint32_t lb_masked[256]; /* Offset: 0x400 - 0x7FC (R/W)
|
||||
* Lower byte masked access register */
|
||||
volatile uint32_t ub_masked[256]; /* Offset: 0x800 - 0xBFC (R/W)
|
||||
* Upper byte masked access register */
|
||||
};
|
||||
|
||||
/*
|
||||
* \brief Configures the pin or port.
|
||||
*
|
||||
* \param[in] p_gpio_port GPIO port to configure \ref ahbarm_gpio_reg_map_t
|
||||
* \param[in] mask Pin bit mask.
|
||||
* \param[in] flags Pin flags.
|
||||
*/
|
||||
static void set_port_config(struct arm_gpio_reg_map_t* p_gpio_port,
|
||||
uint32_t mask,
|
||||
uint32_t flags)
|
||||
{
|
||||
if(flags & ARM_GPIO_PIN_DISABLE) {
|
||||
p_gpio_port->altfuncset = mask;
|
||||
return;
|
||||
}
|
||||
|
||||
if(flags & ARM_GPIO_OUTPUT) {
|
||||
p_gpio_port->outenableset = mask;
|
||||
} else if(flags & ARM_GPIO_INPUT) {
|
||||
p_gpio_port->outenableclr = mask;
|
||||
}
|
||||
|
||||
/* Sets interrupt configuration */
|
||||
if(flags & ARM_GPIO_IRQ) {
|
||||
/* Interrupt type: EDGE = 1 - LEVEL = 0 */
|
||||
if(flags & ARM_GPIO_IRQ_EDGE) {
|
||||
p_gpio_port->inttypeset = mask;
|
||||
} else if(flags & ARM_GPIO_IRQ_LEVEL) {
|
||||
p_gpio_port->inttypeclr = mask;
|
||||
}
|
||||
|
||||
/* Interrupt polarity */
|
||||
if(flags & ARM_GPIO_IRQ_ACTIVE_LOW) {
|
||||
p_gpio_port->intpolclr = mask;
|
||||
} else if(flags & ARM_GPIO_IRQ_ACTIVE_HIGH) {
|
||||
p_gpio_port->intpolset = mask;
|
||||
}
|
||||
}
|
||||
|
||||
if(flags & ARM_GPIO_PIN_ENABLE) {
|
||||
p_gpio_port->altfuncclr = mask;
|
||||
}
|
||||
}
|
||||
|
||||
void arm_gpio_init(struct arm_gpio_dev_t* dev)
|
||||
{
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state != ARM_GPIO_INITIALIZED) {
|
||||
/* Disables all pins in this port */
|
||||
set_port_config(p_gpio_port, DEFAULT_PORT_MASK, ARM_GPIO_PIN_DISABLE);
|
||||
|
||||
dev->data->port_mask = DEFAULT_PORT_MASK;
|
||||
dev->data->state = ARM_GPIO_INITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
enum arm_gpio_error_t arm_gpio_config(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t flags)
|
||||
{
|
||||
uint32_t pin_mask;
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state != ARM_GPIO_INITIALIZED) {
|
||||
return ARM_GPIO_ERR_PORT_NOT_INIT;
|
||||
}
|
||||
|
||||
if(pin_num >= MAX_PIN_NBR) {
|
||||
return ARM_GPIO_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
switch(access) {
|
||||
case ARM_GPIO_ACCESS_PIN:
|
||||
pin_mask = (1UL << pin_num);
|
||||
set_port_config(p_gpio_port, pin_mask, flags);
|
||||
break;
|
||||
case ARM_GPIO_ACCESS_PORT:
|
||||
set_port_config(p_gpio_port, dev->data->port_mask, flags);
|
||||
break;
|
||||
/* default: The default is not defined intentionally to force the
|
||||
* compiler to check that all the enumeration values are
|
||||
* covered in the switch.*/
|
||||
}
|
||||
|
||||
return ARM_GPIO_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_gpio_error_t arm_gpio_write(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t value)
|
||||
{
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(pin_num >= MAX_PIN_NBR) {
|
||||
return ARM_GPIO_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* As ARM is a read-modify-write architecture, before set a
|
||||
* value on a GPIO register it is required to disable the
|
||||
* interrupts to prevent problems in a multitasking
|
||||
* environment */
|
||||
switch(access) {
|
||||
case ARM_GPIO_ACCESS_PIN:
|
||||
if(value) {
|
||||
/* Sets the pin */
|
||||
p_gpio_port->dataout |= (1UL << pin_num);
|
||||
} else {
|
||||
/* Clears the pin */
|
||||
p_gpio_port->dataout &= ~(1UL << pin_num);
|
||||
}
|
||||
break;
|
||||
case ARM_GPIO_ACCESS_PORT:
|
||||
if(value) {
|
||||
/* Sets masked pins */
|
||||
p_gpio_port->dataout |= dev->data->port_mask;
|
||||
} else {
|
||||
/* Clears masked pins */
|
||||
p_gpio_port->dataout &= ~(dev->data->port_mask);
|
||||
}
|
||||
break;
|
||||
/* default: The default is not defined intentionally to force the
|
||||
* compiler to check that all the enumeration values are
|
||||
* covered in the switch. */
|
||||
}
|
||||
|
||||
return ARM_GPIO_ERR_NONE;
|
||||
}
|
||||
|
||||
int32_t arm_gpio_read(struct arm_gpio_dev_t* dev, enum arm_gpio_access_t access,
|
||||
uint8_t pin_num)
|
||||
{
|
||||
uint32_t value;
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
value = p_gpio_port->data;
|
||||
|
||||
if(access == ARM_GPIO_ACCESS_PIN) {
|
||||
if(pin_num >= MAX_PIN_NBR) {
|
||||
return -1;
|
||||
}
|
||||
value = ((value >> pin_num) & 1UL);
|
||||
} else {
|
||||
value &= dev->data->port_mask;
|
||||
}
|
||||
|
||||
return (int32_t)value;
|
||||
}
|
||||
|
||||
enum arm_gpio_error_t arm_gpio_set_interrupt(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
enum arm_gpio_irq_status_t status)
|
||||
{
|
||||
uint32_t mask = 0;
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state != ARM_GPIO_INITIALIZED) {
|
||||
return ARM_GPIO_ERR_PORT_NOT_INIT;
|
||||
}
|
||||
|
||||
if(pin_num >= MAX_PIN_NBR) {
|
||||
return ARM_GPIO_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
switch(access) {
|
||||
case ARM_GPIO_ACCESS_PIN:
|
||||
mask = (1UL << pin_num);
|
||||
break;
|
||||
case ARM_GPIO_ACCESS_PORT:
|
||||
mask = dev->data->port_mask;
|
||||
break;
|
||||
/* default: The default is not defined intentionally to force the
|
||||
* compiler to check that all the enumeration values are
|
||||
* covered in the switch.*/
|
||||
}
|
||||
|
||||
if(status == ARM_GPIO_IRQ_ENABLE) {
|
||||
p_gpio_port->intenset = mask;
|
||||
} else {
|
||||
p_gpio_port->intenclr = mask;
|
||||
}
|
||||
|
||||
return ARM_GPIO_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_gpio_error_t arm_gpio_get_irq_status(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t* status)
|
||||
{
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state != ARM_GPIO_INITIALIZED) {
|
||||
return ARM_GPIO_ERR_PORT_NOT_INIT;
|
||||
}
|
||||
|
||||
if(pin_num >= MAX_PIN_NBR) {
|
||||
return ARM_GPIO_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*status = p_gpio_port->intreg.intstatus;
|
||||
|
||||
if(access == ARM_GPIO_ACCESS_PIN) {
|
||||
*status = ((*status >> pin_num) & 1UL);
|
||||
} else {
|
||||
*status &= dev->data->port_mask;
|
||||
}
|
||||
|
||||
return ARM_GPIO_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_gpio_error_t arm_gpio_clear_interrupt(struct arm_gpio_dev_t* dev,
|
||||
uint8_t pin_num)
|
||||
{
|
||||
struct arm_gpio_reg_map_t* p_gpio_port =
|
||||
(struct arm_gpio_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state != ARM_GPIO_INITIALIZED) {
|
||||
return ARM_GPIO_ERR_PORT_NOT_INIT;
|
||||
}
|
||||
|
||||
if(pin_num >= MAX_PIN_NBR) {
|
||||
return ARM_GPIO_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
p_gpio_port->intreg.intstatus = (1UL << pin_num);
|
||||
|
||||
return ARM_GPIO_ERR_NONE;
|
||||
}
|
||||
|
||||
void arm_gpio_set_port_mask(struct arm_gpio_dev_t* dev, uint32_t port_mask)
|
||||
{
|
||||
dev->data->port_mask = (port_mask & DEFAULT_PORT_MASK);
|
||||
}
|
||||
|
||||
uint32_t arm_gpio_get_port_mask(struct arm_gpio_dev_t* dev)
|
||||
{
|
||||
if(dev->data->state != ARM_GPIO_INITIALIZED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (dev->data->port_mask & DEFAULT_PORT_MASK);
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file arm_gpio_drv.h
|
||||
* \brief Generic driver for ARM GPIO.
|
||||
*/
|
||||
|
||||
#ifndef __ARM_GPIO_DRV_H__
|
||||
#define __ARM_GPIO_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DEFAULT_PORT_MASK 0xFFFF /* Default port mask */
|
||||
|
||||
/* GPIO flags */
|
||||
#define ARM_GPIO_PIN_DISABLE (1 << 0)
|
||||
#define ARM_GPIO_PIN_ENABLE (1 << 1)
|
||||
#define ARM_GPIO_OUTPUT (1 << 2)
|
||||
#define ARM_GPIO_INPUT (1 << 3)
|
||||
#define ARM_GPIO_IRQ (1 << 4)
|
||||
#define ARM_GPIO_IRQ_EDGE (1 << 5)
|
||||
#define ARM_GPIO_IRQ_LEVEL (1 << 6)
|
||||
#define ARM_GPIO_IRQ_ACTIVE_LOW (1 << 7)
|
||||
#define ARM_GPIO_IRQ_ACTIVE_HIGH (1 << 8)
|
||||
|
||||
/* ARM GPIO enumeration types */
|
||||
enum arm_gpio_access_t {
|
||||
ARM_GPIO_ACCESS_PIN = 0, /*!< Pin access to GPIO */
|
||||
ARM_GPIO_ACCESS_PORT /*!< Port access to GPIO */
|
||||
};
|
||||
|
||||
enum arm_gpio_irq_status_t {
|
||||
ARM_GPIO_IRQ_DISABLE = 0, /*!< Disable interruptions */
|
||||
ARM_GPIO_IRQ_ENABLE /*!< Enable interruptions */
|
||||
};
|
||||
|
||||
enum arm_gpio_error_t {
|
||||
ARM_GPIO_ERR_NONE = 0, /*!< No error */
|
||||
ARM_GPIO_ERR_INVALID_ARG, /*!< Error invalid input argument */
|
||||
ARM_GPIO_ERR_PORT_NOT_INIT /*!< Error GPIO port not initialized */
|
||||
};
|
||||
|
||||
/* ARM GPIO device configuration structure */
|
||||
struct arm_gpio_dev_cfg_t {
|
||||
const uint32_t base; /*!< GPIO base address */
|
||||
};
|
||||
|
||||
/* ARM GPIO device data structure */
|
||||
struct arm_gpio_dev_data_t {
|
||||
uint32_t state; /*!< Indicates if the gpio driver
|
||||
is initialized and enabled */
|
||||
uint32_t port_mask; /*!< Port mask used for any port access */
|
||||
};
|
||||
|
||||
/* ARM GPIO device structure */
|
||||
struct arm_gpio_dev_t {
|
||||
const struct arm_gpio_dev_cfg_t* const cfg; /*!< GPIO configuration */
|
||||
struct arm_gpio_dev_data_t* const data; /*!< GPIO data */
|
||||
};
|
||||
|
||||
/* ARM GPIO pin structure */
|
||||
struct arm_gpio_pin_t {
|
||||
uint32_t number; /*!< Pin number */
|
||||
enum arm_gpio_access_t access_type; /*!< Type of access in the
|
||||
GPIO block */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Initializes GPIO port.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_gpio_init(struct arm_gpio_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Configurates pin or port.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
* \param[in] access Access type \ref arm_gpio_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
* \param[in] flags Pin flags \ref arm_gpio_flags_t
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_gpio_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_gpio_error_t arm_gpio_config(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t flags);
|
||||
|
||||
/**
|
||||
* \brief Writes to output pin or port.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
* \param[in] access Access type \ref arm_gpio_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
* \param[in] value Value(s) to set.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_gpio_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
* \note As ARM is a read-modify-write architecture, before writing a
|
||||
* value on a GPIO pin it is required to disable the
|
||||
* interrupts to prevent problems in a multitasking
|
||||
* environment.
|
||||
*/
|
||||
enum arm_gpio_error_t arm_gpio_write(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t value);
|
||||
|
||||
/**
|
||||
* \brief Reads the pin or port status.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
* \param[in] access Access type \ref arm_gpio_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
* \param[in] value Value of input pin(s).
|
||||
*
|
||||
* \return Returns bit value for Pin access or port value for port access.
|
||||
* Negative value for error.
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
int32_t arm_gpio_read(struct arm_gpio_dev_t* dev, enum arm_gpio_access_t access,
|
||||
uint8_t pin_num);
|
||||
|
||||
/**
|
||||
* \brief Sets interrupt status for the given pin or port.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
* \param[in] access Access type \ref arm_gpio_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
* \param[in] status Interrupt status \ref arm_gpio_irq_status
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_gpio_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_gpio_error_t arm_gpio_set_interrupt(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
enum arm_gpio_irq_status_t status);
|
||||
|
||||
/**
|
||||
* \brief Gets interrupt status for the given pin or port.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
* \param[in] access Access type \ref arm_gpio_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
* \param[out] status Interrupt status values. If the access is by pin, then
|
||||
* the status will be 0 or 1.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_gpio_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_gpio_error_t arm_gpio_get_irq_status(struct arm_gpio_dev_t* dev,
|
||||
enum arm_gpio_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t* status);
|
||||
|
||||
/**
|
||||
* \brief Clears gpio interrupt.
|
||||
*
|
||||
* \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t
|
||||
* \param[in] pin_num Pin number.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_gpio_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_gpio_error_t arm_gpio_clear_interrupt(struct arm_gpio_dev_t* dev,
|
||||
uint8_t pin_num);
|
||||
|
||||
/**
|
||||
* \brief Sets gpio mask for port access.
|
||||
*
|
||||
* \param[in] dev GPIO port \ref arm_gpio_dev_t
|
||||
* \param[in] port_mask New port mask to set, only the 16 LSb are taken into
|
||||
* account
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_gpio_set_port_mask(struct arm_gpio_dev_t* dev, uint32_t port_mask);
|
||||
|
||||
/**
|
||||
* \brief Gets gpio mask for port access.
|
||||
*
|
||||
* \param[in] dev GPIO port \ref arm_gpio_dev_t
|
||||
*
|
||||
* \return Returns the current port mask
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_gpio_get_port_mask(struct arm_gpio_dev_t* dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __ARM_GPIO_DRV_H__ */
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "arm_mps2_io_drv.h"
|
||||
|
||||
/* There is at most 8 LEDs and switches on MPS2 SCC and 2 on FPGA IO */
|
||||
#define MAX_PIN_NBR_SCC 8
|
||||
#define MAX_PIN_NBR_FPGAIO 2
|
||||
|
||||
/* Mask to 1 the first X bits */
|
||||
#define MASK(X) ((1 << (X)) - 1)
|
||||
|
||||
/* MPS2 IO register map structure */
|
||||
struct arm_mps2_io_reg_map_t {
|
||||
union {
|
||||
volatile uint32_t scc_leds; /* Offset: 0x000 (R/W) Controls the MCC
|
||||
* user LEDs
|
||||
* [31:8] : Reserved
|
||||
* [7:0] : MCC LEDs */
|
||||
volatile uint32_t fpgaio_leds; /* Offset: 0x000 (R/W) LED connections
|
||||
* [31:2] : Reserved
|
||||
* [1:0] : FPGAIO LEDs */
|
||||
} led_reg;
|
||||
volatile uint32_t reserved[1];
|
||||
union {
|
||||
volatile uint32_t scc_switches; /* Offset: 0x008 (R/ ) Denotes the
|
||||
* state of the MCC
|
||||
* user switches
|
||||
* [31:8] : Reserved
|
||||
* [7:0] : State of the MCC
|
||||
* switches */
|
||||
volatile uint32_t fpgaio_buttons;/* Offset: 0x008 (R/ ) Buttons
|
||||
* [31:2] : Reserved
|
||||
* [1:0] : Buttons */
|
||||
} button_reg;
|
||||
};
|
||||
|
||||
void arm_mps2_io_write_leds(struct arm_mps2_io_dev_t* dev,
|
||||
enum arm_mps2_io_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t value)
|
||||
{
|
||||
struct arm_mps2_io_reg_map_t* p_mps2_io_port =
|
||||
(struct arm_mps2_io_reg_map_t*)dev->cfg->base;
|
||||
/* Mask of involved bits */
|
||||
uint32_t write_mask = 0;
|
||||
|
||||
switch (dev->cfg->type) {
|
||||
case ARM_MPS2_IO_TYPE_SCC:
|
||||
if (pin_num >= MAX_PIN_NBR_SCC) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (access) {
|
||||
case ARM_MPS2_IO_ACCESS_PIN:
|
||||
write_mask = (1UL << pin_num);
|
||||
break;
|
||||
case ARM_MPS2_IO_ACCESS_PORT:
|
||||
write_mask = MASK(MAX_PIN_NBR_SCC);
|
||||
break;
|
||||
/*
|
||||
* default: explicitely not used to force to cover all enumeration
|
||||
* cases
|
||||
*/
|
||||
}
|
||||
|
||||
if (value) {
|
||||
p_mps2_io_port->led_reg.scc_leds |= write_mask;
|
||||
} else {
|
||||
p_mps2_io_port->led_reg.scc_leds &= ~write_mask;
|
||||
}
|
||||
|
||||
break;
|
||||
case ARM_MPS2_IO_TYPE_FPGAIO:
|
||||
if (pin_num >= MAX_PIN_NBR_FPGAIO) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (access) {
|
||||
case ARM_MPS2_IO_ACCESS_PIN:
|
||||
write_mask = (1UL << pin_num);
|
||||
break;
|
||||
case ARM_MPS2_IO_ACCESS_PORT:
|
||||
write_mask = MASK(MAX_PIN_NBR_FPGAIO);
|
||||
break;
|
||||
/*
|
||||
* default: explicitely not used to force to cover all enumeration
|
||||
* cases
|
||||
*/
|
||||
}
|
||||
|
||||
if (value) {
|
||||
p_mps2_io_port->led_reg.fpgaio_leds |= write_mask;
|
||||
} else {
|
||||
p_mps2_io_port->led_reg.fpgaio_leds &= ~write_mask;
|
||||
}
|
||||
|
||||
break;
|
||||
/* default: explicitely not used to force to cover all enumeration cases */
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t arm_mps2_io_read_buttons(struct arm_mps2_io_dev_t* dev,
|
||||
enum arm_mps2_io_access_t access,
|
||||
uint8_t pin_num)
|
||||
{
|
||||
struct arm_mps2_io_reg_map_t* p_mps2_io_port =
|
||||
(struct arm_mps2_io_reg_map_t*)dev->cfg->base;
|
||||
uint32_t value = 0;
|
||||
|
||||
switch (dev->cfg->type) {
|
||||
case ARM_MPS2_IO_TYPE_SCC:
|
||||
if (pin_num >= MAX_PIN_NBR_SCC) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only read significant bits from this register */
|
||||
value = p_mps2_io_port->button_reg.scc_switches & MASK(MAX_PIN_NBR_SCC);
|
||||
|
||||
break;
|
||||
case ARM_MPS2_IO_TYPE_FPGAIO:
|
||||
if (pin_num >= MAX_PIN_NBR_FPGAIO) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only read significant bits from this register */
|
||||
value = p_mps2_io_port->button_reg.fpgaio_buttons &
|
||||
MASK(MAX_PIN_NBR_FPGAIO);
|
||||
|
||||
break;
|
||||
/* default: explicitely not used to force to cover all enumeration cases */
|
||||
}
|
||||
|
||||
if (access == ARM_MPS2_IO_ACCESS_PIN) {
|
||||
value = ((value >> pin_num) & 1UL);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t arm_mps2_io_read_leds(struct arm_mps2_io_dev_t* dev,
|
||||
enum arm_mps2_io_access_t access,
|
||||
uint8_t pin_num)
|
||||
{
|
||||
struct arm_mps2_io_reg_map_t* p_mps2_io_port =
|
||||
(struct arm_mps2_io_reg_map_t*)dev->cfg->base;
|
||||
uint32_t value = 0;
|
||||
|
||||
switch (dev->cfg->type) {
|
||||
case ARM_MPS2_IO_TYPE_SCC:
|
||||
if (pin_num >= MAX_PIN_NBR_SCC) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only read significant bits from this register */
|
||||
value = p_mps2_io_port->led_reg.scc_leds & MASK(MAX_PIN_NBR_SCC);
|
||||
|
||||
break;
|
||||
case ARM_MPS2_IO_TYPE_FPGAIO:
|
||||
if (pin_num >= MAX_PIN_NBR_FPGAIO) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only read significant bits from this register */
|
||||
value = p_mps2_io_port->led_reg.fpgaio_leds & MASK(MAX_PIN_NBR_FPGAIO);
|
||||
|
||||
break;
|
||||
/* default: explicitely not used to force to cover all enumeration cases */
|
||||
}
|
||||
|
||||
if (access == ARM_MPS2_IO_ACCESS_PIN) {
|
||||
value = ((value >> pin_num) & 1UL);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2018 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file arm_mps2_io_drv.h
|
||||
* \brief Generic driver for ARM MPS2 IO.
|
||||
*/
|
||||
|
||||
#ifndef __ARM_MPS2_IO_DRV_H__
|
||||
#define __ARM_MPS2_IO_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ARM MPS2 IO enumeration types */
|
||||
enum arm_mps2_io_access_t {
|
||||
ARM_MPS2_IO_ACCESS_PIN = 0, /*!< Pin access to MPS2 IO */
|
||||
ARM_MPS2_IO_ACCESS_PORT /*!< Port access to MPS2 IO */
|
||||
};
|
||||
|
||||
enum arm_mps2_io_type_t {
|
||||
ARM_MPS2_IO_TYPE_SCC = 0, /*!< Use the SCC IO device */
|
||||
ARM_MPS2_IO_TYPE_FPGAIO /*!< Use the FPGA IO device */
|
||||
};
|
||||
|
||||
/* ARM MPS2 IO device configuration structure */
|
||||
struct arm_mps2_io_dev_cfg_t {
|
||||
const uint32_t base; /*!< MPS2 IO base address */
|
||||
const enum arm_mps2_io_type_t type; /*!< SCC or FPGAIO */
|
||||
};
|
||||
|
||||
/* ARM MPS2 IO device structure */
|
||||
struct arm_mps2_io_dev_t {
|
||||
const struct arm_mps2_io_dev_cfg_t* const cfg; /*!< MPS2 IO configuration */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Writes to output LEDs.
|
||||
*
|
||||
* \param[in] dev MPS2 IO device where to write \ref arm_mps2_io_dev_t
|
||||
* \param[in] access Access type \ref arm_mps2_io_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
* \param[in] value Value(s) to set.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_mps2_io_write_leds(struct arm_mps2_io_dev_t* dev,
|
||||
enum arm_mps2_io_access_t access,
|
||||
uint8_t pin_num,
|
||||
uint32_t value);
|
||||
|
||||
/**
|
||||
* \brief Reads the buttons status.
|
||||
*
|
||||
* \param[in] dev MPS2 IO device where to read \ref arm_mps2_io_dev_t
|
||||
* \param[in] access Access type \ref arm_mps2_io_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
*
|
||||
* \return Returns bit value for Pin access or port value for port access.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_mps2_io_read_buttons(struct arm_mps2_io_dev_t* dev,
|
||||
enum arm_mps2_io_access_t access,
|
||||
uint8_t pin_num);
|
||||
|
||||
/**
|
||||
* \brief Reads the LED status.
|
||||
*
|
||||
* \param[in] dev MPS2 IO device where to read \ref arm_mps2_io_dev_t
|
||||
* \param[in] access Access type \ref arm_mps2_io_access_t
|
||||
* \param[in] pin_num Pin number.
|
||||
*
|
||||
* \return Returns bit value for Pin access or port value for port access.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_mps2_io_read_leds(struct arm_mps2_io_dev_t* dev,
|
||||
enum arm_mps2_io_access_t access,
|
||||
uint8_t pin_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ARM_MPS2_IO_DRV_H__ */
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "arm_uart_drv.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* UART register map structure */
|
||||
struct _arm_uart_reg_map_t {
|
||||
volatile uint32_t data; /* Offset: 0x000 (R/W) data register */
|
||||
volatile uint32_t state; /* Offset: 0x004 (R/W) status register */
|
||||
volatile uint32_t ctrl; /* Offset: 0x008 (R/W) control register */
|
||||
union {
|
||||
volatile uint32_t intrstatus; /* Offset: 0x00c (R/ ) interrupt status
|
||||
* register */
|
||||
volatile uint32_t intrclear; /* Offset: 0x00c ( /W) interrupt clear
|
||||
* register */
|
||||
}intr_reg;
|
||||
volatile uint32_t bauddiv; /* Offset: 0x010 (R/W) Baudrate divider
|
||||
* register */
|
||||
};
|
||||
|
||||
/* CTRL Register */
|
||||
#define ARM_UART_TX_EN (1ul << 0)
|
||||
#define ARM_UART_RX_EN (1ul << 1)
|
||||
#define ARM_UART_TX_INTR_EN (1ul << 2)
|
||||
#define ARM_UART_RX_INTR_EN (1ul << 3)
|
||||
|
||||
/* STATE Register */
|
||||
#define ARM_UART_TX_BF (1ul << 0)
|
||||
#define ARM_UART_RX_BF (1ul << 1)
|
||||
|
||||
/* INTSTATUS Register */
|
||||
#define ARM_UART_TX_INTR (1ul << 0)
|
||||
#define ARM_UART_RX_INTR (1ul << 1)
|
||||
|
||||
/* UART state definitions */
|
||||
#define ARM_UART_INITIALIZED (1ul << 0)
|
||||
|
||||
enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev,
|
||||
uint32_t system_clk)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
if(system_clk == 0) {
|
||||
return ARM_UART_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Sets baudrate and system clock */
|
||||
dev->data->system_clk = system_clk;
|
||||
dev->data->baudrate = dev->cfg->default_baudrate;
|
||||
|
||||
/* Sets baudrate */
|
||||
p_uart->bauddiv = (dev->data->system_clk / dev->cfg->default_baudrate);
|
||||
|
||||
/* Enables receiver and transmitter */
|
||||
p_uart->ctrl = ARM_UART_RX_EN | ARM_UART_TX_EN;
|
||||
|
||||
dev->data->state = ARM_UART_INITIALIZED;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev,
|
||||
uint32_t baudrate)
|
||||
{
|
||||
uint32_t bauddiv;
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(baudrate == 0) {
|
||||
return ARM_UART_ERR_INVALID_BAUD;
|
||||
}
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return ARM_UART_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
/* Sets baudrate */
|
||||
bauddiv = (dev->data->system_clk / baudrate);
|
||||
dev->data->baudrate = baudrate;
|
||||
|
||||
/* Minimum bauddiv value */
|
||||
if(bauddiv < 16) {
|
||||
return ARM_UART_ERR_INVALID_BAUD;
|
||||
}
|
||||
|
||||
p_uart->bauddiv = bauddiv;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
return dev->data->baudrate;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev,
|
||||
uint32_t system_clk)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(system_clk == 0) {
|
||||
return ARM_UART_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return ARM_UART_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
/* Sets system clock */
|
||||
dev->data->system_clk = system_clk;
|
||||
|
||||
/* Updates baudrate divider */
|
||||
p_uart->bauddiv = (dev->data->system_clk / dev->data->baudrate);
|
||||
|
||||
/* Enables receiver and transmitter */
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(p_uart->state & ARM_UART_RX_BF)) {
|
||||
return ARM_UART_ERR_NOT_READY;
|
||||
}
|
||||
|
||||
/* Reads data */
|
||||
*byte = (uint8_t)p_uart->data;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(p_uart->state & ARM_UART_TX_BF) {
|
||||
return ARM_UART_ERR_NOT_READY;
|
||||
}
|
||||
|
||||
/* Sends data */
|
||||
p_uart->data = byte;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return ARM_UART_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
p_uart->ctrl |= ARM_UART_TX_INTR_EN;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state & ARM_UART_INITIALIZED ) {
|
||||
p_uart->ctrl &= ~ARM_UART_TX_INTR_EN;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return !(p_uart->state & ARM_UART_TX_BF);
|
||||
}
|
||||
|
||||
enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return ARM_UART_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
p_uart->ctrl |= ARM_UART_RX_INTR_EN;
|
||||
|
||||
return ARM_UART_ERR_NONE;
|
||||
}
|
||||
|
||||
void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state & ARM_UART_INITIALIZED) {
|
||||
p_uart->ctrl &= ~ARM_UART_RX_INTR_EN;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & ARM_UART_INITIALIZED)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (p_uart->state & ARM_UART_RX_BF);
|
||||
}
|
||||
|
||||
void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev,
|
||||
enum arm_uart_irq_t irq)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if(dev->data->state & ARM_UART_INITIALIZED) {
|
||||
/* Clears pending interrupts */
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
p_uart->intr_reg.intrclear = ARM_UART_RX_INTR;
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
p_uart->intr_reg.intrclear = ARM_UART_TX_INTR;
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
p_uart->intr_reg.intrclear = (ARM_UART_RX_INTR | ARM_UART_TX_INTR);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
break;
|
||||
/* default: not defined to force all cases to be handled */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum arm_uart_irq_t arm_uart_get_interrupt_status(struct arm_uart_dev_t* dev)
|
||||
{
|
||||
struct _arm_uart_reg_map_t* p_uart =
|
||||
(struct _arm_uart_reg_map_t*)dev->cfg->base;
|
||||
|
||||
|
||||
if(dev->data->state & ARM_UART_INITIALIZED) {
|
||||
switch(p_uart->intr_reg.intrstatus) {
|
||||
case ARM_UART_TX_INTR:
|
||||
return ARM_UART_IRQ_TX;
|
||||
break;
|
||||
case ARM_UART_RX_INTR:
|
||||
return ARM_UART_IRQ_RX;
|
||||
break;
|
||||
case ARM_UART_TX_INTR | ARM_UART_RX_INTR:
|
||||
return ARM_UART_IRQ_COMBINED;
|
||||
break;
|
||||
/* default: not defined to force all cases to be handled */
|
||||
}
|
||||
}
|
||||
return ARM_UART_IRQ_NONE;
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file arm_uart_drv.h
|
||||
* \brief Generic driver for ARM UART.
|
||||
*/
|
||||
|
||||
#ifndef __ARM_UART_DRV_H__
|
||||
#define __ARM_UART_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ARM UART device configuration structure */
|
||||
struct arm_uart_dev_cfg_t {
|
||||
const uint32_t base; /*!< UART base address */
|
||||
const uint32_t default_baudrate; /*!< Default baudrate */
|
||||
};
|
||||
|
||||
/* ARM UART device data structure */
|
||||
struct arm_uart_dev_data_t {
|
||||
uint32_t state; /*!< Indicates if the uart driver
|
||||
is initialized and enabled */
|
||||
uint32_t system_clk; /*!< System clock */
|
||||
uint32_t baudrate; /*!< Baudrate */
|
||||
};
|
||||
|
||||
/* ARM UART device structure */
|
||||
struct arm_uart_dev_t {
|
||||
const struct arm_uart_dev_cfg_t* const cfg; /*!< UART configuration */
|
||||
struct arm_uart_dev_data_t* const data; /*!< UART data */
|
||||
};
|
||||
|
||||
/* ARM UART enumeration types */
|
||||
enum arm_uart_error_t {
|
||||
ARM_UART_ERR_NONE = 0, /*!< No error */
|
||||
ARM_UART_ERR_INVALID_ARG, /*!< Error invalid input argument */
|
||||
ARM_UART_ERR_INVALID_BAUD, /*!< Invalid baudrate */
|
||||
ARM_UART_ERR_NOT_INIT, /*!< Error UART not initialized */
|
||||
ARM_UART_ERR_NOT_READY, /*!< Error UART not ready */
|
||||
};
|
||||
|
||||
enum arm_uart_irq_t {
|
||||
ARM_UART_IRQ_RX, /*!< RX interrupt source */
|
||||
ARM_UART_IRQ_TX, /*!< TX interrupt source */
|
||||
ARM_UART_IRQ_COMBINED, /*!< RX-TX combined interrupt source */
|
||||
ARM_UART_IRQ_NONE = 0xFF /*!< RX-TX combined interrupt source */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Initializes UART. It uses the default baudrate to configure
|
||||
* the peripheral at this point.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] system_clk System clock used by the device.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev,
|
||||
uint32_t system_clk);
|
||||
|
||||
/**
|
||||
* \brief Sets the UART baudrate.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] baudrate New baudrate.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev,
|
||||
uint32_t baudrate);
|
||||
|
||||
/**
|
||||
* \brief Gets the UART baudrate.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return Returns the UART baudrate.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets system clock.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] system_clk System clock used by the device.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev,
|
||||
uint32_t system_clk);
|
||||
/**
|
||||
* \brief Reads one byte from UART dev.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] byte Pointer to byte.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note For better performance, this function doesn't check if dev and byte
|
||||
* pointer are NULL, and if the driver is initialized.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte);
|
||||
|
||||
/**
|
||||
* \brief Writes a byte to UART dev.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] byte Byte to write.
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note For better performance, this function doesn't check if dev is NULL and
|
||||
* if the driver is initialized to have better performance.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte);
|
||||
|
||||
/**
|
||||
* \brief Enables TX interrupt.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables TX interrupt.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Verifies if Tx is ready to send more data.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return 1 if TX is ready, 0 otherwise.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables RX interrupt.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return Returns error code as specified in \ref arm_uart_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables RX interrupt
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Verifies if Rx has data.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return 1 if RX has data, 0 otherwise.
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Clears UART interrupt.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
* \param[in] irq IRQ source to clean \ref arm_uart_irq_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev,
|
||||
enum arm_uart_irq_t irq);
|
||||
|
||||
/**
|
||||
* \brief Returns UART interrupt status.
|
||||
*
|
||||
* \param[in] dev UART device struct \ref arm_uart_dev_t
|
||||
*
|
||||
* \return IRQ status \ref arm_uart_irq_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum arm_uart_irq_t arm_uart_get_interrupt_status(struct arm_uart_dev_t* dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __ARM_UART_DRV_H__ */
|
|
@ -0,0 +1,870 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "spi_pl022_drv.h"
|
||||
|
||||
/******************************************************************************
|
||||
* PL022 device specific definitions based on DDI0194H_ssp_pl022_trm.pdf which
|
||||
* is available from infocenter.arm.com.
|
||||
*
|
||||
* This version of driver aims at necessary functionality for MPS2 board only
|
||||
*****************************************************************************/
|
||||
|
||||
/* Structure for the SSP Primary Cell device registers */
|
||||
struct spi_pl022_dev_reg_map_t {
|
||||
volatile uint32_t sspcr0; /* Control register 0 */
|
||||
volatile uint32_t sspcr1; /* Control register 1 */
|
||||
volatile uint32_t sspdr; /* Data register */
|
||||
volatile uint32_t sspsr; /* Status register */
|
||||
volatile uint32_t sspcpsr; /* Clock prescale register */
|
||||
volatile uint32_t sspimsc; /* Interrupt mask set or clear register */
|
||||
volatile uint32_t sspris; /* Raw interrupt status register */
|
||||
volatile uint32_t sspmis; /* Masked interrupt status register */
|
||||
volatile uint32_t sspicr; /* Interrupt clear register */
|
||||
volatile uint32_t sspdmacr; /* DMA control register */
|
||||
volatile uint32_t reserved[1006];/* Reserved from Base+0x28-0xFE0 */
|
||||
volatile uint32_t sspperiphid0; /* Peripheral id register 0 */
|
||||
volatile uint32_t sspperiphid1; /* Peripheral id register 1 */
|
||||
volatile uint32_t sspperiphid2; /* Peripheral id register 2 */
|
||||
volatile uint32_t sspperiphid3; /* Peripheral id register 3 */
|
||||
volatile uint32_t ssppcellid0; /* Primary cell id register 0 */
|
||||
volatile uint32_t ssppcellid1; /* Primary cell id register 1 */
|
||||
volatile uint32_t ssppcellid2; /* Primary cell id register 2 */
|
||||
volatile uint32_t ssppcellid3; /* Primary cell id register 3 */
|
||||
};
|
||||
|
||||
/*--- SSP Control Register 0 ---*/
|
||||
|
||||
/* Data Size Select {0x3=4 ... 0xF=16} */
|
||||
#define SPI_PL022_SSPCR0_DSS_POS 0
|
||||
#define SPI_PL022_SSPCR0_DSS_MSK 0xF
|
||||
|
||||
/* Frame format */
|
||||
#define SPI_PL022_SSPCR0_FRF_POS 4
|
||||
#define SPI_PL022_SSPCR0_FRF_MSK (0x3ul<<SPI_PL022_SSPCR0_FRF_POS)
|
||||
#define SPI_PL022_SSPCR0_FRF_MOT_SPI 0x0
|
||||
#define SPI_PL022_SSPCR0_FRF_TI_SS 0x1
|
||||
#define SPI_PL022_SSPCR0_FRF_MICROWIRE 0x2
|
||||
#define SPI_PL022_SSPCR0_FRF_RES 0x3
|
||||
|
||||
/* Clock polarity applicable to Motorola SPI format only */
|
||||
#define SPI_PL022_SSPCR0_SPO_POS 6
|
||||
#define SPI_PL022_SSPCR0_SPO_MSK (0x1ul<<SPI_PL022_SSPCR0_SPO_POS)
|
||||
|
||||
/* Clock phase applicable to Motorola SPI format only */
|
||||
#define SPI_PL022_SSPCR0_SPH_POS 7
|
||||
#define SPI_PL022_SSPCR0_SPH_MSK (0x1ul<<SPI_PL022_SSPCR0_SPH_POS)
|
||||
|
||||
/* Serial clock rate */
|
||||
#define SPI_PL022_SSPCR0_SCR_POS 8
|
||||
#define SPI_PL022_SSPCR0_SCR_MSK (0xFFul<<SPI_PL022_SSPCR0_SCR_POS)
|
||||
|
||||
/*--- SSP Control Register 1 ---*/
|
||||
|
||||
/* Loopback mode*/
|
||||
#define SPI_PL022_SSPCR1_LBM_POS 0
|
||||
#define SPI_PL022_SSPCR1_LBM_MSK (0x1ul<<SPI_PL022_SSPCR1_LBM_POS)
|
||||
|
||||
/* Syncrhonous serial port enable*/
|
||||
#define SPI_PL022_SSPCR1_SSE_POS 1
|
||||
#define SPI_PL022_SSPCR1_SSE_MSK (0x1ul<<SPI_PL022_SSPCR1_SSE_POS)
|
||||
|
||||
/* Master or Slave select */
|
||||
#define SPI_PL022_SSPCR1_MS_POS 2
|
||||
#define SPI_PL022_SSPCR1_MS_MSK (0x1ul<<SPI_PL022_SSPCR1_MS_POS)
|
||||
|
||||
/* Slave mode output disable */
|
||||
#define SPI_PL022_SSPCR1_SOD_POS 3
|
||||
#define SPI_PL022_SSPCR1_SOD_MSK (0x1ul<<SPI_PL022_SSPCR1_SOD_POS)
|
||||
|
||||
/*--- Clock PreScale Register ---*/
|
||||
|
||||
/* Divisor */
|
||||
#define SPI_PL022_SSPCPSR_CPSDVSR_POS 0
|
||||
#define SPI_PL022_SSPCPSR_CPSDVSR_MSK (0xFFul<<SPI_PL022_SSPCPSR_CPSDVSR_POS)
|
||||
#define SPI_PL022_INVALID_SSPCPSR_VALUE 0
|
||||
#define SPI_PL022_MIN_SSPCPSR_VALUE 2
|
||||
#define SPI_PL022_MAX_SSPCPSR_VALUE 254
|
||||
#define SPI_PL022_MAX_SCR_VALUE 255
|
||||
|
||||
|
||||
/*--- Interrupt Mask Set or Clear Register --- */
|
||||
|
||||
/* Receive Overrun Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RORIM_POS 0
|
||||
#define SPI_PL022_SSPIMSC_RORIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RORIM_POS)
|
||||
|
||||
/* Receive Timeout Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RTIM_POS 1
|
||||
#define SPI_PL022_SSPIMSC_RTIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RTIM_POS)
|
||||
|
||||
/* Receive FIFO Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RXIM_POS 2
|
||||
#define SPI_PL022_SSPIMSC_RXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RXIM_POS)
|
||||
|
||||
/* Transmit FIFO Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_TXIM_POS 3
|
||||
#define SPI_PL022_SSPIMSC_TXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_TXIM_POS)
|
||||
|
||||
/*--- Interrupt Mask Set or Clear Register ---*/
|
||||
|
||||
/* Receive Overrun Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RORIM_POS 0
|
||||
#define SPI_PL022_SSPIMSC_RORIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RORIM_POS)
|
||||
|
||||
/* Receive Timeout Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RTIM_POS 1
|
||||
#define SPI_PL022_SSPIMSC_RTIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RTIM_POS)
|
||||
|
||||
/* Receive FIFO Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RXIM_POS 2
|
||||
#define SPI_PL022_SSPIMSC_RXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RXIM_POS)
|
||||
|
||||
/* Transmit FIFO Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_TXIM_POS 3
|
||||
#define SPI_PL022_SSPIMSC_TXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_TXIM_POS)
|
||||
|
||||
#define SPI_PL022_SSPIMSC_VALID_MSK \
|
||||
((0x1ul<<(SPI_PL022_SSPIMSC_TXIM_POS+1))-1)
|
||||
|
||||
/*--- Raw Interrupt Status Register ---*/
|
||||
|
||||
/* SSPRORINTR */
|
||||
#define SPI_PL022_SSPRIS_RORRIS_POS 0
|
||||
#define SPI_PL022_SSPRIS_RORRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_RORRIS_POS)
|
||||
|
||||
/* SSPRTINTR */
|
||||
#define SPI_PL022_SSPRIS_RTRIS_POS 1
|
||||
#define SPI_PL022_SSPRIS_RTRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_RTRIS_POS)
|
||||
|
||||
/* SSPRXINTR */
|
||||
#define SPI_PL022_SSPRIS_RXRIS_POS 2
|
||||
#define SPI_PL022_SSPRIS_RXRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_RXRIS_POS)
|
||||
|
||||
/* SSPTXINTR */
|
||||
#define SPI_PL022_SSPRIS_TXRIS_POS 3
|
||||
#define SPI_PL022_SSPRIS_TXRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_TXRIS_POS)
|
||||
|
||||
#define SPI_PL022_SSPRIS_VALID_MSK \
|
||||
((0x1ul<<(SPI_PL022_SSPRIS_TXRIS_POS+1))-1)
|
||||
|
||||
/*--- Masked Interrupt Status Register ---*/
|
||||
|
||||
/* SSPRORINTR */
|
||||
#define SPI_PL022_SSPMIS_RORMIS_POS 0
|
||||
#define SPI_PL022_SSPMIS_RORMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_RORMIS_POS)
|
||||
|
||||
/* SSPRTINTR */
|
||||
#define SPI_PL022_SSPMIS_RTMIS_POS 1
|
||||
#define SPI_PL022_SSPMIS_RTMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_RTMIS_POS)
|
||||
|
||||
/* SSPRXINTR */
|
||||
#define SPI_PL022_SSPMIS_RXMIS_POS 2
|
||||
#define SPI_PL022_SSPMIS_RXMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_RXMIS_POS)
|
||||
|
||||
/* SSPTXINTR */
|
||||
#define SPI_PL022_SSPMIS_TXMIS_POS 3
|
||||
#define SPI_PL022_SSPMIS_TXMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_TXMIS_POS)
|
||||
|
||||
#define SPI_PL022_SSPMIS_VALID_MSK \
|
||||
((0x1ul<<(SPI_PL022_SSPMIS_TXMIS_POS+1))-1)
|
||||
|
||||
/*--- Interrupt Clear Register --- */
|
||||
|
||||
/* SSPRORINTR Clear */
|
||||
#define SPI_PL022_SSPICR_RORIC_POS 0
|
||||
#define SPI_PL022_SSPICR_RORIC_MSK (0x1ul<<SPI_PL022_SSPICR_RORIC_POS)
|
||||
|
||||
/* SSPRTINTR Clear */
|
||||
#define SPI_PL022_SSPICR_RTIC_POS 1
|
||||
#define SPI_PL022_SSPICR_RTIC_MSK (0x1ul<<SPI_PL022_SSPICR_RTIC_POS)
|
||||
|
||||
#define SPI_PL022_SSPICR_VALID_MSK ((0x1ul<<(SPI_PL022_SSPICR_RTIC_POS+1))-1)
|
||||
|
||||
/*--- DMA Control Register --- */
|
||||
|
||||
/* Receive DMA Enable */
|
||||
#define SPI_PL022_SSPDMACR_RXDMAE_POS 0
|
||||
#define SPI_PL022_SSPDMACR_RXDMAE_MSK (0x1ul<<SPI_PL022_SSPDMACR_RXDMAE_POS)
|
||||
|
||||
/* Transmit DMA Enable */
|
||||
#define SPI_PL022_SSPDMACR_TXDMAE_POS 1
|
||||
#define SPI_PL022_SSPDMACR_TXDMAE_MSK (0x1ul<<SPI_PL022_SSPDMACR_TXDMAE_POS)
|
||||
|
||||
#define SPI_PL022_SSPDMACR_VALID_MSK ((0x1ul<<(SPI_PL022_SSPDMACR_TXDMAE_POS+1))-1)
|
||||
|
||||
/*--- Peripheral Identification Registers ---*/
|
||||
|
||||
#define SPI_PL022_SSPPERIPH_ID_OFFSET (0xFE0ul)
|
||||
|
||||
/* Part Number 0 */
|
||||
#define SPI_PL022_SSPPERIPH_ID0_PARTNO_0_POS 0
|
||||
#define SPI_PL022_SSPPERIPH_ID0_PARTNO_0_SIZE 8
|
||||
#define SPI_PL022_SSPPERIPH_ID0_PARTNO_0_MSK \
|
||||
(0xFFul<<SPI_PL022_SSPPERIPH_ID0_PARTNO_0_POS)
|
||||
|
||||
/* Part Number 1 */
|
||||
#define SPI_PL022_SSPPERIPH_ID1_PARTNO_1_POS 0
|
||||
#define SPI_PL022_SSPPERIPH_ID1_PARTNO_1_SIZE 0
|
||||
#define SPI_PL022_SSPPERIPH_ID1_PARTNO_1_MSK \
|
||||
(0xFul<<SPI_PL022_SSPPERIPH_ID1_PARTNO_1_POS)
|
||||
|
||||
/* Designer 0 */
|
||||
#define SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS 4
|
||||
#define SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_SIZE 4
|
||||
#define SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_MSK \
|
||||
(0xFul<<SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS)
|
||||
|
||||
/* Designer 1 */
|
||||
#define SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_POS 0
|
||||
#define SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_SIZE 4
|
||||
#define SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_MSK \
|
||||
(0xFul<<SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_POS)
|
||||
|
||||
/* Revision */
|
||||
#define SPI_PL022_SSPPERIPH_ID2_REVISION_POS 4
|
||||
#define SPI_PL022_SSPPERIPH_ID2_REVISION_SIZE 4
|
||||
#define SPI_PL022_SSPPERIPH_ID2_REVIISON_MSK \
|
||||
(0xFul<<SPI_PL022_SSPPERIPH_ID2_REVISION_POS)
|
||||
|
||||
/* Config */
|
||||
#define SPI_PL022_SSPPERIPH_ID3_CONFIG_POS 0
|
||||
#define SPI_PL022_SSPPERIPH_ID3_CONFIG_MSK \
|
||||
(0xFFul<<SPI_PL022_SSPPERIPH_ID3_CONFIG_POS)
|
||||
|
||||
/*--- PrimeCell Identification Registers ---*/
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID_OFFSET (0xFF0ul)
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID0_POS 0
|
||||
#define SPI_PL022_SSPPCELL_ID0_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID0_POS)
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID1_POS 0
|
||||
#define SPI_PL022_SSPPCELL_ID1_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID1_POS)
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID2_POS 0
|
||||
#define SPI_PL022_SSPPCELL_ID2_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID2_POS)
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID3_POS 0
|
||||
#define SPI_PL022_SSPPCELL_ID3_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID3_POS)
|
||||
|
||||
/* ARM SPI PL022 state definitions */
|
||||
#define SPI_PL022_INITIALIZED (1 << 0)
|
||||
|
||||
#define WORD_1BYTE_MASK (0xFFul)
|
||||
#define WORD_2BYTES_MASK (0xFFFFul)
|
||||
|
||||
|
||||
/************************* PL022 TEST Definitions ******************************/
|
||||
#define SPI_PL022_TEST_REG_BASE (0x80ul)
|
||||
|
||||
struct spi_pl022_dev_test_reg_map_t {
|
||||
volatile uint32_t ssptcr; /* Test Control register */
|
||||
volatile uint32_t sspitip; /* Integration test input register */
|
||||
volatile uint32_t sspitop; /* Integration test output register */
|
||||
volatile uint32_t ssptdr; /* Test data register */
|
||||
};
|
||||
|
||||
/* Test control register */
|
||||
#define SPI_PL022_SSPTCR_ITEN_POS 0
|
||||
#define SPI_PL022_SSPTCR_ITEN_MSK (0x1ul<<SPI_PL022_SSPTCR_ITEN_POS)
|
||||
|
||||
#define SPI_PL022_SSPTCR_TESTFIFO_POS 1
|
||||
#define SPI_PL022_SSPTCR_TESTFIFO_MSK (0x1ul<<SPI_PL022_SSPTCR_TESTFIFO_POS)
|
||||
|
||||
|
||||
/* Integration test input register */
|
||||
#define SPI_PL022_SSPITIP_RXD_POS 0
|
||||
#define SPI_PL022_SSPITIP_RXD_MSK (0x1ul<<SPI_PL022_SSPITIP_RXD_POS)
|
||||
|
||||
#define SPI_PL022_SSPITIP_FSSIN_POS 1
|
||||
#define SPI_PL022_SSPITIP_FSSIN_MSK (0x1ul<<SPI_PL022_SSPITIP_FSSIN_POS)
|
||||
|
||||
#define SPI_PL022_SSPITIP_CLKIN_POS 2
|
||||
#define SPI_PL022_SSPITIP_CLKIN_MSK (0x1ul<<SPI_PL022_SSPITIP_CLKIN_POS)
|
||||
|
||||
#define SPI_PL022_SSPITIP_RXDMACLR_POS 3
|
||||
#define SPI_PL022_SSPITIP_RXDMACLR_MSK (0x1ul<<SPI_PL022_SSPITIP_RXDMACLR_POS)
|
||||
|
||||
#define SPI_PL022_SSPITIP_TXDMACLR_POS 4
|
||||
#define SPI_PL022_SSPITIP_TXDMACLR_MSK (0x1ul<<SPI_PL022_SSPITIP_TXDMACLR_POS)
|
||||
|
||||
/* Integration test output register */
|
||||
#define SPI_PL022_SSPITOP_RXDMABREQ_POS 10
|
||||
#define SPI_PL022_SSPITOP_RXDMABREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_RXDMABREQ_POS)
|
||||
|
||||
#define SPI_PL022_SSPITOP_RXDMASREQ_POS 11
|
||||
#define SPI_PL022_SSPITOP_RXDMASREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_RXDMASREQ_POS)
|
||||
|
||||
#define SPI_PL022_SSPITOP_TXDMABREQ_POS 12
|
||||
#define SPI_PL022_SSPITOP_TXDMABREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_TXDMABREQ_POS)
|
||||
|
||||
#define SPI_PL022_SSPITOP_TXDMASREQ_POS 13
|
||||
#define SPI_PL022_SSPITOP_TXDMASREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_TXDMASREQ_POS)
|
||||
|
||||
/************************* PL022 Definitions End ******************************/
|
||||
|
||||
|
||||
/*
|
||||
* \brief Calculates clock prescale divisor and sets serial clock rate
|
||||
* for the SPI PL022 device.
|
||||
*
|
||||
* \param[in] ctrl_cfg SPI control configuration \ref spi_pl022_ctrl_cfg_t
|
||||
* \param[in] sys_clk System clock.
|
||||
* \param[in/out] cr0 Pointer to PL022 control register 0
|
||||
* \ref spi_pl022_dev_reg_map_t
|
||||
*
|
||||
* \return Value of the SSPCPSR register \ref spi_pl022_dev_reg_map_t
|
||||
*
|
||||
* \note This function doesn't check if sys_clk or ctrl_cfg->bit_rate is 0
|
||||
*/
|
||||
static uint32_t spi_calc_clock_rate(
|
||||
const struct spi_pl022_ctrl_cfg_t* ctrl_cfg,
|
||||
uint32_t sys_clk, volatile uint32_t *cr0)
|
||||
{
|
||||
uint32_t clkps_dvsr; /* clock prescale divisor */
|
||||
uint32_t scr; /* serial clock rate */
|
||||
|
||||
for(clkps_dvsr = SPI_PL022_MIN_SSPCPSR_VALUE;
|
||||
clkps_dvsr <= SPI_PL022_MAX_SSPCPSR_VALUE; clkps_dvsr += 2) {
|
||||
|
||||
/* Calculate clock rate based on the new clock prescale divisor */
|
||||
scr = (sys_clk / (clkps_dvsr * ctrl_cfg->bit_rate)) - 1;
|
||||
|
||||
/* Checks if it can be supported by the divider */
|
||||
if (scr <= SPI_PL022_MAX_SCR_VALUE) {
|
||||
*cr0 &= ~SPI_PL022_SSPCR0_SCR_MSK;
|
||||
*cr0 |= (scr << SPI_PL022_SSPCR0_SCR_POS);
|
||||
return clkps_dvsr;
|
||||
}
|
||||
}
|
||||
|
||||
/* no good value was found */
|
||||
*cr0 &= ~SPI_PL022_SSPCR0_SCR_MSK;
|
||||
return SPI_PL022_INVALID_SSPCPSR_VALUE;
|
||||
}
|
||||
|
||||
void spi_pl022_dev_enable(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspcr1 |= SPI_PL022_SSPCR1_SSE_MSK;
|
||||
}
|
||||
|
||||
void spi_pl022_dev_disable(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspcr1 &= ~SPI_PL022_SSPCR1_SSE_MSK;
|
||||
}
|
||||
|
||||
uint32_t spi_pl022_get_status(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
return p_spi->sspsr;
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Configures the SPI PL022 device.
|
||||
*
|
||||
* \param[in] spi_dev Pointer to SPI memory map \ref spi_pl022_dev_reg_map_t
|
||||
* \param[in] ctrl_cfg SPI control configuration \ref spi_pl022_ctrl_cfg_t
|
||||
* \param[in] sys_clk System clock.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*/
|
||||
static enum spi_pl022_error_t spi_set_configuration(
|
||||
struct spi_pl022_dev_reg_map_t* spi_dev,
|
||||
const struct spi_pl022_ctrl_cfg_t* ctrl_cfg,
|
||||
uint32_t sys_clk)
|
||||
{
|
||||
uint32_t tmp_cr0, tmp_cr1;
|
||||
uint32_t clk_dvsr;
|
||||
|
||||
if(!sys_clk || !ctrl_cfg->bit_rate) {
|
||||
return SPI_PL022_ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
/* Word size */
|
||||
tmp_cr0 = ((ctrl_cfg->word_size -1) << SPI_PL022_SSPCR0_DSS_POS)
|
||||
& SPI_PL022_SSPCR0_DSS_MSK;
|
||||
|
||||
/* Frame format is stored in the least 2 bits*/
|
||||
switch(ctrl_cfg->frame_format & 0x3ul)
|
||||
{
|
||||
case SPI_PL022_CFG_FRF_MOT:
|
||||
tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_MOT_SPI << SPI_PL022_SSPCR0_FRF_POS)
|
||||
& SPI_PL022_SSPCR0_FRF_MSK;
|
||||
/* Add motorola phase & polarity */
|
||||
tmp_cr0 |= (SPI_PL022_SSPCR0_SPO_MSK & SPI_PL022_SSPCR0_SPH_MSK);
|
||||
break;
|
||||
case SPI_PL022_CFG_FRF_TI:
|
||||
tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_TI_SS << SPI_PL022_SSPCR0_FRF_POS)
|
||||
& SPI_PL022_SSPCR0_FRF_MSK;
|
||||
break;
|
||||
case SPI_PL022_CFG_FRF_MICROWIRE:
|
||||
tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_MICROWIRE << SPI_PL022_SSPCR0_FRF_POS)
|
||||
& SPI_PL022_SSPCR0_FRF_MSK;
|
||||
break;
|
||||
default:
|
||||
return SPI_PL022_ERR_BAD_CONFIG;
|
||||
/* break; */
|
||||
}
|
||||
|
||||
/* Clock logic */
|
||||
clk_dvsr = spi_calc_clock_rate(ctrl_cfg, sys_clk, &tmp_cr0);
|
||||
|
||||
if (SPI_PL022_INVALID_SSPCPSR_VALUE == clk_dvsr) {
|
||||
return SPI_PL022_ERR_BAD_CONFIG;
|
||||
}
|
||||
|
||||
/* Enable device and set configured mode */
|
||||
tmp_cr1 = (0x1 << SPI_PL022_SSPCR1_SSE_POS) & SPI_PL022_SSPCR1_SSE_MSK;
|
||||
tmp_cr1 |= ((ctrl_cfg->spi_mode << SPI_PL022_SSPCR1_MS_POS)
|
||||
& SPI_PL022_SSPCR1_MS_MSK);
|
||||
|
||||
|
||||
/* Start initialization by disabling the device */
|
||||
spi_dev->sspcr1 = 0;
|
||||
|
||||
/* Set the value received for the configuration */
|
||||
spi_dev->sspcpsr = clk_dvsr;
|
||||
spi_dev->sspcr0 = tmp_cr0;
|
||||
|
||||
/* Default setup hard coded */
|
||||
spi_dev->sspimsc = 0;
|
||||
spi_dev->sspdmacr = 0;
|
||||
spi_dev->sspicr = (SPI_PL022_SSPICR_RORIC_MSK | SPI_PL022_SSPICR_RTIC_MSK);
|
||||
|
||||
spi_dev->sspcr1 = tmp_cr1;
|
||||
|
||||
return SPI_PL022_ERR_NONE;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_init(struct spi_pl022_dev_t* dev,
|
||||
uint32_t sys_clk)
|
||||
{
|
||||
enum spi_pl022_error_t ret;
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
ret = spi_set_configuration(p_spi, &dev->cfg->default_ctrl_cfg, sys_clk);
|
||||
|
||||
if(ret != SPI_PL022_ERR_NONE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev->data->sys_clk = sys_clk;
|
||||
|
||||
/* Initilizes current SPI control configuration */
|
||||
memcpy(&dev->data->ctrl_cfg, &dev->cfg->default_ctrl_cfg,
|
||||
sizeof(struct spi_pl022_ctrl_cfg_t));
|
||||
|
||||
dev->data->state = SPI_PL022_INITIALIZED;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_set_ctrl_cfg(struct spi_pl022_dev_t* dev,
|
||||
const struct spi_pl022_ctrl_cfg_t* ctrl_cfg)
|
||||
{
|
||||
enum spi_pl022_error_t ret;
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & SPI_PL022_INITIALIZED)) {
|
||||
return SPI_PL022_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
if(ctrl_cfg == NULL) {
|
||||
return SPI_PL022_ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
ret = spi_set_configuration(p_spi, ctrl_cfg, dev->data->sys_clk);
|
||||
|
||||
if(ret != SPI_PL022_ERR_NONE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Updates current SPI control configuration */
|
||||
memcpy(&dev->data->ctrl_cfg, ctrl_cfg,
|
||||
sizeof(struct spi_pl022_ctrl_cfg_t));
|
||||
|
||||
return SPI_PL022_ERR_NONE;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_get_ctrl_cfg(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_ctrl_cfg_t* ctrl_cfg)
|
||||
{
|
||||
if(!(dev->data->state & SPI_PL022_INITIALIZED)) {
|
||||
return SPI_PL022_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
if(ctrl_cfg == NULL) {
|
||||
return SPI_PL022_ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
/* Copy current SPI control configuration */
|
||||
memcpy(ctrl_cfg, &dev->data->ctrl_cfg,
|
||||
sizeof(struct spi_pl022_ctrl_cfg_t));
|
||||
|
||||
return SPI_PL022_ERR_NONE;
|
||||
}
|
||||
|
||||
void spi_pl022_select_mode(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_mode_select_t mode)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
|
||||
/* Disable device */
|
||||
p_spi->sspcr1 &= ~SPI_PL022_SSPCR1_SSE_MSK;
|
||||
/* Set mode */
|
||||
p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_MS_MSK)
|
||||
| (mode << SPI_PL022_SSPCR1_MS_POS);
|
||||
dev->data->ctrl_cfg.spi_mode = mode;
|
||||
/* Re-enable device */
|
||||
p_spi->sspcr1 |= SPI_PL022_SSPCR1_SSE_MSK;
|
||||
}
|
||||
|
||||
void spi_pl022_set_slave_output(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_slave_output_mode_t mode)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_SOD_MSK)
|
||||
| (mode << SPI_PL022_SSPCR1_SOD_POS);
|
||||
}
|
||||
|
||||
void spi_pl022_set_loopback_mode(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_loopback_select_t mode)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_LBM_MSK)
|
||||
| (mode << SPI_PL022_SSPCR1_LBM_POS);
|
||||
}
|
||||
|
||||
void spi_pl022_enable_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspimsc |= (irq_mask & SPI_PL022_SSPIMSC_VALID_MSK);
|
||||
}
|
||||
|
||||
void spi_pl022_disable_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspimsc &= ~(irq_mask & SPI_PL022_SSPIMSC_VALID_MSK);
|
||||
}
|
||||
|
||||
uint32_t spi_pl022_get_raw_irq_status(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
return (p_spi->sspris & SPI_PL022_SSPRIS_VALID_MSK);
|
||||
}
|
||||
|
||||
uint32_t spi_pl022_get_masked_irq_status(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
return (p_spi->sspmis & SPI_PL022_SSPMIS_VALID_MSK);
|
||||
}
|
||||
|
||||
void spi_pl022_clear_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspicr = (irq_mask & SPI_PL022_SSPICR_VALID_MSK);
|
||||
}
|
||||
|
||||
void spi_pl022_dma_mode_enable(struct spi_pl022_dev_t* dev,
|
||||
uint32_t dma)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspdmacr |= (dma & SPI_PL022_SSPDMACR_VALID_MSK);
|
||||
}
|
||||
|
||||
void spi_pl022_dma_mode_disable(struct spi_pl022_dev_t* dev,
|
||||
uint32_t dma)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
p_spi->sspdmacr &= ~(dma & SPI_PL022_SSPDMACR_VALID_MSK);
|
||||
}
|
||||
|
||||
void spi_pl022_get_periphID(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_periphid_t* periphid)
|
||||
{
|
||||
uint32_t tempid, tempid2;
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
tempid = p_spi->sspperiphid0 & SPI_PL022_SSPPERIPH_ID0_PARTNO_0_MSK;
|
||||
tempid2 = (p_spi->sspperiphid1 & SPI_PL022_SSPPERIPH_ID1_PARTNO_1_MSK)
|
||||
<< SPI_PL022_SSPPERIPH_ID0_PARTNO_0_SIZE;
|
||||
periphid->partNumber = tempid | tempid2;
|
||||
|
||||
tempid = (p_spi->sspperiphid1 & SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_MSK)
|
||||
>> SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS;
|
||||
tempid2 = (p_spi->sspperiphid2 & SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_MSK)
|
||||
<< SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_SIZE;
|
||||
periphid->designerID = tempid | tempid2;
|
||||
|
||||
tempid = (p_spi->sspperiphid2 & SPI_PL022_SSPPERIPH_ID2_REVIISON_MSK)
|
||||
>> SPI_PL022_SSPPERIPH_ID2_REVISION_SIZE;
|
||||
periphid->revision = tempid;
|
||||
|
||||
tempid = p_spi->sspperiphid3 & SPI_PL022_SSPPERIPH_ID3_CONFIG_MSK;
|
||||
periphid->configuration = tempid;
|
||||
}
|
||||
|
||||
void spi_pl022_get_PrimeCell_ID(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_primecell_id_t* cellid)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
cellid->cellid0 = (uint8_t) p_spi->ssppcellid0;
|
||||
cellid->cellid1 = (uint8_t) p_spi->ssppcellid1;
|
||||
cellid->cellid2 = (uint8_t) p_spi->ssppcellid2;
|
||||
cellid->cellid3 = (uint8_t) p_spi->ssppcellid3;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_set_sys_clk(struct spi_pl022_dev_t* dev,
|
||||
uint32_t sys_clk)
|
||||
{
|
||||
uint32_t clk_dvsr;
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
if(!(dev->data->state & SPI_PL022_INITIALIZED)) {
|
||||
return SPI_PL022_ERR_NOT_INIT;
|
||||
}
|
||||
|
||||
if(!sys_clk) {
|
||||
return SPI_PL022_ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
clk_dvsr = spi_calc_clock_rate(&dev->data->ctrl_cfg, sys_clk, &p_spi->sspcr0);
|
||||
|
||||
if(SPI_PL022_INVALID_SSPCPSR_VALUE == clk_dvsr) {
|
||||
return SPI_PL022_ERR_BAD_CONFIG;
|
||||
}
|
||||
|
||||
p_spi->sspcpsr = clk_dvsr;
|
||||
dev->data->sys_clk = sys_clk;
|
||||
|
||||
return SPI_PL022_ERR_NONE;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_read(struct spi_pl022_dev_t* dev,
|
||||
void *rx_ptr)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
if(p_spi->sspsr & SPI_PL022_SSPSR_RNE_MSK) {
|
||||
if(dev->data->ctrl_cfg.word_size <= 8) {
|
||||
*(uint8_t*)rx_ptr = p_spi->sspdr & WORD_1BYTE_MASK;
|
||||
} else {
|
||||
*(uint16_t*)rx_ptr = p_spi->sspdr & WORD_2BYTES_MASK;
|
||||
}
|
||||
return SPI_PL022_ERR_NONE;
|
||||
}
|
||||
return SPI_PL022_ERR_NO_RX;
|
||||
}
|
||||
|
||||
uint32_t spi_pl022_slave_read(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
uint32_t data;
|
||||
|
||||
if(dev->data->ctrl_cfg.word_size <= 8) {
|
||||
data = p_spi->sspdr & WORD_1BYTE_MASK;
|
||||
} else {
|
||||
data = p_spi->sspdr & WORD_2BYTES_MASK;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_write(struct spi_pl022_dev_t* dev,
|
||||
const enum spi_pl022_mode_select_t mode,
|
||||
const void *tx_ptr)
|
||||
{
|
||||
struct spi_pl022_dev_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_reg_map_t*) dev->cfg->base;
|
||||
|
||||
if(p_spi->sspsr & SPI_PL022_SSPSR_TNF_MSK){
|
||||
if(dev->data->ctrl_cfg.word_size <= 8) {
|
||||
p_spi->sspdr = *(const uint8_t*)tx_ptr;
|
||||
} else {
|
||||
p_spi->sspdr = *(const uint16_t*)tx_ptr;
|
||||
}
|
||||
/* Wait for write to go through */
|
||||
if (mode == SPI_PL022_MASTER_SELECT) {
|
||||
while(p_spi->sspsr & SPI_PL022_SSPSR_BSY_MSK) {};
|
||||
}
|
||||
return SPI_PL022_ERR_NONE;
|
||||
}
|
||||
return SPI_PL022_ERR_NO_TX;
|
||||
}
|
||||
|
||||
enum spi_pl022_error_t spi_pl022_txrx_blocking(struct spi_pl022_dev_t* dev,
|
||||
const void *tx_ptr,
|
||||
uint32_t *tx_len_ptr,
|
||||
void *rx_ptr,
|
||||
uint32_t *rx_len_ptr)
|
||||
{
|
||||
uint32_t i;
|
||||
enum spi_pl022_error_t retval = SPI_PL022_ERR_NONE;
|
||||
uint8_t word_size = 1;
|
||||
uint32_t rx_data, tx_data, total_len;
|
||||
|
||||
if(dev->data->ctrl_cfg.word_size > 8) {
|
||||
word_size = 2;
|
||||
/* return error if sizes are not word_size aligned */
|
||||
if ((*tx_len_ptr & 0x1) || (*rx_len_ptr & 0x1)) {
|
||||
return SPI_PL022_ERR_INVALID_ARGS;
|
||||
}
|
||||
}
|
||||
|
||||
total_len = (*tx_len_ptr > *rx_len_ptr) ? *tx_len_ptr : *rx_len_ptr;
|
||||
|
||||
for(i=0;i<total_len;i+=word_size){
|
||||
if (i<*tx_len_ptr) {
|
||||
tx_data = *(const uint16_t*)tx_ptr;
|
||||
} else {
|
||||
/* send FF if there is no more valid data to send */
|
||||
tx_data = 0xFFFF;
|
||||
}
|
||||
retval = spi_pl022_write(dev, dev->data->ctrl_cfg.spi_mode, &tx_data);
|
||||
if(retval != SPI_PL022_ERR_NONE) {
|
||||
*tx_len_ptr = i;
|
||||
*rx_len_ptr = i;
|
||||
break;
|
||||
}
|
||||
if(i < *tx_len_ptr) {
|
||||
tx_ptr = (const uint8_t*)tx_ptr + word_size;
|
||||
}
|
||||
retval = spi_pl022_read(dev, &rx_data);
|
||||
if(retval != SPI_PL022_ERR_NONE) {
|
||||
/* send went through, align tx_len to the updated tx_ptr */
|
||||
*tx_len_ptr = i + word_size;
|
||||
/* don't update rx_len if there is an overflow */
|
||||
if (i < *rx_len_ptr) {
|
||||
*rx_len_ptr = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* do not overflow rx buffer */
|
||||
if(i<*rx_len_ptr) {
|
||||
if (word_size == 1) {
|
||||
*(uint8_t*)rx_ptr = (uint8_t) rx_data;
|
||||
} else {
|
||||
*(uint16_t*)rx_ptr = (uint16_t) rx_data;
|
||||
}
|
||||
rx_ptr = (uint8_t*)rx_ptr + word_size;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* TEST APIs
|
||||
*/
|
||||
void spi_pl022_test_fifo_enable(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_test_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_test_reg_map_t*)
|
||||
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
|
||||
|
||||
p_spi->ssptcr |= SPI_PL022_SSPTCR_TESTFIFO_MSK;
|
||||
}
|
||||
|
||||
void spi_pl022_test_fifo_disable(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_test_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_test_reg_map_t*)
|
||||
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
|
||||
|
||||
p_spi->ssptcr &= ~SPI_PL022_SSPTCR_TESTFIFO_MSK;
|
||||
}
|
||||
|
||||
void spi_pl022_integration_test_enable(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_test_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_test_reg_map_t*)
|
||||
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
|
||||
|
||||
p_spi->ssptcr |= SPI_PL022_SSPTCR_ITEN_MSK;
|
||||
}
|
||||
|
||||
void spi_pl022_integration_test_disable(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_test_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_test_reg_map_t*)
|
||||
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
|
||||
|
||||
p_spi->ssptcr &= ~SPI_PL022_SSPTCR_ITEN_MSK;
|
||||
}
|
||||
|
||||
|
||||
void spi_pl022_write_test_data(struct spi_pl022_dev_t* dev,
|
||||
void *tx_ptr)
|
||||
{
|
||||
struct spi_pl022_dev_test_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_test_reg_map_t*)
|
||||
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
|
||||
|
||||
if(dev->data->ctrl_cfg.word_size <= 8) {
|
||||
p_spi->ssptdr = *(const uint8_t*)tx_ptr;
|
||||
} else {
|
||||
p_spi->ssptdr = *(const uint16_t*)tx_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t spi_pl022_read_test_output_reg(struct spi_pl022_dev_t* dev)
|
||||
{
|
||||
struct spi_pl022_dev_test_reg_map_t* p_spi =
|
||||
(struct spi_pl022_dev_test_reg_map_t*)
|
||||
(dev->cfg->base + SPI_PL022_TEST_REG_BASE);
|
||||
|
||||
return p_spi->sspitop;
|
||||
}
|
||||
|
|
@ -0,0 +1,501 @@
|
|||
/*
|
||||
* Copyright (c) 2018 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file spi_pl022_drv.h
|
||||
* \brief Generic driver for ARM SPI PL022.
|
||||
*/
|
||||
|
||||
#ifndef __SPI_PL022_DRV_H__
|
||||
#define __SPI_PL022_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Frame format */
|
||||
#define SPI_PL022_CFG_FRF_MOT 0
|
||||
#define SPI_PL022_CFG_FRF_TI 1
|
||||
#define SPI_PL022_CFG_FRF_MICROWIRE 2
|
||||
|
||||
enum spi_pl022_mode_select_t {
|
||||
SPI_PL022_MASTER_SELECT = 0,
|
||||
SPI_PL022_SLAVE_SELECT,
|
||||
};
|
||||
|
||||
enum spi_pl022_slave_output_mode_t {
|
||||
SPI_PL022_SLAVE_OUTPUT_EN = 0,
|
||||
SPI_PL022_SLAVE_OUTPUT_DIS,
|
||||
};
|
||||
|
||||
enum spi_pl022_loopback_select_t {
|
||||
SPI_PL022_LOOPBACK_MODE_DIS = 0,
|
||||
SPI_PL022_LOOPBACK_MODE_EN,
|
||||
};
|
||||
|
||||
struct spi_pl022_periphid_t {
|
||||
uint32_t partNumber;
|
||||
uint32_t designerID;
|
||||
uint32_t revision;
|
||||
uint32_t configuration;
|
||||
};
|
||||
|
||||
struct spi_pl022_primecell_id_t {
|
||||
uint8_t cellid0;
|
||||
uint8_t cellid1;
|
||||
uint8_t cellid2;
|
||||
uint8_t cellid3;
|
||||
};
|
||||
|
||||
/* ARM SPI PL022 device control configuration structure */
|
||||
struct spi_pl022_ctrl_cfg_t {
|
||||
enum spi_pl022_mode_select_t spi_mode; /*!< master-slave */
|
||||
uint8_t frame_format; /*!< frame format bitmap
|
||||
clock phase [7] polarity [6]
|
||||
reserved [5:3]
|
||||
frame_format [1:0] */
|
||||
uint8_t word_size; /*!< value 4 to 16 */
|
||||
uint8_t reserved[2]; /*!< to keep 32 bits aligned */
|
||||
uint32_t bit_rate; /*!< required bit rate */
|
||||
};
|
||||
|
||||
/* ARM SPI PL022 device configuration structure */
|
||||
struct spi_pl022_dev_cfg_t {
|
||||
const uint32_t base; /*!< SPI PL022 base address */
|
||||
const struct spi_pl022_ctrl_cfg_t default_ctrl_cfg; /*!< Default SPI
|
||||
configuration */
|
||||
};
|
||||
|
||||
/* ARM SPI PL022 device data structure */
|
||||
struct spi_pl022_dev_data_t {
|
||||
uint32_t state; /*!< SPI driver state */
|
||||
uint32_t sys_clk; /*!< System clock frequency */
|
||||
struct spi_pl022_ctrl_cfg_t ctrl_cfg; /*!< SPI control
|
||||
configuration data */
|
||||
};
|
||||
|
||||
/* ARM SPI PL022 device structure */
|
||||
struct spi_pl022_dev_t {
|
||||
const struct spi_pl022_dev_cfg_t* const cfg; /*!< SPI driver
|
||||
configuration */
|
||||
struct spi_pl022_dev_data_t* const data; /*!< SPI driver data */
|
||||
};
|
||||
|
||||
enum spi_pl022_error_t {
|
||||
SPI_PL022_ERR_NONE = 0, /*!< No error */
|
||||
SPI_PL022_ERR_INVALID_ARGS, /*!< Invalid input arguments */
|
||||
SPI_PL022_ERR_NOT_INIT, /*!< SPI driver is not initialized */
|
||||
SPI_PL022_ERR_NO_TX, /*!< SPI transm FIFO full */
|
||||
SPI_PL022_ERR_NO_RX, /*!< SPI receive FIFO empty */
|
||||
SPI_PL022_ERR_BAD_CONFIG, /*!< Bad SPI configuration */
|
||||
};
|
||||
|
||||
|
||||
/* Interrupt mask defines for the interrupt APIs */
|
||||
|
||||
/* Receive Overrun Interrupt */
|
||||
#define SPI_PL022_RX_OR_INTR_POS 0
|
||||
#define SPI_PL022_RX_OR_INTR_MSK (0x1ul<<SPI_PL022_RX_OR_INTR_POS)
|
||||
|
||||
/* Receive Timeout Interrupt */
|
||||
#define SPI_PL022_RX_TO_INTR_POS 1
|
||||
#define SPI_PL022_RX_TO_INTR_MSK (0x1ul<<SPI_PL022_RX_TO_INTR_POS)
|
||||
|
||||
/* Receive FIFO Interrupt */
|
||||
#define SPI_PL022_RX_FIFO_INTR_POS 2
|
||||
#define SPI_PL022_RX_FIFO_INTR_MSK (0x1ul<<SPI_PL022_RX_FIFO_INTR_POS)
|
||||
|
||||
/* Transmit FIFO Interrupt */
|
||||
#define SPI_PL022_TX_FIFO_INTR_POS 3
|
||||
#define SPI_PL022_TX_FIFO_INTR_MSK (0x1ul<<SPI_PL022_TX_FIFO_INTR_POS)
|
||||
|
||||
#define SPI_PL022_ALL_INTR_MSK \
|
||||
((0x1ul<<(SPI_PL022_TX_FIFO_INTR_POS+1))-1)
|
||||
|
||||
/* Status register bit defines */
|
||||
|
||||
/* Transmit FIFO empty */
|
||||
#define SPI_PL022_SSPSR_TFE_POS 0
|
||||
#define SPI_PL022_SSPSR_TFE_MSK (0x1ul<<SPI_PL022_SSPSR_TFE_POS)
|
||||
|
||||
/* Transmit FIFO not full */
|
||||
#define SPI_PL022_SSPSR_TNF_POS 1
|
||||
#define SPI_PL022_SSPSR_TNF_MSK (0x1ul<<SPI_PL022_SSPSR_TNF_POS)
|
||||
|
||||
/* Receive FIFO not empty */
|
||||
#define SPI_PL022_SSPSR_RNE_POS 2
|
||||
#define SPI_PL022_SSPSR_RNE_MSK (0x1ul<<SPI_PL022_SSPSR_RNE_POS)
|
||||
|
||||
/* Receive FIFO full */
|
||||
#define SPI_PL022_SSPSR_RFF_POS 3
|
||||
#define SPI_PL022_SSPSR_RFF_MSK (0x1ul<<SPI_PL022_SSPSR_RFF_POS)
|
||||
|
||||
/* Busy either tx/rx or transmit fifo not empty */
|
||||
#define SPI_PL022_SSPSR_BSY_POS 4
|
||||
#define SPI_PL022_SSPSR_BSY_MSK (0x1ul<<SPI_PL022_SSPSR_BSY_POS)
|
||||
|
||||
/**
|
||||
* \brief Enables PL022 SPI device
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_dev_enable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables PL022 SPI device
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_dev_disable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Returns SPI status register
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t spi_pl022_get_status(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Initializes the SPI PL022 device.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] sys_clk System clock.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_init(struct spi_pl022_dev_t* dev,
|
||||
uint32_t sys_clk);
|
||||
|
||||
/**
|
||||
* \brief Sets the SPI PL022 device configuration.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] ctrl_cfg SPI control configuration.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_set_ctrl_cfg(struct spi_pl022_dev_t* dev,
|
||||
const struct spi_pl022_ctrl_cfg_t* ctrl_cfg);
|
||||
|
||||
/**
|
||||
* \brief Gets the SPI PL022 device configuration.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[out] ctrl_cfg Pointer to fill the SPI control configuration.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_get_ctrl_cfg(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_ctrl_cfg_t* ctrl_cfg);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Selects SPI PL022 device as Master or Slave
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] mode Mode selection \ref spi_pl022_mode_select_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_select_mode(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_mode_select_t mode);
|
||||
|
||||
/**
|
||||
* \brief Enables/disables SPI PL022 Slave device output
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] mode Mode selection \ref spi_pl022_slave_output_mode_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
* \note This function doesn't check if dev is Slave or Master
|
||||
*/
|
||||
void spi_pl022_set_slave_output(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_slave_output_mode_t mode);
|
||||
|
||||
/**
|
||||
* \brief Enables SPI PL022 device in loopback mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] mode Mode selection \ref spi_pl022_loopback_select_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_set_loopback_mode(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_loopback_select_t mode);
|
||||
|
||||
/**
|
||||
* \brief Clears interrupt mask of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] irq_mask Selection of interrupts to enable
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_enable_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask);
|
||||
|
||||
/**
|
||||
* \brief Sets interrupt mask of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] irq_mask Selection of interrupts to disable
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_disable_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask);
|
||||
|
||||
/**
|
||||
* \brief Gets raw interrupt status of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \return Returns raw interrupt status value
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t spi_pl022_get_raw_irq_status(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Gets masked interrupt status of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \return Returns masked interrupt status value
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t spi_pl022_get_masked_irq_status(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets interrupt mask of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] irq_mask Selection of interrupts to disable
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_clear_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask);
|
||||
|
||||
/**
|
||||
* \brief Enables transmit or receive DMA
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] dma Selects the DMA to be enabled
|
||||
* - bit position 0 - Receive DMA
|
||||
* - bit position 1 - Transmit DMA
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_dma_mode_enable(struct spi_pl022_dev_t* dev,
|
||||
uint32_t dma);
|
||||
|
||||
/**
|
||||
* \brief Disables transmit or receive DMA
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] dma Selects the DMA to be disabled
|
||||
* - bit position 0 - Receive DMA
|
||||
* - bit position 1 - Transmit DMA
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_dma_mode_disable(struct spi_pl022_dev_t* dev,
|
||||
uint32_t dma);
|
||||
|
||||
/**
|
||||
* \brief Gets peripheral identification of the device
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[out] periphid Pointer to fill peripheral ids
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_get_periphID(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_periphid_t* periphid);
|
||||
|
||||
/**
|
||||
* \brief Gets PrimeCell identification of the device
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[out] cellid Pointer to fill PrimeCell ids
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_get_PrimeCell_ID(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_primecell_id_t* cellid);
|
||||
|
||||
/**
|
||||
* \brief Sets system clock.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] sys_clk System clock.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_set_sys_clk(struct spi_pl022_dev_t* dev,
|
||||
uint32_t sys_clk);
|
||||
|
||||
/**
|
||||
* \brief Reads single data from SPI. Non blocking.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[out] rx_ptr Buffer pointer to be filled
|
||||
* must be enough for configured word size
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* if the driver is initialized to reduce the number of checks and
|
||||
* make the function execution faster.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_read(struct spi_pl022_dev_t* dev,
|
||||
void *rx_ptr);
|
||||
|
||||
/**
|
||||
* \brief Reads single data from slave SPI. Non blocking.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \return Returns data value from the device
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* does not validate whether there is any data in the RX buffer
|
||||
*/
|
||||
uint32_t spi_pl022_slave_read(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Writes single data to SPI. Non blocking.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] mode Master or slave \ref spi_pl022_mode_select_t
|
||||
* \param[out] tx_ptr Pointer to the data to be sent
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* if the driver is initialized to reduce the number of checks and
|
||||
* make the function execution faster.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_write(struct spi_pl022_dev_t* dev,
|
||||
const enum spi_pl022_mode_select_t mode,
|
||||
const void *tx_ptr);
|
||||
|
||||
/**
|
||||
* \brief Transmit and Receive data on SPI in a blocking call
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] tx_ptr Buffer pointer to be filled
|
||||
* \param[in/out] tx_len_ptr Num values to transfer (updated on error)
|
||||
* need to be multiples of transfer word length
|
||||
* \param[out] rx_ptr Buffer pointer to be filled
|
||||
* \param[in/out] rx_len_ptr Num values to receive (updated on error)
|
||||
* need to be multiples of transfer word length
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* if the driver is initialized to reduce the number of checks and
|
||||
* make the function execution faster.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_txrx_blocking(struct spi_pl022_dev_t* dev,
|
||||
const void *tx_ptr,
|
||||
uint32_t *tx_len_ptr,
|
||||
void *rx_ptr,
|
||||
uint32_t *rx_len_ptr);
|
||||
|
||||
|
||||
/************************** TEST APIs ****************************/
|
||||
|
||||
/**
|
||||
* \brief Enables Test FIFO mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
void spi_pl022_test_fifo_enable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables Test FIFO mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
void spi_pl022_test_fifo_disable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables Integration Test mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
void spi_pl022_integration_test_enable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables Integration Test mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
void spi_pl022_integration_test_disable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Writes data to Test data register
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* whether Test FIFO mode is enabled
|
||||
*/
|
||||
void spi_pl022_write_test_data(struct spi_pl022_dev_t* dev, void *tx_ptr);
|
||||
|
||||
/**
|
||||
* \brief Reads integration test output register
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
uint32_t spi_pl022_read_test_output_reg(struct spi_pl022_dev_t* dev);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __SPI_PL022_DRV_H__ */
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file timer_cmsdk_drv.c
|
||||
* \brief Generic driver for CMSDK APB Timers.
|
||||
* The timer is a 32-bit down-counter with the following features:
|
||||
* - optional programmable external clock source
|
||||
* - programmable interrupt source, triggered if counter reaches 0
|
||||
* - automatic reload if counter reaches 0
|
||||
*/
|
||||
|
||||
#include "timer_cmsdk_drv.h"
|
||||
|
||||
/** Setter bit manipulation macro */
|
||||
#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX)))
|
||||
/** Clearing bit manipulation macro */
|
||||
#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX)))
|
||||
/** Getter bit manipulation macro */
|
||||
#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX))))
|
||||
|
||||
/**
|
||||
* \brief Timer register map structure
|
||||
*
|
||||
*/
|
||||
struct timer_cmsdk_reg_map_t {
|
||||
volatile uint32_t ctrl; /* Offset: 0x000 (R/W) control register */
|
||||
volatile uint32_t value; /* Offset: 0x004 (R/W) current value register */
|
||||
volatile uint32_t reload; /* Offset: 0x008 (R/W) reload value register */
|
||||
union {
|
||||
volatile uint32_t intstatus; /* Offset: 0x00C (R/ ) interrupt
|
||||
* status register */
|
||||
volatile uint32_t intclear; /* Offset: 0x00C ( /W) interrupt
|
||||
* clear register */
|
||||
}intreg;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief CTRL register bit definitions
|
||||
*
|
||||
*/
|
||||
enum ctrl_reg_bits_t{
|
||||
CTRL_REG_ENUM_ENABLE_INDEX = 0,
|
||||
CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX = 1,
|
||||
CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX = 2,
|
||||
CTRL_REG_ENUM_IRQ_ENABLE_INDEX = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief INTSTATUS/INTCLEAR register bit definitions
|
||||
*
|
||||
*/
|
||||
enum interrupt_reg_bits_t{
|
||||
INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX = 0
|
||||
};
|
||||
|
||||
void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
|
||||
if (dev->data->is_initialized == 0) {
|
||||
register_map->ctrl = 0;
|
||||
register_map->reload = TIMER_CMSDK_DEFAULT_RELOAD;
|
||||
dev->data->is_initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
return dev->data->is_initialized;
|
||||
}
|
||||
|
||||
void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return GET_BIT(register_map->ctrl,
|
||||
CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
|
||||
}
|
||||
|
||||
bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return GET_BIT(register_map->ctrl,
|
||||
CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
SET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
|
||||
}
|
||||
|
||||
bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return GET_BIT(register_map->intreg.intstatus,
|
||||
INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX);
|
||||
}
|
||||
|
||||
void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
SET_BIT(register_map->intreg.intclear,
|
||||
INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX);
|
||||
}
|
||||
|
||||
uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return register_map->value;
|
||||
}
|
||||
|
||||
void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev,
|
||||
uint32_t reload)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
register_map->reload = reload;
|
||||
}
|
||||
|
||||
void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
register_map->value = register_map->reload;
|
||||
}
|
||||
|
||||
uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return register_map->reload;
|
||||
}
|
||||
|
||||
uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev)
|
||||
{
|
||||
struct timer_cmsdk_reg_map_t* register_map =
|
||||
(struct timer_cmsdk_reg_map_t*)dev->cfg->base;
|
||||
return register_map->reload - register_map->value;
|
||||
}
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file timer_cmsdk_drv.h
|
||||
* \brief Generic driver for CMSDK APB Timers.
|
||||
* The timer is a 32-bit down-counter with the following features:
|
||||
* - optional programmable external clock source
|
||||
* - programmable interrupt source, triggered if counter reaches 0
|
||||
* - automatic reload if counter reaches 0
|
||||
*/
|
||||
|
||||
#ifndef __TIMER_CMSDK_DRV_H__
|
||||
#define __TIMER_CMSDK_DRV_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Maximum reload value */
|
||||
#define TIMER_CMSDK_MAX_RELOAD UINT32_MAX /* max of 32-bit */
|
||||
#define TIMER_CMSDK_DEFAULT_RELOAD TIMER_CMSDK_MAX_RELOAD
|
||||
|
||||
/** CMSDK timer device configuration structure */
|
||||
struct timer_cmsdk_dev_cfg_t {
|
||||
const uintptr_t base; /*!< Timer base address */
|
||||
};
|
||||
|
||||
/** CMSDK timer device data structure */
|
||||
struct timer_cmsdk_dev_data_t {
|
||||
bool is_initialized; /*!< Indicates if the timer is initialized */
|
||||
};
|
||||
|
||||
/* CMSDK timer device structure */
|
||||
struct timer_cmsdk_dev_t {
|
||||
const struct timer_cmsdk_dev_cfg_t* const cfg; /*!< Timer configuration */
|
||||
struct timer_cmsdk_dev_data_t* const data; /*!< Timer data */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Initializes timer to a known default state, which is:
|
||||
* - timer disabled
|
||||
* - timer interrupt disabled
|
||||
* - clock source set to internal
|
||||
* - external input disabled
|
||||
* - reload value maxed out
|
||||
* Init should be called prior to any other process and
|
||||
* it's the caller's responsibility to follow proper call order.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Checks if a timer is initialized.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return true if initialized, false otherwise
|
||||
*/
|
||||
bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables external input, which could be used as clock source
|
||||
* by calling \ref timer_cmsdk_set_clock_to_external.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables external input.
|
||||
* Make sure if the timer is explicitly wanted to be stopped or set
|
||||
* the clock source to internal by \ref timer_cmsdk_set_clock_to_internal.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Checks if external input is enabled.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return true if enabled, false otherwise
|
||||
*/
|
||||
bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets the clock source to internal.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets the clock source to external.
|
||||
* Make sure external input is enabled correspondingly
|
||||
* by \ref timer_cmsdk_enable_external_input.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Checks if clock source is external input.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return true if external, false if internal
|
||||
*/
|
||||
bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables timer operation.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables the given hardware timer.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Checks if a timer is enabled.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return true if enabled, false otherwise
|
||||
*/
|
||||
bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables timer interrupt.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables timer interrupt.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Checks if a timer interrupt is enabled.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return true if enabled, false otherwise
|
||||
*/
|
||||
bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Gets timer interrupt status
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* * \return true if active, false otherwise
|
||||
*/
|
||||
bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Clears timer interrupt
|
||||
* The interrupt request is held until it is cleared.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Reads timer current value.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return Timer value
|
||||
*/
|
||||
uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets the reload value of the selected timer.
|
||||
*
|
||||
* New reload value takes effect when:
|
||||
* - timer is restarted
|
||||
* - on timer underflow
|
||||
* - when timer_cmsdk_reset is called
|
||||
*
|
||||
* \note In r1p0 technical reference manual it's incorrectly stated
|
||||
* writing the reload value automatically sets the current value also.
|
||||
* r1p1 technical reference manual includes the fix.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
* \param[in] reload Timer reload value to set.
|
||||
* This is the start value of the 32-bit down counter,
|
||||
* which automatically reloaded if 0 is reached.
|
||||
*/
|
||||
void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev,
|
||||
uint32_t reload);
|
||||
|
||||
/**
|
||||
* \brief Resets the timer counter to the reload value instantly
|
||||
* (i.e. without waiting for underflow).
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*/
|
||||
void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Gets the reload value of the selected timer.
|
||||
* This is the start value of the 32-bit down counter,
|
||||
* which is automatically reloaded if 0 is reached by the counter.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return Reload value of the selected timer.
|
||||
*/
|
||||
uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Reads the number of ticks elapsed in the current cycle.
|
||||
*
|
||||
* \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
|
||||
*
|
||||
* \return Get elapsed number of ticks since last reload was set.
|
||||
* Elapsed = (Reload value - Current value)
|
||||
*/
|
||||
uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __TIMER_CMSDK_DRV_H__ */
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "platform_devices.h"
|
||||
#include "SMM_MPS2.h"
|
||||
|
||||
/* ARM CMSDK Timer driver structures */
|
||||
#ifdef ARM_CMSDK_TIMER0
|
||||
static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG = {
|
||||
.base = CMSDK_TIMER0_BASE};
|
||||
static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA = {
|
||||
.is_initialized = 0};
|
||||
struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV = {&(CMSDK_TIMER0_DEV_CFG),
|
||||
&(CMSDK_TIMER0_DEV_DATA)};
|
||||
#endif
|
||||
|
||||
#ifdef ARM_CMSDK_TIMER1
|
||||
static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER1_DEV_CFG = {
|
||||
.base = CMSDK_TIMER1_BASE};
|
||||
static struct timer_cmsdk_dev_data_t CMSDK_TIMER1_DEV_DATA = {
|
||||
.is_initialized = 0};
|
||||
struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV = {&(CMSDK_TIMER1_DEV_CFG),
|
||||
&(CMSDK_TIMER1_DEV_DATA)};
|
||||
#endif
|
||||
|
||||
/* ARM GPIO driver structures */
|
||||
#ifdef ARM_GPIO0
|
||||
static const struct arm_gpio_dev_cfg_t ARM_GPIO0_DEV_CFG = {
|
||||
.base = CMSDK_GPIO0_BASE};
|
||||
static struct arm_gpio_dev_data_t ARM_GPIO0_DEV_DATA = {
|
||||
.state = 0,
|
||||
.port_mask = DEFAULT_PORT_MASK};
|
||||
struct arm_gpio_dev_t ARM_GPIO0_DEV = {&(ARM_GPIO0_DEV_CFG),
|
||||
&(ARM_GPIO0_DEV_DATA)};
|
||||
#endif /* ARM_GPIO0 */
|
||||
|
||||
#ifdef ARM_GPIO1
|
||||
static const struct arm_gpio_dev_cfg_t ARM_GPIO1_DEV_CFG = {
|
||||
.base = CMSDK_GPIO1_BASE};
|
||||
static struct arm_gpio_dev_data_t ARM_GPIO1_DEV_DATA = {
|
||||
.state = 0,
|
||||
.port_mask = DEFAULT_PORT_MASK};
|
||||
struct arm_gpio_dev_t ARM_GPIO1_DEV = {&(ARM_GPIO1_DEV_CFG),
|
||||
&(ARM_GPIO1_DEV_DATA)};
|
||||
#endif /* ARM_GPIO1 */
|
||||
|
||||
#ifdef ARM_GPIO2
|
||||
static const struct arm_gpio_dev_cfg_t ARM_GPIO2_DEV_CFG = {
|
||||
.base = CMSDK_GPIO2_BASE};
|
||||
static struct arm_gpio_dev_data_t ARM_GPIO2_DEV_DATA = {
|
||||
.state = 0,
|
||||
.port_mask = DEFAULT_PORT_MASK};
|
||||
struct arm_gpio_dev_t ARM_GPIO2_DEV = {&(ARM_GPIO2_DEV_CFG),
|
||||
&(ARM_GPIO2_DEV_DATA)};
|
||||
#endif /* ARM_GPIO2 */
|
||||
|
||||
#ifdef ARM_GPIO3
|
||||
static const struct arm_gpio_dev_cfg_t ARM_GPIO3_DEV_CFG = {
|
||||
.base = CMSDK_GPIO3_BASE};
|
||||
static struct arm_gpio_dev_data_t ARM_GPIO3_DEV_DATA = {
|
||||
.state = 0,
|
||||
.port_mask = DEFAULT_PORT_MASK};
|
||||
struct arm_gpio_dev_t ARM_GPIO3_DEV = {&(ARM_GPIO3_DEV_CFG),
|
||||
&(ARM_GPIO3_DEV_DATA)};
|
||||
#endif /* ARM_GPIO3 */
|
||||
|
||||
/* ARM MPS2 IO FPGAIO driver structures */
|
||||
#ifdef ARM_MPS2_IO_FPGAIO
|
||||
static const struct arm_mps2_io_dev_cfg_t ARM_MPS2_IO_FPGAIO_DEV_CFG = {
|
||||
.base = MPS2_FPGAIO_BASE,
|
||||
.type = ARM_MPS2_IO_TYPE_FPGAIO};
|
||||
struct arm_mps2_io_dev_t ARM_MPS2_IO_FPGAIO_DEV =
|
||||
{&(ARM_MPS2_IO_FPGAIO_DEV_CFG)};
|
||||
#endif /* ARM_MPS2_IO_FPGAIO */
|
||||
|
||||
/* ARM MPS2 IO SCC driver structures */
|
||||
#ifdef ARM_MPS2_IO_SCC
|
||||
static const struct arm_mps2_io_dev_cfg_t ARM_MPS2_IO_SCC_DEV_CFG = {
|
||||
/*
|
||||
* MPS2 IO SCC and FPGAIO registers have similar structure
|
||||
* with 4 byte offset addresses.
|
||||
*/
|
||||
.base = MPS2_SCC_BASE + 4,
|
||||
.type = ARM_MPS2_IO_TYPE_SCC};
|
||||
struct arm_mps2_io_dev_t ARM_MPS2_IO_SCC_DEV = {&(ARM_MPS2_IO_SCC_DEV_CFG)};
|
||||
#endif /* ARM_MPS2_IO_SCC */
|
||||
|
||||
/* ARM SPI driver structure */
|
||||
#ifdef ARM_SPI0
|
||||
static const struct spi_pl022_dev_cfg_t SPI0_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP0_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI0_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI0_PL022_DEV = {&(SPI0_PL022_DEV_CFG),
|
||||
&(SPI0_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI0 */
|
||||
|
||||
#ifdef ARM_SPI1
|
||||
static const struct spi_pl022_dev_cfg_t SPI1_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP1_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI1_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI1_PL022_DEV = {&(SPI1_PL022_DEV_CFG),
|
||||
&(SPI1_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI1 */
|
||||
|
||||
#ifdef ARM_SPI2
|
||||
static const struct spi_pl022_dev_cfg_t SPI2_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP2_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI2_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI2_PL022_DEV = {&(SPI2_PL022_DEV_CFG),
|
||||
&(SPI2_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI2 */
|
||||
|
||||
#ifdef ARM_SPI3
|
||||
static const struct spi_pl022_dev_cfg_t SPI3_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP3_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI3_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI3_PL022_DEV = {&(SPI3_PL022_DEV_CFG),
|
||||
&(SPI3_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI3 */
|
||||
|
||||
#ifdef ARM_SPI4
|
||||
static const struct spi_pl022_dev_cfg_t SPI4_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP4_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI4_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI4_PL022_DEV = {&(SPI4_PL022_DEV_CFG),
|
||||
&(SPI4_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI4 */
|
||||
|
||||
/* ARM UART driver structures */
|
||||
#ifdef ARM_UART0
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART0_DEV_CFG = {
|
||||
.base = CMSDK_UART0_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART0_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART0_DEV = {&(ARM_UART0_DEV_CFG),
|
||||
&(ARM_UART0_DEV_DATA)};
|
||||
#endif /* ARM_UART0 */
|
||||
|
||||
#ifdef ARM_UART1
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART1_DEV_CFG = {
|
||||
.base = CMSDK_UART1_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART1_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART1_DEV = {&(ARM_UART1_DEV_CFG),
|
||||
&(ARM_UART1_DEV_DATA)};
|
||||
#endif /* ARM_UART1 */
|
||||
|
||||
#ifdef ARM_UART2
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART2_DEV_CFG = {
|
||||
.base = CMSDK_UART2_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART2_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART2_DEV = {&(ARM_UART2_DEV_CFG),
|
||||
&(ARM_UART2_DEV_DATA)};
|
||||
#endif /* ARM_UART2 */
|
||||
|
||||
#ifdef ARM_UART3
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART3_DEV_CFG = {
|
||||
.base = CMSDK_UART3_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART3_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART3_DEV = {&(ARM_UART3_DEV_CFG),
|
||||
&(ARM_UART3_DEV_DATA)};
|
||||
#endif /* ARM_UART3 */
|
||||
|
||||
#ifdef ARM_UART4
|
||||
static const struct arm_uart_dev_cfg_t ARM_UART4_DEV_CFG = {
|
||||
.base = CMSDK_UART4_BASE,
|
||||
.default_baudrate = DEFAULT_UART_BAUDRATE};
|
||||
static struct arm_uart_dev_data_t ARM_UART4_DEV_DATA = {
|
||||
.state = 0,
|
||||
.system_clk = 0,
|
||||
.baudrate = 0};
|
||||
struct arm_uart_dev_t ARM_UART4_DEV = {&(ARM_UART4_DEV_CFG),
|
||||
&(ARM_UART4_DEV_DATA)};
|
||||
#endif /* ARM_UART4 */
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018 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 __ARM_LTD_PLATFORM_DEVICES_H__
|
||||
#define __ARM_LTD_PLATFORM_DEVICES_H__
|
||||
|
||||
#include "device_cfg.h"
|
||||
|
||||
/* ======= Includes generic driver headers ======= */
|
||||
#include "timer_cmsdk_drv.h"
|
||||
#include "arm_gpio_drv.h"
|
||||
#include "arm_mps2_io_drv.h"
|
||||
#include "spi_pl022_drv.h"
|
||||
#include "arm_uart_drv.h"
|
||||
|
||||
/* ======= Defines peripheral configuration structures ======= */
|
||||
|
||||
/* ARM CMSDK Timer driver structures */
|
||||
#ifdef ARM_CMSDK_TIMER0
|
||||
extern struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV;
|
||||
#endif
|
||||
|
||||
#ifdef ARM_CMSDK_TIMER1
|
||||
extern struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV;
|
||||
#endif
|
||||
|
||||
/* ARM GPIO driver structures */
|
||||
#ifdef ARM_GPIO0
|
||||
extern struct arm_gpio_dev_t ARM_GPIO0_DEV;
|
||||
#endif
|
||||
#ifdef ARM_GPIO1
|
||||
extern struct arm_gpio_dev_t ARM_GPIO1_DEV;
|
||||
#endif
|
||||
#ifdef ARM_GPIO2
|
||||
extern struct arm_gpio_dev_t ARM_GPIO2_DEV;
|
||||
#endif
|
||||
#ifdef ARM_GPIO3
|
||||
extern struct arm_gpio_dev_t ARM_GPIO3_DEV;
|
||||
#endif
|
||||
|
||||
/* ARM MPS2 IO FPGAIO driver structures */
|
||||
#ifdef ARM_MPS2_IO_FPGAIO
|
||||
extern struct arm_mps2_io_dev_t ARM_MPS2_IO_FPGAIO_DEV;
|
||||
#endif
|
||||
|
||||
/* ARM MPS2 IO SCC driver structures */
|
||||
#ifdef ARM_MPS2_IO_SCC
|
||||
extern struct arm_mps2_io_dev_t ARM_MPS2_IO_SCC_DEV;
|
||||
#endif
|
||||
|
||||
/* ARM SPI driver structures */
|
||||
#ifdef ARM_SPI0
|
||||
extern struct spi_pl022_dev_t SPI0_PL022_DEV;
|
||||
#endif
|
||||
#ifdef ARM_SPI1
|
||||
extern struct spi_pl022_dev_t SPI1_PL022_DEV;
|
||||
#endif
|
||||
#ifdef ARM_SPI2
|
||||
extern struct spi_pl022_dev_t SPI2_PL022_DEV;
|
||||
#endif
|
||||
#ifdef ARM_SPI3
|
||||
extern struct spi_pl022_dev_t SPI3_PL022_DEV;
|
||||
#endif
|
||||
#ifdef ARM_SPI4
|
||||
extern struct spi_pl022_dev_t SPI4_PL022_DEV;
|
||||
#endif
|
||||
|
||||
/* ARM UART driver structures */
|
||||
#ifdef ARM_UART0
|
||||
extern struct arm_uart_dev_t ARM_UART0_DEV;
|
||||
#endif
|
||||
#ifdef ARM_UART1
|
||||
extern struct arm_uart_dev_t ARM_UART1_DEV;
|
||||
#endif
|
||||
#ifdef ARM_UART2
|
||||
extern struct arm_uart_dev_t ARM_UART2_DEV;
|
||||
#endif
|
||||
#ifdef ARM_UART3
|
||||
extern struct arm_uart_dev_t ARM_UART3_DEV;
|
||||
#endif
|
||||
#ifdef ARM_UART4
|
||||
extern struct arm_uart_dev_t ARM_UART4_DEV;
|
||||
#endif
|
||||
|
||||
#endif /* __ARM_LTD_PLATFORM_DEVICES_H__ */
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -17,177 +17,236 @@
|
|||
#include <stddef.h>
|
||||
#include "gpio_api.h"
|
||||
#include "pinmap.h"
|
||||
#include "objects.h"
|
||||
#include "mbed_error.h"
|
||||
|
||||
#define GPIO_PIN_POS_MASK 0x0F /* pin % 16 */
|
||||
#define RESERVED_MISC_PIN 7
|
||||
enum io_type {
|
||||
GPIO_DEVICE,
|
||||
MPS2_IO_DEVICE,
|
||||
DEVICE_UNKNOWN
|
||||
};
|
||||
|
||||
/* \brief Gets the FPGA MISC (Miscellaneous control) bit position for the given
|
||||
* pin name
|
||||
*
|
||||
* FPGA MISC bit mapping:
|
||||
* [31:7] Reserved
|
||||
* [6] CLCD_BL_CTRL
|
||||
* [5] CLCD_RD
|
||||
* [4] CLCD_RS
|
||||
* [3] CLCD_RESET
|
||||
* [2] Reserved
|
||||
* [1] SPI_nSS
|
||||
* [0] CLCD_CS
|
||||
*
|
||||
* \param[in] pin MISC pin name
|
||||
*
|
||||
* \return FPGA MISC bit position
|
||||
*/
|
||||
static uint8_t get_fpga_misc_pin_pos(PinName pin)
|
||||
/* Tell if the gpio is from GPIO device or MPS2 IO */
|
||||
static enum io_type io_type(gpio_t *obj)
|
||||
{
|
||||
uint8_t pin_position = RESERVED_MISC_PIN;
|
||||
|
||||
if (pin == SPI_SCLK) {
|
||||
pin_position = 0;
|
||||
} else if (pin == CLCD_SSEL) {
|
||||
pin_position = 1;
|
||||
} else if (pin == CLCD_RESET) {
|
||||
pin_position = 3;
|
||||
} else if (pin == CLCD_RS) {
|
||||
pin_position = 4;
|
||||
} else if (pin == CLCD_RD) {
|
||||
pin_position = 5;
|
||||
} else if (pin == CLCD_BL_CTRL){
|
||||
pin_position = 6;
|
||||
if (obj->gpio_dev != NULL && obj->mps2_io_dev == NULL) {
|
||||
return GPIO_DEVICE;
|
||||
}
|
||||
|
||||
return pin_position;
|
||||
if (obj->gpio_dev == NULL && obj->mps2_io_dev != NULL) {
|
||||
return MPS2_IO_DEVICE;
|
||||
}
|
||||
return DEVICE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Return the correct mask of the given PIN */
|
||||
uint32_t gpio_set(PinName pin)
|
||||
{
|
||||
uint8_t pin_position;
|
||||
pin_function(pin, (int)GPIO_FUNC);
|
||||
|
||||
if (pin >=EXP0 && pin <= EXP51) {
|
||||
/* Set pin functinality as GPIO. pin_function asserts if pin == NC */
|
||||
pin_function(pin, GPIO_FUNC);
|
||||
if (pin >= EXP0 && pin <= EXP51) {
|
||||
/* GPIO pins */
|
||||
return (1 << GPIO_PIN_NUMBER(pin));
|
||||
} else if (pin == USERLED1 || pin == USERLED2) {
|
||||
/* User LEDs */
|
||||
return (1 << (pin - USERLED1));
|
||||
} else if (pin == USERSW1 || pin == USERSW2) {
|
||||
/* User Push buttons */
|
||||
return (1 << (pin - USERSW1));
|
||||
} else if (pin >= LED1 && pin <= LED8) {
|
||||
/* MCC LEDs */
|
||||
return (1 << (pin - LED1));
|
||||
} else if (pin >= SW1 && pin <= SW8) {
|
||||
/* MCC Switches */
|
||||
return (1 << (pin - SW1));
|
||||
} else {
|
||||
/* Check if pin is a MISC pin */
|
||||
pin_position = get_fpga_misc_pin_pos(pin);
|
||||
if (pin_position != RESERVED_MISC_PIN) {
|
||||
return (1 << pin_position);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return pin mask */
|
||||
return (1 << (pin & 0xFF));
|
||||
}
|
||||
|
||||
void gpio_init(gpio_t *obj, PinName pin)
|
||||
{
|
||||
uint8_t pin_position;
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
|
||||
if (pin == NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
obj->pin = pin;
|
||||
obj->pin_number = pin;
|
||||
|
||||
if (pin <= EXP15) {
|
||||
obj->reg_data = &CMSDK_GPIO0->DATAOUT;
|
||||
obj->reg_in = &CMSDK_GPIO0->DATA;
|
||||
obj->reg_dir = &CMSDK_GPIO0->OUTENABLESET;
|
||||
obj->reg_dirclr = &CMSDK_GPIO0->OUTENABLECLR;
|
||||
/* Set pin function as a GPIO */
|
||||
pin_function(pin, GPIO_FUNC);
|
||||
pin_position = pin;
|
||||
} else if (pin >= EXP16 && pin <= EXP31) {
|
||||
obj->reg_data = &CMSDK_GPIO1->DATAOUT;
|
||||
obj->reg_in = &CMSDK_GPIO1->DATA;
|
||||
obj->reg_dir = &CMSDK_GPIO1->OUTENABLESET;
|
||||
obj->reg_dirclr = &CMSDK_GPIO1->OUTENABLECLR;
|
||||
/* Set pin function as a GPIO */
|
||||
pin_function(pin, GPIO_FUNC);
|
||||
pin_position = (pin & GPIO_PIN_POS_MASK);
|
||||
} else if (pin >= EXP32 && pin <= EXP47) {
|
||||
obj->reg_data = &CMSDK_GPIO2->DATAOUT;
|
||||
obj->reg_in = &CMSDK_GPIO2->DATA;
|
||||
obj->reg_dir = &CMSDK_GPIO2->OUTENABLESET;
|
||||
obj->reg_dirclr = &CMSDK_GPIO2->OUTENABLECLR;
|
||||
/* Set pin function as a GPIO */
|
||||
pin_function(pin, GPIO_FUNC);
|
||||
pin_position = (pin & GPIO_PIN_POS_MASK);
|
||||
} else if (pin >= EXP48 && pin <= EXP51) {
|
||||
obj->reg_data = &CMSDK_GPIO3->DATAOUT;
|
||||
obj->reg_in = &CMSDK_GPIO3->DATA;
|
||||
obj->reg_dir = &CMSDK_GPIO3->OUTENABLESET;
|
||||
obj->reg_dirclr = &CMSDK_GPIO3->OUTENABLECLR;
|
||||
/* Set pin function as a GPIO */
|
||||
pin_function(pin, GPIO_FUNC);
|
||||
pin_position = (pin & GPIO_PIN_POS_MASK);
|
||||
} else if (pin == 100 || pin == 101) {
|
||||
/* User LEDs */
|
||||
pin_position = (pin - 100);
|
||||
obj->reg_data = &MPS2_FPGAIO->LED;
|
||||
obj->reg_in = &MPS2_FPGAIO->LED;
|
||||
obj->reg_dir = NULL;
|
||||
obj->reg_dirclr = NULL;
|
||||
} else if (pin == 110 || pin == 111) {
|
||||
/* User buttons */
|
||||
pin_position = (pin - 110);
|
||||
obj->reg_data = &MPS2_FPGAIO->BUTTON;
|
||||
obj->reg_in = &MPS2_FPGAIO->BUTTON;
|
||||
obj->reg_dir = NULL;
|
||||
obj->reg_dirclr = NULL;
|
||||
} else if (pin >= 200 && pin <= 207) {
|
||||
/* MCC LEDs */
|
||||
pin_position = (pin - 200);
|
||||
obj->reg_data = &MPS2_SCC->LEDS;
|
||||
obj->reg_in = &MPS2_SCC->LEDS;
|
||||
obj->reg_dir = NULL;
|
||||
obj->reg_dirclr = NULL;
|
||||
} else if (pin >= 210 && pin <= 217) {
|
||||
/* MCC switches */
|
||||
pin_position = (pin - 210);
|
||||
obj->reg_in = &MPS2_SCC->SWITCHES;
|
||||
obj->reg_data = NULL;
|
||||
obj->reg_dir = NULL;
|
||||
obj->reg_dirclr = NULL;
|
||||
} else {
|
||||
/* Check if pin is a MISC pin */
|
||||
pin_position = get_fpga_misc_pin_pos(pin);
|
||||
if (pin_position != RESERVED_MISC_PIN) {
|
||||
obj->reg_data = &MPS2_FPGAIO->MISC;
|
||||
} else {
|
||||
pin_position = 0;
|
||||
if (pin >= EXP0 && pin <= EXP51) {
|
||||
/* GPIO pins */
|
||||
switch (GPIO_DEV_NUMBER(pin)) {
|
||||
#ifdef ARM_GPIO0
|
||||
case GPIO0_NUMBER:
|
||||
gpio_dev = &ARM_GPIO0_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO0 */
|
||||
#ifdef ARM_GPIO1
|
||||
case GPIO1_NUMBER:
|
||||
gpio_dev = &ARM_GPIO1_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO1 */
|
||||
#ifdef ARM_GPIO2
|
||||
case GPIO2_NUMBER:
|
||||
gpio_dev = &ARM_GPIO2_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO2 */
|
||||
#ifdef ARM_GPIO3
|
||||
case GPIO3_NUMBER:
|
||||
gpio_dev = &ARM_GPIO3_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO3 */
|
||||
default:
|
||||
error("GPIO %d, associated with expansion pin %d, is disabled",
|
||||
GPIO_DEV_NUMBER(pin), pin);
|
||||
return;
|
||||
}
|
||||
|
||||
arm_gpio_init(gpio_dev);
|
||||
|
||||
obj->gpio_dev = gpio_dev;
|
||||
obj->mps2_io_dev = NULL;
|
||||
obj->pin_number = GPIO_PIN_NUMBER(pin);
|
||||
/* GPIO is input by default */
|
||||
obj->direction = PIN_INPUT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set pin mask */
|
||||
obj->mask = (1 << pin_position);
|
||||
#ifdef ARM_MPS2_IO_FPGAIO
|
||||
if (pin == USERLED1 || pin == USERLED2) {
|
||||
/* User LEDs */
|
||||
obj->gpio_dev = NULL;
|
||||
obj->mps2_io_dev = &ARM_MPS2_IO_FPGAIO_DEV;
|
||||
obj->pin_number = pin - USERLED1;
|
||||
obj->direction = PIN_OUTPUT;
|
||||
return;
|
||||
} else if (pin == USERSW1 || pin == USERSW2) {
|
||||
/* User Push buttons */
|
||||
obj->gpio_dev = NULL;
|
||||
obj->mps2_io_dev = &ARM_MPS2_IO_FPGAIO_DEV;
|
||||
obj->pin_number = pin - USERSW1;
|
||||
obj->direction = PIN_INPUT;
|
||||
return;
|
||||
}
|
||||
#endif /* ARM_MPS2_IO_FPGAIO */
|
||||
|
||||
#ifdef ARM_MPS2_IO_SCC
|
||||
if (pin >= LED1 && pin <= LED8) {
|
||||
/* MCC LEDs */
|
||||
obj->gpio_dev = NULL;
|
||||
obj->mps2_io_dev = &ARM_MPS2_IO_SCC_DEV;
|
||||
obj->pin_number = pin - LED1;
|
||||
obj->direction = PIN_OUTPUT;
|
||||
return;
|
||||
} else if (pin >= SW1 && pin <= SW8) {
|
||||
/* MCC Switches */
|
||||
obj->gpio_dev = NULL;
|
||||
obj->mps2_io_dev = &ARM_MPS2_IO_SCC_DEV;
|
||||
obj->pin_number = pin - SW1;
|
||||
obj->direction = PIN_INPUT;
|
||||
return;
|
||||
}
|
||||
#endif /* ARM_MPS2_IO_SCC */
|
||||
|
||||
error("pin %d is not a GPIO", pin);
|
||||
}
|
||||
|
||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||
{
|
||||
pin_mode(obj->pin, mode);
|
||||
/* PinMode is not supported */
|
||||
}
|
||||
|
||||
void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||
{
|
||||
if (obj->pin >= EXP0 && obj->pin <= EXP51) {
|
||||
uint32_t flags = ARM_GPIO_PIN_ENABLE;
|
||||
|
||||
obj->direction = direction;
|
||||
|
||||
switch (io_type(obj)) {
|
||||
case GPIO_DEVICE:
|
||||
switch (direction) {
|
||||
case PIN_INPUT :
|
||||
*obj->reg_dirclr = obj->mask;
|
||||
break;
|
||||
case PIN_OUTPUT:
|
||||
*obj->reg_dir |= obj->mask;
|
||||
break;
|
||||
case PIN_INPUT:
|
||||
flags |= ARM_GPIO_INPUT;
|
||||
break;
|
||||
case PIN_OUTPUT:
|
||||
flags |= ARM_GPIO_OUTPUT;
|
||||
break;
|
||||
/* default: not added to force to cover all enumeration cases */
|
||||
}
|
||||
|
||||
(void)arm_gpio_config(obj->gpio_dev, ARM_GPIO_ACCESS_PIN,
|
||||
obj->pin_number, flags);
|
||||
return;
|
||||
case MPS2_IO_DEVICE:
|
||||
/* Do nothing as MPS2 IO direction can not be changed */
|
||||
return;
|
||||
case DEVICE_UNKNOWN:
|
||||
break;
|
||||
/* default: The default is not defined intentionally to force the
|
||||
* compiler to check that all the enumeration values are
|
||||
* covered in the switch.*/
|
||||
}
|
||||
|
||||
error("can not change the direction of pin");
|
||||
}
|
||||
|
||||
int gpio_is_connected(const gpio_t *obj)
|
||||
{
|
||||
if (obj->pin != (PinName)NC) {
|
||||
if (obj->pin_number == (uint32_t)NC) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpio_write(gpio_t *obj, int value)
|
||||
{
|
||||
switch (io_type(obj)) {
|
||||
case GPIO_DEVICE:
|
||||
(void)arm_gpio_write(obj->gpio_dev, ARM_GPIO_ACCESS_PIN,
|
||||
obj->pin_number, (uint32_t)value);
|
||||
return;
|
||||
case MPS2_IO_DEVICE:
|
||||
if (obj->direction == PIN_INPUT) {
|
||||
/*
|
||||
* If the given gpio is in fact a button, ignore the call to not
|
||||
* write to the corresponding LED instead.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
arm_mps2_io_write_leds(obj->mps2_io_dev, ARM_MPS2_IO_ACCESS_PIN,
|
||||
obj->pin_number, (uint32_t)value);
|
||||
return;
|
||||
case DEVICE_UNKNOWN:
|
||||
break;
|
||||
/* default: The default is not defined intentionally to force the
|
||||
* compiler to check that all the enumeration values are
|
||||
* covered in the switch.*/
|
||||
}
|
||||
|
||||
error("can not write pin");
|
||||
}
|
||||
|
||||
int gpio_read(gpio_t *obj)
|
||||
{
|
||||
switch (io_type(obj)) {
|
||||
case GPIO_DEVICE:
|
||||
return (int)arm_gpio_read(obj->gpio_dev, ARM_GPIO_ACCESS_PIN,
|
||||
obj->pin_number);
|
||||
case MPS2_IO_DEVICE:
|
||||
switch (obj->direction) {
|
||||
case PIN_INPUT:
|
||||
|
||||
return (int)arm_mps2_io_read_buttons(obj->mps2_io_dev,
|
||||
ARM_MPS2_IO_ACCESS_PIN,
|
||||
obj->pin_number);
|
||||
case PIN_OUTPUT:
|
||||
return (int)arm_mps2_io_read_leds(obj->mps2_io_dev,
|
||||
ARM_MPS2_IO_ACCESS_PIN,
|
||||
obj->pin_number);
|
||||
}
|
||||
|
||||
case DEVICE_UNKNOWN:
|
||||
break;
|
||||
/* default: The default is not defined intentionally to force the
|
||||
* compiler to check that all the enumeration values are
|
||||
* covered in the switch.*/
|
||||
}
|
||||
|
||||
error("can not read pin");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -14,425 +14,192 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "cmsis.h"
|
||||
#include "objects.h"
|
||||
#include "gpio_irq_api.h"
|
||||
#include "mbed_error.h"
|
||||
|
||||
#define CHANNEL_NUM 32
|
||||
#define CMSDK_GPIO_0 CMSDK_GPIO0
|
||||
#define CMSDK_GPIO_1 CMSDK_GPIO1
|
||||
#define PININT_IRQ 0
|
||||
#define ERROR_BIT_NUMBER 0xFF
|
||||
|
||||
static uint32_t channel_ids[CHANNEL_NUM] = {0};
|
||||
static gpio_irq_handler irq_handler;
|
||||
struct gpio_irq_handler_t {
|
||||
gpio_irq_handler handler;
|
||||
gpio_irq_event event;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
static inline void handle_interrupt_in(uint32_t channel)
|
||||
/* Handlers registered */
|
||||
static struct gpio_irq_handler_t gpio_irq[PINS_NUMBER];
|
||||
|
||||
/*
|
||||
* Return the bit number of the lowest significant bit set to 1 or
|
||||
* ERROR_BIT_NUMBER if there is no bit set.
|
||||
*/
|
||||
static uint8_t find_first_set_bit(uint32_t word)
|
||||
{
|
||||
uint32_t ch_bit = (1 << channel);
|
||||
// Return immediately if:
|
||||
// * The interrupt was already served
|
||||
// * There is no user handler
|
||||
// * It is a level interrupt, not an edge interrupt
|
||||
if (ch_bit < 16) {
|
||||
if (((CMSDK_GPIO_0->INTSTATUS) == 0)
|
||||
|| (channel_ids[channel] == 0)
|
||||
|| ((CMSDK_GPIO_0->INTTYPESET) == 0) ) {
|
||||
return;
|
||||
}
|
||||
uint8_t bit_number = 0;
|
||||
|
||||
if ((CMSDK_GPIO_0->INTTYPESET & ch_bit) && (CMSDK_GPIO_0->INTPOLSET & ch_bit)) {
|
||||
irq_handler(channel_ids[channel], IRQ_RISE);
|
||||
CMSDK_GPIO_0->INTPOLSET = ch_bit;
|
||||
}
|
||||
if ((CMSDK_GPIO_0->INTTYPESET & ch_bit) && ~(CMSDK_GPIO_0->INTPOLSET & ch_bit)) {
|
||||
irq_handler(channel_ids[channel], IRQ_FALL);
|
||||
}
|
||||
|
||||
CMSDK_GPIO_0->INTCLEAR = ch_bit;
|
||||
} else {
|
||||
if (((CMSDK_GPIO_1->INTSTATUS) == 0)
|
||||
|| (channel_ids[channel] == 0)
|
||||
|| ((CMSDK_GPIO_1->INTTYPESET) == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((CMSDK_GPIO_1->INTTYPESET & ch_bit) && (CMSDK_GPIO_1->INTPOLSET & ch_bit)) {
|
||||
irq_handler(channel_ids[channel], IRQ_RISE);
|
||||
CMSDK_GPIO_1->INTPOLSET = ch_bit;
|
||||
}
|
||||
if ((CMSDK_GPIO_1->INTTYPESET & ch_bit) && ~(CMSDK_GPIO_1->INTPOLSET & ch_bit)) {
|
||||
irq_handler(channel_ids[channel], IRQ_FALL);
|
||||
}
|
||||
CMSDK_GPIO_1->INTCLEAR = ch_bit;
|
||||
if (word == 0) {
|
||||
return ERROR_BIT_NUMBER;
|
||||
}
|
||||
|
||||
while (((word >> bit_number++) & 1UL) == 0);
|
||||
|
||||
return (bit_number - 1);
|
||||
}
|
||||
|
||||
void gpio0_irq0(void)
|
||||
static void handler(struct arm_gpio_dev_t* dev, uint32_t gpio_number,
|
||||
uint32_t exp_pin_base)
|
||||
{
|
||||
handle_interrupt_in(0);
|
||||
uint32_t irq_status = 0;
|
||||
/* Pin that triggered the IRQ in this GPIO */
|
||||
uint8_t pin_number;
|
||||
/* Pin number in the expension port */
|
||||
uint8_t exp_pin_number;
|
||||
|
||||
(void)arm_gpio_get_irq_status(dev, ARM_GPIO_ACCESS_PORT, ARG_NOT_USED,
|
||||
&irq_status);
|
||||
|
||||
pin_number = find_first_set_bit(irq_status);
|
||||
if (pin_number == ERROR_BIT_NUMBER) {
|
||||
/* There was no IRQ */
|
||||
return;
|
||||
}
|
||||
|
||||
(void)arm_gpio_clear_interrupt(dev, pin_number);
|
||||
|
||||
exp_pin_number = exp_pin_base + pin_number;
|
||||
|
||||
gpio_irq[exp_pin_number].handler(gpio_irq[exp_pin_number].id,
|
||||
gpio_irq[exp_pin_number].event);
|
||||
}
|
||||
|
||||
void gpio0_irq1(void)
|
||||
#ifdef ARM_GPIO0
|
||||
void PORT0_IRQHandler(void)
|
||||
{
|
||||
handle_interrupt_in(1);
|
||||
handler(&ARM_GPIO0_DEV, GPIO0_NUMBER, EXP_PIN_BASE0);
|
||||
}
|
||||
#endif /* ARM_GPIO0 */
|
||||
|
||||
void gpio0_irq2(void)
|
||||
#ifdef ARM_GPIO1
|
||||
void PORT1_ALL_IRQHandler(void)
|
||||
{
|
||||
handle_interrupt_in(2);
|
||||
handler(&ARM_GPIO1_DEV, GPIO1_NUMBER, EXP_PIN_BASE1);
|
||||
}
|
||||
#endif /* ARM_GPIO1 */
|
||||
|
||||
void gpio0_irq3(void)
|
||||
#ifdef ARM_GPIO2
|
||||
void PORT2_ALL_IRQHandler(void)
|
||||
{
|
||||
handle_interrupt_in(3);
|
||||
handler(&ARM_GPIO2_DEV, GPIO2_NUMBER, EXP_PIN_BASE2);
|
||||
}
|
||||
#endif /* ARM_GPIO2 */
|
||||
|
||||
void gpio0_irq4(void)
|
||||
#ifdef ARM_GPIO3
|
||||
void PORT3_ALL_IRQHandler(void)
|
||||
{
|
||||
handle_interrupt_in(4);
|
||||
handler(&ARM_GPIO3_DEV, GPIO3_NUMBER, EXP_PIN_BASE3);
|
||||
}
|
||||
#endif /* ARM_GPIO3 */
|
||||
|
||||
void gpio0_irq5(void)
|
||||
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler,
|
||||
uint32_t id)
|
||||
{
|
||||
handle_interrupt_in(5);
|
||||
}
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
|
||||
void gpio0_irq6(void)
|
||||
{
|
||||
handle_interrupt_in(6);
|
||||
}
|
||||
if (pin >= EXP0 && pin <= EXP51) {
|
||||
/* GPIO pins */
|
||||
switch (GPIO_DEV_NUMBER(pin)) {
|
||||
#ifdef ARM_GPIO0
|
||||
case 0:
|
||||
gpio_dev = &ARM_GPIO0_DEV;
|
||||
obj->irq_number = PORT0_ALL_IRQn;
|
||||
break;
|
||||
#endif /* ARM_GPIO0 */
|
||||
#ifdef ARM_GPIO1
|
||||
case 1:
|
||||
gpio_dev = &ARM_GPIO1_DEV;
|
||||
obj->irq_number = PORT1_ALL_IRQn;
|
||||
break;
|
||||
#endif /* ARM_GPIO1 */
|
||||
#ifdef ARM_GPIO2
|
||||
case 2:
|
||||
gpio_dev = &ARM_GPIO2_DEV;
|
||||
obj->irq_number = PORT2_ALL_IRQn;
|
||||
break;
|
||||
#endif /* ARM_GPIO2 */
|
||||
#ifdef ARM_GPIO3
|
||||
case 3:
|
||||
gpio_dev = &ARM_GPIO3_DEV;
|
||||
obj->irq_number = PORT3_ALL_IRQn;
|
||||
break;
|
||||
#endif /* ARM_GPIO3 */
|
||||
default:
|
||||
error("GPIO %d is not enabled", GPIO_DEV_NUMBER(pin));
|
||||
return -1;
|
||||
}
|
||||
|
||||
void gpio0_irq7(void)
|
||||
{
|
||||
handle_interrupt_in(7);
|
||||
}
|
||||
obj->gpio_dev = gpio_dev;
|
||||
obj->pin_number = GPIO_PIN_NUMBER(pin);
|
||||
obj->exp_pin_number = pin;
|
||||
|
||||
void gpio0_irq8(void)
|
||||
{
|
||||
handle_interrupt_in(8);
|
||||
}
|
||||
arm_gpio_init(gpio_dev);
|
||||
|
||||
void gpio0_irq9(void)
|
||||
{
|
||||
handle_interrupt_in(9);
|
||||
}
|
||||
/* Save the handler and id into the global structure */
|
||||
gpio_irq[pin].handler = handler;
|
||||
gpio_irq[pin].id = id;
|
||||
|
||||
void gpio0_irq10(void)
|
||||
{
|
||||
handle_interrupt_in(10);
|
||||
}
|
||||
|
||||
void gpio0_irq11(void)
|
||||
{
|
||||
handle_interrupt_in(11);
|
||||
}
|
||||
|
||||
void gpio0_irq12(void)
|
||||
{
|
||||
handle_interrupt_in(12);
|
||||
}
|
||||
|
||||
void gpio0_irq13(void)
|
||||
{
|
||||
handle_interrupt_in(13);
|
||||
}
|
||||
|
||||
void gpio0_irq14(void)
|
||||
{
|
||||
handle_interrupt_in(14);
|
||||
}
|
||||
|
||||
void gpio0_irq15(void)
|
||||
{
|
||||
handle_interrupt_in(15);
|
||||
}
|
||||
|
||||
void gpio1_irq0(void)
|
||||
{
|
||||
handle_interrupt_in(16);
|
||||
}
|
||||
|
||||
void gpio1_irq1(void)
|
||||
{
|
||||
handle_interrupt_in(17);
|
||||
}
|
||||
void gpio1_irq2(void)
|
||||
{
|
||||
handle_interrupt_in(18);
|
||||
}
|
||||
|
||||
void gpio1_irq3(void)
|
||||
{
|
||||
handle_interrupt_in(19);
|
||||
}
|
||||
|
||||
void gpio1_irq4(void)
|
||||
{
|
||||
handle_interrupt_in(20);
|
||||
}
|
||||
|
||||
void gpio1_irq5(void)
|
||||
{
|
||||
handle_interrupt_in(21);
|
||||
}
|
||||
|
||||
void gpio1_irq6(void)
|
||||
{
|
||||
handle_interrupt_in(22);
|
||||
}
|
||||
|
||||
void gpio1_irq7(void)
|
||||
{
|
||||
handle_interrupt_in(23);
|
||||
}
|
||||
|
||||
void gpio1_irq8(void)
|
||||
{
|
||||
handle_interrupt_in(24);
|
||||
}
|
||||
|
||||
void gpio1_irq9(void)
|
||||
{
|
||||
handle_interrupt_in(25);
|
||||
}
|
||||
|
||||
void gpio1_irq10(void)
|
||||
{
|
||||
handle_interrupt_in(26);
|
||||
}
|
||||
|
||||
void gpio1_irq11(void)
|
||||
{
|
||||
handle_interrupt_in(27);
|
||||
}
|
||||
|
||||
void gpio1_irq12(void)
|
||||
{
|
||||
handle_interrupt_in(28);
|
||||
}
|
||||
|
||||
void gpio1_irq13(void)
|
||||
{
|
||||
handle_interrupt_in(29);
|
||||
}
|
||||
|
||||
void gpio1_irq14(void)
|
||||
{
|
||||
handle_interrupt_in(30);
|
||||
}
|
||||
|
||||
void gpio1_irq15(void)
|
||||
{
|
||||
handle_interrupt_in(31);
|
||||
}
|
||||
|
||||
int gpio_irq_init(gpio_irq_t *obj, PinName pin,
|
||||
gpio_irq_handler handler, uint32_t id)
|
||||
{
|
||||
int found_free_channel = 0;
|
||||
int i = 0;
|
||||
|
||||
if (pin == NC) {
|
||||
return 0;
|
||||
} else {
|
||||
/* The pin is not concerned with GPIO IRQ */
|
||||
error("Pin %d is not a GPIO", pin);
|
||||
return -1;
|
||||
}
|
||||
|
||||
irq_handler = handler;
|
||||
|
||||
for (i=0; i<CHANNEL_NUM; i++) {
|
||||
if (channel_ids[i] == 0) {
|
||||
channel_ids[i] = id;
|
||||
obj->ch = i;
|
||||
found_free_channel = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_free_channel) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* To select a pin for any of the eight pin interrupts, write the pin number
|
||||
* as 0 to 23 for pins PIO0_0 to PIO0_23 and 24 to 55.
|
||||
* @see: mbed_capi/PinNames.h
|
||||
*/
|
||||
if (pin <16) {
|
||||
CMSDK_GPIO_0->INTENSET |= (0x1 << pin);
|
||||
}
|
||||
|
||||
if (pin >= 16) {
|
||||
CMSDK_GPIO_1->INTENSET |= (0x1 << pin);
|
||||
}
|
||||
|
||||
void (*channels_irq)(void) = NULL;
|
||||
switch (obj->ch) {
|
||||
case 0:
|
||||
channels_irq = &gpio0_irq0;
|
||||
break;
|
||||
case 1:
|
||||
channels_irq = &gpio0_irq1;
|
||||
break;
|
||||
case 2:
|
||||
channels_irq = &gpio0_irq2;
|
||||
break;
|
||||
case 3:
|
||||
channels_irq = &gpio0_irq3;
|
||||
break;
|
||||
case 4:
|
||||
channels_irq = &gpio0_irq4;
|
||||
break;
|
||||
case 5:
|
||||
channels_irq = &gpio0_irq5;
|
||||
break;
|
||||
case 6:
|
||||
channels_irq = &gpio0_irq6;
|
||||
break;
|
||||
case 7:
|
||||
channels_irq = &gpio0_irq7;
|
||||
break;
|
||||
case 8:
|
||||
channels_irq = &gpio0_irq8;
|
||||
break;
|
||||
case 9:
|
||||
channels_irq = &gpio0_irq9;
|
||||
break;
|
||||
case 10:
|
||||
channels_irq = &gpio0_irq10;
|
||||
break;
|
||||
case 11:
|
||||
channels_irq = &gpio0_irq11;
|
||||
break;
|
||||
case 12:
|
||||
channels_irq = &gpio0_irq12;
|
||||
break;
|
||||
case 13:
|
||||
channels_irq = &gpio0_irq13;
|
||||
break;
|
||||
case 14:
|
||||
channels_irq = &gpio0_irq14;
|
||||
break;
|
||||
case 15:
|
||||
channels_irq = &gpio0_irq15;
|
||||
break;
|
||||
case 16:
|
||||
channels_irq = &gpio1_irq0;
|
||||
break;
|
||||
case 17:
|
||||
channels_irq = &gpio1_irq1;
|
||||
break;
|
||||
case 18:
|
||||
channels_irq = &gpio1_irq2;
|
||||
break;
|
||||
case 19:
|
||||
channels_irq = &gpio1_irq3;
|
||||
break;
|
||||
case 20:
|
||||
channels_irq = &gpio1_irq4;
|
||||
break;
|
||||
case 21:
|
||||
channels_irq = &gpio1_irq5;
|
||||
break;
|
||||
case 22:
|
||||
channels_irq = &gpio1_irq6;
|
||||
break;
|
||||
case 23:
|
||||
channels_irq = &gpio1_irq7;
|
||||
break;
|
||||
case 24:
|
||||
channels_irq = &gpio1_irq8;
|
||||
break;
|
||||
case 25:
|
||||
channels_irq = &gpio1_irq9;
|
||||
break;
|
||||
case 26:
|
||||
channels_irq = &gpio1_irq10;
|
||||
break;
|
||||
case 27:
|
||||
channels_irq = &gpio1_irq11;
|
||||
break;
|
||||
case 28:
|
||||
channels_irq = &gpio1_irq12;
|
||||
break;
|
||||
case 29:
|
||||
channels_irq = &gpio1_irq13;
|
||||
break;
|
||||
case 30:
|
||||
channels_irq = &gpio1_irq14;
|
||||
break;
|
||||
case 31:
|
||||
channels_irq = &gpio1_irq15;
|
||||
break;
|
||||
}
|
||||
|
||||
NVIC_SetVector((IRQn_Type)(PININT_IRQ + obj->ch), (uint32_t)channels_irq);
|
||||
NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ + obj->ch));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpio_irq_free(gpio_irq_t *obj)
|
||||
{
|
||||
channel_ids[obj->ch] = 0;
|
||||
/* Not implemented because the device can not be uninitialized. */
|
||||
}
|
||||
|
||||
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
|
||||
{
|
||||
unsigned int ch_bit = (1 << obj->ch);
|
||||
/* Interrupt is set on an input pin on rising or falling edge */
|
||||
uint32_t flags = ARM_GPIO_PIN_ENABLE | ARM_GPIO_INPUT | ARM_GPIO_IRQ |
|
||||
ARM_GPIO_IRQ_EDGE;
|
||||
|
||||
if (obj->ch <16) {
|
||||
/* Clear interrupt */
|
||||
if (!(CMSDK_GPIO_0->INTTYPESET & ch_bit)) {
|
||||
CMSDK_GPIO_0->INTCLEAR = ch_bit;
|
||||
}
|
||||
CMSDK_GPIO_0->INTTYPESET &= ch_bit;
|
||||
switch (event) {
|
||||
case IRQ_RISE:
|
||||
flags |= ARM_GPIO_IRQ_ACTIVE_HIGH;
|
||||
break;
|
||||
case IRQ_FALL:
|
||||
flags |= ARM_GPIO_IRQ_ACTIVE_LOW;
|
||||
break;
|
||||
case IRQ_NONE:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set interrupt */
|
||||
if (event == IRQ_RISE) {
|
||||
CMSDK_GPIO_0->INTPOLSET |= ch_bit;
|
||||
if (enable) {
|
||||
CMSDK_GPIO_0->INTENSET |= ch_bit;
|
||||
} else {
|
||||
CMSDK_GPIO_0->INTENCLR |= ch_bit;
|
||||
}
|
||||
} else {
|
||||
CMSDK_GPIO_0->INTPOLCLR |= ch_bit;
|
||||
if (enable) {
|
||||
CMSDK_GPIO_0->INTENSET |= ch_bit;
|
||||
} else {
|
||||
CMSDK_GPIO_0->INTENCLR |= ch_bit;
|
||||
}
|
||||
}
|
||||
(void)arm_gpio_config(obj->gpio_dev, ARM_GPIO_ACCESS_PIN, obj->pin_number,
|
||||
flags);
|
||||
|
||||
/* Record the event type of this pin */
|
||||
gpio_irq[obj->exp_pin_number].event = event;
|
||||
|
||||
NVIC_EnableIRQ(obj->irq_number);
|
||||
|
||||
if (enable) {
|
||||
gpio_irq_enable(obj);
|
||||
} else {
|
||||
/* Clear interrupt */
|
||||
if (!(CMSDK_GPIO_1->INTTYPESET & ch_bit)) {
|
||||
CMSDK_GPIO_1->INTCLEAR = ch_bit;
|
||||
}
|
||||
CMSDK_GPIO_1->INTTYPESET &= ch_bit;
|
||||
|
||||
/* Set interrupt */
|
||||
if (event == IRQ_RISE) {
|
||||
CMSDK_GPIO_1->INTPOLSET |= ch_bit;
|
||||
if (enable) {
|
||||
CMSDK_GPIO_1->INTENSET |= ch_bit;
|
||||
} else {
|
||||
CMSDK_GPIO_1->INTENCLR |= ch_bit;
|
||||
}
|
||||
} else {
|
||||
CMSDK_GPIO_1->INTPOLCLR |= ch_bit;
|
||||
if (enable) {
|
||||
CMSDK_GPIO_1->INTENSET |= ch_bit;
|
||||
} else {
|
||||
CMSDK_GPIO_1->INTENCLR |= ch_bit;
|
||||
}
|
||||
}
|
||||
gpio_irq_disable(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_irq_enable(gpio_irq_t *obj)
|
||||
{
|
||||
NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ + obj->ch));
|
||||
(void)arm_gpio_set_interrupt(obj->gpio_dev, ARM_GPIO_ACCESS_PIN,
|
||||
obj->pin_number, ARM_GPIO_IRQ_ENABLE);
|
||||
}
|
||||
|
||||
void gpio_irq_disable(gpio_irq_t *obj)
|
||||
{
|
||||
NVIC_DisableIRQ((IRQn_Type)(PININT_IRQ + obj->ch));
|
||||
(void)arm_gpio_set_interrupt(obj->gpio_dev, ARM_GPIO_ACCESS_PIN,
|
||||
obj->pin_number, ARM_GPIO_IRQ_DISABLE);
|
||||
}
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MBED_GPIO_OBJECT_H
|
||||
#define MBED_GPIO_OBJECT_H
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "PortNames.h"
|
||||
#include "PeripheralNames.h"
|
||||
#include "PinNames.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PinName pin;
|
||||
uint32_t mask;
|
||||
uint32_t pin_number;
|
||||
__IO uint32_t *reg_dir;
|
||||
__IO uint32_t *reg_dirclr;
|
||||
__IO uint32_t *reg_data;
|
||||
__I uint32_t *reg_in;
|
||||
} gpio_t;
|
||||
|
||||
static inline void gpio_write(gpio_t *obj, int value)
|
||||
{
|
||||
if (value) {
|
||||
*obj->reg_data |= (obj->mask);
|
||||
} else {
|
||||
*obj->reg_data &= ~(obj->mask);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int gpio_read(gpio_t *obj)
|
||||
{
|
||||
return ((*obj->reg_in & obj->mask) ? 1 : 0);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018 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_GPIO_OBJECTS_H__
|
||||
#define __MBED_GPIO_OBJECTS_H__
|
||||
|
||||
/*
|
||||
* GPIO device number, there are 16 pins per GPIO
|
||||
* equivalent: pin / 16
|
||||
*/
|
||||
#define GPIO_DEV_NUMBER(pin) ((pin) >> 4)
|
||||
/*
|
||||
* Pin number of this pin inside its GPIO
|
||||
* equivalent: pin % 16
|
||||
*/
|
||||
#define GPIO_PIN_NUMBER(pin) ((pin) & 0xF)
|
||||
|
||||
/* Number of the GPIO device */
|
||||
#define GPIO0_NUMBER 0
|
||||
#define GPIO1_NUMBER 1
|
||||
#define GPIO2_NUMBER 2
|
||||
#define GPIO3_NUMBER 3
|
||||
|
||||
/* Base EXP pin number for the corresponding GPIO */
|
||||
#define EXP_PIN_BASE0 EXP0
|
||||
#define EXP_PIN_BASE1 EXP16
|
||||
#define EXP_PIN_BASE2 EXP32
|
||||
#define EXP_PIN_BASE3 EXP48
|
||||
|
||||
#define GPIO_DEVICES 4
|
||||
#define PINS_PER_GPIO 16
|
||||
/* Pins 4 to 15 of GPIO3 are not used */
|
||||
#define PINS_NOT_USED 12
|
||||
#define PINS_NUMBER (GPIO_DEVICES * PINS_PER_GPIO - PINS_NOT_USED)
|
||||
|
||||
/* GPIO3 port only uses first 4 pins */
|
||||
#define GPIO3_PIN_NUMBER 4
|
||||
|
||||
/* When doing a port access, the pin number argument is useless */
|
||||
#define ARG_NOT_USED 0
|
||||
|
||||
#endif /* __MBED_GPIO_OBJECTS_H__ */
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Low-power elapsed time measure and interval timer in micro-secundum,
|
||||
* servicing \ref lp_ticker_api.h, using CMSDK Timer1 \ref CMSDK_TIMER1_DEV.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "cmsdk_ticker.h"
|
||||
#include "lp_ticker_api.h"
|
||||
#include "platform_devices.h"
|
||||
|
||||
/**
|
||||
* \brief Calculate clocks to us
|
||||
*
|
||||
* \param[in] tick Number of clock ticks
|
||||
*
|
||||
* \return Number of usec, relative to the timer frequency,
|
||||
* that a given ammount of ticks equates to.
|
||||
*/
|
||||
static uint32_t convert_tick_to_us(uint32_t tick)
|
||||
{
|
||||
return (tick / (SystemCoreClock / SEC_TO_USEC_MULTIPLIER));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Calculate us to clock ticks
|
||||
*
|
||||
* \param[in] us Time to convert to clock ticks
|
||||
*
|
||||
* \return Number of clock ticks relative to the timer frequency,
|
||||
* that a given period of usec equates to.
|
||||
*/
|
||||
static uint32_t convert_us_to_tick(uint32_t us)
|
||||
{
|
||||
return (us * (SystemCoreClock / SEC_TO_USEC_MULTIPLIER));
|
||||
}
|
||||
|
||||
static const struct tick_cfg_t cfg =
|
||||
{
|
||||
.timer_driver = &CMSDK_TIMER1_DEV,
|
||||
.irq_n = TIMER1_IRQn,
|
||||
.interval_callback = &lp_ticker_irq_handler,
|
||||
.convert_tick_to_time = &convert_tick_to_us,
|
||||
.convert_time_to_tick = &convert_us_to_tick
|
||||
};
|
||||
|
||||
static struct tick_data_t data =
|
||||
{
|
||||
.is_initialized = false,
|
||||
.cumulated_time = 0,
|
||||
.max_interval_time = 0,
|
||||
.reload_time = 0,
|
||||
.interval_callback_enabled = false,
|
||||
.previous_cumulated_time = 0,
|
||||
.previous_elapsed = 0
|
||||
};
|
||||
|
||||
static struct tick_drv_data_t timer_data =
|
||||
{
|
||||
.cfg = &cfg,
|
||||
.data = &data
|
||||
};
|
||||
|
||||
void lp_ticker_init(void)
|
||||
{
|
||||
cmsdk_ticker_init(&timer_data);
|
||||
}
|
||||
|
||||
uint32_t lp_ticker_read()
|
||||
{
|
||||
return cmsdk_ticker_read(&timer_data);
|
||||
}
|
||||
|
||||
void lp_ticker_set_interrupt(timestamp_t timestamp)
|
||||
{
|
||||
cmsdk_ticker_set_interrupt(&timer_data, timestamp);
|
||||
}
|
||||
|
||||
void lp_ticker_disable_interrupt(void)
|
||||
{
|
||||
cmsdk_ticker_disable_interrupt(&timer_data);
|
||||
}
|
||||
|
||||
void lp_ticker_clear_interrupt(void)
|
||||
{
|
||||
cmsdk_ticker_clear_interrupt(&timer_data);
|
||||
}
|
||||
|
||||
void lp_ticker_fire_interrupt(void)
|
||||
{
|
||||
cmsdk_ticker_fire_interrupt(&timer_data);
|
||||
}
|
||||
|
||||
void TIMER1_IRQHandler(void)
|
||||
{
|
||||
cmsdk_ticker_irq_handler(&timer_data);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,34 +13,44 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MBED_OBJECTS_H
|
||||
#define MBED_OBJECTS_H
|
||||
#ifndef __MBED_OBJECTS_H__
|
||||
#define __MBED_OBJECTS_H__
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "PortNames.h"
|
||||
#include "PeripheralNames.h"
|
||||
#include "PinNames.h"
|
||||
#include "platform_devices.h"
|
||||
#include "gpio_objects.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct gpio_s {
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
struct arm_mps2_io_dev_t *mps2_io_dev;
|
||||
uint32_t pin_number;
|
||||
PinDirection direction;
|
||||
} gpio_t;
|
||||
|
||||
struct gpio_irq_s {
|
||||
uint32_t ch;
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
uint32_t pin_number; /* Pin number inside the GPIO */
|
||||
uint32_t exp_pin_number; /* Pin number on the expension port */
|
||||
IRQn_Type irq_number; /* IRQ number of the GPIO interrupt of
|
||||
this pin */
|
||||
};
|
||||
|
||||
struct port_s {
|
||||
__IO uint32_t *reg_dir;
|
||||
__IO uint32_t *reg_dirclr;
|
||||
__IO uint32_t *reg_out;
|
||||
__IO uint32_t *reg_in;
|
||||
PortName port;
|
||||
uint32_t mask;
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
};
|
||||
|
||||
struct serial_s {
|
||||
CMSDK_UART_TypeDef *uart;
|
||||
int index;
|
||||
struct arm_uart_dev_t *uart;
|
||||
UARTName index;
|
||||
IRQn_Type irq_number; /* IRQ number of the RX interrupt for
|
||||
this UART device */
|
||||
};
|
||||
|
||||
struct i2c_s {
|
||||
|
@ -58,21 +68,15 @@ struct audio_s {
|
|||
};
|
||||
|
||||
struct spi_s {
|
||||
MPS2_SSP_TypeDef *spi;
|
||||
};
|
||||
|
||||
struct clcd_s {
|
||||
MPS2_SSP_TypeDef *clcd;
|
||||
struct spi_pl022_dev_t *spi;
|
||||
};
|
||||
|
||||
struct analogin_s {
|
||||
uint16_t ctrl_register; /* Control bits with the channel identifier */
|
||||
};
|
||||
|
||||
#include "gpio_object.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* __MBED_OBJECTS_H__ */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,40 +16,64 @@
|
|||
#include "mbed_assert.h"
|
||||
#include "pinmap.h"
|
||||
#include "mbed_error.h"
|
||||
|
||||
#define GET_GPIO_PIN_POS(pin) (pin & 0x0F) /* pin % 16 */
|
||||
#define GET_GPIO_MAP_NUM(pin) (pin >> 4) /* pin / 16 */
|
||||
#define GPIO_NUM 4
|
||||
|
||||
static CMSDK_GPIO_TypeDef* GPIO_MAP[GPIO_NUM] = {
|
||||
CMSDK_GPIO0,
|
||||
CMSDK_GPIO1,
|
||||
CMSDK_GPIO2,
|
||||
CMSDK_GPIO3
|
||||
};
|
||||
#include "objects.h"
|
||||
|
||||
void pin_function(PinName pin, int function)
|
||||
{
|
||||
CMSDK_GPIO_TypeDef* p_gpio_map = 0;
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
uint32_t flags;
|
||||
|
||||
MBED_ASSERT(pin != (PinName)NC);
|
||||
MBED_ASSERT(pin != NC);
|
||||
|
||||
/* The pin has to be a GPIO pin */
|
||||
if (pin >= EXP0 && pin <= EXP51) {
|
||||
if (function == ALTERNATE_FUNC) {
|
||||
p_gpio_map = GPIO_MAP[GET_GPIO_MAP_NUM(pin)];
|
||||
p_gpio_map->ALTFUNCSET = (1 << GET_GPIO_PIN_POS(pin));
|
||||
} else if(function == GPIO_FUNC) {
|
||||
p_gpio_map = GPIO_MAP[GET_GPIO_MAP_NUM(pin)];
|
||||
p_gpio_map->ALTFUNCCLR = (1 << GET_GPIO_PIN_POS(pin));
|
||||
} else {
|
||||
error("Invalid pin_function value %d", function);
|
||||
switch (function) {
|
||||
case ALTERNATE_FUNC:
|
||||
flags = ARM_GPIO_PIN_DISABLE;
|
||||
break;
|
||||
case GPIO_FUNC:
|
||||
flags = ARM_GPIO_PIN_ENABLE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
switch (GPIO_DEV_NUMBER(pin)) {
|
||||
#ifdef ARM_GPIO0
|
||||
case GPIO0_NUMBER:
|
||||
gpio_dev = &ARM_GPIO0_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO0 */
|
||||
#ifdef ARM_GPIO1
|
||||
case GPIO1_NUMBER:
|
||||
gpio_dev = &ARM_GPIO1_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO1 */
|
||||
#ifdef ARM_GPIO2
|
||||
case GPIO2_NUMBER:
|
||||
gpio_dev = &ARM_GPIO2_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO2 */
|
||||
#ifdef ARM_GPIO3
|
||||
case GPIO3_NUMBER:
|
||||
gpio_dev = &ARM_GPIO3_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO3 */
|
||||
default:
|
||||
error("GPIO %d, associated with expansion pin %d, is disabled",
|
||||
pin, GPIO_DEV_NUMBER(pin));
|
||||
return;
|
||||
}
|
||||
|
||||
arm_gpio_init(gpio_dev);
|
||||
(void)arm_gpio_config(gpio_dev, ARM_GPIO_ACCESS_PIN,
|
||||
GPIO_PIN_NUMBER(pin), flags);
|
||||
}
|
||||
}
|
||||
|
||||
void pin_mode(PinName pin, PinMode mode)
|
||||
{
|
||||
MBED_ASSERT(pin != (PinName)NC);
|
||||
MBED_ASSERT(pin != NC);
|
||||
|
||||
/* Pin modes configuration is not supported */
|
||||
/* PinMode is not supported */
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,86 +13,90 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "port_api.h"
|
||||
#include "pinmap.h"
|
||||
#include "gpio_api.h"
|
||||
|
||||
#define MAX_GPIO_PINS 16
|
||||
#include "objects.h"
|
||||
#include "mbed_error.h"
|
||||
|
||||
PinName port_pin(PortName port, int pin_n)
|
||||
{
|
||||
if (pin_n < 0 || pin_n > MAX_GPIO_PINS) {
|
||||
error("Invalid GPIO pin number %d", pin_n);
|
||||
if (pin_n < 0 || pin_n >= PINS_PER_GPIO ||
|
||||
((port == Port3) && (pin_n >= GPIO3_PIN_NUMBER))) {
|
||||
return NC;
|
||||
}
|
||||
|
||||
return (PinName)((port << PORT_SHIFT) | pin_n);
|
||||
return (PINS_PER_GPIO * port + pin_n);
|
||||
}
|
||||
|
||||
void port_init(port_t *obj, PortName port, int mask, PinDirection dir)
|
||||
{
|
||||
uint32_t i;
|
||||
CMSDK_GPIO_TypeDef *port_reg;
|
||||
struct arm_gpio_dev_t *gpio_dev;
|
||||
uint32_t flags = ARM_GPIO_PIN_ENABLE;
|
||||
|
||||
switch (port) {
|
||||
case Port0:
|
||||
port_reg = (CMSDK_GPIO_TypeDef *)(CMSDK_GPIO0_BASE);
|
||||
break;
|
||||
case Port1:
|
||||
port_reg = (CMSDK_GPIO_TypeDef *)(CMSDK_GPIO1_BASE);
|
||||
break;
|
||||
case Port2:
|
||||
port_reg = (CMSDK_GPIO_TypeDef *)(CMSDK_GPIO2_BASE);
|
||||
break;
|
||||
case Port3:
|
||||
port_reg = (CMSDK_GPIO_TypeDef *)(CMSDK_GPIO3_BASE);
|
||||
break;
|
||||
#ifdef ARM_GPIO0
|
||||
case Port0:
|
||||
gpio_dev = &ARM_GPIO0_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO0 */
|
||||
#ifdef ARM_GPIO1
|
||||
case Port1:
|
||||
gpio_dev = &ARM_GPIO1_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO1 */
|
||||
#ifdef ARM_GPIO2
|
||||
case Port2:
|
||||
gpio_dev = &ARM_GPIO2_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO2 */
|
||||
#ifdef ARM_GPIO3
|
||||
case Port3:
|
||||
gpio_dev = &ARM_GPIO3_DEV;
|
||||
break;
|
||||
#endif /* ARM_GPIO3 */
|
||||
default:
|
||||
error("Port%d is not enabled", port);
|
||||
return;
|
||||
}
|
||||
|
||||
obj->port = port;
|
||||
obj->mask = mask;
|
||||
obj->reg_in = &port_reg->DATAOUT;
|
||||
obj->reg_dir = &port_reg->OUTENABLESET;
|
||||
obj->reg_dirclr = &port_reg->OUTENABLECLR;
|
||||
arm_gpio_init(gpio_dev);
|
||||
obj->gpio_dev = gpio_dev;
|
||||
|
||||
/* The function is set per pin: reuse gpio logic */
|
||||
for (i=0; i < MAX_GPIO_PINS; i++) {
|
||||
if (obj->mask & (1<<i)) {
|
||||
gpio_set(port_pin(obj->port, i));
|
||||
}
|
||||
arm_gpio_set_port_mask(gpio_dev, mask);
|
||||
|
||||
switch (dir) {
|
||||
case PIN_INPUT:
|
||||
flags |= ARM_GPIO_INPUT;
|
||||
break;
|
||||
case PIN_OUTPUT:
|
||||
flags |= ARM_GPIO_OUTPUT;
|
||||
break;
|
||||
/* default: not added to force to cover all enumeration cases */
|
||||
}
|
||||
|
||||
port_dir(obj, dir);
|
||||
(void)arm_gpio_config(gpio_dev, ARM_GPIO_ACCESS_PORT, ARG_NOT_USED, flags);
|
||||
}
|
||||
|
||||
void port_mode(port_t *obj, PinMode mode)
|
||||
{
|
||||
uint32_t i;
|
||||
/* The mode is set per pin: reuse pinmap logic */
|
||||
for (i=0; i < MAX_GPIO_PINS; i++) {
|
||||
if (obj->mask & (1 << i)) {
|
||||
pin_mode(port_pin(obj->port, i), mode);
|
||||
}
|
||||
}
|
||||
/* PinMode is not supported */
|
||||
}
|
||||
|
||||
void port_dir(port_t *obj, PinDirection dir)
|
||||
{
|
||||
switch (dir) {
|
||||
case PIN_INPUT:
|
||||
*obj->reg_dir &= ~obj->mask;
|
||||
break;
|
||||
case PIN_OUTPUT:
|
||||
*obj->reg_dir |= obj->mask;
|
||||
break;
|
||||
}
|
||||
uint32_t flags = (dir == PIN_OUTPUT) ? ARM_GPIO_OUTPUT : ARM_GPIO_INPUT;
|
||||
(void)arm_gpio_config(obj->gpio_dev, ARM_GPIO_ACCESS_PORT, ARG_NOT_USED,
|
||||
flags);
|
||||
}
|
||||
|
||||
void port_write(port_t *obj, int value)
|
||||
{
|
||||
*obj->reg_in = value;
|
||||
(void)arm_gpio_write(obj->gpio_dev, ARM_GPIO_ACCESS_PORT, ARG_NOT_USED,
|
||||
(uint32_t)value);
|
||||
}
|
||||
|
||||
int port_read(port_t *obj)
|
||||
{
|
||||
return (*obj->reg_in);
|
||||
return (int)arm_gpio_read(obj->gpio_dev, ARM_GPIO_ACCESS_PORT,
|
||||
ARG_NOT_USED);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,174 +20,138 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "serial_api.h"
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "mbed_error.h"
|
||||
#include "gpio_api.h"
|
||||
#include "platform_devices.h"
|
||||
|
||||
/******************************************************************************
|
||||
* INITIALIZATION
|
||||
******************************************************************************/
|
||||
|
||||
#define STDIO_UART_NOT_INITED 0
|
||||
#define STDIO_UART_INITED 1
|
||||
#define UART_NUMBER 5
|
||||
|
||||
struct uart_irq_t {
|
||||
uart_irq_handler handler;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
static const PinMap PinMap_UART_TX[] = {
|
||||
{MCC_TX , UART_0, 0},
|
||||
{USBTX , UART_1, 0},
|
||||
{SH0_TX , UART_2, ALTERNATE_FUNC},
|
||||
{SH1_TX , UART_3, ALTERNATE_FUNC},
|
||||
{XB_TX , UART_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{MCC_TX, UART_0, 0},
|
||||
{USBTX, UART_1, 0},
|
||||
{SH0_TX, UART_2, ALTERNATE_FUNC},
|
||||
{SH1_TX, UART_3, ALTERNATE_FUNC},
|
||||
{XB_TX, UART_4, ALTERNATE_FUNC},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static const PinMap PinMap_UART_RX[] = {
|
||||
{MCC_RX , UART_0, 0},
|
||||
{USBRX , UART_1, 0},
|
||||
{SH0_RX , UART_2, ALTERNATE_FUNC},
|
||||
{SH1_RX , UART_3, ALTERNATE_FUNC},
|
||||
{XB_RX , UART_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{MCC_RX, UART_0, 0},
|
||||
{USBRX, UART_1, 0},
|
||||
{SH0_RX, UART_2, ALTERNATE_FUNC},
|
||||
{SH1_RX, UART_3, ALTERNATE_FUNC},
|
||||
{XB_RX, UART_4, ALTERNATE_FUNC},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
#define UART_NUM 5
|
||||
/* Handlers registered */
|
||||
static struct uart_irq_t uart_irq[UART_NUMBER];
|
||||
|
||||
static uart_irq_handler irq_handler;
|
||||
|
||||
int stdio_uart_inited = 0;
|
||||
/* Global variables needed for mbed */
|
||||
int stdio_uart_inited = STDIO_UART_NOT_INITED;
|
||||
serial_t stdio_uart;
|
||||
|
||||
struct serial_global_data_s {
|
||||
uint32_t serial_irq_id;
|
||||
gpio_t sw_rts, sw_cts;
|
||||
uint8_t count, rx_irq_set_flow, rx_irq_set_api;
|
||||
};
|
||||
/*
|
||||
* Fill the serial_obj structure with good elements.
|
||||
*/
|
||||
static uint32_t fill_serial_object(struct serial_s *serial_obj, PinName tx,
|
||||
PinName rx)
|
||||
{
|
||||
UARTName uart_peripheral;
|
||||
|
||||
static struct serial_global_data_s uart_data[UART_NUM];
|
||||
if (serial_obj == NULL) {
|
||||
error("serial_s structure is NULL");
|
||||
return 1;
|
||||
}
|
||||
|
||||
uart_peripheral = pinmap_merge(pinmap_peripheral(tx, PinMap_UART_TX),
|
||||
pinmap_peripheral(rx, PinMap_UART_RX));
|
||||
|
||||
switch (uart_peripheral) {
|
||||
#ifdef ARM_UART0
|
||||
case UART_0:
|
||||
serial_obj->uart = &ARM_UART0_DEV;
|
||||
serial_obj->index = UART_0;
|
||||
serial_obj->irq_number = UART0_IRQn;
|
||||
/* Fill stdio_uart global variable with these settings */
|
||||
memcpy(&stdio_uart, serial_obj, sizeof(struct serial_s));
|
||||
stdio_uart_inited = STDIO_UART_INITED;
|
||||
return 0;
|
||||
#endif /* ARM_UART0 */
|
||||
#ifdef ARM_UART1
|
||||
case UART_1:
|
||||
serial_obj->uart = &ARM_UART1_DEV;
|
||||
serial_obj->index = UART_1;
|
||||
serial_obj->irq_number = UART1_IRQn;
|
||||
return 0;
|
||||
#endif /* ARM_UART1 */
|
||||
#ifdef ARM_UART2
|
||||
case UART_2:
|
||||
serial_obj->uart = &ARM_UART2_DEV;
|
||||
serial_obj->index = UART_2;
|
||||
serial_obj->irq_number = UART2_IRQn;
|
||||
return 0;
|
||||
#endif /* ARM_UART2 */
|
||||
#ifdef ARM_UART3
|
||||
case UART_3:
|
||||
serial_obj->uart = &ARM_UART3_DEV;
|
||||
serial_obj->index = UART_3;
|
||||
serial_obj->irq_number = UART3_IRQn;
|
||||
return 0;
|
||||
#endif /* ARM_UART3 */
|
||||
#ifdef ARM_UART4
|
||||
case UART_4:
|
||||
serial_obj->uart = &ARM_UART4_DEV;
|
||||
serial_obj->index = UART_4;
|
||||
serial_obj->irq_number = UART4_IRQn;
|
||||
return 0;
|
||||
#endif /* ARM_UART4 */
|
||||
default:
|
||||
error("can not assign a valid UART peripheral to TX and RX pins given");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void serial_init(serial_t *obj, PinName tx, PinName rx)
|
||||
{
|
||||
uint32_t uart_ctrl = 0;
|
||||
|
||||
/* Determine the UART to use */
|
||||
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
|
||||
UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
|
||||
UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
|
||||
|
||||
if ((int)uart == NC) {
|
||||
error("Serial pinout mapping failed");
|
||||
if (fill_serial_object(obj, tx, rx) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
obj->uart = (CMSDK_UART_TypeDef *)uart;
|
||||
|
||||
if (tx != NC) {
|
||||
uart_ctrl = 0x01; /* TX enable */
|
||||
}
|
||||
if (rx != NC) {
|
||||
uart_ctrl |= 0x02; /* RX enable */
|
||||
}
|
||||
|
||||
switch (uart) {
|
||||
case UART_0:
|
||||
CMSDK_UART0->CTRL = uart_ctrl;
|
||||
obj->index = 0;
|
||||
break;
|
||||
case UART_1:
|
||||
CMSDK_UART1->CTRL = uart_ctrl;
|
||||
obj->index = 1;
|
||||
break;
|
||||
case UART_2:
|
||||
CMSDK_UART2->CTRL = 0;
|
||||
obj->index = 2;
|
||||
pin_function(tx, ALTERNATE_FUNC);
|
||||
pin_function(rx, ALTERNATE_FUNC);
|
||||
CMSDK_UART2->CTRL = uart_ctrl;
|
||||
break;
|
||||
case UART_3:
|
||||
CMSDK_UART3->CTRL = 0;
|
||||
obj->index = 3;
|
||||
pin_function(tx, ALTERNATE_FUNC);
|
||||
pin_function(rx, ALTERNATE_FUNC);
|
||||
CMSDK_UART3->CTRL = uart_ctrl;
|
||||
break;
|
||||
case UART_4:
|
||||
CMSDK_UART4->CTRL = 0;
|
||||
obj->index = 4;
|
||||
pin_function(tx, ALTERNATE_FUNC);
|
||||
pin_function(rx, ALTERNATE_FUNC);
|
||||
CMSDK_UART4->CTRL = uart_ctrl;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set default baud rate and format */
|
||||
serial_baud(obj, 9600);
|
||||
(void)arm_uart_init(obj->uart, SystemCoreClock);
|
||||
|
||||
/*
|
||||
* The CMSDK APB UART doesn't have support for flow control.
|
||||
* Ref. DDI0479C_cortex_m_system_design_kit_r1p0_trm.pdf
|
||||
* If tx and rx pins are not linked to a GPIO (like for UART0),
|
||||
* pin_function will have no effect.
|
||||
*/
|
||||
uart_data[obj->index].sw_rts.pin = NC;
|
||||
uart_data[obj->index].sw_cts.pin = NC;
|
||||
|
||||
if (uart == STDIO_UART) {
|
||||
stdio_uart_inited = 1;
|
||||
memcpy(&stdio_uart, obj, sizeof(serial_t));
|
||||
}
|
||||
|
||||
/* Clear UART */
|
||||
serial_clear(obj);
|
||||
pin_function(tx, pinmap_function(tx, PinMap_UART_TX));
|
||||
pin_function(rx, pinmap_function(rx, PinMap_UART_RX));
|
||||
}
|
||||
|
||||
void serial_free(serial_t *obj)
|
||||
{
|
||||
uart_data[obj->index].serial_irq_id = 0;
|
||||
uart_irq[obj->index].id = 0;
|
||||
uart_irq[obj->index].handler = 0;
|
||||
}
|
||||
|
||||
void serial_baud(serial_t *obj, int baudrate)
|
||||
{
|
||||
/*
|
||||
* The MPS2 has a simple divider to control the baud rate.
|
||||
* The formula is:
|
||||
* Baudrate = PCLK / BAUDDIV where PCLK = SystemCoreClock and
|
||||
* BAUDDIV is the desire baudrate
|
||||
*
|
||||
* So, if the desired baud rate is 9600 the calculation will be:
|
||||
* Baudrate = SystemCoreClock / 9600;
|
||||
*/
|
||||
|
||||
/* Check to see if minimum baud value entered */
|
||||
int baudrate_div = 0;
|
||||
|
||||
if (baudrate == 0) {
|
||||
error("Invalid baudrate value");
|
||||
return;
|
||||
if (arm_uart_set_baudrate(obj->uart, (uint32_t)baudrate) !=
|
||||
ARM_UART_ERR_NONE) {
|
||||
error("Invalid baudrate value or uart not initialized");
|
||||
}
|
||||
|
||||
baudrate_div = SystemCoreClock / baudrate;
|
||||
|
||||
if (baudrate >= 16) {
|
||||
switch ((int)obj->uart) {
|
||||
case UART_0:
|
||||
CMSDK_UART0->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
case UART_1:
|
||||
CMSDK_UART1->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
case UART_2:
|
||||
CMSDK_UART2->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
case UART_3:
|
||||
CMSDK_UART3->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
case UART_4:
|
||||
CMSDK_UART4->BAUDDIV = baudrate_div;
|
||||
break;
|
||||
default:
|
||||
error("Invalid uart object");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
error("Invalid baudrate value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void serial_format(serial_t *obj, int data_bits,
|
||||
|
@ -204,138 +168,160 @@ void serial_format(serial_t *obj, int data_bits,
|
|||
/******************************************************************************
|
||||
* INTERRUPTS HANDLING
|
||||
******************************************************************************/
|
||||
static inline void uart_irq(uint32_t intstatus, uint32_t index,
|
||||
CMSDK_UART_TypeDef *puart)
|
||||
#ifdef ARM_UART0
|
||||
void UART0_IRQHandler()
|
||||
{
|
||||
SerialIrq irq_type;
|
||||
|
||||
switch (intstatus) {
|
||||
case 1:
|
||||
irq_type = TxIrq;
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART0_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART0_DEV, irq);
|
||||
if(uart_irq[UART_0].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_0].handler(uart_irq[UART_0].id, RxIrq);
|
||||
break;
|
||||
case 2:
|
||||
irq_type = RxIrq;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_0].handler(uart_irq[UART_0].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_0].handler(uart_irq[UART_0].id, RxIrq);
|
||||
uart_irq[UART_0].handler(uart_irq[UART_0].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if ((RxIrq == irq_type) && (NC != uart_data[index].sw_rts.pin)) {
|
||||
gpio_write(&uart_data[index].sw_rts, 1);
|
||||
/* Disable interrupt if it wasn't enabled by the application */
|
||||
if (!uart_data[index].rx_irq_set_api) {
|
||||
/* Disable Rx interrupt */
|
||||
puart->CTRL &= ~(CMSDK_UART_CTRL_RXIRQEN_Msk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART0 */
|
||||
|
||||
if (uart_data[index].serial_irq_id != 0) {
|
||||
if ((irq_type != RxIrq) || (uart_data[index].rx_irq_set_api)) {
|
||||
irq_handler(uart_data[index].serial_irq_id, irq_type);
|
||||
#ifdef ARM_UART1
|
||||
void UART1_IRQHandler()
|
||||
{
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART1_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART1_DEV, irq);
|
||||
if(uart_irq[UART_1].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_1].handler(uart_irq[UART_1].id, RxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_1].handler(uart_irq[UART_1].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_1].handler(uart_irq[UART_1].id, RxIrq);
|
||||
uart_irq[UART_1].handler(uart_irq[UART_1].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART1 */
|
||||
|
||||
if (irq_type == TxIrq) {
|
||||
/* Clear the TX interrupt Flag */
|
||||
puart->INTCLEAR |= 0x01;
|
||||
} else {
|
||||
/* Clear the Rx interupt Flag */
|
||||
puart->INTCLEAR |= 0x02;
|
||||
#ifdef ARM_UART2
|
||||
void UART2_IRQHandler()
|
||||
{
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART2_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART2_DEV, irq);
|
||||
if(uart_irq[UART_2].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_2].handler(uart_irq[UART_2].id, RxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_2].handler(uart_irq[UART_2].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_2].handler(uart_irq[UART_2].id, RxIrq);
|
||||
uart_irq[UART_2].handler(uart_irq[UART_2].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART2 */
|
||||
|
||||
void uart0_irq()
|
||||
#ifdef ARM_UART3
|
||||
void UART3_IRQHandler()
|
||||
{
|
||||
uart_irq(CMSDK_UART0->INTSTATUS & 0x3, 0, (CMSDK_UART_TypeDef*)CMSDK_UART0);
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART3_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART3_DEV, irq);
|
||||
if(uart_irq[UART_3].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_3].handler(uart_irq[UART_3].id, RxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_3].handler(uart_irq[UART_3].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_3].handler(uart_irq[UART_3].id, RxIrq);
|
||||
uart_irq[UART_3].handler(uart_irq[UART_3].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART3 */
|
||||
|
||||
void uart1_irq()
|
||||
#ifdef ARM_UART4
|
||||
void UART4_IRQHandler()
|
||||
{
|
||||
uart_irq(CMSDK_UART1->INTSTATUS & 0x3, 1, (CMSDK_UART_TypeDef*)CMSDK_UART1);
|
||||
}
|
||||
|
||||
void uart2_irq()
|
||||
{
|
||||
uart_irq(CMSDK_UART2->INTSTATUS & 0x3, 2, (CMSDK_UART_TypeDef*)CMSDK_UART2);
|
||||
}
|
||||
|
||||
void uart3_irq() {
|
||||
uart_irq(CMSDK_UART3->INTSTATUS & 0x3, 3, (CMSDK_UART_TypeDef*)CMSDK_UART3);
|
||||
}
|
||||
|
||||
void uart4_irq() {
|
||||
uart_irq(CMSDK_UART4->INTSTATUS & 0x3, 4, (CMSDK_UART_TypeDef*)CMSDK_UART4);
|
||||
enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART4_DEV);
|
||||
arm_uart_clear_interrupt(&ARM_UART4_DEV, irq);
|
||||
if(uart_irq[UART_4].handler) {
|
||||
switch(irq) {
|
||||
case ARM_UART_IRQ_RX:
|
||||
uart_irq[UART_4].handler(uart_irq[UART_4].id, RxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_TX:
|
||||
uart_irq[UART_4].handler(uart_irq[UART_4].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_COMBINED:
|
||||
uart_irq[UART_4].handler(uart_irq[UART_4].id, RxIrq);
|
||||
uart_irq[UART_4].handler(uart_irq[UART_4].id, TxIrq);
|
||||
break;
|
||||
case ARM_UART_IRQ_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ARM_UART4 */
|
||||
|
||||
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
|
||||
{
|
||||
irq_handler = handler;
|
||||
uart_data[obj->index].serial_irq_id = id;
|
||||
}
|
||||
|
||||
static void serial_irq_set_internal(serial_t *obj, SerialIrq irq, uint32_t enable)
|
||||
{
|
||||
|
||||
IRQn_Type irq_n = (IRQn_Type)0;
|
||||
uint32_t vector = 0;
|
||||
|
||||
switch ((int)obj->uart) {
|
||||
case UART_0:
|
||||
irq_n = UART0_IRQn;
|
||||
vector = (uint32_t)&uart0_irq;
|
||||
break;
|
||||
case UART_1:
|
||||
irq_n = UART1_IRQn;
|
||||
vector = (uint32_t)&uart1_irq;
|
||||
break;
|
||||
case UART_2:
|
||||
irq_n = UART2_IRQn;
|
||||
vector = (uint32_t)&uart2_irq;
|
||||
break;
|
||||
case UART_3:
|
||||
irq_n = UART3_IRQn;
|
||||
vector = (uint32_t)&uart3_irq;
|
||||
break;
|
||||
case UART_4:
|
||||
irq_n = UART4_IRQn;
|
||||
vector = (uint32_t)&uart4_irq;
|
||||
break;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
if (irq == TxIrq) {
|
||||
/* Set TX interrupt enable in CTRL REG */
|
||||
obj->uart->CTRL |= CMSDK_UART_CTRL_TXIRQEN_Msk;
|
||||
} else {
|
||||
/* Set Rx interrupt on in CTRL REG */
|
||||
obj->uart->CTRL |= CMSDK_UART_CTRL_RXIRQEN_Msk;
|
||||
}
|
||||
NVIC_SetVector(irq_n, vector);
|
||||
NVIC_EnableIRQ(irq_n);
|
||||
} else if ((irq == TxIrq) ||
|
||||
(uart_data[obj->index].rx_irq_set_api
|
||||
+ uart_data[obj->index].rx_irq_set_flow == 0)) {
|
||||
/* Disable IRQ */
|
||||
int all_disabled = 0;
|
||||
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
|
||||
|
||||
obj->uart->CTRL &= ~(1 << (irq + 2));
|
||||
|
||||
all_disabled = (obj->uart->CTRL & (1 << (other_irq + 2))) == 0;
|
||||
|
||||
if (all_disabled) {
|
||||
NVIC_DisableIRQ(irq_n);
|
||||
}
|
||||
}
|
||||
uart_irq[obj->index].handler = handler;
|
||||
uart_irq[obj->index].id = id;
|
||||
}
|
||||
|
||||
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
|
||||
{
|
||||
if (RxIrq == irq) {
|
||||
uart_data[obj->index].rx_irq_set_api = enable;
|
||||
switch (irq) {
|
||||
case RxIrq:
|
||||
if (enable) {
|
||||
NVIC_EnableIRQ(obj->irq_number);
|
||||
(void)arm_uart_irq_rx_enable(obj->uart);
|
||||
} else {
|
||||
arm_uart_irq_rx_disable(obj->uart);
|
||||
NVIC_DisableIRQ(obj->irq_number);
|
||||
}
|
||||
break;
|
||||
case TxIrq:
|
||||
if (enable) {
|
||||
NVIC_EnableIRQ(obj->irq_number);
|
||||
(void)arm_uart_irq_tx_enable(obj->uart);
|
||||
} else {
|
||||
arm_uart_irq_tx_disable(obj->uart);
|
||||
NVIC_DisableIRQ(obj->irq_number);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
serial_irq_set_internal(obj, irq, enable);
|
||||
/* default: not added to force to cover all enumeration cases */
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -343,34 +329,33 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
|
|||
******************************************************************************/
|
||||
int serial_getc(serial_t *obj)
|
||||
{
|
||||
while (serial_readable(obj) == 0) {
|
||||
/* NOP */
|
||||
}
|
||||
uint8_t byte = 0;
|
||||
|
||||
return obj->uart->DATA;
|
||||
while (!serial_readable(obj)){};
|
||||
(void)arm_uart_read(obj->uart, &byte);
|
||||
|
||||
return (int)byte;
|
||||
}
|
||||
|
||||
void serial_putc(serial_t *obj, int c)
|
||||
{
|
||||
while (serial_writable(obj)) {
|
||||
/* NOP */
|
||||
}
|
||||
obj->uart->DATA = c;
|
||||
while (!serial_writable(obj)){};
|
||||
(void)arm_uart_write(obj->uart, (int)c);
|
||||
}
|
||||
|
||||
int serial_readable(serial_t *obj)
|
||||
{
|
||||
return obj->uart->STATE & 0x2;
|
||||
return arm_uart_rx_ready(obj->uart);
|
||||
}
|
||||
|
||||
int serial_writable(serial_t *obj)
|
||||
{
|
||||
return obj->uart->STATE & 0x1;
|
||||
return arm_uart_tx_ready(obj->uart);
|
||||
}
|
||||
|
||||
void serial_clear(serial_t *obj)
|
||||
{
|
||||
obj->uart->DATA = 0x00;
|
||||
(void)arm_uart_write(obj->uart, 0x00);
|
||||
}
|
||||
|
||||
void serial_pinout_tx(PinName tx)
|
||||
|
@ -395,7 +380,8 @@ void serial_break_clear(serial_t *obj)
|
|||
*/
|
||||
error("serial_break_clear function not supported");
|
||||
}
|
||||
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow)
|
||||
void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow,
|
||||
PinName txflow)
|
||||
{
|
||||
/*
|
||||
* The CMSDK APB UART doesn't have support for flow control.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -13,282 +13,253 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <math.h>
|
||||
|
||||
#include "spi_api.h"
|
||||
#include "spi_def.h"
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "mbed_error.h"
|
||||
#include "mbed_wait_api.h"
|
||||
#include "platform_devices.h"
|
||||
|
||||
#define SPI_PL022_MIN_SSPCPSR_VALUE 2
|
||||
#define SPI_PL022_MAX_SSPCPSR_VALUE 254
|
||||
#define SPI_PL022_MAX_SRC_VALUE 255
|
||||
#define SPI_PL022_SSPCR0_SCR_POS 8
|
||||
#define SPI_PL022_SSPCR0_SCR_MSK (0xFFul<<SPI_PL022_SSPCR0_SCR_POS)
|
||||
|
||||
static const PinMap PinMap_SPI_SCLK[] = {
|
||||
{SPI_SCLK , SPI_0, 0},
|
||||
{CLCD_SCLK , SPI_1, 0},
|
||||
{ADC_SCLK , SPI_2, ALTERNATE_FUNC},
|
||||
{SHIELD_0_SPI_SCK , SPI_3, ALTERNATE_FUNC},
|
||||
{SHIELD_1_SPI_SCK , SPI_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{SPI_SCLK, SPI_0, 0},
|
||||
{CLCD_SCLK, SPI_1, 0},
|
||||
{ADC_SCLK, SPI_2, ALTERNATE_FUNC},
|
||||
{SHIELD_0_SPI_SCK, SPI_3, ALTERNATE_FUNC},
|
||||
{SHIELD_1_SPI_SCK, SPI_4, ALTERNATE_FUNC},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static const PinMap PinMap_SPI_MOSI[] = {
|
||||
{SPI_MOSI , SPI_0, 0},
|
||||
{CLCD_MOSI , SPI_1, 0},
|
||||
{ADC_MOSI , SPI_2, ALTERNATE_FUNC},
|
||||
{SPI_MOSI, SPI_0, 0},
|
||||
{CLCD_MOSI, SPI_1, 0},
|
||||
{ADC_MOSI, SPI_2, ALTERNATE_FUNC},
|
||||
{SHIELD_0_SPI_MOSI, SPI_3, ALTERNATE_FUNC},
|
||||
{SHIELD_1_SPI_MOSI, SPI_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static const PinMap PinMap_SPI_MISO[] = {
|
||||
{SPI_MISO , SPI_0, 0},
|
||||
{CLCD_MISO , SPI_1, 0},
|
||||
{ADC_MISO , SPI_2, ALTERNATE_FUNC},
|
||||
{SPI_MISO, SPI_0, 0},
|
||||
{CLCD_MISO, SPI_1, 0},
|
||||
{ADC_MISO, SPI_2, ALTERNATE_FUNC},
|
||||
{SHIELD_0_SPI_MISO, SPI_3, ALTERNATE_FUNC},
|
||||
{SHIELD_1_SPI_MISO, SPI_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static const PinMap PinMap_SPI_SSEL[] = {
|
||||
{SPI_SSEL , SPI_0, 0},
|
||||
{CLCD_SSEL , SPI_1, 0},
|
||||
{ADC_SSEL , SPI_2, ALTERNATE_FUNC},
|
||||
{SPI_SSEL, SPI_0, 0},
|
||||
{CLCD_SSEL, SPI_1, 0},
|
||||
{ADC_SSEL, SPI_2, ALTERNATE_FUNC},
|
||||
{SHIELD_0_SPI_nCS, SPI_3, ALTERNATE_FUNC},
|
||||
{SHIELD_1_SPI_nCS, SPI_4, ALTERNATE_FUNC},
|
||||
{NC , NC , 0}
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static inline int ssp_disable(spi_t *obj);
|
||||
static inline int ssp_enable(spi_t *obj);
|
||||
/* SPI configuration values */
|
||||
#define SPI_BITS_MIN_VALUE 4
|
||||
#define SPI_BITS_MAX_VALUE 16
|
||||
#define SPI_MODE_PHASE_BIT 0
|
||||
#define SPI_MODE_PHASE_BIT_MSK (0x1ul << SPI_MODE_PHASE_BIT)
|
||||
#define SPI_MODE_POLARITY_BIT 1
|
||||
#define SPI_MODE_POLARITY_BIT_MSK (0x1ul << SPI_MODE_POLARITY_BIT)
|
||||
#define SPI_MODE_MAX_VALUE_MSK ((0x1ul << (SPI_MODE_POLARITY_BIT+1))-1)
|
||||
|
||||
static uint32_t spi_fill_object(spi_t *obj, PinName mosi, PinName miso,
|
||||
PinName sclk, PinName ssel)
|
||||
{
|
||||
/* Determine the SPI to use */
|
||||
uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI);
|
||||
uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO);
|
||||
uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
||||
uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL);
|
||||
uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso);
|
||||
uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel);
|
||||
uint32_t spi_index = pinmap_merge(spi_data, spi_cntl);
|
||||
if ((spi_data == (uint32_t)NC) || (spi_index == (uint32_t)NC)) {
|
||||
/* Both miso and mosi or all 4 pins are NC */
|
||||
error("SPI pinout mapping failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (spi_index) {
|
||||
#ifdef ARM_SPI0
|
||||
case SPI_0:
|
||||
obj->spi = &SPI0_PL022_DEV;
|
||||
return 0;
|
||||
#endif /* ARM_SPI0 */
|
||||
#ifdef ARM_SPI1
|
||||
case SPI_1:
|
||||
obj->spi = &SPI1_PL022_DEV;
|
||||
return 0;
|
||||
#endif /* ARM_SPI1 */
|
||||
#ifdef ARM_SPI2
|
||||
case SPI_2:
|
||||
obj->spi = &SPI2_PL022_DEV;
|
||||
return 0;
|
||||
#endif /* ARM_SPI2 */
|
||||
#ifdef ARM_SPI3
|
||||
case SPI_3:
|
||||
obj->spi = &SPI3_PL022_DEV;
|
||||
return 0;
|
||||
#endif /* ARM_SPI3 */
|
||||
#ifdef ARM_SPI4
|
||||
case SPI_4:
|
||||
obj->spi = &SPI4_PL022_DEV;
|
||||
return 0;
|
||||
#endif /* ARM_SPI4 */
|
||||
default:
|
||||
error("Can not assign valid SPI peripheral to the pins given");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
||||
{
|
||||
/* Determine the SPI to use */
|
||||
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
|
||||
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
|
||||
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
||||
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
|
||||
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
|
||||
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
|
||||
|
||||
obj->spi = (MPS2_SSP_TypeDef*)pinmap_merge(spi_data, spi_cntl);
|
||||
if ((int)obj->spi == NC) {
|
||||
error("SPI pinout mapping failed");
|
||||
if (spi_fill_object(obj, mosi, miso, sclk, ssel) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable power and clocking */
|
||||
switch ((int)obj->spi) {
|
||||
case SPI_0:
|
||||
obj->spi->CR1 = 0;
|
||||
obj->spi->CR0 = SSP_CR0_SCR_DFLT | SSP_CR0_FRF_MOT | SSP_CR0_DSS_8;
|
||||
obj->spi->CPSR = SSP_CPSR_DFLT;
|
||||
obj->spi->IMSC = 0x8;
|
||||
obj->spi->DMACR = 0;
|
||||
obj->spi->CR1 = SSP_CR1_SSE_Msk;
|
||||
obj->spi->ICR = 0x3;
|
||||
break;
|
||||
case SPI_1: /* Configure SSP used for LCD */
|
||||
obj->spi->CR1 = 0; /* Synchronous serial port disable */
|
||||
obj->spi->DMACR = 0; /* Disable FIFO DMA */
|
||||
obj->spi->IMSC = 0; /* Mask all FIFO/IRQ interrupts */
|
||||
obj->spi->ICR = ((1ul << 0) | /* Clear SSPRORINTR interrupt */
|
||||
(1ul << 1) ); /* Clear SSPRTINTR interrupt */
|
||||
obj->spi->CR0 = ((7ul << 0) | /* 8 bit data size */
|
||||
(0ul << 4) | /* Motorola frame format */
|
||||
(0ul << 6) | /* CPOL = 0 */
|
||||
(0ul << 7) | /* CPHA = 0 */
|
||||
(1ul << 8) ); /* Set serial clock rate */
|
||||
obj->spi->CPSR = (2ul << 0); /* set SSP clk to 6MHz (6.6MHz max) */
|
||||
obj->spi->CR1 = ((1ul << 1) | /* Synchronous serial port enable */
|
||||
(0ul << 2) ); /* Device configured as master */
|
||||
break;
|
||||
case SPI_2: /* Shield ADC SPI */
|
||||
case SPI_3: /* Shield 0 SPI */
|
||||
case SPI_4: /* Shield 1 SPI */
|
||||
obj->spi->CR1 = 0;
|
||||
obj->spi->CR0 = SSP_CR0_SCR_DFLT | SSP_CR0_FRF_MOT | SSP_CR0_DSS_8;
|
||||
obj->spi->CPSR = SSP_CPSR_DFLT;
|
||||
obj->spi->IMSC = 0x8;
|
||||
obj->spi->DMACR = 0;
|
||||
obj->spi->CR1 = SSP_CR1_SSE_Msk;
|
||||
obj->spi->ICR = 0x3;
|
||||
/* Set pin function as an alt-function */
|
||||
if (mosi != NC) {
|
||||
pin_function(mosi, ALTERNATE_FUNC);
|
||||
}
|
||||
if (miso != NC) {
|
||||
pin_function(miso, ALTERNATE_FUNC);
|
||||
}
|
||||
if (sclk != NC) {
|
||||
pin_function(sclk, ALTERNATE_FUNC);
|
||||
}
|
||||
if (ssel != NC) {
|
||||
pin_function(ssel, ALTERNATE_FUNC);
|
||||
}
|
||||
break;
|
||||
(void)spi_pl022_init(obj->spi, SystemCoreClock);
|
||||
|
||||
/*
|
||||
* If the pins are not linked to a GPIO,
|
||||
* pin_function will have no effect.
|
||||
* Mosi, miso and ssel pins are allowed to be NC,
|
||||
* call pin_function only if they are connected
|
||||
*/
|
||||
if (mosi != NC) {
|
||||
pin_function(mosi, pinmap_function(mosi, PinMap_SPI_MOSI));
|
||||
}
|
||||
|
||||
/* Set default format and frequency */
|
||||
if (ssel == NC) {
|
||||
spi_format(obj, 8, 0, 0); /* 8 bits, mode 0, master */
|
||||
} else {
|
||||
spi_format(obj, 8, 0, 1); /* 8 bits, mode 0, slave */
|
||||
if (miso != NC) {
|
||||
pin_function(miso, pinmap_function(miso, PinMap_SPI_MISO));
|
||||
}
|
||||
|
||||
/* Default SPI frequency */
|
||||
spi_frequency(obj, 1000000);
|
||||
|
||||
/* Enable the ssp channel */
|
||||
ssp_enable(obj);
|
||||
if (ssel != NC) {
|
||||
pin_function(ssel, pinmap_function(ssel, PinMap_SPI_SSEL));
|
||||
}
|
||||
pin_function(sclk, pinmap_function(sclk, PinMap_SPI_SCLK));
|
||||
}
|
||||
|
||||
void spi_free(spi_t *obj)
|
||||
{
|
||||
error("SPI free error");
|
||||
/* No need to implement free function, this API is intentionally blank */
|
||||
}
|
||||
|
||||
void spi_format(spi_t *obj, int bits, int mode, int slave)
|
||||
{
|
||||
ssp_disable(obj);
|
||||
if (!(bits >= 4 && bits <= 16) || !(mode >= 0 && mode <= 3)) {
|
||||
uint32_t polarity, phase, frame_format;
|
||||
struct spi_pl022_ctrl_cfg_t ctrl_cfg;
|
||||
|
||||
if (!(bits >= SPI_BITS_MIN_VALUE && bits <= SPI_BITS_MAX_VALUE) ||
|
||||
(mode & ~SPI_MODE_MAX_VALUE_MSK)) {
|
||||
error("SPI format error");
|
||||
return;
|
||||
}
|
||||
|
||||
int polarity = (mode & 0x2) ? 1 : 0;
|
||||
int phase = (mode & 0x1) ? 1 : 0;
|
||||
spi_pl022_dev_disable(obj->spi);
|
||||
if (spi_pl022_get_ctrl_cfg(obj->spi, &ctrl_cfg) != 0) {
|
||||
error("SPI not initialized");
|
||||
return;
|
||||
};
|
||||
|
||||
// set it up
|
||||
int DSS = bits - 1; /* DSS (data select size) */
|
||||
int SPO = (polarity) ? 1 : 0; /* SPO - clock out polarity */
|
||||
int SPH = (phase) ? 1 : 0; /* SPH - clock out phase */
|
||||
polarity = (mode & SPI_MODE_POLARITY_BIT_MSK) ? 1u : 0;
|
||||
phase = (mode & SPI_MODE_PHASE_BIT_MSK) ? 1u : 0;
|
||||
frame_format = (SPI_PL022_CFG_FRF_MOT << 0 |
|
||||
polarity << 6 |
|
||||
phase << 7);
|
||||
|
||||
int FRF = 0; /* FRF (frame format) = SPI */
|
||||
uint32_t tmp = obj->spi->CR0;
|
||||
tmp &= ~(0xFFFF);
|
||||
tmp |= DSS << 0
|
||||
| FRF << 4
|
||||
| SPO << 6
|
||||
| SPH << 7;
|
||||
obj->spi->CR0 = tmp;
|
||||
ctrl_cfg.frame_format = (uint8_t) frame_format;
|
||||
ctrl_cfg.word_size = (uint8_t) bits;
|
||||
ctrl_cfg.spi_mode =
|
||||
slave ? SPI_PL022_SLAVE_SELECT : SPI_PL022_MASTER_SELECT;
|
||||
|
||||
tmp = obj->spi->CR1;
|
||||
tmp &= ~(0xD);
|
||||
tmp |= 0 << 0 /* LBM - loop back mode - off */
|
||||
| ((slave) ? 1 : 0) << 2 /* MS - master slave mode, 1 = slave */
|
||||
| 0 << 3; /* SOD - slave output disable - na */
|
||||
obj->spi->CR1 = tmp;
|
||||
if (spi_pl022_set_ctrl_cfg(obj->spi, &ctrl_cfg) != 0) {
|
||||
error("SPI configuration failed");
|
||||
}
|
||||
|
||||
ssp_enable(obj);
|
||||
spi_pl022_dev_enable(obj->spi);
|
||||
}
|
||||
|
||||
void spi_frequency(spi_t *obj, int hz)
|
||||
{
|
||||
uint32_t clkps_dvsr, scr;
|
||||
uint32_t sys_clk = SystemCoreClock;
|
||||
spi_pl022_dev_disable(obj->spi);
|
||||
|
||||
for(clkps_dvsr = SPI_PL022_MIN_SSPCPSR_VALUE;
|
||||
clkps_dvsr <= SPI_PL022_MAX_SSPCPSR_VALUE; clkps_dvsr += 2) {
|
||||
|
||||
/* Calculate clock rate based on the new clock prescale divisor */
|
||||
scr = (sys_clk / (clkps_dvsr * hz)) - 1;
|
||||
|
||||
/* Checks if it can be supported by the divider */
|
||||
if (scr <= SPI_PL022_MAX_SRC_VALUE) {
|
||||
ssp_disable(obj);
|
||||
obj->spi->CPSR = clkps_dvsr;
|
||||
obj->spi->CR0 &= ~SPI_PL022_SSPCR0_SCR_MSK;
|
||||
obj->spi->CR0 |= (scr << SPI_PL022_SSPCR0_SCR_POS);
|
||||
ssp_enable(obj);
|
||||
return;
|
||||
}
|
||||
obj->spi->data->ctrl_cfg.bit_rate = hz;
|
||||
if (spi_pl022_set_sys_clk(obj->spi, SystemCoreClock) != 0) {
|
||||
error("SPI frequency config failed");
|
||||
}
|
||||
|
||||
error("Couldn't setup requested SPI frequency %dHz", hz);
|
||||
}
|
||||
|
||||
static inline int ssp_disable(spi_t *obj)
|
||||
{
|
||||
return obj->spi->CR1 &= ~(1 << 1);
|
||||
}
|
||||
|
||||
static inline int ssp_enable(spi_t *obj)
|
||||
{
|
||||
return obj->spi->CR1 |= SSP_CR1_SSE_Msk;
|
||||
}
|
||||
|
||||
static inline int ssp_readable(spi_t *obj)
|
||||
{
|
||||
return obj->spi->SR & (1 << 2);
|
||||
}
|
||||
|
||||
static inline int ssp_writeable(spi_t *obj)
|
||||
{
|
||||
return obj->spi->SR & SSP_SR_BSY_Msk;
|
||||
}
|
||||
|
||||
static inline void ssp_write(spi_t *obj, int value)
|
||||
{
|
||||
obj->spi->DR = value;
|
||||
while (ssp_writeable(obj));
|
||||
}
|
||||
static inline int ssp_read(spi_t *obj)
|
||||
{
|
||||
int read_DR = obj->spi->DR;
|
||||
return read_DR;
|
||||
}
|
||||
|
||||
static inline int ssp_busy(spi_t *obj)
|
||||
{
|
||||
return (obj->spi->SR & (1 << 4)) ? (1) : (0);
|
||||
spi_pl022_dev_enable(obj->spi);
|
||||
}
|
||||
|
||||
int spi_master_write(spi_t *obj, int value)
|
||||
{
|
||||
ssp_write(obj, value);
|
||||
while (obj->spi->SR & SSP_SR_BSY_Msk); /* Wait for send to finish */
|
||||
return (ssp_read(obj));
|
||||
int32_t rx_data = 0;
|
||||
uint32_t size = 1;
|
||||
|
||||
if(obj->spi->data->ctrl_cfg.word_size > 8) {
|
||||
size = 2;
|
||||
}
|
||||
|
||||
if (spi_pl022_txrx_blocking(obj->spi, &value, &size, &rx_data, &size) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rx_data;
|
||||
}
|
||||
|
||||
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;
|
||||
char out, in;
|
||||
|
||||
for (int i = 0; i < total; i++) {
|
||||
out = (i < tx_length) ? tx_buffer[i] : write_fill;
|
||||
in = spi_master_write(obj, out);
|
||||
if (i < rx_length) {
|
||||
rx_buffer[i] = in;
|
||||
}
|
||||
if (spi_pl022_txrx_blocking(obj->spi, tx_buffer, (uint32_t*)&tx_length,
|
||||
rx_buffer, (uint32_t*)&rx_length)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return total;
|
||||
return ((tx_length > rx_length) ? tx_length : rx_length);
|
||||
}
|
||||
|
||||
int spi_slave_receive(spi_t *obj)
|
||||
{
|
||||
return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
|
||||
int32_t status = spi_pl022_get_status(obj->spi);
|
||||
/* Rx FIFO not empty and device not busy */
|
||||
int32_t ret = ((status & SPI_PL022_SSPSR_RNE_MSK) &&
|
||||
!(status & SPI_PL022_SSPSR_BSY_MSK));
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t spi_get_module(spi_t *obj)
|
||||
{
|
||||
if (obj->spi == &SPI0_PL022_DEV) {
|
||||
return SPI_0;
|
||||
} else if (obj->spi == &SPI1_PL022_DEV) {
|
||||
return SPI_1;
|
||||
} else if (obj->spi == &SPI2_PL022_DEV) {
|
||||
return SPI_2;
|
||||
} else if (obj->spi == &SPI3_PL022_DEV) {
|
||||
return SPI_3;
|
||||
} else if (obj->spi == &SPI4_PL022_DEV) {
|
||||
return SPI_4;
|
||||
} else {
|
||||
error("SPI object is not initialized");
|
||||
return (SPI_NC);
|
||||
}
|
||||
}
|
||||
|
||||
int spi_slave_read(spi_t *obj)
|
||||
{
|
||||
return obj->spi->DR;
|
||||
while(spi_slave_receive(obj) == 0) {};
|
||||
return spi_pl022_slave_read(obj->spi);
|
||||
}
|
||||
|
||||
void spi_slave_write(spi_t *obj, int value)
|
||||
{
|
||||
while (ssp_writeable(obj) == 0);
|
||||
obj->spi->DR = value;
|
||||
(void)spi_pl022_write(obj->spi, SPI_PL022_SLAVE_SELECT, &value);
|
||||
}
|
||||
|
||||
int spi_busy(spi_t *obj)
|
||||
{
|
||||
return ssp_busy(obj);
|
||||
int32_t status = spi_pl022_get_status(obj->spi);
|
||||
return (status & SPI_PL022_SSPSR_BSY_MSK);
|
||||
}
|
||||
|
|
|
@ -1,174 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ----------------------------------------------------------------
|
||||
* File: spi_def.h
|
||||
* Release: Version 2.0
|
||||
* ----------------------------------------------------------------
|
||||
*
|
||||
* SSP interface Support
|
||||
* =====================
|
||||
*/
|
||||
|
||||
#define SSPCS_BASE (0x4002804C) // SSP chip select register
|
||||
#define SSP_BASE (0x40020000) // SSP Prime Cell
|
||||
|
||||
#define SSPCR0 ((volatile unsigned int *)(SSP_BASE + 0x00))
|
||||
#define SSPCR1 ((volatile unsigned int *)(SSP_BASE + 0x04))
|
||||
#define SSPDR ((volatile unsigned int *)(SSP_BASE + 0x08))
|
||||
#define SSPSR ((volatile unsigned int *)(SSP_BASE + 0x0C))
|
||||
#define SSPCPSR ((volatile unsigned int *)(SSP_BASE + 0x10))
|
||||
#define SSPIMSC ((volatile unsigned int *)(SSP_BASE + 0x14))
|
||||
#define SSPRIS ((volatile unsigned int *)(SSP_BASE + 0x18))
|
||||
#define SSPMIS ((volatile unsigned int *)(SSP_BASE + 0x1C))
|
||||
#define SSPICR ((volatile unsigned int *)(SSP_BASE + 0x20))
|
||||
#define SSPDMACR ((volatile unsigned int *)(SSP_BASE + 0x24))
|
||||
#define SSPCS ((volatile unsigned int *)(SSPCS_BASE))
|
||||
|
||||
// SSPCR0 Control register 0
|
||||
#define SSPCR0_SCR_DFLT 0x0300 // Serial Clock Rate (divide), default set at 3
|
||||
#define SSPCR0_SPH 0x0080 // SSPCLKOUT phase
|
||||
#define SSPCR0_SPO 0x0040 // SSPCLKOUT polarity
|
||||
#define SSPCR0_FRF_MOT 0x0000 // Frame format, Motorola
|
||||
#define SSPCR0_DSS_8 0x0007 // Data packet size, 8bits
|
||||
#define SSPCR0_DSS_16 0x000F // Data packet size, 16bits
|
||||
|
||||
// SSPCR1 Control register 1
|
||||
#define SSPCR1_SOD 0x0008 // Slave Output mode Disable
|
||||
#define SSPCR1_MS 0x0004 // Master or Slave mode
|
||||
#define SSPCR1_SSE 0x0002 // Serial port enable
|
||||
#define SSPCR1_LBM 0x0001 // Loop Back Mode
|
||||
|
||||
// SSPSR Status register
|
||||
#define SSPSR_BSY 0x0010 // Busy
|
||||
#define SSPSR_RFF 0x0008 // Receive FIFO full
|
||||
#define SSPSR_RNE 0x0004 // Receive FIFO not empty
|
||||
#define SSPSR_TNF 0x0002 // Transmit FIFO not full
|
||||
#define SSPSR_TFE 0x0001 // Transmit FIFO empty
|
||||
|
||||
// SSPCPSR Clock prescale register
|
||||
#define SSPCPSR_DFLT 0x0008 // Clock prescale (use with SCR), default set at 8
|
||||
|
||||
// SSPIMSC Interrupt mask set and clear register
|
||||
#define SSPIMSC_TXIM 0x0008 // Transmit FIFO not Masked
|
||||
#define SSPIMSC_RXIM 0x0004 // Receive FIFO not Masked
|
||||
#define SSPIMSC_RTIM 0x0002 // Receive timeout not Masked
|
||||
#define SSPIMSC_RORIM 0x0001 // Receive overrun not Masked
|
||||
|
||||
// SSPRIS Raw interrupt status register
|
||||
#define SSPRIS_TXRIS 0x0008 // Raw Transmit interrupt flag
|
||||
#define SSPRIS_RXRIS 0x0004 // Raw Receive interrupt flag
|
||||
#define SSPRIS_RTRIS 0x0002 // Raw Timemout interrupt flag
|
||||
#define SSPRIS_RORRIS 0x0001 // Raw Overrun interrupt flag
|
||||
|
||||
// SSPMIS Masked interrupt status register
|
||||
#define SSPMIS_TXMIS 0x0008 // Masked Transmit interrupt flag
|
||||
#define SSPMIS_RXMIS 0x0004 // Masked Receive interrupt flag
|
||||
#define SSPMIS_RTMIS 0x0002 // Masked Timemout interrupt flag
|
||||
#define SSPMIS_RORMIS 0x0001 // Masked Overrun interrupt flag
|
||||
|
||||
// SSPICR Interrupt clear register
|
||||
#define SSPICR_RTIC 0x0002 // Clears Timeout interrupt flag
|
||||
#define SSPICR_RORIC 0x0001 // Clears Overrun interrupt flag
|
||||
|
||||
// SSPDMACR DMA control register
|
||||
#define SSPDMACR_TXDMAE 0x0002 // Enable Transmit FIFO DMA
|
||||
#define SSPDMACR_RXDMAE 0x0001 // Enable Receive FIFO DMA
|
||||
|
||||
// SPICS register (0=Chip Select low)
|
||||
#define SSPCS_nCS1 0x0002 // nCS1 (SPI_nSS)
|
||||
|
||||
// SPI defaults
|
||||
#define SSPMAXTIME 1000 // Maximum time to wait for SSP (10*10uS)
|
||||
|
||||
// EEPROM instruction set
|
||||
#define EEWRSR 0x0001 // Write status
|
||||
#define EEWRITE 0x0002 // Write data
|
||||
#define EEREAD 0x0003 // Read data
|
||||
#define EEWDI 0x0004 // Write disable
|
||||
#define EEWREN 0x0006 // Write enable
|
||||
#define EERDSR 0x0005 // Read status
|
||||
|
||||
// EEPROM status register flags
|
||||
#define EERDSR_WIP 0x0001 // Write in process
|
||||
#define EERDSR_WEL 0x0002 // Write enable latch
|
||||
#define EERDSR_BP0 0x0004 // Block protect 0
|
||||
#define EERDSR_BP1 0x0008 // Block protect 1
|
||||
#define EERDSR_WPEN 0x0080 // Write protect enable
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
*
|
||||
* Color LCD Support
|
||||
* =================
|
||||
*/
|
||||
|
||||
// Color LCD Controller Internal Register addresses
|
||||
#define LSSPCS_BASE (0x4002804C) // LSSP chip select register
|
||||
#define LSSP_BASE (0x40021000) // LSSP Prime Cell
|
||||
|
||||
#define LSSPCR0 ((volatile unsigned int *)(LSSP_BASE + 0x00))
|
||||
#define LSSPCR1 ((volatile unsigned int *)(LSSP_BASE + 0x04))
|
||||
#define LSSPDR ((volatile unsigned int *)(LSSP_BASE + 0x08))
|
||||
#define LSSPSR ((volatile unsigned int *)(LSSP_BASE + 0x0C))
|
||||
#define LSSPCPSR ((volatile unsigned int *)(LSSP_BASE + 0x10))
|
||||
#define LSSPIMSC ((volatile unsigned int *)(LSSP_BASE + 0x14))
|
||||
#define LSSPRIS ((volatile unsigned int *)(LSSP_BASE + 0x18))
|
||||
#define LSSPMIS ((volatile unsigned int *)(LSSP_BASE + 0x1C))
|
||||
#define LSSPICR ((volatile unsigned int *)(LSSP_BASE + 0x20))
|
||||
#define LSSPDMACR ((volatile unsigned int *)(LSSP_BASE + 0x24))
|
||||
#define LSSPCS ((volatile unsigned int *)(LSSPCS_BASE))
|
||||
|
||||
// LSSPCR0 Control register 0
|
||||
#define LSSPCR0_SCR_DFLT 0x0100 // Serial Clock Rate (divide), CLK/(CPSR*(1+SCR))
|
||||
#define LSSPCR0_SPH 0x0080 // LSSPCLKOUT phase
|
||||
#define LSSPCR0_SPO 0x0040 // LSSPCLKOUT polarity
|
||||
#define LSSPCR0_FRF_MOT 0x0000 // Frame format, Motorola
|
||||
#define LSSPCR0_DSS_8 0x0007 // Data packet size, 8bits
|
||||
#define LSSPCR0_DSS_16 0x000F // Data packet size, 16bits
|
||||
|
||||
// LSSPCR1 Control register 1
|
||||
#define LSSPCR1_SOD 0x0008 // Slave Output mode Disable
|
||||
#define LSSPCR1_MS 0x0004 // Master or Slave mode
|
||||
#define LSSPCR1_SSE 0x0002 // Serial port enable
|
||||
#define LSSPCR1_LBM 0x0001 // Loop Back Mode
|
||||
|
||||
// LSSPSR Status register
|
||||
#define LSSPSR_BSY 0x0010 // Busy
|
||||
#define LSSPSR_RFF 0x0008 // Receive FIFO full
|
||||
#define LSSPSR_RNE 0x0004 // Receive FIFO not empty
|
||||
#define LSSPSR_TNF 0x0002 // Transmit FIFO not full
|
||||
#define LSSPSR_TFE 0x0001 // Transmit FIFO empty
|
||||
|
||||
// LSSPCPSR Clock prescale register
|
||||
#define LSSPCPSR_DFLT 0x0002 // Clock prescale (use with SCR)
|
||||
|
||||
// SPICS register
|
||||
#define LSSPCS_nCS0 0x0001 // nCS0 (CLCD_CS)
|
||||
#define LSSPCS_nCS2 0x0004 // nCS2 (CLCD_T_CS)
|
||||
#define LCD_RESET 0x0008 // RESET (CLCD_RESET)
|
||||
#define LCD_RS 0x0010 // RS (CLCD_RS)
|
||||
#define LCD_RD 0x0020 // RD (CLCD_RD)
|
||||
#define LCD_BL 0x0040 // Backlight (CLCD_BL_CTRL)
|
||||
|
||||
// SPI defaults
|
||||
#define LSSPMAXTIME 10000 // Maximum time to wait for LSSP (10*10uS)
|
||||
#define LSPI_START (0x70) // Start byte for SPI transfer
|
||||
#define LSPI_RD (0x01) // WR bit 1 within start
|
||||
#define LSPI_WR (0x00) // WR bit 0 within start
|
||||
#define LSPI_DATA (0x02) // RS bit 1 within start byte
|
||||
#define LSPI_INDEX (0x00) // RS bit 0 within start byte
|
||||
|
||||
// Screen size
|
||||
#define LCD_WIDTH 320 // Screen Width (in pixels)
|
||||
#define LCD_HEIGHT 240 // Screen Height (in pixels)
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -14,125 +14,98 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* This file is derivative of us_ticker.c from BEETLE */
|
||||
/**
|
||||
* Elapsed time measure and interval timer in micro-secundum,
|
||||
* servicing \ref us_ticker_api.h, using CMSDK Timer0 \ref CMSDK_TIMER0_DEV.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "cmsis.h"
|
||||
#include "cmsdk_ticker.h"
|
||||
#include "us_ticker_api.h"
|
||||
#include "PeripheralNames.h"
|
||||
#include "platform_devices.h"
|
||||
|
||||
#define TIMER_MAX_VALUE 0
|
||||
|
||||
/* Private data */
|
||||
struct us_ticker_drv_data_t {
|
||||
uint32_t inited; /* us ticker initialized */
|
||||
uint32_t overflow_delta; /* us ticker overflow */
|
||||
uint32_t overflow_limit; /* us ticker overflow limit */
|
||||
};
|
||||
|
||||
static struct us_ticker_drv_data_t us_ticker_drv_data = {
|
||||
.inited = 0,
|
||||
.overflow_delta = 0,
|
||||
.overflow_limit = 0
|
||||
};
|
||||
|
||||
|
||||
void __us_ticker_irq_handler(void)
|
||||
/**
|
||||
* \brief Convert clocks to us
|
||||
*
|
||||
* \param[in] tick Number of clocks
|
||||
*
|
||||
* \return Number of usec, relative to the timer frequency,
|
||||
* that a given ammount of ticks equates to.
|
||||
*/
|
||||
static uint32_t convert_tick_to_us(uint32_t tick)
|
||||
{
|
||||
Timer_ClearInterrupt(TIMER1);
|
||||
/*
|
||||
* For each overflow event adds the timer max represented value to
|
||||
* the delta. This allows the us_ticker to keep track of the elapsed
|
||||
* time:
|
||||
* elapsed_time = (num_overflow * overflow_limit) + current_time
|
||||
*/
|
||||
us_ticker_drv_data.overflow_delta += us_ticker_drv_data.overflow_limit;
|
||||
return (tick / (SystemCoreClock / SEC_TO_USEC_MULTIPLIER));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert us to clock ticks
|
||||
*
|
||||
* \param[in] us Time to convert to clock ticks
|
||||
*
|
||||
* \return Number of clock ticks relative to the timer frequency,
|
||||
* that a given period of usec equates to.
|
||||
*/
|
||||
static uint32_t convert_us_to_tick(uint32_t us)
|
||||
{
|
||||
return (us * (SystemCoreClock / SEC_TO_USEC_MULTIPLIER));
|
||||
}
|
||||
|
||||
static const struct tick_cfg_t cfg =
|
||||
{
|
||||
.timer_driver = &CMSDK_TIMER0_DEV,
|
||||
.irq_n = TIMER0_IRQn,
|
||||
.interval_callback = &us_ticker_irq_handler,
|
||||
.convert_tick_to_time = &convert_tick_to_us,
|
||||
.convert_time_to_tick = &convert_us_to_tick
|
||||
};
|
||||
|
||||
static struct tick_data_t data =
|
||||
{
|
||||
.is_initialized = false,
|
||||
.cumulated_time = 0,
|
||||
.max_interval_time = 0,
|
||||
.reload_time = 0,
|
||||
.interval_callback_enabled = false,
|
||||
.previous_cumulated_time = 0,
|
||||
.previous_elapsed = 0
|
||||
};
|
||||
|
||||
static struct tick_drv_data_t timer_data =
|
||||
{
|
||||
.cfg = &cfg,
|
||||
.data = &data
|
||||
};
|
||||
|
||||
void us_ticker_init(void)
|
||||
{
|
||||
uint32_t us_ticker_irqn0 = 0;
|
||||
uint32_t us_ticker_irqn1 = 0;
|
||||
|
||||
if (us_ticker_drv_data.inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
us_ticker_drv_data.inited = 1;
|
||||
|
||||
/* Initialize Timer 0 */
|
||||
Timer_Initialize(TIMER0, TIMER_MAX_VALUE);
|
||||
/* Enable Timer 0 */
|
||||
Timer_Enable(TIMER0);
|
||||
|
||||
/* Initialize Timer 1 */
|
||||
Timer_Initialize(TIMER1, TIMER_MAX_VALUE);
|
||||
/* Enable Timer 1 */
|
||||
Timer_Enable(TIMER1);
|
||||
|
||||
/* Timer 0 get IRQn */
|
||||
us_ticker_irqn0 = Timer_GetIRQn(TIMER0);
|
||||
NVIC_SetVector((IRQn_Type)us_ticker_irqn0, (uint32_t)us_ticker_irq_handler);
|
||||
NVIC_EnableIRQ((IRQn_Type)us_ticker_irqn0);
|
||||
|
||||
/* Timer 1 get IRQn */
|
||||
us_ticker_irqn1 = Timer_GetIRQn(TIMER1);
|
||||
NVIC_SetVector((IRQn_Type)us_ticker_irqn1, (uint32_t)__us_ticker_irq_handler);
|
||||
NVIC_EnableIRQ((IRQn_Type)us_ticker_irqn1);
|
||||
|
||||
/* Timer set interrupt on TIMER1 */
|
||||
Timer_SetInterrupt(TIMER1, TIMER_DEFAULT_RELOAD);
|
||||
|
||||
/*
|
||||
* Set us_ticker Overflow limit. The us_ticker overflow limit is required
|
||||
* to calculated the return value of the us_ticker read function in us
|
||||
* on 32bit.
|
||||
* A 32bit us value cannot be represented directly in the Timer Load
|
||||
* register if it is greater than (0xFFFFFFFF ticks)/TIMER_DIVIDER_US.
|
||||
*/
|
||||
us_ticker_drv_data.overflow_limit = Timer_GetReloadValue(TIMER1);
|
||||
cmsdk_ticker_init(&timer_data);
|
||||
}
|
||||
|
||||
uint32_t us_ticker_read()
|
||||
{
|
||||
uint32_t return_value = 0;
|
||||
|
||||
if (!us_ticker_drv_data.inited) {
|
||||
us_ticker_init();
|
||||
}
|
||||
|
||||
return_value = us_ticker_drv_data.overflow_delta + Timer_Read(TIMER1);
|
||||
|
||||
return return_value;
|
||||
return cmsdk_ticker_read(&timer_data);
|
||||
}
|
||||
|
||||
void us_ticker_set_interrupt(timestamp_t timestamp)
|
||||
{
|
||||
uint32_t delta = 0;
|
||||
|
||||
if (!us_ticker_drv_data.inited) {
|
||||
us_ticker_init();
|
||||
}
|
||||
|
||||
delta = timestamp - us_ticker_read();
|
||||
|
||||
/* If the event was not in the past enable interrupt */
|
||||
Timer_SetInterrupt(TIMER0, delta);
|
||||
|
||||
}
|
||||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
uint32_t us_ticker_irqn1 = Timer_GetIRQn(TIMER1);
|
||||
NVIC_SetPendingIRQ((IRQn_Type)us_ticker_irqn1);
|
||||
cmsdk_ticker_set_interrupt(&timer_data, timestamp);
|
||||
}
|
||||
|
||||
void us_ticker_disable_interrupt(void)
|
||||
{
|
||||
Timer_DisableInterrupt(TIMER0);
|
||||
cmsdk_ticker_disable_interrupt(&timer_data);
|
||||
}
|
||||
|
||||
void us_ticker_clear_interrupt(void)
|
||||
{
|
||||
Timer_ClearInterrupt(TIMER0);
|
||||
cmsdk_ticker_clear_interrupt(&timer_data);
|
||||
}
|
||||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
cmsdk_ticker_fire_interrupt(&timer_data);
|
||||
}
|
||||
|
||||
void TIMER0_IRQHandler(void)
|
||||
{
|
||||
cmsdk_ticker_irq_handler(&timer_data);
|
||||
}
|
||||
|
|
|
@ -199,6 +199,9 @@ void us_ticker_set_interrupt(timestamp_t timestamp) {
|
|||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
us_ticker_int_counter = 0;
|
||||
us_ticker_int_remainder = 0;
|
||||
|
||||
#if defined(TARGET_KL43Z)
|
||||
NVIC_SetPendingIRQ(LPTMR0_IRQn);
|
||||
#else
|
||||
|
|
|
@ -236,7 +236,9 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
|
|||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
NVIC_SetPendingIRQ(US_TIMER_IRQn);
|
||||
US_TIMER->ctrl &= ~MXC_F_TMR_CTRL_ENABLE0; // disable timer
|
||||
US_TIMER->term_cnt32 = 1;
|
||||
US_TIMER->ctrl |= MXC_F_TMR_CTRL_ENABLE0; // enable timer
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
|
|
@ -236,7 +236,9 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
|
|||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
NVIC_SetPendingIRQ(US_TIMER_IRQn);
|
||||
US_TIMER->ctrl &= ~MXC_F_TMR_CTRL_ENABLE0; // disable timer
|
||||
US_TIMER->term_cnt32 = 1;
|
||||
US_TIMER->ctrl |= MXC_F_TMR_CTRL_ENABLE0; // enable timer
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
|
|
@ -267,7 +267,9 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
|
|||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
NVIC_SetPendingIRQ(US_TIMER_IRQn);
|
||||
US_TIMER->ctrl &= ~MXC_F_TMR_CTRL_ENABLE0; // disable timer
|
||||
US_TIMER->term_cnt32 = 1;
|
||||
US_TIMER->ctrl |= MXC_F_TMR_CTRL_ENABLE0; // enable timer
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
|
|
@ -230,7 +230,7 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
|
|||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
NVIC_SetPendingIRQ(US_TIMER_IRQn);
|
||||
TMR32_SetCompare(US_TIMER, 1);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
|
|
@ -230,7 +230,7 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
|
|||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
NVIC_SetPendingIRQ(US_TIMER_IRQn);
|
||||
TMR32_SetCompare(US_TIMER, 1);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "PeripheralNames.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "mbed_toolchain.h"
|
||||
#include "mbed_critical.h"
|
||||
|
||||
/*
|
||||
* Note: The micro-second timer API on the nRF51 platform is implemented using
|
||||
|
@ -52,6 +53,8 @@
|
|||
#define RTC_UNITS_TO_MICROSECONDS(RTC_UNITS) (((RTC_UNITS) * (uint64_t)1000000) / RTC_CLOCK_FREQ)
|
||||
#define MICROSECONDS_TO_RTC_UNITS(MICROS) ((((uint64_t)(MICROS) * RTC_CLOCK_FREQ) + 999999) / 1000000)
|
||||
|
||||
#define US_TICKER_SW_IRQ_MASK 0x1
|
||||
|
||||
static bool us_ticker_inited = false;
|
||||
static volatile uint32_t overflowCount; /**< The number of times the 24-bit RTC counter has overflowed. */
|
||||
static volatile bool us_ticker_callbackPending = false;
|
||||
|
@ -62,6 +65,9 @@ static bool os_tick_started = false; /**< flag indicating i
|
|||
*/
|
||||
static uint32_t previous_tick_cc_value = 0;
|
||||
|
||||
// us ticker fire interrupt flag for IRQ handler
|
||||
volatile uint8_t m_common_sw_irq_flag = 0;
|
||||
|
||||
/*
|
||||
RTX provide the following definitions which are used by the tick code:
|
||||
* os_trv: The number (minus 1) of clock cycle between two tick.
|
||||
|
@ -181,6 +187,11 @@ static inline uint32_t rtc1_getCounter(void)
|
|||
*/
|
||||
void us_ticker_handler(void)
|
||||
{
|
||||
if (m_common_sw_irq_flag & US_TICKER_SW_IRQ_MASK) {
|
||||
m_common_sw_irq_flag &= ~US_TICKER_SW_IRQ_MASK;
|
||||
us_ticker_irq_handler();
|
||||
}
|
||||
|
||||
if (NRF_RTC1->EVENTS_OVRFLW) {
|
||||
overflowCount++;
|
||||
NRF_RTC1->EVENTS_OVRFLW = 0;
|
||||
|
@ -287,7 +298,10 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
|
|||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
core_util_critical_section_enter();
|
||||
m_common_sw_irq_flag |= US_TICKER_SW_IRQ_MASK;
|
||||
NVIC_SetPendingIRQ(RTC1_IRQn);
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
void us_ticker_disable_interrupt(void)
|
||||
|
|
|
@ -171,7 +171,7 @@
|
|||
#define NRF_MAXIMUM_LATENCY_US 2000
|
||||
|
||||
/* RNG */
|
||||
#define RNG_ENABLED 0
|
||||
#define RNG_ENABLED 1
|
||||
|
||||
#if (RNG_ENABLED == 1)
|
||||
#define RNG_CONFIG_ERROR_CORRECTION true
|
||||
|
|
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Nordic Semiconductor ASA
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief RNG HAL API.
|
||||
*/
|
||||
|
||||
#ifndef NRF_RNG_H__
|
||||
#define NRF_RNG_H__
|
||||
/**
|
||||
* @defgroup nrf_rng_hal RNG HAL
|
||||
* @{
|
||||
* @ingroup nrf_rng
|
||||
* @brief Hardware access layer for managing the random number generator (RNG).
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "nrf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NRF_RNG_TASK_SET (1UL)
|
||||
#define NRF_RNG_EVENT_CLEAR (0UL)
|
||||
/**
|
||||
* @enum nrf_rng_task_t
|
||||
* @brief RNG tasks.
|
||||
*/
|
||||
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
|
||||
{
|
||||
NRF_RNG_TASK_START = offsetof(NRF_RNG_Type, TASKS_START), /**< Start the random number generator. */
|
||||
NRF_RNG_TASK_STOP = offsetof(NRF_RNG_Type, TASKS_STOP) /**< Stop the random number generator. */
|
||||
} nrf_rng_task_t; /*lint -restore */
|
||||
|
||||
/**
|
||||
* @enum nrf_rng_event_t
|
||||
* @brief RNG events.
|
||||
*/
|
||||
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
|
||||
{
|
||||
NRF_RNG_EVENT_VALRDY = offsetof(NRF_RNG_Type, EVENTS_VALRDY) /**< New random number generated event. */
|
||||
} nrf_rng_event_t; /*lint -restore */
|
||||
|
||||
/**
|
||||
* @enum nrf_rng_int_mask_t
|
||||
* @brief RNG interrupts.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRF_RNG_INT_VALRDY_MASK = RNG_INTENSET_VALRDY_Msk /**< Mask for enabling or disabling an interrupt on VALRDY event. */
|
||||
} nrf_rng_int_mask_t;
|
||||
|
||||
/**
|
||||
* @enum nrf_rng_short_mask_t
|
||||
* @brief Types of RNG shortcuts.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NRF_RNG_SHORT_VALRDY_STOP_MASK = RNG_SHORTS_VALRDY_STOP_Msk /**< Mask for setting shortcut between EVENT_VALRDY and TASK_STOP. */
|
||||
} nrf_rng_short_mask_t;
|
||||
|
||||
/**
|
||||
* @brief Function for enabling interrupts.
|
||||
*
|
||||
* @param[in] rng_int_mask Mask of interrupts.
|
||||
*/
|
||||
__STATIC_INLINE void nrf_rng_int_enable(uint32_t rng_int_mask);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling interrupts.
|
||||
*
|
||||
* @param[in] rng_int_mask Mask of interrupts.
|
||||
*/
|
||||
__STATIC_INLINE void nrf_rng_int_disable(uint32_t rng_int_mask);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the state of a specific interrupt.
|
||||
*
|
||||
* @param[in] rng_int_mask Interrupt.
|
||||
*
|
||||
* @retval true If the interrupt is not enabled.
|
||||
* @retval false If the interrupt is enabled.
|
||||
*/
|
||||
__STATIC_INLINE bool nrf_rng_int_get(nrf_rng_int_mask_t rng_int_mask);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the address of a specific task.
|
||||
*
|
||||
* This function can be used by the PPI module.
|
||||
*
|
||||
* @param[in] rng_task Task.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t * nrf_rng_task_address_get(nrf_rng_task_t rng_task);
|
||||
|
||||
/**
|
||||
* @brief Function for setting a specific task.
|
||||
*
|
||||
* @param[in] rng_task Task.
|
||||
*/
|
||||
__STATIC_INLINE void nrf_rng_task_trigger(nrf_rng_task_t rng_task);
|
||||
|
||||
/**
|
||||
* @brief Function for getting address of a specific event.
|
||||
*
|
||||
* This function can be used by the PPI module.
|
||||
*
|
||||
* @param[in] rng_event Event.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t * nrf_rng_event_address_get(nrf_rng_event_t rng_event);
|
||||
|
||||
/**
|
||||
* @brief Function for clearing a specific event.
|
||||
*
|
||||
* @param[in] rng_event Event.
|
||||
*/
|
||||
__STATIC_INLINE void nrf_rng_event_clear(nrf_rng_event_t rng_event);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the state of a specific event.
|
||||
*
|
||||
* @param[in] rng_event Event.
|
||||
*
|
||||
* @retval true If the event is not set.
|
||||
* @retval false If the event is set.
|
||||
*/
|
||||
__STATIC_INLINE bool nrf_rng_event_get(nrf_rng_event_t rng_event);
|
||||
|
||||
/**
|
||||
* @brief Function for setting shortcuts.
|
||||
*
|
||||
* @param[in] rng_short_mask Mask of shortcuts.
|
||||
*
|
||||
*/
|
||||
__STATIC_INLINE void nrf_rng_shorts_enable(uint32_t rng_short_mask);
|
||||
|
||||
/**
|
||||
* @brief Function for clearing shortcuts.
|
||||
*
|
||||
* @param[in] rng_short_mask Mask of shortcuts.
|
||||
*
|
||||
*/
|
||||
__STATIC_INLINE void nrf_rng_shorts_disable(uint32_t rng_short_mask);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the previously generated random value.
|
||||
*
|
||||
* @return Previously generated random value.
|
||||
*/
|
||||
__STATIC_INLINE uint8_t nrf_rng_random_value_get(void);
|
||||
|
||||
/**
|
||||
* @brief Function for enabling digital error correction.
|
||||
*/
|
||||
__STATIC_INLINE void nrf_rng_error_correction_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Function for disabling digital error correction.
|
||||
*/
|
||||
__STATIC_INLINE void nrf_rng_error_correction_disable(void);
|
||||
|
||||
/**
|
||||
*@}
|
||||
**/
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
__STATIC_INLINE void nrf_rng_int_enable(uint32_t rng_int_mask)
|
||||
{
|
||||
NRF_RNG->INTENSET = rng_int_mask;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrf_rng_int_disable(uint32_t rng_int_mask)
|
||||
{
|
||||
NRF_RNG->INTENCLR = rng_int_mask;
|
||||
}
|
||||
|
||||
__STATIC_INLINE bool nrf_rng_int_get(nrf_rng_int_mask_t rng_int_mask)
|
||||
{
|
||||
return (bool)(NRF_RNG->INTENCLR & rng_int_mask);
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t * nrf_rng_task_address_get(nrf_rng_task_t rng_task)
|
||||
{
|
||||
return (uint32_t *)((uint8_t *)NRF_RNG + rng_task);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrf_rng_task_trigger(nrf_rng_task_t rng_task)
|
||||
{
|
||||
*((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_task)) = NRF_RNG_TASK_SET;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t * nrf_rng_event_address_get(nrf_rng_event_t rng_event)
|
||||
{
|
||||
return (uint32_t *)((uint8_t *)NRF_RNG + rng_event);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrf_rng_event_clear(nrf_rng_event_t rng_event)
|
||||
{
|
||||
*((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_event)) = NRF_RNG_EVENT_CLEAR;
|
||||
#if __CORTEX_M == 0x04
|
||||
volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_event));
|
||||
(void)dummy;
|
||||
#endif
|
||||
}
|
||||
|
||||
__STATIC_INLINE bool nrf_rng_event_get(nrf_rng_event_t rng_event)
|
||||
{
|
||||
return (bool) * ((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_event));
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrf_rng_shorts_enable(uint32_t rng_short_mask)
|
||||
{
|
||||
NRF_RNG->SHORTS |= rng_short_mask;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrf_rng_shorts_disable(uint32_t rng_short_mask)
|
||||
{
|
||||
NRF_RNG->SHORTS &= ~rng_short_mask;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint8_t nrf_rng_random_value_get(void)
|
||||
{
|
||||
return (uint8_t)(NRF_RNG->VALUE & RNG_VALUE_VALUE_Msk);
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrf_rng_error_correction_enable(void)
|
||||
{
|
||||
NRF_RNG->CONFIG |= RNG_CONFIG_DERCEN_Msk;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void nrf_rng_error_correction_disable(void)
|
||||
{
|
||||
NRF_RNG->CONFIG &= ~RNG_CONFIG_DERCEN_Msk;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NRF_RNG_H__ */
|
|
@ -0,0 +1,250 @@
|
|||
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "nrf_drv_rng.h"
|
||||
#include "nrf_assert.h"
|
||||
#include "nrf_drv_common.h"
|
||||
#include "nordic_common.h"
|
||||
#include "nrf_error.h"
|
||||
#include "nrf_assert.h"
|
||||
#ifdef SOFTDEVICE_PRESENT
|
||||
#include "nrf_sdm.h"
|
||||
#include "nrf_soc.h"
|
||||
#else
|
||||
#include "app_fifo.h"
|
||||
#include "app_util_platform.h"
|
||||
|
||||
static __INLINE uint32_t fifo_length(app_fifo_t * p_fifo)
|
||||
{
|
||||
uint32_t tmp = p_fifo->read_pos;
|
||||
return p_fifo->write_pos - tmp;
|
||||
}
|
||||
|
||||
#define FIFO_LENGTH(fifo) fifo_length(&(fifo)) /**< Macro for calculating the FIFO length. */
|
||||
|
||||
#endif // SOFTDEVICE_PRESENT
|
||||
typedef struct
|
||||
{
|
||||
nrf_drv_state_t state;
|
||||
#ifndef SOFTDEVICE_PRESENT
|
||||
app_fifo_t rand_pool;
|
||||
uint8_t buffer[RNG_CONFIG_POOL_SIZE];
|
||||
#endif // SOFTDEVICE_PRESENT
|
||||
} nrf_drv_rng_cb_t;
|
||||
|
||||
static nrf_drv_rng_cb_t m_rng_cb;
|
||||
#ifndef SOFTDEVICE_PRESENT
|
||||
static const nrf_drv_rng_config_t m_default_config = NRF_DRV_RNG_DEFAULT_CONFIG;
|
||||
static void rng_start(void)
|
||||
{
|
||||
if (FIFO_LENGTH(m_rng_cb.rand_pool) <= m_rng_cb.rand_pool.buf_size_mask)
|
||||
{
|
||||
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
|
||||
nrf_rng_int_enable(NRF_RNG_INT_VALRDY_MASK);
|
||||
nrf_rng_task_trigger(NRF_RNG_TASK_START);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void rng_stop(void)
|
||||
{
|
||||
nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK);
|
||||
nrf_rng_task_trigger(NRF_RNG_TASK_STOP);
|
||||
}
|
||||
|
||||
|
||||
#endif // SOFTDEVICE_PRESENT
|
||||
|
||||
|
||||
ret_code_t nrf_drv_rng_init(nrf_drv_rng_config_t const * p_config)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
if (m_rng_cb.state == NRF_DRV_STATE_UNINITIALIZED)
|
||||
{
|
||||
#ifndef SOFTDEVICE_PRESENT
|
||||
|
||||
result = app_fifo_init(&m_rng_cb.rand_pool, m_rng_cb.buffer, RNG_CONFIG_POOL_SIZE);
|
||||
|
||||
if (p_config == NULL)
|
||||
{
|
||||
p_config = &m_default_config;
|
||||
}
|
||||
|
||||
if (result == NRF_SUCCESS)
|
||||
{
|
||||
if (p_config->error_correction)
|
||||
{
|
||||
nrf_rng_error_correction_enable();
|
||||
}
|
||||
|
||||
nrf_drv_common_irq_enable(RNG_IRQn, p_config->interrupt_priority);
|
||||
|
||||
nrf_rng_shorts_disable(NRF_RNG_SHORT_VALRDY_STOP_MASK);
|
||||
|
||||
rng_start();
|
||||
m_rng_cb.state = NRF_DRV_STATE_INITIALIZED;
|
||||
}
|
||||
#else
|
||||
UNUSED_VARIABLE(p_config);
|
||||
uint8_t softdevice_is_enabled;
|
||||
result = sd_softdevice_is_enabled(&softdevice_is_enabled);
|
||||
|
||||
if (softdevice_is_enabled)
|
||||
{
|
||||
m_rng_cb.state = NRF_DRV_STATE_INITIALIZED;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = NRF_ERROR_SOFTDEVICE_NOT_ENABLED;
|
||||
}
|
||||
#endif // SOFTDEVICE_PRESENT
|
||||
}
|
||||
else
|
||||
{
|
||||
result = NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void nrf_drv_rng_uninit(void)
|
||||
{
|
||||
ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
|
||||
|
||||
m_rng_cb.state = NRF_DRV_STATE_UNINITIALIZED;
|
||||
#ifndef SOFTDEVICE_PRESENT
|
||||
rng_stop();
|
||||
nrf_drv_common_irq_disable(RNG_IRQn);
|
||||
#endif // SOFTDEVICE_PRESENT
|
||||
}
|
||||
|
||||
ret_code_t nrf_drv_rng_bytes_available(uint8_t * p_bytes_available)
|
||||
{
|
||||
ret_code_t result;
|
||||
ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
|
||||
|
||||
#ifndef SOFTDEVICE_PRESENT
|
||||
|
||||
result = NRF_SUCCESS;
|
||||
*p_bytes_available = FIFO_LENGTH(m_rng_cb.rand_pool);
|
||||
|
||||
#else
|
||||
|
||||
result = sd_rand_application_bytes_available_get(p_bytes_available);
|
||||
|
||||
#endif // SOFTDEVICE_PRESENT
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ret_code_t nrf_drv_rng_pool_capacity(uint8_t * p_pool_capacity)
|
||||
{
|
||||
ret_code_t result;
|
||||
ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
|
||||
|
||||
#ifndef SOFTDEVICE_PRESENT
|
||||
|
||||
result = NRF_SUCCESS;
|
||||
*p_pool_capacity = RNG_CONFIG_POOL_SIZE;
|
||||
|
||||
#else
|
||||
|
||||
result = sd_rand_application_pool_capacity_get(p_pool_capacity);
|
||||
|
||||
#endif // SOFTDEVICE_PRESENT
|
||||
return result;
|
||||
}
|
||||
|
||||
ret_code_t nrf_drv_rng_rand(uint8_t * p_buff, uint8_t length)
|
||||
{
|
||||
ret_code_t result;
|
||||
|
||||
ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
|
||||
|
||||
#ifndef SOFTDEVICE_PRESENT
|
||||
if (FIFO_LENGTH(m_rng_cb.rand_pool) >= length)
|
||||
{
|
||||
result = NRF_SUCCESS;
|
||||
|
||||
for (uint32_t i = 0; (i < length) && (result == NRF_SUCCESS); i++)
|
||||
{
|
||||
result = app_fifo_get(&(m_rng_cb.rand_pool), &p_buff[i]);
|
||||
}
|
||||
rng_start();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = NRF_ERROR_NO_MEM;
|
||||
}
|
||||
#else
|
||||
|
||||
result = sd_rand_application_vector_get(p_buff, length);
|
||||
|
||||
#endif // SOFTDEVICE_PRESENT
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ret_code_t nrf_drv_rng_block_rand(uint8_t * p_buff, uint32_t length)
|
||||
{
|
||||
uint32_t count = 0, poolsz = 0;
|
||||
ret_code_t result;
|
||||
ASSERT(m_rng_cb.state == NRF_DRV_STATE_INITIALIZED);
|
||||
|
||||
result = nrf_drv_rng_pool_capacity((uint8_t *) &poolsz);
|
||||
if(result != NRF_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
while(length)
|
||||
{
|
||||
uint32_t len = length >= poolsz ? poolsz : length;
|
||||
while((result = nrf_drv_rng_rand(&p_buff[count], len)) != NRF_SUCCESS)
|
||||
{
|
||||
#ifndef SOFTDEVICE_PRESENT
|
||||
ASSERT(result == NRF_ERROR_NO_MEM);
|
||||
#else
|
||||
ASSERT(result == NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES);
|
||||
#endif
|
||||
}
|
||||
|
||||
length -= len;
|
||||
count += len;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SOFTDEVICE_PRESENT
|
||||
void RNG_IRQHandler(void)
|
||||
{
|
||||
if (nrf_rng_event_get(NRF_RNG_EVENT_VALRDY) &&
|
||||
nrf_rng_int_get(NRF_RNG_INT_VALRDY_MASK))
|
||||
{
|
||||
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
|
||||
uint32_t nrf_error = app_fifo_put(&m_rng_cb.rand_pool, nrf_rng_random_value_get());
|
||||
|
||||
if ((FIFO_LENGTH(m_rng_cb.rand_pool) > m_rng_cb.rand_pool.buf_size_mask) || (nrf_error == NRF_ERROR_NO_MEM))
|
||||
{
|
||||
rng_stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SOFTDEVICE_PRESENT
|
|
@ -0,0 +1,115 @@
|
|||
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
|
||||
*
|
||||
* The information contained herein is property of Nordic Semiconductor ASA.
|
||||
* Terms and conditions of usage are described in detail in NORDIC
|
||||
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||
*
|
||||
* Licensees are granted free, non-transferable use of the information. NO
|
||||
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||
* the file.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NRF_DRV_RNG_H__
|
||||
#define NRF_DRV_RNG_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "nrf_rng.h"
|
||||
#include "sdk_errors.h"
|
||||
#include "nrf_drv_config.h"
|
||||
|
||||
/**
|
||||
* @addtogroup nrf_rng RNG HAL and driver
|
||||
* @ingroup nrf_drivers
|
||||
* @brief Random number generator (RNG) APIs.
|
||||
* @details The RNG HAL provides basic APIs for accessing the registers of the random number generator.
|
||||
* The RNG driver provides APIs on a higher level.
|
||||
*
|
||||
* @defgroup nrf_drv_rng RNG driver
|
||||
* @{
|
||||
* @ingroup nrf_rng
|
||||
* @brief Driver for managing the random number generator (RNG).
|
||||
*/
|
||||
|
||||
/**@brief Struct for RNG configuration. */
|
||||
typedef struct
|
||||
{
|
||||
bool error_correction; /**< Error correction flag. */
|
||||
uint8_t interrupt_priority; /**< interrupt priority */
|
||||
} nrf_drv_rng_config_t;
|
||||
|
||||
/**@brief RNG default configuration. */
|
||||
#define NRF_DRV_RNG_DEFAULT_CONFIG \
|
||||
{ \
|
||||
.error_correction = RNG_CONFIG_ERROR_CORRECTION, \
|
||||
.interrupt_priority = RNG_CONFIG_IRQ_PRIORITY, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for initializing the nrf_drv_rng module.
|
||||
*
|
||||
* @param[in] p_config Initial configuration. Default configuration used if NULL.
|
||||
*
|
||||
* @retval NRF_SUCCESS Driver was successfully initialized.
|
||||
* @retval NRF_ERROR_INVALID_STATE Driver was already initialized.
|
||||
* @retval NRF_ERROR_INVALID_LENGTH Pool size have to be a power of 2.
|
||||
* @retval NRF_ERROR_SOFTDEVICE_NOT_ENABLED SoftDevice is present, but not enabled.
|
||||
*/
|
||||
ret_code_t nrf_drv_rng_init(nrf_drv_rng_config_t const * p_config);
|
||||
|
||||
/**
|
||||
* @brief Function for uninitializing the nrf_drv_rng module.
|
||||
*/
|
||||
void nrf_drv_rng_uninit(void);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the number of currently available random bytes.
|
||||
*
|
||||
* @param[out] p_bytes_available The number of bytes currently available in the pool.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the number of available random bytes was written to p_bytes_available.
|
||||
*/
|
||||
ret_code_t nrf_drv_rng_bytes_available(uint8_t * p_bytes_available);
|
||||
|
||||
/**
|
||||
* @brief Function for querying the capacity of the application random pool.
|
||||
*
|
||||
* @param[out] p_pool_capacity The capacity of the pool.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the capacity of the pool was written to p_pool_capacity.
|
||||
*/
|
||||
ret_code_t nrf_drv_rng_pool_capacity(uint8_t * p_pool_capacity);
|
||||
|
||||
/**
|
||||
* @brief Function for getting the vector of random numbers.
|
||||
*
|
||||
* @param[out] p_buff Pointer to uint8_t buffer for storing the bytes.
|
||||
* @param[in] length Number of bytes to take from the pool and place in p_buff.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the requested bytes were written to p_buff.
|
||||
* @retval NRF_ERROR_NO_MEM If no bytes were written to the buffer
|
||||
* because there were not enough bytes available in p_buff.
|
||||
* @retval NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES If no bytes were written to the buffer
|
||||
* because there were not enough bytes available in the pool.
|
||||
*/
|
||||
ret_code_t nrf_drv_rng_rand(uint8_t * p_buff, uint8_t length);
|
||||
|
||||
/**
|
||||
* @brief Blocking function for getting an arbitrary array of random numbers.
|
||||
*
|
||||
* @note This function may execute for a substantial amount of time depending on the length of the buffer
|
||||
* required and on the state of the current internal pool of random numbers.
|
||||
*
|
||||
* @param[out] p_buff Pointer to uint8_t buffer for storing the bytes.
|
||||
* @param[in] length Number of bytes place in p_buff.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the requested bytes were written to p_buff.
|
||||
*/
|
||||
ret_code_t nrf_drv_rng_block_rand(uint8_t * p_buff, uint32_t length);
|
||||
|
||||
/**
|
||||
*@}
|
||||
**/
|
||||
#endif // NRF_DRV_RNG_H__
|
|
@ -33,6 +33,9 @@
|
|||
#define OS_TICK_CC_CHANNEL 1
|
||||
#define LP_TICKER_CC_CHANNEL 2
|
||||
|
||||
#define US_TICKER_SW_IRQ_MASK 0x1
|
||||
#define LP_TICKER_SW_IRQ_MASK 0x2
|
||||
|
||||
#define COMMON_RTC_EVENT_COMPARE(channel) \
|
||||
CONCAT_2(NRF_RTC_EVENT_COMPARE_, channel)
|
||||
#define COMMON_RTC_INT_COMPARE_MASK(channel) \
|
||||
|
@ -47,6 +50,7 @@
|
|||
|
||||
extern bool m_common_rtc_enabled;
|
||||
extern uint32_t volatile m_common_rtc_overflows;
|
||||
extern uint8_t volatile m_common_sw_irq_flag;
|
||||
|
||||
void common_rtc_init(void);
|
||||
uint32_t common_rtc_32bit_ticks_get(void);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#if DEVICE_LOWPOWERTIMER
|
||||
|
||||
#include "common_rtc.h"
|
||||
#include "mbed_critical.h"
|
||||
|
||||
void lp_ticker_init(void)
|
||||
{
|
||||
|
@ -37,10 +38,10 @@ void lp_ticker_set_interrupt(timestamp_t timestamp)
|
|||
|
||||
void lp_ticker_fire_interrupt(void)
|
||||
{
|
||||
uint32_t closest_safe_compare = common_rtc_32bit_ticks_get() + 2;
|
||||
|
||||
nrf_rtc_cc_set(COMMON_RTC_INSTANCE, LP_TICKER_CC_CHANNEL, RTC_WRAP(closest_safe_compare));
|
||||
nrf_rtc_event_enable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK);
|
||||
core_util_critical_section_enter();
|
||||
m_common_sw_irq_flag |= LP_TICKER_SW_IRQ_MASK;
|
||||
NVIC_SetPendingIRQ(RTC1_IRQn);
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
void lp_ticker_disable_interrupt(void)
|
||||
|
|
|
@ -37,54 +37,146 @@
|
|||
*/
|
||||
|
||||
#if defined(DEVICE_TRNG)
|
||||
#include "trng_api.h"
|
||||
|
||||
#include "hal/trng_api.h"
|
||||
#include "hal/lp_ticker_api.h"
|
||||
|
||||
#include "nrf_drv_rng.h"
|
||||
|
||||
#define DEFAULT_TIMEOUT_US (1000*1000)
|
||||
|
||||
/* Macro for testing if the SoftDevice is active, regardless of whether the
|
||||
* application is build with the SoftDevice or not.
|
||||
*/
|
||||
#if defined(SOFTDEVICE_PRESENT)
|
||||
#include "nrf_sdm.h"
|
||||
static uint8_t wrapper(void) {
|
||||
uint8_t softdevice_is_enabled;
|
||||
ret_code_t result = sd_softdevice_is_enabled(&softdevice_is_enabled);
|
||||
return ((result == NRF_SUCCESS) && (softdevice_is_enabled == 1));
|
||||
}
|
||||
#define NRF_HAL_SD_IS_ENABLED() wrapper()
|
||||
#else
|
||||
#define NRF_HAL_SD_IS_ENABLED() 0
|
||||
#endif
|
||||
|
||||
/** Initialize the TRNG peripheral
|
||||
*
|
||||
* @param obj The TRNG object
|
||||
*/
|
||||
void trng_init(trng_t *obj)
|
||||
{
|
||||
(void) obj;
|
||||
|
||||
(void)nrf_drv_rng_init(NULL);
|
||||
/* Initialize low power ticker. Used for timeouts. */
|
||||
static bool first_init = true;
|
||||
|
||||
if (first_init) {
|
||||
first_init = false;
|
||||
lp_ticker_init();
|
||||
}
|
||||
}
|
||||
|
||||
/** Deinitialize the TRNG peripheral
|
||||
*
|
||||
* @param obj The TRNG object
|
||||
*/
|
||||
void trng_free(trng_t *obj)
|
||||
{
|
||||
(void) obj;
|
||||
|
||||
nrf_drv_rng_uninit();
|
||||
}
|
||||
|
||||
/* Get random data from NRF5x TRNG peripheral.
|
||||
/** Get random data from TRNG peripheral
|
||||
*
|
||||
* This implementation returns num of random bytes in range <1, length>.
|
||||
* For parameters description see trng_api.h file.
|
||||
* @param obj The TRNG object
|
||||
* @param output The pointer to an output array
|
||||
* @param length The size of output data, to avoid buffer overwrite
|
||||
* @param output_length The length of generated data
|
||||
* @return 0 success, -1 fail
|
||||
*/
|
||||
int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length)
|
||||
{
|
||||
uint8_t bytes_available;
|
||||
|
||||
(void) obj;
|
||||
|
||||
nrf_drv_rng_bytes_available(&bytes_available);
|
||||
/* Use SDK RNG driver if SoftDevice is enabled. */
|
||||
if (NRF_HAL_SD_IS_ENABLED()) {
|
||||
|
||||
if (bytes_available == 0) {
|
||||
nrf_drv_rng_block_rand(output, 1);
|
||||
*output_length = 1;
|
||||
/* Initialize driver once. */
|
||||
static bool nordic_driver_init = true;
|
||||
|
||||
if (nordic_driver_init) {
|
||||
nordic_driver_init = false;
|
||||
nrf_drv_rng_init(NULL);
|
||||
}
|
||||
|
||||
/* Query how many bytes are available. */
|
||||
uint8_t bytes_available;
|
||||
nrf_drv_rng_bytes_available(&bytes_available);
|
||||
|
||||
/* If no bytes are cached, block until at least 1 byte is available. */
|
||||
if (bytes_available == 0) {
|
||||
nrf_drv_rng_block_rand(output, 1);
|
||||
*output_length = 1;
|
||||
} else {
|
||||
|
||||
/* Get up to the requested number of bytes. */
|
||||
if (bytes_available > length) {
|
||||
bytes_available = length;
|
||||
}
|
||||
|
||||
ret_code_t result = nrf_drv_rng_rand(output, bytes_available);
|
||||
|
||||
/* Set output length with available bytes. */
|
||||
if (result == NRF_SUCCESS) {
|
||||
*output_length = bytes_available;
|
||||
} else {
|
||||
*output_length = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (bytes_available > length) {
|
||||
bytes_available = length;
|
||||
/* Initialize low-level registers once. */
|
||||
static bool nordic_register_init = true;
|
||||
|
||||
if (nordic_register_init) {
|
||||
nordic_register_init = false;
|
||||
|
||||
/* Enable RNG */
|
||||
nrf_rng_error_correction_enable();
|
||||
nrf_rng_task_trigger(NRF_RNG_TASK_START);
|
||||
}
|
||||
|
||||
if (nrf_drv_rng_rand(output, bytes_available) != NRF_SUCCESS) {
|
||||
*output_length = 0;
|
||||
return -1;
|
||||
} else {
|
||||
*output_length = bytes_available;
|
||||
/* Copy out one byte at a time. */
|
||||
size_t index = 0;
|
||||
for ( ; index < length; index++) {
|
||||
|
||||
/* Setup stop watch for timeout. */
|
||||
uint32_t start_us = lp_ticker_read();
|
||||
uint32_t now_us = start_us;
|
||||
|
||||
/* Block until timeout or random numer is ready. */
|
||||
while (((now_us - start_us) < DEFAULT_TIMEOUT_US) &&
|
||||
!nrf_rng_event_get(NRF_RNG_EVENT_VALRDY)) {
|
||||
now_us = lp_ticker_read();
|
||||
}
|
||||
|
||||
/* Abort if timeout was reached. */
|
||||
if ((now_us - start_us) >= DEFAULT_TIMEOUT_US) {
|
||||
break;
|
||||
} else {
|
||||
|
||||
/* Read random byte and clear event in preparation for the next byte. */
|
||||
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
|
||||
output[index] = nrf_rng_random_value_get();
|
||||
}
|
||||
}
|
||||
|
||||
/* Set output length with available bytes. */
|
||||
*output_length = index;
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* Set return value based on how many bytes was read. */
|
||||
return (*output_length == 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -55,6 +55,9 @@
|
|||
bool m_common_rtc_enabled = false;
|
||||
uint32_t volatile m_common_rtc_overflows = 0;
|
||||
|
||||
// lp/us ticker fire interrupt flag for IRQ handler
|
||||
volatile uint8_t m_common_sw_irq_flag = 0;
|
||||
|
||||
__STATIC_INLINE void rtc_ovf_event_check(void)
|
||||
{
|
||||
if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) {
|
||||
|
@ -74,11 +77,15 @@ void COMMON_RTC_IRQ_HANDLER(void)
|
|||
|
||||
rtc_ovf_event_check();
|
||||
|
||||
if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, US_TICKER_EVENT)) {
|
||||
if ((m_common_sw_irq_flag & US_TICKER_SW_IRQ_MASK) || nrf_rtc_event_pending(COMMON_RTC_INSTANCE, US_TICKER_EVENT)) {
|
||||
us_ticker_irq_handler();
|
||||
}
|
||||
|
||||
#if DEVICE_LOWPOWERTIMER
|
||||
if (m_common_sw_irq_flag & LP_TICKER_SW_IRQ_MASK) {
|
||||
m_common_sw_irq_flag &= ~LP_TICKER_SW_IRQ_MASK;
|
||||
lp_ticker_irq_handler();
|
||||
}
|
||||
if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, LP_TICKER_EVENT)) {
|
||||
|
||||
lp_ticker_irq_handler();
|
||||
|
@ -273,10 +280,10 @@ void us_ticker_set_interrupt(timestamp_t timestamp)
|
|||
|
||||
void us_ticker_fire_interrupt(void)
|
||||
{
|
||||
uint32_t closest_safe_compare = common_rtc_32bit_ticks_get() + 2;
|
||||
|
||||
nrf_rtc_cc_set(COMMON_RTC_INSTANCE, US_TICKER_CC_CHANNEL, RTC_WRAP(closest_safe_compare));
|
||||
nrf_rtc_event_enable(COMMON_RTC_INSTANCE, US_TICKER_INT_MASK);
|
||||
core_util_critical_section_enter();
|
||||
m_common_sw_irq_flag |= US_TICKER_SW_IRQ_MASK;
|
||||
NVIC_SetPendingIRQ(RTC1_IRQn);
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
void us_ticker_disable_interrupt(void)
|
||||
|
@ -286,6 +293,7 @@ void us_ticker_disable_interrupt(void)
|
|||
|
||||
void us_ticker_clear_interrupt(void)
|
||||
{
|
||||
m_common_sw_irq_flag &= ~US_TICKER_SW_IRQ_MASK;
|
||||
nrf_rtc_event_clear(COMMON_RTC_INSTANCE, US_TICKER_EVENT);
|
||||
}
|
||||
|
||||
|
|
|
@ -82,10 +82,17 @@ typedef enum {
|
|||
// Cellular modem (a DCE)
|
||||
MDMPWRON = PE_14, // Power (active high)
|
||||
MDMRST = PB_5, // Reset (active low)
|
||||
#if defined(TARGET_UBLOX_C030_R410M)
|
||||
MDMTXD = PA_9, // Transmit Data
|
||||
MDMRXD = PA_10, // Receive Data
|
||||
MDMCTS = PA_11, // Clear to Send
|
||||
MDMRTS = PA_12, // Request to Send
|
||||
#else
|
||||
MDMTXD = PD_5, // Transmit Data
|
||||
MDMRXD = PD_6, // Receive Data
|
||||
MDMCTS = PD_3, // Clear to Send
|
||||
MDMRTS = PD_4, // Request to Send
|
||||
#endif
|
||||
MDMDCD = NC, // DCD line not connected
|
||||
MDMDSR = NC, // DSR line not connected
|
||||
MDMDTR = NC, // DTR line not connected
|
||||
|
@ -148,13 +155,21 @@ typedef enum {
|
|||
// STDIO for console print
|
||||
#ifdef MBED_CONF_TARGET_STDIO_UART_TX
|
||||
STDIO_UART_TX = MBED_CONF_TARGET_STDIO_UART_TX,
|
||||
#else
|
||||
#if defined(TARGET_UBLOX_C030_R410M)
|
||||
STDIO_UART_TX = PD_5,
|
||||
#else
|
||||
STDIO_UART_TX = PA_9,
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MBED_CONF_TARGET_STDIO_UART_RX
|
||||
STDIO_UART_RX = MBED_CONF_TARGET_STDIO_UART_RX,
|
||||
#else
|
||||
#if defined(TARGET_UBLOX_C030_R410M)
|
||||
STDIO_UART_RX = PD_6,
|
||||
#else
|
||||
STDIO_UART_RX = PA_10,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ST-Link
|
||||
|
|
|
@ -28,7 +28,12 @@ static void press_power_button(int time_us)
|
|||
{
|
||||
gpio_t gpio;
|
||||
|
||||
#if defined(TARGET_UBLOX_C030_R410M)
|
||||
gpio_init_inout(&gpio, MDMPWRON, PIN_OUTPUT, OpenDrain, 0);
|
||||
#else
|
||||
gpio_init_out_ex(&gpio, MDMPWRON, 0);
|
||||
#endif
|
||||
|
||||
wait_us(time_us);
|
||||
gpio_write(&gpio, 1);
|
||||
}
|
||||
|
@ -51,16 +56,27 @@ void onboard_modem_deinit()
|
|||
|
||||
void onboard_modem_power_up()
|
||||
{
|
||||
/* keep the power line low for 50 microseconds */
|
||||
#if defined(TARGET_UBLOX_C030_R410M)
|
||||
/* keep the power line low for 1 seconds */
|
||||
press_power_button(1000000);
|
||||
#else
|
||||
/* keep the power line low for 50 microseconds */
|
||||
press_power_button(50);
|
||||
#endif
|
||||
|
||||
/* give modem a little time to respond */
|
||||
wait_ms(100);
|
||||
}
|
||||
|
||||
void onboard_modem_power_down()
|
||||
{
|
||||
/* keep the power line low for 1 second */
|
||||
#if defined(TARGET_UBLOX_C030_R410M)
|
||||
/* keep the power line low for 1.5 seconds */
|
||||
press_power_button(1500000);
|
||||
#else
|
||||
/* keep the power line low for 1 seconds */
|
||||
press_power_button(1000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //MODEM_ON_BOARD
|
||||
|
|
|
@ -26,12 +26,18 @@ void ublox_board_init(void) {
|
|||
|
||||
// start with modem disabled
|
||||
gpio_init_out_ex(&gpio, MDMRST, 0);
|
||||
#if defined(TARGET_UBLOX_C030_R410M)
|
||||
gpio_init_inout(&gpio, MDMPWRON, PIN_OUTPUT, OpenDrain, 1);
|
||||
#else
|
||||
gpio_init_out_ex(&gpio, MDMPWRON, 0);
|
||||
#endif
|
||||
gpio_init_out_ex(&gpio, MDMRTS, 0);
|
||||
gpio_init_in_ex(&gpio, MDMCURRENTSENSE, PullNone);
|
||||
|
||||
// start with GNSS disabled
|
||||
#if !defined (TARGET_UBLOX_C030_R410M)
|
||||
// start with GNSS disabled, this is ONLY TEMPORARY and that once the HW issue with the GNSSEN pin on the R410M board is resolved then this line will become default for all platforms.
|
||||
gpio_init_inout(&gpio, GNSSEN, PIN_OUTPUT, PushPullNoPull, 0);
|
||||
#endif
|
||||
|
||||
// power on SD card
|
||||
gpio_init_out_ex(&gpio, SDPWRON, 1);
|
||||
|
|
|
@ -148,16 +148,14 @@ typedef enum {
|
|||
//P_TP11, // BOOT0
|
||||
|
||||
// Internal
|
||||
LED1 = PD_9,
|
||||
LED2 = PA_12,
|
||||
LED3 = PD_8,
|
||||
LED4 = PA_11,
|
||||
LED5 = PC_2,
|
||||
LED6 = PA_3,
|
||||
LED7 = PF_6,
|
||||
LED_RED = PE_0,
|
||||
LED_GREEN = PB_6,
|
||||
LED_BLUE = PB_8,
|
||||
|
||||
LED1 = LED_RED,
|
||||
LED2 = LED_GREEN,
|
||||
LED3 = LED_BLUE,
|
||||
|
||||
SW1 = PF_2,
|
||||
SW2 = PG_4,
|
||||
|
||||
|
|
|
@ -2112,6 +2112,10 @@
|
|||
"inherits": ["UBLOX_C030"],
|
||||
"release_versions": ["5"]
|
||||
},
|
||||
"UBLOX_C030_R410M": {
|
||||
"inherits": ["UBLOX_C030"],
|
||||
"release_versions": ["5"]
|
||||
},
|
||||
"NZ32_SC151": {
|
||||
"inherits": ["FAMILY_STM32"],
|
||||
"core": "Cortex-M3",
|
||||
|
@ -2642,7 +2646,7 @@
|
|||
"supported_toolchains": ["ARM", "GCC_ARM", "IAR"],
|
||||
"extra_labels": ["ARM_SSG", "CM3DS_MPS2"],
|
||||
"macros": ["CMSDK_CM3DS"],
|
||||
"device_has": ["ANALOGIN", "ETHERNET", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SPI", "RTC"],
|
||||
"device_has": ["ANALOGIN", "ETHERNET", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SPI", "RTC", "LOWPOWERTIMER"],
|
||||
"release_versions": ["2", "5"],
|
||||
"copy_method": "mps2",
|
||||
"reset_method": "reboot.txt"
|
||||
|
@ -3433,7 +3437,7 @@
|
|||
"inherits": ["Target"],
|
||||
"core": "Cortex-M4F",
|
||||
"macros": ["NRF52", "TARGET_NRF52832", "BLE_STACK_SUPPORT_REQD", "SOFTDEVICE_PRESENT", "S132", "CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\"", "MBED_TICKLESS"],
|
||||
"device_has": ["STCLK_OFF_DURING_SLEEP", "ITM"],
|
||||
"device_has": ["STCLK_OFF_DURING_SLEEP", "ITM", "TRNG"],
|
||||
"extra_labels": ["NORDIC", "MCU_NRF52", "MCU_NRF52832", "NRF5", "SDK11", "NRF52_COMMON"],
|
||||
"OUTPUT_EXT": "hex",
|
||||
"is_disk_virtual": true,
|
||||
|
|
|
@ -528,24 +528,19 @@ def build_project(src_paths, build_path, target, toolchain_name,
|
|||
memap_instance = getattr(toolchain, 'memap_instance', None)
|
||||
memap_table = ''
|
||||
if memap_instance:
|
||||
real_stats_depth = stats_depth if stats_depth is not None else 2
|
||||
memap_table = memap_instance.generate_output('table', real_stats_depth)
|
||||
# Write output to stdout in text (pretty table) format
|
||||
memap_table = memap_instance.generate_output('table', stats_depth)
|
||||
|
||||
if not silent:
|
||||
if not stats_depth:
|
||||
memap_bars = memap_instance.generate_output('bars',
|
||||
real_stats_depth, None,
|
||||
getattr(toolchain.target, 'device_name', None))
|
||||
print(memap_bars)
|
||||
else:
|
||||
print(memap_table)
|
||||
print(memap_table)
|
||||
|
||||
# Write output to file in JSON format
|
||||
map_out = join(build_path, name + "_map.json")
|
||||
memap_instance.generate_output('json', real_stats_depth, map_out)
|
||||
memap_instance.generate_output('json', stats_depth, map_out)
|
||||
|
||||
# Write output to file in CSV format for the CI
|
||||
map_csv = join(build_path, name + "_map.csv")
|
||||
memap_instance.generate_output('csv-ci', real_stats_depth, map_csv)
|
||||
memap_instance.generate_output('csv-ci', stats_depth, map_csv)
|
||||
|
||||
resources.detect_duplicates(toolchain)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ limitations under the License.
|
|||
"""
|
||||
import uuid
|
||||
from os.path import splitext, basename, dirname
|
||||
from os import remove
|
||||
|
||||
from tools.export.exporters import Exporter, deprecated_exporter
|
||||
|
||||
|
@ -83,3 +84,8 @@ class AtmelStudio(Exporter):
|
|||
target = self.target.lower()
|
||||
self.gen_file('atmelstudio/atsln.tmpl', ctx, '%s.atsln' % self.project_name)
|
||||
self.gen_file('atmelstudio/cppproj.tmpl', ctx, '%s.cppproj' % self.project_name)
|
||||
|
||||
@staticmethod
|
||||
def clean(project_name):
|
||||
remove('%s.atsln' % project_name)
|
||||
remove('%s.cppproj' % project_name)
|
||||
|
|
|
@ -408,6 +408,12 @@ class CCES(Exporter):
|
|||
|
||||
print("CCES files generated.")
|
||||
|
||||
|
||||
@staticmethod
|
||||
def clean(_):
|
||||
os.remove('cces.json')
|
||||
os.remove('README.md')
|
||||
|
||||
@staticmethod
|
||||
def build(project_name, log_name='build_log.txt', cleanup=True):
|
||||
"""
|
||||
|
@ -436,6 +442,7 @@ class CCES(Exporter):
|
|||
# cleanup workspace
|
||||
if os.path.exists(workspace):
|
||||
shutil.rmtree(workspace, True)
|
||||
CCES.clean(project_name)
|
||||
|
||||
# check return code for failure
|
||||
if ret_code != 0:
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import re
|
||||
|
||||
from os.path import join, exists
|
||||
from os import makedirs
|
||||
from os import makedirs, remove
|
||||
import shutil
|
||||
|
||||
from tools.export.makefile import Makefile, GccArm, Armc5, IAR
|
||||
|
||||
|
@ -39,6 +40,12 @@ class Eclipse(Makefile):
|
|||
self.gen_file('cdt/.cproject.tmpl', ctx, '.cproject')
|
||||
self.gen_file('cdt/.project.tmpl', ctx, '.project')
|
||||
|
||||
@staticmethod
|
||||
def clean(project_name):
|
||||
shutil.rmtree("eclipse-extras")
|
||||
remove(".cproject")
|
||||
remove(".project")
|
||||
|
||||
|
||||
class EclipseGcc(Eclipse, GccArm):
|
||||
LOAD_EXE = True
|
||||
|
|
|
@ -112,6 +112,15 @@ class CMake(Exporter):
|
|||
except TemplateNotFound:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def clean(_):
|
||||
remove("CMakeLists.txt")
|
||||
# legacy .build directory cleaned if exists
|
||||
if exists('.build'):
|
||||
shutil.rmtree('.build')
|
||||
if exists('BUILD'):
|
||||
shutil.rmtree('BUILD')
|
||||
|
||||
@staticmethod
|
||||
def build(project_name, log_name="build_log.txt", cleanup=True):
|
||||
""" Build Make project """
|
||||
|
@ -162,13 +171,8 @@ class CMake(Exporter):
|
|||
|
||||
# Cleanup the exported and built files
|
||||
if cleanup:
|
||||
remove("CMakeLists.txt")
|
||||
remove(log_name)
|
||||
# legacy .build directory cleaned if exists
|
||||
if exists('.build'):
|
||||
shutil.rmtree('.build')
|
||||
if exists('BUILD'):
|
||||
shutil.rmtree('BUILD')
|
||||
CMake.clean(project_name)
|
||||
|
||||
if ret_code != 0:
|
||||
# Seems like something went wrong.
|
||||
|
|
|
@ -153,3 +153,8 @@ class CMSIS(Exporter):
|
|||
'date': ''
|
||||
}
|
||||
self.gen_file('cmsis/cpdsc.tmpl', ctx, 'project.cpdsc')
|
||||
|
||||
|
||||
@staticmethod
|
||||
def clean(_):
|
||||
os.remove('project.cpdsc')
|
||||
|
|
|
@ -15,6 +15,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
"""
|
||||
from os.path import splitext, basename
|
||||
from os import remove
|
||||
|
||||
from tools.export.exporters import Exporter, deprecated_exporter
|
||||
|
||||
|
@ -109,3 +110,7 @@ class CoIDE(Exporter):
|
|||
|
||||
# Project file
|
||||
self.gen_file('coide/%s.coproj.tmpl' % target, ctx, '%s.coproj' % self.project_name)
|
||||
|
||||
@staticmethod
|
||||
def clean(project_name):
|
||||
remove('%s.coproj' % project_name)
|
||||
|
|
|
@ -14,6 +14,7 @@ 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.
|
||||
"""
|
||||
from os import remove
|
||||
from tools.export.gnuarmeclipse import GNUARMEclipse
|
||||
|
||||
class E2Studio(GNUARMEclipse):
|
||||
|
@ -39,3 +40,8 @@ class E2Studio(GNUARMEclipse):
|
|||
self.gen_file('gnuarmeclipse/.project.tmpl', jinja_ctx, '.project', trim_blocks=True, lstrip_blocks=True)
|
||||
self.gen_file_nonoverwrite('gnuarmeclipse/mbedignore.tmpl', jinja_ctx, '.mbedignore')
|
||||
self.gen_file('gnuarmeclipse/makefile.targets.tmpl', jinja_ctx, 'makefile.targets', trim_blocks=True, lstrip_blocks=True)
|
||||
|
||||
@staticmethod
|
||||
def clean(project_name):
|
||||
remove('%s OpenOCD 5x.launch' % project_name)
|
||||
remove('%s OpenOCD.launch' % project_name)
|
||||
|
|
|
@ -15,6 +15,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
"""
|
||||
from os.path import splitext, basename
|
||||
from os import remove
|
||||
from tools.targets import TARGET_MAP
|
||||
from tools.export.exporters import Exporter, apply_supported_whitelist
|
||||
|
||||
|
@ -87,3 +88,7 @@ class EmBitz(Exporter):
|
|||
}
|
||||
|
||||
self.gen_file('embitz/eix.tmpl', ctx, '%s.eix' % self.project_name)
|
||||
|
||||
@staticmethod
|
||||
def clean(project_name):
|
||||
remove("%s.eix" % project_name)
|
||||
|
|
|
@ -50,6 +50,7 @@ class Exporter(object):
|
|||
NAME = None
|
||||
TARGETS = set()
|
||||
TOOLCHAIN = None
|
||||
CLEAN_FILES = ("GettingStarted.html",)
|
||||
|
||||
|
||||
def __init__(self, target, export_dir, project_name, toolchain,
|
||||
|
@ -217,12 +218,28 @@ class Exporter(object):
|
|||
|
||||
Returns -1 on failure and 0 on success
|
||||
"""
|
||||
raise NotImplemented("Implement in derived Exporter class.")
|
||||
raise NotImplementedError("Implement in derived Exporter class.")
|
||||
|
||||
@staticmethod
|
||||
def clean(project_name):
|
||||
"""Clean a previously exported project
|
||||
This method is assumed to be executed at the same level as exporter
|
||||
project files and project source code.
|
||||
See uvision/__init__.py, iar/__init__.py, and makefile/__init__.py for
|
||||
example implemenation.
|
||||
|
||||
Positional Arguments:
|
||||
project_name - the name of the project to build; often required by
|
||||
exporter's build command.
|
||||
|
||||
Returns nothing. May raise exceptions
|
||||
"""
|
||||
raise NotImplementedError("Implement in derived Exporter class.")
|
||||
|
||||
@abstractmethod
|
||||
def generate(self):
|
||||
"""Generate an IDE/tool specific project file"""
|
||||
raise NotImplemented("Implement a generate function in Exporter child class")
|
||||
raise NotImplementedError("Implement a generate function in Exporter child class")
|
||||
|
||||
@classmethod
|
||||
def is_target_supported(cls, target_name):
|
||||
|
|
|
@ -299,6 +299,17 @@ class GNUARMEclipse(Exporter):
|
|||
print
|
||||
print 'Done. Import the \'{0}\' project in Eclipse.'.format(self.project_name)
|
||||
|
||||
@staticmethod
|
||||
def clean(_):
|
||||
os.remove('.project')
|
||||
os.remove('.cproject')
|
||||
if exists('Debug'):
|
||||
shutil.rmtree('Debug')
|
||||
if exists('Release'):
|
||||
shutil.rmtree('Release')
|
||||
if exists('makefile.targets'):
|
||||
os.remove('makefile.targets')
|
||||
|
||||
# override
|
||||
@staticmethod
|
||||
def build(project_name, log_name="build_log.txt", cleanup=True):
|
||||
|
@ -366,14 +377,6 @@ class GNUARMEclipse(Exporter):
|
|||
if cleanup:
|
||||
if exists(log_name):
|
||||
os.remove(log_name)
|
||||
os.remove('.project')
|
||||
os.remove('.cproject')
|
||||
if exists('Debug'):
|
||||
shutil.rmtree('Debug')
|
||||
if exists('Release'):
|
||||
shutil.rmtree('Release')
|
||||
if exists('makefile.targets'):
|
||||
os.remove('makefile.targets')
|
||||
|
||||
# Always remove the temporary folder.
|
||||
if exists(tmp_folder):
|
||||
|
|
|
@ -138,6 +138,17 @@ class IAR(Exporter):
|
|||
self.gen_file('iar/ewd.tmpl', ctx, self.project_name + ".ewd")
|
||||
self.gen_file('iar/ewp.tmpl', ctx, self.project_name + ".ewp")
|
||||
|
||||
@staticmethod
|
||||
def clean(project_name):
|
||||
os.remove(project_name + ".ewp")
|
||||
os.remove(project_name + ".ewd")
|
||||
os.remove(project_name + ".eww")
|
||||
# legacy output file location
|
||||
if exists('.build'):
|
||||
shutil.rmtree('.build')
|
||||
if exists('BUILD'):
|
||||
shutil.rmtree('BUILD')
|
||||
|
||||
@staticmethod
|
||||
def build(project_name, log_name="build_log.txt", cleanup=True):
|
||||
""" Build IAR project """
|
||||
|
@ -179,14 +190,7 @@ class IAR(Exporter):
|
|||
|
||||
# Cleanup the exported and built files
|
||||
if cleanup:
|
||||
os.remove(project_name + ".ewp")
|
||||
os.remove(project_name + ".ewd")
|
||||
os.remove(project_name + ".eww")
|
||||
# legacy output file location
|
||||
if exists('.build'):
|
||||
shutil.rmtree('.build')
|
||||
if exists('BUILD'):
|
||||
shutil.rmtree('BUILD')
|
||||
IAR.clean(project_name)
|
||||
|
||||
if ret_code !=0:
|
||||
# Seems like something went wrong.
|
||||
|
|
|
@ -15,6 +15,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
"""
|
||||
from os.path import splitext, basename
|
||||
from os import remove
|
||||
|
||||
from tools.export.exporters import Exporter, deprecated_exporter
|
||||
|
||||
|
@ -47,3 +48,7 @@ class KDS(Exporter):
|
|||
self.gen_file('kds/%s_project.tmpl' % self.target.lower(), ctx, '.project')
|
||||
self.gen_file('kds/%s_cproject.tmpl' % self.target.lower(), ctx, '.cproject')
|
||||
self.gen_file('kds/launch.tmpl', ctx, '%s.launch' % self.project_name)
|
||||
|
||||
@staticmethod
|
||||
def clean(project_name):
|
||||
remove('%s.launch' % project_name)
|
||||
|
|
|
@ -148,6 +148,15 @@ class Makefile(Exporter):
|
|||
|
||||
return flags
|
||||
|
||||
@staticmethod
|
||||
def clean(_):
|
||||
remove("Makefile")
|
||||
# legacy .build directory cleaned if exists
|
||||
if exists('.build'):
|
||||
shutil.rmtree('.build')
|
||||
if exists('BUILD'):
|
||||
shutil.rmtree('BUILD')
|
||||
|
||||
@staticmethod
|
||||
def build(project_name, log_name="build_log.txt", cleanup=True):
|
||||
""" Build Make project """
|
||||
|
@ -178,13 +187,8 @@ class Makefile(Exporter):
|
|||
|
||||
# Cleanup the exported and built files
|
||||
if cleanup:
|
||||
remove("Makefile")
|
||||
remove(log_name)
|
||||
# legacy .build directory cleaned if exists
|
||||
if exists('.build'):
|
||||
shutil.rmtree('.build')
|
||||
if exists('BUILD'):
|
||||
shutil.rmtree('BUILD')
|
||||
Makefile.clean(project_name)
|
||||
|
||||
if ret_code != 0:
|
||||
# Seems like something went wrong.
|
||||
|
|
|
@ -230,6 +230,17 @@ class MCUXpresso(GNUARMEclipse):
|
|||
print
|
||||
print 'Done. Import the \'{0}\' project in Eclipse.'.format(self.project_name)
|
||||
|
||||
@staticmethod
|
||||
def clean(_):
|
||||
remove('.project')
|
||||
remove('.cproject')
|
||||
if exists('Debug'):
|
||||
shutil.rmtree('Debug')
|
||||
if exists('Release'):
|
||||
shutil.rmtree('Release')
|
||||
if exists('makefile.targets'):
|
||||
remove('makefile.targets')
|
||||
|
||||
# override
|
||||
@staticmethod
|
||||
def build(project_name, log_name="build_log.txt", cleanup=True):
|
||||
|
@ -299,14 +310,7 @@ class MCUXpresso(GNUARMEclipse):
|
|||
if cleanup:
|
||||
if exists(log_name):
|
||||
remove(log_name)
|
||||
remove('.project')
|
||||
remove('.cproject')
|
||||
if exists('Debug'):
|
||||
shutil.rmtree('Debug')
|
||||
if exists('Release'):
|
||||
shutil.rmtree('Release')
|
||||
if exists('makefile.targets'):
|
||||
remove('makefile.targets')
|
||||
MCUXpresso.clean(project_name)
|
||||
|
||||
# Always remove the temporary folder.
|
||||
if exists(tmp_folder):
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
import copy
|
||||
import shutil
|
||||
|
||||
from os.path import relpath, join, exists, dirname, basename
|
||||
from os import makedirs
|
||||
|
@ -275,6 +276,11 @@ class GNUARMNetbeans(Exporter):
|
|||
print
|
||||
print 'Done. Import the \'{0}\' project in Netbeans.'.format(self.project_name)
|
||||
|
||||
@staticmethod
|
||||
def clean(_):
|
||||
shutil.rmtree("nbproject")
|
||||
remove("Makefile")
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -15,6 +15,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
"""
|
||||
from os.path import splitext, basename
|
||||
from os import remove
|
||||
from tools.targets import TARGET_MAP
|
||||
from tools.export.exporters import Exporter
|
||||
from tools.export.makefile import GccArm
|
||||
|
@ -63,3 +64,8 @@ class QtCreator(GccArm):
|
|||
|
||||
# finally, generate the Makefile
|
||||
super(QtCreator, self).generate()
|
||||
|
||||
@staticmethod
|
||||
def clean(project_name):
|
||||
for ext in ['creator', 'files', 'includes', 'config']:
|
||||
remove("%s.%s" % (project_name, ext))
|
||||
|
|
|
@ -15,6 +15,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
"""
|
||||
from os.path import split,splitext, basename
|
||||
from os import remove
|
||||
|
||||
from tools.export.exporters import Exporter, deprecated_exporter
|
||||
|
||||
|
@ -194,3 +195,7 @@ class SimplicityV3(Exporter):
|
|||
'''
|
||||
|
||||
self.gen_file('simplicity/slsproj.tmpl', ctx, '%s.slsproj' % self.project_name)
|
||||
|
||||
@staticmethod
|
||||
def clean(project_name):
|
||||
remove('%s.slsproj' % project_name)
|
||||
|
|
|
@ -16,6 +16,7 @@ limitations under the License.
|
|||
"""
|
||||
|
||||
from os.path import splitext, basename, join
|
||||
import shutil
|
||||
from tools.utils import mkdir
|
||||
from tools.export.gnuarmeclipse import GNUARMEclipse
|
||||
from tools.export.gnuarmeclipse import UID
|
||||
|
@ -557,3 +558,7 @@ class Sw4STM32(GNUARMEclipse):
|
|||
'makefile.targets', trim_blocks=True, lstrip_blocks=True)
|
||||
self.gen_file('sw4stm32/launch.tmpl', ctx, self.project_name +
|
||||
' ' + options['debug']['name'] + '.launch')
|
||||
|
||||
@staticmethod
|
||||
def clean(_):
|
||||
shutil.rmtree(".settings")
|
||||
|
|
|
@ -238,6 +238,16 @@ class Uvision(Exporter):
|
|||
self.gen_file('uvision/uvision.tmpl', ctx, self.project_name+".uvprojx")
|
||||
self.gen_file('uvision/uvision_debug.tmpl', ctx, self.project_name + ".uvoptx")
|
||||
|
||||
@staticmethod
|
||||
def clean(project_name):
|
||||
os.remove(project_name + ".uvprojx")
|
||||
os.remove(project_name + ".uvoptx")
|
||||
# legacy .build directory cleaned if exists
|
||||
if exists('.build'):
|
||||
shutil.rmtree('.build')
|
||||
if exists('BUILD'):
|
||||
shutil.rmtree('BUILD')
|
||||
|
||||
@staticmethod
|
||||
def build(project_name, log_name='build_log.txt', cleanup=True):
|
||||
""" Build Uvision project """
|
||||
|
@ -257,13 +267,7 @@ class Uvision(Exporter):
|
|||
# Cleanup the exported and built files
|
||||
if cleanup:
|
||||
os.remove(log_name)
|
||||
os.remove(project_name+".uvprojx")
|
||||
os.remove(project_name+".uvoptx")
|
||||
# legacy .build directory cleaned if exists
|
||||
if exists('.build'):
|
||||
shutil.rmtree('.build')
|
||||
if exists('BUILD'):
|
||||
shutil.rmtree('BUILD')
|
||||
Uvision.clean(project_name)
|
||||
|
||||
# Returns 0 upon success, 1 upon a warning, and neither upon an error
|
||||
if ret_code != 0 and ret_code != 1:
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
# limitations under the License.
|
||||
|
||||
from os.path import join, exists, realpath, relpath, basename, isfile, splitext
|
||||
from os import makedirs, listdir
|
||||
from os import makedirs, listdir, remove, rmdir
|
||||
import json
|
||||
|
||||
from tools.export.makefile import Makefile, GccArm, Armc5, IAR
|
||||
|
@ -83,6 +83,11 @@ class VSCode(Makefile):
|
|||
with open(join(self.export_dir, '.vscode', 'c_cpp_properties.json'), 'w') as outfile:
|
||||
json.dump(cpp_props, outfile, indent=4, separators=(',', ': '))
|
||||
|
||||
@staticmethod
|
||||
def clean(_):
|
||||
for f in ['launch', 'settings', 'tasts', 'c_cpp_properties']:
|
||||
remove(".vscode/%s.json" % f)
|
||||
rmdir(".vscode")
|
||||
|
||||
class VSCodeGcc(VSCode, GccArm):
|
||||
LOAD_EXE = True
|
||||
|
|
|
@ -118,7 +118,7 @@ if __name__ == '__main__':
|
|||
"--stats-depth",
|
||||
type=int,
|
||||
dest="stats_depth",
|
||||
default=None,
|
||||
default=2,
|
||||
help="Depth level for static memory report")
|
||||
|
||||
# Local run
|
||||
|
|
|
@ -10,11 +10,9 @@ from os.path import basename, dirname, join, relpath, commonprefix
|
|||
import re
|
||||
import csv
|
||||
import json
|
||||
import math
|
||||
from argparse import ArgumentParser
|
||||
from copy import deepcopy
|
||||
from prettytable import PrettyTable
|
||||
from tools.arm_pack_manager import Cache
|
||||
|
||||
from .utils import (argparse_filestring_type, argparse_lowercase_hyphen_type,
|
||||
argparse_uppercase_type)
|
||||
|
@ -509,7 +507,7 @@ class MemapParser(object):
|
|||
|
||||
export_formats = ["json", "csv-ci", "table"]
|
||||
|
||||
def generate_output(self, export_format, depth, file_output=None, *args):
|
||||
def generate_output(self, export_format, depth, file_output=None):
|
||||
""" Generates summary of memory map data
|
||||
|
||||
Positional arguments:
|
||||
|
@ -534,9 +532,8 @@ class MemapParser(object):
|
|||
|
||||
to_call = {'json': self.generate_json,
|
||||
'csv-ci': self.generate_csv,
|
||||
'table': self.generate_table,
|
||||
'bars': self.generate_bars}[export_format]
|
||||
output = to_call(file_desc, *args)
|
||||
'table': self.generate_table}[export_format]
|
||||
output = to_call(file_desc)
|
||||
|
||||
if file_desc is not stdout:
|
||||
file_desc.close()
|
||||
|
@ -620,71 +617,6 @@ class MemapParser(object):
|
|||
|
||||
return output
|
||||
|
||||
def generate_bars(self, file_desc, device_name=None):
|
||||
""" Generates nice looking bars that represent the memory consumption
|
||||
|
||||
Returns: string containing nice looking bars
|
||||
"""
|
||||
|
||||
# TODO add tty detection, and width detection probably
|
||||
WIDTH = 72
|
||||
try:
|
||||
# NOTE this only works on linux
|
||||
import sys, fcntl, termios, struct
|
||||
height, width, _, _ = struct.unpack('HHHH',
|
||||
fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ,
|
||||
struct.pack('HHHH', 0, 0, 0, 0)))
|
||||
WIDTH = min(width, WIDTH)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
text = self.subtotal['.text']
|
||||
data = self.subtotal['.data']
|
||||
bss = self.subtotal['.bss']
|
||||
rom_used = self.mem_summary['total_flash']
|
||||
ram_used = self.mem_summary['static_ram']
|
||||
|
||||
# No device_name = no cmsis-pack = we don't know the memory layout
|
||||
if device_name is not None:
|
||||
try:
|
||||
cache = Cache(False, False)
|
||||
cmsis_part = cache.index[device_name]
|
||||
rom_avail = int(cmsis_part['memory']['IROM1']['size'], 0)
|
||||
ram_avail = int(cmsis_part['memory']['IRAM1']['size'], 0)
|
||||
except KeyError:
|
||||
# If we don't have the expected regions, fall back to no device_name
|
||||
device_name = None
|
||||
|
||||
PREFIXES = ['', 'K', 'M', 'G', 'T', 'P', 'E']
|
||||
def unit(n, u='B', p=3):
|
||||
if n == 0:
|
||||
return '0' + u
|
||||
|
||||
scale = math.floor(math.log(n, 1024))
|
||||
return '{1:.{0}g}{2}{3}'.format(p, n/(1024**scale), PREFIXES[int(scale)], u)
|
||||
|
||||
usage = "Text {} Data {} BSS {}".format(unit(text), unit(data), unit(bss))
|
||||
avail = "ROM {} RAM {}".format(unit(rom_used), unit(ram_used))
|
||||
output = ["{0} {1:>{2}}".format(usage, avail,
|
||||
abs(WIDTH-len(usage)-1) if device_name is not None else 0)]
|
||||
|
||||
if device_name is not None:
|
||||
for region, avail, uses in [
|
||||
('ROM', rom_avail, [('|', text), ('|', data)]),
|
||||
('RAM', ram_avail, [('|', bss), ('|', data)])]:
|
||||
barwidth = WIDTH-17 - len(region)
|
||||
|
||||
used = sum(use for c, use in uses)
|
||||
bars = [(c, (barwidth*use) // avail) for c, use in uses]
|
||||
bars.append((' ', barwidth - sum(width for c, width in bars)))
|
||||
bars = ''.join(c*width for c, width in bars)
|
||||
|
||||
output.append("{0} [{2:<{1}}] {3:>13}".format(
|
||||
region, barwidth, bars,
|
||||
"{}/{}".format(unit(used), unit(avail))))
|
||||
|
||||
return '\n'.join(output)
|
||||
|
||||
toolchains = ["ARM", "ARM_STD", "ARM_MICRO", "GCC_ARM", "GCC_CR", "IAR"]
|
||||
|
||||
def compute_report(self):
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
""" The CLI entry point for exporting projects from the mbed tools to any of the
|
||||
supported IDEs or project structures.
|
||||
"""
|
||||
from __future__ import absolute_import, print_function
|
||||
import sys
|
||||
from os.path import join, abspath, dirname, exists, basename
|
||||
from os.path import (join, abspath, dirname, exists, basename, normpath,
|
||||
realpath, basename)
|
||||
from os import remove
|
||||
ROOT = abspath(join(dirname(__file__), ".."))
|
||||
sys.path.insert(0, ROOT)
|
||||
|
||||
from shutil import move, rmtree
|
||||
from argparse import ArgumentParser
|
||||
from os.path import normpath, realpath
|
||||
|
||||
from tools.paths import EXPORT_DIR, MBED_HAL, MBED_LIBRARIES, MBED_TARGETS_PATH
|
||||
from tools.settings import BUILD_DIR
|
||||
|
@ -191,7 +193,7 @@ def main():
|
|||
|
||||
# Print available tests in order and exit
|
||||
if options.list_tests is True:
|
||||
print '\n'.join([str(test) for test in sorted(TEST_MAP.values())])
|
||||
print('\n'.join([str(test) for test in sorted(TEST_MAP.values())]))
|
||||
sys.exit()
|
||||
|
||||
# Only prints matrix of supported IDEs
|
||||
|
@ -199,7 +201,7 @@ def main():
|
|||
if options.supported_ides == "matrix":
|
||||
print_large_string(mcu_ide_matrix())
|
||||
elif options.supported_ides == "ides":
|
||||
print mcu_ide_list()
|
||||
print(mcu_ide_list())
|
||||
exit(0)
|
||||
|
||||
# Only prints matrix of supported IDEs
|
||||
|
@ -212,9 +214,9 @@ def main():
|
|||
readme.write("\n")
|
||||
readme.write(html)
|
||||
except IOError as exc:
|
||||
print "I/O error({0}): {1}".format(exc.errno, exc.strerror)
|
||||
print("I/O error({0}): {1}".format(exc.errno, exc.strerror))
|
||||
except:
|
||||
print "Unexpected error:", sys.exc_info()[0]
|
||||
print("Unexpected error:", sys.exc_info()[0])
|
||||
raise
|
||||
exit(0)
|
||||
|
||||
|
@ -246,14 +248,20 @@ def main():
|
|||
args_error(parser, "%s not supported by %s"%(mcu,options.ide))
|
||||
profile = extract_profile(parser, options, toolchain_name, fallback="debug")
|
||||
if options.clean:
|
||||
rmtree(BUILD_DIR)
|
||||
for cls in EXPORTERS.values():
|
||||
try:
|
||||
cls.clean(basename(abspath(options.source_dir[0])))
|
||||
except (NotImplementedError, IOError, OSError):
|
||||
pass
|
||||
for f in EXPORTERS.values()[0].CLEAN_FILES:
|
||||
remove(f)
|
||||
try:
|
||||
export(mcu, options.ide, build=options.build,
|
||||
src=options.source_dir, macros=options.macros,
|
||||
project_id=options.program, zip_proj=zip_proj,
|
||||
build_profile=profile, app_config=options.app_config)
|
||||
except NotSupportedException as exc:
|
||||
print "[ERROR] %s" % str(exc)
|
||||
print("[ERROR] %s" % str(exc))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -337,25 +337,6 @@ def check_required_modules(required_modules, verbose=True):
|
|||
else:
|
||||
return True
|
||||
|
||||
def dict_to_ascii(dictionary):
|
||||
""" Utility function: traverse a dictionary and change all the strings in
|
||||
the dictionary to ASCII from Unicode. Useful when reading ASCII JSON data,
|
||||
because the JSON decoder always returns Unicode string. Based on
|
||||
http://stackoverflow.com/a/13105359
|
||||
|
||||
Positional arguments:
|
||||
dictionary - The dict that contains some Unicode that should be ASCII
|
||||
"""
|
||||
if isinstance(dictionary, dict):
|
||||
return OrderedDict([(dict_to_ascii(key), dict_to_ascii(value))
|
||||
for key, value in dictionary.items()])
|
||||
elif isinstance(dictionary, list):
|
||||
return [dict_to_ascii(element) for element in dictionary]
|
||||
elif isinstance(dictionary, unicode):
|
||||
return dictionary.encode('ascii').decode()
|
||||
else:
|
||||
return dictionary
|
||||
|
||||
def json_file_to_dict(fname):
|
||||
""" Read a JSON file and return its Python representation, transforming all
|
||||
the strings from Unicode to ASCII. The order of keys in the JSON file is
|
||||
|
@ -366,8 +347,8 @@ def json_file_to_dict(fname):
|
|||
"""
|
||||
try:
|
||||
with open(fname, "r") as file_obj:
|
||||
return dict_to_ascii(json.load(file_obj,
|
||||
object_pairs_hook=OrderedDict))
|
||||
return json.loads(file_obj.read().encode('ascii', 'ignore'),
|
||||
object_pairs_hook=OrderedDict)
|
||||
except (ValueError, IOError):
|
||||
sys.stderr.write("Error parsing '%s':\n" % fname)
|
||||
raise
|
||||
|
|
Loading…
Reference in New Issue