diff --git a/.gitignore b/.gitignore index 259148f..a901d64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,30 @@ -# Prerequisites -*.d - -# Compiled Object files -*.slo -*.lo +# Build outputs *.o -*.obj +*.d +lib*.so +lib*.so.* +*.a +build*/ +.dep +__pycache__ +*.pyc -# Precompiled Headers -*.gch -*.pch +# Eclipse +.metadata +.settings +.project +.cproject +.pydevproject +.gdbinit -# Compiled Dynamic libraries -*.so -*.dylib -*.dll +# vsstudio code +.vscode -# Fortran module files -*.mod -*.smod +# vagrant +.vagrant -# Compiled Static libraries -*.lai -*.la -*.a -*.lib +# libuavcan DSDL compiler default output directory +dsdlc_generated -# Executables -*.exe -*.out -*.app +# Log files +*.log diff --git a/README.md b/README.md index 7fc77f5..528a5ce 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ -# libuavcan_lpc11c24 Libuavcan platform driver for NXP LPC11C24 +========================================== + +See . diff --git a/driver/include.mk b/driver/include.mk new file mode 100644 index 0000000..f47e698 --- /dev/null +++ b/driver/include.mk @@ -0,0 +1,9 @@ +# +# Copyright (C) 2014 Pavel Kirienko +# + +LIBUAVCAN_LPC11C24_DIR := $(dir $(lastword $(MAKEFILE_LIST))) + +LIBUAVCAN_LPC11C24_SRC := $(shell find $(LIBUAVCAN_LPC11C24_DIR)/src -type f -name '*.cpp') + +LIBUAVCAN_LPC11C24_INC := $(LIBUAVCAN_LPC11C24_DIR)/include/ diff --git a/driver/include/uavcan_lpc11c24/can.hpp b/driver/include/uavcan_lpc11c24/can.hpp new file mode 100644 index 0000000..35de461 --- /dev/null +++ b/driver/include/uavcan_lpc11c24/can.hpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#pragma once + +#include + +namespace uavcan_lpc11c24 +{ +/** + * This class implements CAN driver interface for libuavcan. + * No configuration needed other than CAN baudrate. + * This class is a singleton. + */ +class CanDriver + : public uavcan::ICanDriver + , public uavcan::ICanIface + , uavcan::Noncopyable +{ + static CanDriver self; + + CanDriver() { } + +public: + /** + * Returns the singleton reference. + * No other copies can be created. + */ + static CanDriver& instance() { return self; } + + /** + * Attempts to detect bit rate of the CAN bus. + * This function may block for up to X seconds, where X is the number of bit rates to try. + * This function is NOT guaranteed to reset the CAN controller upon return. + * @return On success: detected bit rate, in bits per second. + * On failure: zero. + */ + static uavcan::uint32_t detectBitRate(void (*idle_callback)() = nullptr); + + /** + * Returns negative value if the requested baudrate can't be used. + * Returns zero if OK. + */ + int init(uavcan::uint32_t bitrate); + + bool hasReadyRx() const; + bool hasEmptyTx() const; + + /** + * This method will return true only if there was any CAN bus activity since previous call of this method. + * This is intended to be used for LED iface activity indicators. + */ + bool hadActivity(); + + /** + * Returns the number of times the RX queue was overrun. + */ + uavcan::uint32_t getRxQueueOverflowCount() const; + + /** + * Whether the controller is currently in bus off state. + * Note that the driver recovers the CAN controller from the bus off state automatically! + * Therefore, this method serves only monitoring purposes and is not necessary to use. + */ + bool isInBusOffState() const; + + uavcan::int16_t send(const uavcan::CanFrame& frame, + uavcan::MonotonicTime tx_deadline, + uavcan::CanIOFlags flags) override; + + uavcan::int16_t receive(uavcan::CanFrame& out_frame, + uavcan::MonotonicTime& out_ts_monotonic, + uavcan::UtcTime& out_ts_utc, + uavcan::CanIOFlags& out_flags) override; + + uavcan::int16_t select(uavcan::CanSelectMasks& inout_masks, + const uavcan::CanFrame* (&)[uavcan::MaxCanIfaces], + uavcan::MonotonicTime blocking_deadline) override; + + uavcan::int16_t configureFilters(const uavcan::CanFilterConfig* filter_configs, + uavcan::uint16_t num_configs) override; + + uavcan::uint64_t getErrorCount() const override; + + uavcan::uint16_t getNumFilters() const override; + + uavcan::ICanIface* getIface(uavcan::uint8_t iface_index) override; + + uavcan::uint8_t getNumIfaces() const override; +}; + +} diff --git a/driver/include/uavcan_lpc11c24/clock.hpp b/driver/include/uavcan_lpc11c24/clock.hpp new file mode 100644 index 0000000..47f3b5f --- /dev/null +++ b/driver/include/uavcan_lpc11c24/clock.hpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#pragma once + +#include + +namespace uavcan_lpc11c24 +{ +namespace clock +{ +/** + * Starts the clock. + * Can be called multiple times, only the first call will be effective. + */ +void init(); + +/** + * Returns current monotonic time passed since the moment when clock::init() was called. + * Note that both monotonic and UTC clocks are implemented using SysTick timer. + */ +uavcan::MonotonicTime getMonotonic(); + +/** + * Returns UTC time if it has been set, otherwise returns zero time. + * Note that both monotonic and UTC clocks are implemented using SysTick timer. + */ +uavcan::UtcTime getUtc(); + +/** + * Performs UTC time adjustment. + * The UTC time will be zero until first adjustment has been performed. + */ +void adjustUtc(uavcan::UtcDuration adjustment); + +/** + * Returns clock error sampled at previous UTC adjustment. + * Positive if the hardware timer is slower than reference time. + */ +uavcan::UtcDuration getPrevUtcAdjustment(); + +} + +/** + * Adapter for uavcan::ISystemClock. + */ +class SystemClock : public uavcan::ISystemClock, uavcan::Noncopyable +{ + static SystemClock self; + + SystemClock() { } + + uavcan::MonotonicTime getMonotonic() const override { return clock::getMonotonic(); } + uavcan::UtcTime getUtc() const override { return clock::getUtc(); } + void adjustUtc(uavcan::UtcDuration adjustment) override { clock::adjustUtc(adjustment); } + +public: + /** + * Calls clock::init() as needed. + */ + static SystemClock& instance(); +}; + +} diff --git a/driver/include/uavcan_lpc11c24/uavcan_lpc11c24.hpp b/driver/include/uavcan_lpc11c24/uavcan_lpc11c24.hpp new file mode 100644 index 0000000..e09051d --- /dev/null +++ b/driver/include/uavcan_lpc11c24/uavcan_lpc11c24.hpp @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#pragma once + +#include +#include +#include diff --git a/driver/src/c_can.hpp b/driver/src/c_can.hpp new file mode 100644 index 0000000..4882e65 --- /dev/null +++ b/driver/src/c_can.hpp @@ -0,0 +1,191 @@ +/* + * Bosch C_CAN controller API. + * + * Copyright (C) 2015 Pavel Kirienko + */ + +#pragma once + +#include +#include + +namespace uavcan_lpc11c24 +{ +namespace c_can +{ + +struct MsgIfaceType +{ + std::uint32_t CMDREQ; + + union + { + std::uint32_t W; + std::uint32_t R; + } CMDMSK; + + std::uint32_t MSK1; + std::uint32_t MSK2; + + std::uint32_t ARB1; + std::uint32_t ARB2; + + std::uint32_t MCTRL; + + std::uint32_t DA1; + std::uint32_t DA2; + std::uint32_t DB1; + std::uint32_t DB2; + + const std::uint32_t _skip[13]; +}; + +static_assert(offsetof(MsgIfaceType, CMDMSK) == 0x04, "C_CAN offset"); +static_assert(offsetof(MsgIfaceType, MSK1) == 0x08, "C_CAN offset"); +static_assert(offsetof(MsgIfaceType, ARB1) == 0x10, "C_CAN offset"); +static_assert(offsetof(MsgIfaceType, MCTRL) == 0x18, "C_CAN offset"); +static_assert(offsetof(MsgIfaceType, DA1) == 0x1c, "C_CAN offset"); +static_assert(offsetof(MsgIfaceType, DB2) == 0x28, "C_CAN offset"); + +static_assert(sizeof(MsgIfaceType) == 96, "C_CAN size"); + + +struct Type +{ + std::uint32_t CNTL; + std::uint32_t STAT; + const std::uint32_t EC; + std::uint32_t BT; + const std::uint32_t INT; + std::uint32_t TEST; + std::uint32_t BRPE; + + const std::uint32_t _skip_a[1]; + + MsgIfaceType IF[2]; // [0] @ 0x020, [1] @ 0x080 + + const std::uint32_t _skip_b[8]; + + const std::uint32_t TXREQ[2]; // 0x100 + + const std::uint32_t _skip_c[6]; + + const std::uint32_t ND[2]; // 0x120 + + const std::uint32_t _skip_d[6]; + + const std::uint32_t IR[2]; // 0x140 + + const std::uint32_t _skip_e[6]; + + const std::uint32_t MSGV[2]; // 0x160 + + const std::uint32_t _skip_f[6]; + + std::uint32_t CLKDIV; // 0x180 +}; + +static_assert(offsetof(Type, CNTL) == 0x000, "C_CAN offset"); +static_assert(offsetof(Type, STAT) == 0x004, "C_CAN offset"); +static_assert(offsetof(Type, TEST) == 0x014, "C_CAN offset"); +static_assert(offsetof(Type, BRPE) == 0x018, "C_CAN offset"); +static_assert(offsetof(Type, IF[0]) == 0x020, "C_CAN offset"); +static_assert(offsetof(Type, IF[1]) == 0x080, "C_CAN offset"); +static_assert(offsetof(Type, TXREQ) == 0x100, "C_CAN offset"); +static_assert(offsetof(Type, ND) == 0x120, "C_CAN offset"); +static_assert(offsetof(Type, IR) == 0x140, "C_CAN offset"); +static_assert(offsetof(Type, MSGV) == 0x160, "C_CAN offset"); +static_assert(offsetof(Type, CLKDIV) == 0x180, "C_CAN offset"); + +static_assert(offsetof(Type, IF[0].DB2) == 0x048, "C_CAN offset"); +static_assert(offsetof(Type, IF[1].DB2) == 0x0A8, "C_CAN offset"); + + +volatile Type& CAN = *reinterpret_cast(0x40050000); + + +/* + * CNTL + */ +static constexpr std::uint32_t CNTL_TEST = 1 << 7; +static constexpr std::uint32_t CNTL_CCE = 1 << 6; +static constexpr std::uint32_t CNTL_DAR = 1 << 5; +static constexpr std::uint32_t CNTL_EIE = 1 << 3; +static constexpr std::uint32_t CNTL_SIE = 1 << 2; +static constexpr std::uint32_t CNTL_IE = 1 << 1; +static constexpr std::uint32_t CNTL_INIT = 1 << 0; + +static constexpr std::uint32_t CNTL_IRQ_MASK = CNTL_EIE | CNTL_IE | CNTL_SIE; + +/* + * TEST + */ +static constexpr std::uint32_t TEST_RX = 1 << 7; +static constexpr std::uint32_t TEST_LBACK = 1 << 4; +static constexpr std::uint32_t TEST_SILENT = 1 << 3; +static constexpr std::uint32_t TEST_BASIC = 1 << 2; +static constexpr std::uint32_t TEST_TX_SHIFT = 5; + +enum class TestTx : std::uint32_t +{ + Controller = 0, + SamplePoint = 1, + LowDominant = 2, + HighRecessive = 3 +}; + +/* + * STAT + */ +static constexpr std::uint32_t STAT_BOFF = 1 << 7; +static constexpr std::uint32_t STAT_EWARN = 1 << 6; +static constexpr std::uint32_t STAT_EPASS = 1 << 5; +static constexpr std::uint32_t STAT_RXOK = 1 << 4; +static constexpr std::uint32_t STAT_TXOK = 1 << 3; +static constexpr std::uint32_t STAT_LEC_MASK = 7; +static constexpr std::uint32_t STAT_LEC_SHIFT = 0; + +enum class StatLec : std::uint32_t +{ + NoError = 0, + StuffError = 1, + FormError = 2, + AckError = 3, + Bit1Error = 4, + Bit0Error = 5, + CRCError = 6, + Unused = 7 +}; + +/* + * IF.CMDREQ + */ +static constexpr std::uint32_t IF_CMDREQ_BUSY = 1 << 15; + +/* + * IF.CMDMSK + */ +static constexpr std::uint32_t IF_CMDMSK_W_DATA_A = 1 << 0; +static constexpr std::uint32_t IF_CMDMSK_W_DATA_B = 1 << 1; +static constexpr std::uint32_t IF_CMDMSK_W_TXRQST = 1 << 2; +static constexpr std::uint32_t IF_CMDMSK_W_CTRL = 1 << 4; +static constexpr std::uint32_t IF_CMDMSK_W_ARB = 1 << 5; +static constexpr std::uint32_t IF_CMDMSK_W_MASK = 1 << 6; +static constexpr std::uint32_t IF_CMDMSK_W_WR_RD = 1 << 7; + +/* + * IF.MCTRL + */ +static constexpr std::uint32_t IF_MCTRL_NEWDAT = 1 << 15; +static constexpr std::uint32_t IF_MCTRL_MSGLST = 1 << 14; +static constexpr std::uint32_t IF_MCTRL_INTPND = 1 << 13; +static constexpr std::uint32_t IF_MCTRL_UMASK = 1 << 12; +static constexpr std::uint32_t IF_MCTRL_TXIE = 1 << 11; +static constexpr std::uint32_t IF_MCTRL_RXIE = 1 << 10; +static constexpr std::uint32_t IF_MCTRL_RMTEN = 1 << 9; +static constexpr std::uint32_t IF_MCTRL_TXRQST = 1 << 8; +static constexpr std::uint32_t IF_MCTRL_EOB = 1 << 7; +static constexpr std::uint32_t IF_MCTRL_DLC_MASK = 15; + +} +} diff --git a/driver/src/can.cpp b/driver/src/can.cpp new file mode 100644 index 0000000..7e7614f --- /dev/null +++ b/driver/src/can.cpp @@ -0,0 +1,649 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#include +#include +#include +#include +#include "c_can.hpp" +#include "internal.hpp" + +/** + * The default value should be OK for any use case. + */ +#ifndef UAVCAN_LPC11C24_RX_QUEUE_LEN +# define UAVCAN_LPC11C24_RX_QUEUE_LEN 8 +#endif + +#if UAVCAN_LPC11C24_RX_QUEUE_LEN > 254 +# error UAVCAN_LPC11C24_RX_QUEUE_LEN is too large +#endif + +extern "C" void canRxCallback(std::uint8_t msg_obj_num); +extern "C" void canTxCallback(std::uint8_t msg_obj_num); +extern "C" void canErrorCallback(std::uint32_t error_info); + +namespace uavcan_lpc11c24 +{ +namespace +{ +/** + * Hardware message objects are allocated as follows: + * - 1 - Single TX object + * - 2..32 - RX objects + * TX priority is defined by the message object number, not by the CAN ID (chapter 16.7.3.5 of the user manual), + * hence we can't use more than one object because that would cause priority inversion on long transfers. + */ +constexpr unsigned NumberOfMessageObjects = 32; +constexpr unsigned NumberOfTxMessageObjects = 1; +constexpr unsigned NumberOfRxMessageObjects = NumberOfMessageObjects - NumberOfTxMessageObjects; +constexpr unsigned TxMessageObjectNumber = 1; + +/** + * Total number of CAN errors. + * Does not overflow. + */ +volatile std::uint32_t error_cnt = 0; + +/** + * False if there's no pending TX frame, i.e. write is possible. + */ +volatile bool tx_pending = false; + +/** + * Currently pending frame must be aborted on first error. + */ +volatile bool tx_abort_on_error = false; + +/** + * Gets updated every time the CAN IRQ handler is being called. + */ +volatile std::uint64_t last_irq_utc_timestamp = 0; + +/** + * Set by the driver on every successful TX or RX; reset by the application. + */ +volatile bool had_activity = false; + +/** + * After a received message gets extracted from C_CAN, it will be stored in the RX queue until libuavcan + * reads it via select()/receive() calls. + */ +class RxQueue +{ + struct Item + { + std::uint64_t utc_usec = 0; + uavcan::CanFrame frame; + }; + + Item buf_[UAVCAN_LPC11C24_RX_QUEUE_LEN]; + std::uint32_t overflow_cnt_ = 0; + std::uint8_t in_ = 0; + std::uint8_t out_ = 0; + std::uint8_t len_ = 0; + +public: + void push(const uavcan::CanFrame& frame, const volatile std::uint64_t& utc_usec) + { + buf_[in_].frame = frame; + buf_[in_].utc_usec = utc_usec; + in_++; + if (in_ >= UAVCAN_LPC11C24_RX_QUEUE_LEN) + { + in_ = 0; + } + len_++; + if (len_ > UAVCAN_LPC11C24_RX_QUEUE_LEN) + { + len_ = UAVCAN_LPC11C24_RX_QUEUE_LEN; + if (overflow_cnt_ < 0xFFFFFFFF) + { + overflow_cnt_++; + } + out_++; + if (out_ >= UAVCAN_LPC11C24_RX_QUEUE_LEN) + { + out_ = 0; + } + } + } + + void pop(uavcan::CanFrame& out_frame, std::uint64_t& out_utc_usec) + { + if (len_ > 0) + { + out_frame = buf_[out_].frame; + out_utc_usec = buf_[out_].utc_usec; + out_++; + if (out_ >= UAVCAN_LPC11C24_RX_QUEUE_LEN) + { + out_ = 0; + } + len_--; + } + } + + unsigned getLength() const { return len_; } + + std::uint32_t getOverflowCount() const { return overflow_cnt_; } +}; + +RxQueue rx_queue; + + +struct BitTimingSettings +{ + std::uint32_t canclkdiv; + std::uint32_t canbtr; + + bool isValid() const { return canbtr != 0; } +}; + +/** + * http://www.bittiming.can-wiki.info + */ +BitTimingSettings computeBitTimings(std::uint32_t bitrate) +{ + if (Chip_Clock_GetSystemClockRate() == 48000000) // 48 MHz is optimal for CAN timings + { + switch (bitrate) + { + case 1000000: return BitTimingSettings{ 0, 0x0505 }; // 8 quanta, 87.5% + case 500000: return BitTimingSettings{ 0, 0x1c05 }; // 16 quanta, 87.5% + case 250000: return BitTimingSettings{ 0, 0x1c0b }; // 16 quanta, 87.5% + case 125000: return BitTimingSettings{ 0, 0x1c17 }; // 16 quanta, 87.5% + case 100000: return BitTimingSettings{ 0, 0x1c1d }; // 16 quanta, 87.5% + default: return BitTimingSettings{ 0, 0 }; + } + } + else + { + return BitTimingSettings{ 0, 0 }; + } +} + +} // namespace + +CanDriver CanDriver::self; + +uavcan::uint32_t CanDriver::detectBitRate(void (*idle_callback)()) +{ + static constexpr uavcan::uint32_t BitRatesToTry[] = + { + 1000000, + 500000, + 250000, + 125000, + 100000 + }; + + const auto ListeningDuration = uavcan::MonotonicDuration::fromMSec(1050); + + NVIC_DisableIRQ(CAN_IRQn); + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_CAN); + + for (auto bitrate : BitRatesToTry) + { + // Computing bit timings + const auto bit_timings = computeBitTimings(bitrate); + if (!bit_timings.isValid()) + { + return 0; + } + + // Configuring the CAN controller + { + CriticalSectionLocker locker; + + LPC_SYSCTL->PRESETCTRL |= (1U << RESET_CAN0); + + // Entering initialization mode + c_can::CAN.CNTL = c_can::CNTL_INIT | c_can::CNTL_CCE; + + while ((c_can::CAN.CNTL & c_can::CNTL_INIT) == 0) + { + ; // Nothing to do + } + + // Configuring bit rate + c_can::CAN.CLKDIV = bit_timings.canclkdiv; + c_can::CAN.BT = bit_timings.canbtr; + c_can::CAN.BRPE = 0; + + // Configuring silent mode + c_can::CAN.CNTL |= c_can::CNTL_TEST; + c_can::CAN.TEST = c_can::TEST_SILENT; + + // Configuring status monitor + c_can::CAN.STAT = (unsigned(c_can::StatLec::Unused) << c_can::STAT_LEC_SHIFT); + + // Leaving initialization mode + c_can::CAN.CNTL &= ~(c_can::CNTL_INIT | c_can::CNTL_CCE); + + while ((c_can::CAN.CNTL & c_can::CNTL_INIT) != 0) + { + ; // Nothing to do + } + } + + // Listening + const auto deadline = clock::getMonotonic() + ListeningDuration; + bool match_detected = false; + while (clock::getMonotonic() < deadline) + { + if (idle_callback != nullptr) + { + idle_callback(); + } + + const auto LastErrorCode = (c_can::CAN.STAT >> c_can::STAT_LEC_SHIFT) & c_can::STAT_LEC_MASK; + + if (LastErrorCode == unsigned(c_can::StatLec::NoError)) + { + match_detected = true; + break; + } + } + + // De-configuring the CAN controller back to reset state + { + CriticalSectionLocker locker; + + c_can::CAN.CNTL = c_can::CNTL_INIT; + + while ((c_can::CAN.CNTL & c_can::CNTL_INIT) == 0) + { + ; // Nothing to do + } + + LPC_SYSCTL->PRESETCTRL &= ~(1U << RESET_CAN0); + } + + // Termination condition + if (match_detected) + { + return bitrate; + } + } + + return 0; // No match +} + +int CanDriver::init(uavcan::uint32_t bitrate) +{ + { + auto bit_timings = computeBitTimings(bitrate); + if (!bit_timings.isValid()) + { + return -1; + } + + CriticalSectionLocker locker; + + error_cnt = 0; + tx_abort_on_error = false; + tx_pending = false; + last_irq_utc_timestamp = 0; + had_activity = false; + + /* + * C_CAN init + */ + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_CAN); + + LPC_CCAN_API->init_can(reinterpret_cast(&bit_timings), true); + + static CCAN_CALLBACKS_T ccan_callbacks = + { + canRxCallback, + canTxCallback, + canErrorCallback, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }; + LPC_CCAN_API->config_calb(&ccan_callbacks); + + /* + * Interrupts + */ + c_can::CAN.CNTL |= c_can::CNTL_SIE; // This is necessary for transmission aborts on error + + NVIC_EnableIRQ(CAN_IRQn); + } + + /* + * Applying default filter configuration (accept all) + */ + if (configureFilters(nullptr, 0) < 0) + { + return -1; + } + + return 0; +} + +bool CanDriver::hasReadyRx() const +{ + CriticalSectionLocker locker; + return rx_queue.getLength() > 0; +} + +bool CanDriver::hasEmptyTx() const +{ + CriticalSectionLocker locker; + return !tx_pending; +} + +bool CanDriver::hadActivity() +{ + CriticalSectionLocker locker; + const bool ret = had_activity; + had_activity = false; + return ret; +} + +uavcan::uint32_t CanDriver::getRxQueueOverflowCount() const +{ + CriticalSectionLocker locker; + return rx_queue.getOverflowCount(); +} + +bool CanDriver::isInBusOffState() const +{ + return (c_can::CAN.STAT & c_can::STAT_BOFF) != 0; +} + +uavcan::int16_t CanDriver::send(const uavcan::CanFrame& frame, uavcan::MonotonicTime tx_deadline, + uavcan::CanIOFlags flags) +{ + if (frame.isErrorFrame() || + frame.dlc > 8 || + (flags & uavcan::CanIOFlagLoopback) != 0) // TX timestamping is not supported by this driver. + { + return -1; + } + + /* + * Frame conversion + */ + CCAN_MSG_OBJ_T msgobj = CCAN_MSG_OBJ_T(); + msgobj.mode_id = frame.id & uavcan::CanFrame::MaskExtID; + if (frame.isExtended()) + { + msgobj.mode_id |= CAN_MSGOBJ_EXT; + } + if (frame.isRemoteTransmissionRequest()) + { + msgobj.mode_id |= CAN_MSGOBJ_RTR; + } + msgobj.dlc = frame.dlc; + uavcan::copy(frame.data, frame.data + frame.dlc, msgobj.data); + + /* + * Transmission + */ + (void)tx_deadline; // TX timeouts are not supported by this driver yet (and hardly going to be). + + CriticalSectionLocker locker; + + if (!tx_pending) + { + tx_pending = true; // Mark as pending - will be released in TX callback + tx_abort_on_error = (flags & uavcan::CanIOFlagAbortOnError) != 0; + msgobj.msgobj = TxMessageObjectNumber; + LPC_CCAN_API->can_transmit(&msgobj); + return 1; + } + return 0; +} + +uavcan::int16_t CanDriver::receive(uavcan::CanFrame& out_frame, uavcan::MonotonicTime& out_ts_monotonic, + uavcan::UtcTime& out_ts_utc, uavcan::CanIOFlags& out_flags) +{ + out_ts_monotonic = clock::getMonotonic(); + out_flags = 0; // We don't support any IO flags + + CriticalSectionLocker locker; + if (rx_queue.getLength() == 0) + { + return 0; + } + std::uint64_t ts_utc = 0; + rx_queue.pop(out_frame, ts_utc); + out_ts_utc = uavcan::UtcTime::fromUSec(ts_utc); + return 1; +} + +uavcan::int16_t CanDriver::select(uavcan::CanSelectMasks& inout_masks, + const uavcan::CanFrame* (&)[uavcan::MaxCanIfaces], + uavcan::MonotonicTime blocking_deadline) +{ + const bool bus_off = isInBusOffState(); + if (bus_off) // Recover automatically on bus-off + { + CriticalSectionLocker locker; + if ((c_can::CAN.CNTL & c_can::CNTL_INIT) != 0) + { + c_can::CAN.CNTL &= ~c_can::CNTL_INIT; + } + } + + const bool noblock = ((inout_masks.read == 1) && hasReadyRx()) || + ((inout_masks.write == 1) && hasEmptyTx()); + + if (!noblock && (clock::getMonotonic() > blocking_deadline)) + { +#if defined(UAVCAN_LPC11C24_USE_WFE) && UAVCAN_LPC11C24_USE_WFE + /* + * It's not cool (literally) to burn cycles in a busyloop, and we have no OS to pass control to other + * tasks, thus solution is to halt the core until a hardware event occurs - e.g. clock timer overflow. + * Upon such event the select() call will return, even if no requested IO operations became available. + * It's OK to do that, libuavcan can handle such behavior. + * + * Note that it is not possible to precisely control the sleep duration with WFE, since we can't predict when + * the next hardware event occurs. Worst case conditions: + * - WFE gets executed right after the clock timer interrupt; + * - CAN bus is completely silent (no traffic); + * - User's application has no interrupts and generates no hardware events. + * In such scenario execution will stuck here for one period of the clock timer interrupt, even if + * blocking_deadline expires sooner. + * If the user's application requires higher timing precision, an extra dummy IRQ can be added just to + * break WFE every once in a while. + */ + __WFE(); +#endif + } + + inout_masks.read = hasReadyRx() ? 1 : 0; + + inout_masks.write = (hasEmptyTx() && !bus_off) ? 1 : 0; // Disable write while in bus-off + + return 0; // Return value doesn't matter as long as it is non-negative +} + +uavcan::int16_t CanDriver::configureFilters(const uavcan::CanFilterConfig* filter_configs, + uavcan::uint16_t num_configs) +{ + CriticalSectionLocker locker; + + /* + * If C_CAN is active (INIT=0) and the CAN bus has intensive traffic, RX object configuration may fail. + * The solution is to disable the controller while configuration is in progress. + * The documentation, as always, doesn't bother to mention this detail. Shame on you, NXP. + */ + struct RAIIDisabler + { + RAIIDisabler() + { + c_can::CAN.CNTL |= c_can::CNTL_INIT; + } + ~RAIIDisabler() + { + c_can::CAN.CNTL &= ~c_can::CNTL_INIT; + } + } can_disabler; // Must be instantiated AFTER the critical section locker + + if (num_configs == 0) + { + auto msg_obj = CCAN_MSG_OBJ_T(); + msg_obj.msgobj = NumberOfTxMessageObjects + 1; + LPC_CCAN_API->config_rxmsgobj(&msg_obj); // all STD frames + + msg_obj.mode_id = CAN_MSGOBJ_EXT; + msg_obj.msgobj = NumberOfTxMessageObjects + 2; + LPC_CCAN_API->config_rxmsgobj(&msg_obj); // all EXT frames + } + else if (num_configs <= NumberOfRxMessageObjects) + { + // Making sure the configs use only EXT frames; otherwise we can't accept them + for (unsigned i = 0; i < num_configs; i++) + { + auto& f = filter_configs[i]; + if ((f.id & f.mask & uavcan::CanFrame::FlagEFF) == 0) + { + return -1; + } + } + + // Installing the configuration + for (unsigned i = 0; i < NumberOfRxMessageObjects; i++) + { + auto msg_obj = CCAN_MSG_OBJ_T(); + msg_obj.msgobj = std::uint8_t(i + 1U + NumberOfTxMessageObjects); // Message objects are numbered from 1 + + if (i < num_configs) + { + msg_obj.mode_id = (filter_configs[i].id & uavcan::CanFrame::MaskExtID) | CAN_MSGOBJ_EXT; // Only EXT + msg_obj.mask = filter_configs[i].mask & uavcan::CanFrame::MaskExtID; + } + else + { + msg_obj.mode_id = CAN_MSGOBJ_RTR; // Using this configuration to disable the object + msg_obj.mask = uavcan::CanFrame::MaskStdID; + } + + LPC_CCAN_API->config_rxmsgobj(&msg_obj); + } + } + else + { + return -1; + } + + return 0; +} + +uavcan::uint64_t CanDriver::getErrorCount() const +{ + CriticalSectionLocker locker; + return std::uint64_t(error_cnt) + std::uint64_t(rx_queue.getOverflowCount()); +} + +uavcan::uint16_t CanDriver::getNumFilters() const +{ + return NumberOfRxMessageObjects; +} + +uavcan::ICanIface* CanDriver::getIface(uavcan::uint8_t iface_index) +{ + return (iface_index == 0) ? this : nullptr; +} + +uavcan::uint8_t CanDriver::getNumIfaces() const +{ + return 1; +} + +} + +/* + * C_CAN handlers + */ +extern "C" +{ + +void canRxCallback(std::uint8_t msg_obj_num) +{ + using namespace uavcan_lpc11c24; + + auto msg_obj = CCAN_MSG_OBJ_T(); + msg_obj.msgobj = msg_obj_num; + LPC_CCAN_API->can_receive(&msg_obj); + + uavcan::CanFrame frame; + + // CAN ID, EXT or not + if (msg_obj.mode_id & CAN_MSGOBJ_EXT) + { + frame.id = msg_obj.mode_id & uavcan::CanFrame::MaskExtID; + frame.id |= uavcan::CanFrame::FlagEFF; + } + else + { + frame.id = msg_obj.mode_id & uavcan::CanFrame::MaskStdID; + } + + // RTR + if (msg_obj.mode_id & CAN_MSGOBJ_RTR) + { + frame.id |= uavcan::CanFrame::FlagRTR; + } + + // Payload + frame.dlc = msg_obj.dlc; + uavcan::copy(msg_obj.data, msg_obj.data + msg_obj.dlc, frame.data); + + rx_queue.push(frame, last_irq_utc_timestamp); + had_activity = true; +} + +void canTxCallback(std::uint8_t msg_obj_num) +{ + using namespace uavcan_lpc11c24; + + (void)msg_obj_num; + + tx_pending = false; + had_activity = true; +} + +void canErrorCallback(std::uint32_t error_info) +{ + using namespace uavcan_lpc11c24; + + // Updating the error counter + if ((error_info != 0) && (error_cnt < 0xFFFFFFFFUL)) + { + error_cnt++; + } + + // Serving abort requests + if (tx_pending && tx_abort_on_error) + { + tx_pending = false; + tx_abort_on_error = false; + + // Using the first interface, because this approach seems to be compliant with the BASIC mode (just in case) + c_can::CAN.IF[0].CMDREQ = TxMessageObjectNumber; + c_can::CAN.IF[0].CMDMSK.W = c_can::IF_CMDMSK_W_WR_RD; // Clearing IF_CMDMSK_W_TXRQST + c_can::CAN.IF[0].MCTRL &= ~c_can::IF_MCTRL_TXRQST; // Clearing IF_MCTRL_TXRQST + } +} + +void CAN_IRQHandler(); + +void CAN_IRQHandler() +{ + using namespace uavcan_lpc11c24; + + last_irq_utc_timestamp = clock::getUtcUSecFromCanInterrupt(); + + LPC_CCAN_API->isr(); +} + +} diff --git a/driver/src/clock.cpp b/driver/src/clock.cpp new file mode 100644 index 0000000..a9d299f --- /dev/null +++ b/driver/src/clock.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#include +#include +#include +#include "internal.hpp" + +namespace uavcan_lpc11c24 +{ +namespace clock +{ +namespace +{ + +bool initialized = false; +bool utc_set = false; + +std::int32_t utc_correction_usec_per_overflow_x16 = 0; +std::int64_t prev_adjustment = 0; + +std::uint64_t time_mono = 0; +std::uint64_t time_utc = 0; + +/** + * If this value is too large for the given core clock, reload value will be out of the 24-bit integer range. + * This will be detected at run time during timer initialization - refer to SysTick_Config(). + */ +constexpr std::uint32_t USecPerOverflow = 65536 * 2; +constexpr std::int32_t MaxUtcSpeedCorrectionX16 = 100 * 16; + +} + +#if __GNUC__ +__attribute__((noreturn)) +#endif +static void fail() +{ + while (true) { } +} + +void init() +{ + CriticalSectionLocker lock; + if (!initialized) + { + initialized = true; + + if ((SystemCoreClock % 1000000) != 0) // Core clock frequency validation + { + fail(); + } + + if (SysTick_Config((SystemCoreClock / 1000000) * USecPerOverflow) != 0) + { + fail(); + } + } +} + +static std::uint64_t sampleFromCriticalSection(const volatile std::uint64_t* const value) +{ + const std::uint32_t reload = SysTick->LOAD + 1; // SysTick counts downwards, hence the value subtracted from reload + + volatile std::uint64_t time = *value; + volatile std::uint32_t cycles = reload - SysTick->VAL; + + if ((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) == SCB_ICSR_PENDSTSET_Msk) + { + cycles = reload - SysTick->VAL; + time += USecPerOverflow; + } + const std::uint32_t cycles_per_usec = SystemCoreClock / 1000000; + return time + (cycles / cycles_per_usec); +} + +std::uint64_t getUtcUSecFromCanInterrupt() +{ + return utc_set ? sampleFromCriticalSection(&time_utc) : 0; +} + +uavcan::MonotonicTime getMonotonic() +{ + if (!initialized) + { + fail(); + } + std::uint64_t usec = 0; + { + CriticalSectionLocker locker; + usec = sampleFromCriticalSection(&time_mono); + } + return uavcan::MonotonicTime::fromUSec(usec); +} + +uavcan::UtcTime getUtc() +{ + if (!initialized) + { + fail(); + } + std::uint64_t usec = 0; + if (utc_set) + { + CriticalSectionLocker locker; + usec = sampleFromCriticalSection(&time_utc); + } + return uavcan::UtcTime::fromUSec(usec); +} + +uavcan::UtcDuration getPrevUtcAdjustment() +{ + return uavcan::UtcDuration::fromUSec(prev_adjustment); +} + +void adjustUtc(uavcan::UtcDuration adjustment) +{ + const std::int64_t adj_delta = adjustment.toUSec() - prev_adjustment; // This is the P term + prev_adjustment = adjustment.toUSec(); + + utc_correction_usec_per_overflow_x16 += adjustment.isPositive() ? 1 : -1; // I + utc_correction_usec_per_overflow_x16 += (adj_delta > 0) ? 1 : -1; // P + + utc_correction_usec_per_overflow_x16 = + uavcan::max(utc_correction_usec_per_overflow_x16, -MaxUtcSpeedCorrectionX16); + utc_correction_usec_per_overflow_x16 = + uavcan::min(utc_correction_usec_per_overflow_x16, MaxUtcSpeedCorrectionX16); + + if (adjustment.getAbs().toMSec() > 9 || !utc_set) + { + const std::int64_t adj_usec = adjustment.toUSec(); + { + CriticalSectionLocker locker; + if ((adj_usec < 0) && std::uint64_t(-adj_usec) > time_utc) + { + time_utc = 1; + } + else + { + time_utc = std::uint64_t(std::int64_t(time_utc) + adj_usec); + } + } + if (!utc_set) + { + utc_set = true; + utc_correction_usec_per_overflow_x16 = 0; + } + } +} + +} // namespace clock + +SystemClock SystemClock::self; + +SystemClock& SystemClock::instance() +{ + clock::init(); + return self; +} + +} + +/* + * Timer interrupt handler + */ +extern "C" +{ + +void SysTick_Handler(); + +void SysTick_Handler() +{ + using namespace uavcan_lpc11c24::clock; + if (initialized) + { + time_mono += USecPerOverflow; + if (utc_set) + { + // Values below 16 are ignored + time_utc += std::uint64_t(std::int32_t(USecPerOverflow) + (utc_correction_usec_per_overflow_x16 / 16)); + } + } + else + { + fail(); + } +} + +} diff --git a/driver/src/internal.hpp b/driver/src/internal.hpp new file mode 100644 index 0000000..80be9f1 --- /dev/null +++ b/driver/src/internal.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#pragma once + +#include +#include + +/* + * Compiler version check + */ +#ifdef __GNUC__ +# if (__GNUC__ * 10 + __GNUC_MINOR__) < 49 +# error "Use GCC 4.9 or newer" +# endif +#endif + + +namespace uavcan_lpc11c24 +{ + +/** + * Locks UAVCAN driver interrupts. + * TODO: priority. + */ +struct CriticalSectionLocker +{ + CriticalSectionLocker() + { + __disable_irq(); + } + ~CriticalSectionLocker() + { + __enable_irq(); + } +}; + +/** + * Internal for the driver + */ +namespace clock +{ + +std::uint64_t getUtcUSecFromCanInterrupt(); + +} + +} diff --git a/test_olimex_lpc_p11c24/Makefile b/test_olimex_lpc_p11c24/Makefile new file mode 100644 index 0000000..9a503bc --- /dev/null +++ b/test_olimex_lpc_p11c24/Makefile @@ -0,0 +1,123 @@ +# +# Pavel Kirienko, 2014 +# + +CPPSRC := $(wildcard src/*.cpp) \ + $(wildcard src/sys/*.cpp) + +CSRC := $(wildcard lpc_chip_11cxx_lib/src/*.c) \ + $(wildcard src/sys/*.c) + +DEF = -DFW_VERSION_MAJOR=1 -DFW_VERSION_MINOR=0 + +INC = -Isrc/sys \ + -isystem lpc_chip_11cxx_lib/inc + +# +# UAVCAN library +# + +DEF += -DUAVCAN_TINY=1 + +include ../../../libuavcan/include.mk +CPPSRC += $(LIBUAVCAN_SRC) +INC += -I$(LIBUAVCAN_INC) + +include ../driver/include.mk +CPPSRC += $(LIBUAVCAN_LPC11C24_SRC) +INC += -I$(LIBUAVCAN_LPC11C24_INC) + +$(info $(shell $(LIBUAVCAN_DSDLC) $(UAVCAN_DSDL_DIR))) +INC += -Idsdlc_generated + +# +# Git commit hash +# + +GIT_HASH := $(shell git rev-parse --short HEAD) +ifeq ($(words $(GIT_HASH)),1) + DEF += -DGIT_HASH=0x$(GIT_HASH) +endif + +# +# Build configuration +# + +BUILDDIR = build +OBJDIR = $(BUILDDIR)/obj +DEPDIR = $(BUILDDIR)/dep + +DEF += -DNDEBUG -DCHIP_LPC11CXX -DCORE_M0 -DTHUMB_NO_INTERWORKING -U__STRICT_ANSI__ + +FLAGS = -mthumb -mcpu=cortex-m0 -mno-thumb-interwork -flto -Os -g3 -Wall -Wextra -Werror -Wundef -ffunction-sections \ + -fdata-sections -fno-common -fno-exceptions -fno-unwind-tables -fno-stack-protector -fomit-frame-pointer \ + -Wfloat-equal -Wconversion -Wsign-conversion -Wmissing-declarations + +C_CPP_FLAGS = $(FLAGS) -MD -MP -MF $(DEPDIR)/$(@F).d + +CFLAGS = $(C_CPP_FLAGS) -std=c99 + +CPPFLAGS = $(C_CPP_FLAGS) -pedantic -std=c++11 -fno-rtti -fno-threadsafe-statics + +LDFLAGS = $(FLAGS) -nodefaultlibs -lc -lgcc -nostartfiles -Tlpc11c24.ld -Xlinker --gc-sections \ + -Wl,-Map,$(BUILDDIR)/output.map + +# Link with nano newlib. Other toolchains may not support this option, so it can be safely removed. +LDFLAGS += --specs=nano.specs + +COBJ = $(addprefix $(OBJDIR)/, $(notdir $(CSRC:.c=.o))) +CPPOBJ = $(addprefix $(OBJDIR)/, $(notdir $(CPPSRC:.cpp=.o))) +OBJ = $(COBJ) $(CPPOBJ) + +VPATH = $(sort $(dir $(CSRC)) $(dir $(CPPSRC))) + +ELF = $(BUILDDIR)/firmware.elf +BIN = $(BUILDDIR)/firmware.bin + +# +# Rules +# + +TOOLCHAIN ?= arm-none-eabi- +CC = $(TOOLCHAIN)gcc +CPPC = $(TOOLCHAIN)g++ +AS = $(TOOLCHAIN)gcc +LD = $(TOOLCHAIN)g++ +CP = $(TOOLCHAIN)objcopy +SIZE = $(TOOLCHAIN)size + +all: $(OBJ) $(ELF) $(BIN) size + +$(OBJ): | $(BUILDDIR) + +$(BUILDDIR): + @mkdir -p $(BUILDDIR) + @mkdir -p $(DEPDIR) + @mkdir -p $(OBJDIR) + +$(BIN): $(ELF) + @echo + $(CP) -O binary $(ELF) $@ + +$(ELF): $(OBJ) + @echo + $(LD) $(OBJ) $(LDFLAGS) -o $@ + +$(COBJ): $(OBJDIR)/%.o: %.c + @echo + $(CC) -c $(DEF) $(INC) $(CFLAGS) $< -o $@ + +$(CPPOBJ): $(OBJDIR)/%.o: %.cpp + @echo + $(CPPC) -c $(DEF) $(INC) $(CPPFLAGS) $< -o $@ + +clean: + rm -rf $(BUILDDIR) dsdlc_generated + +size: $(ELF) + @if [ -f $(ELF) ]; then echo; $(SIZE) $(ELF); echo; fi; + +.PHONY: all clean size $(BUILDDIR) + +# Include the dependency files, should be the last of the makefile +-include $(shell mkdir $(DEPDIR) 2>/dev/null) $(wildcard $(DEPDIR)/*) diff --git a/test_olimex_lpc_p11c24/blackmagic.gdbinit b/test_olimex_lpc_p11c24/blackmagic.gdbinit new file mode 100644 index 0000000..cea9965 --- /dev/null +++ b/test_olimex_lpc_p11c24/blackmagic.gdbinit @@ -0,0 +1,11 @@ +# +# Template for .gdbinit +# Copy the file to .gdbinit in your project root, and adjust the path below to match your system +# + +target extended /dev/serial/by-id/usb-Black_Sphere_Technologies_Black_Magic_Probe_DDE578CC-if00 +# target extended /dev/ttyACM0 + +monitor swdp_scan +attach 1 +monitor vector_catch disable hard diff --git a/test_olimex_lpc_p11c24/blackmagic_flash.sh b/test_olimex_lpc_p11c24/blackmagic_flash.sh new file mode 100755 index 0000000..ed8dc7e --- /dev/null +++ b/test_olimex_lpc_p11c24/blackmagic_flash.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# +# Copyright (C) 2014 Pavel Kirienko +# + +PORT=${1:-'/dev/ttyACM0'} +#/dev/serial/by-id/usb-Black_Sphere_Technologies_Black_Magic_Probe_DDE578CC-if00 + +elf=build/firmware.elf + +arm-none-eabi-size $elf || exit 1 + +tmpfile=fwupload.tempfile +cat > $tmpfile < + * Linker script for LPC11C24 + */ + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 32K + /* Notice RAM offset - this is needed for on-chip CCAN */ + RAM (rwx) : ORIGIN = 0x100000C0, LENGTH = 0x1F40 +} + +ENTRY(Reset_Handler) + +SECTIONS +{ + . = 0; + _text = .; + + startup : + { + KEEP(*(vectors)) + } > FLASH + + constructors : ALIGN(4) SUBALIGN(4) + { + PROVIDE(__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE(__init_array_end = .); + } > FLASH + + /* NO DESTRUCTORS */ + + .text : + { + *(.text.startup.*) + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + *(.glue_7t) + *(.glue_7) + *(.gcc*) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + .ARM.exidx : { + PROVIDE(__exidx_start = .); + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + PROVIDE(__exidx_end = .); + } > FLASH + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + } > FLASH + + .eh_frame : ONLY_IF_RO + { + *(.eh_frame) + } > FLASH + + .textalign : ONLY_IF_RO + { + . = ALIGN(8); + } > FLASH + + . = ALIGN(4); + _etext = .; + _textdata = _etext; + + .data : + { + . = ALIGN(4); + PROVIDE(_data = .); + *(.data) + . = ALIGN(4); + *(.data.*) + . = ALIGN(4); + *(.ramtext) + . = ALIGN(4); + PROVIDE(_edata = .); + } > RAM AT > FLASH + + .bss : + { + . = ALIGN(4); + PROVIDE(_bss = .); + *(.bss) + . = ALIGN(4); + *(.bss.*) + . = ALIGN(4); + *(COMMON) + . = ALIGN(4); + PROVIDE(_ebss = .); + } > RAM + + PROVIDE(__stack_end = ORIGIN(RAM) + LENGTH(RAM)); +} diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/adc_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/adc_11xx.h new file mode 100755 index 0000000..af894e7 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/adc_11xx.h @@ -0,0 +1,271 @@ +/* + * @brief LPC11xx A/D conversion driver (except LPC1125) + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __ADC_11XX_H_ +#define __ADC_11XX_H_ + +#if !defined(CHIP_LPC1125) + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup ADC_11XX CHIP: LPC11xx A/D conversion driver + * @ingroup CHIP_11XX_Drivers + * This ADC driver is for LPC11xx variants except for LPC1125. + * @{ + */ + +#define ADC_MAX_SAMPLE_RATE 400000 + +/** + * @brief 10 or 12-bit ADC register block structure + */ +typedef struct { /*!< ADCn Structure */ + __IO uint32_t CR; /*!< A/D Control Register. The AD0CR register must be written to select the operating mode before A/D conversion can occur. */ + __I uint32_t GDR; /*!< A/D Global Data Register. Contains the result of the most recent A/D conversion. */ + __I uint32_t RESERVED0; + __IO uint32_t INTEN; /*!< A/D Interrupt Enable Register. This register contains enable bits that allow the DONE flag of each A/D channel to be included or excluded from contributing to the generation of an A/D interrupt. */ + __I uint32_t DR[8]; /*!< A/D Channel Data Register. This register contains the result of the most recent conversion completed on channel n. */ + __I uint32_t STAT; /*!< A/D Status Register. This register contains DONE and OVERRUN flags for all of the A/D channels, as well as the A/D interrupt flag. */ +} LPC_ADC_T; + +/** + * @brief ADC register support bitfields and mask + */ + #define ADC_DR_RESULT(n) ((((n) >> 6) & 0x3FF)) /*!< Mask for getting the 10 bits ADC data read value */ + #define ADC_CR_BITACC(n) ((((n) & 0x7) << 17)) /*!< Number of ADC accuracy bits */ + +#define ADC_DR_DONE(n) (((n) >> 31)) /*!< Mask for reading the ADC done status */ +#define ADC_DR_OVERRUN(n) ((((n) >> 30) & (1UL))) /*!< Mask for reading the ADC overrun status */ +#define ADC_CR_CH_SEL(n) ((1UL << (n))) /*!< Selects which of the AD0.0:7 pins is (are) to be sampled and converted */ +#define ADC_CR_CLKDIV(n) ((((n) & 0xFF) << 8)) /*!< The APB clock (PCLK) is divided by (this value plus one) to produce the clock for the A/D */ +#define ADC_CR_BURST ((1UL << 16)) /*!< Repeated conversions A/D enable bit */ +#define ADC_CR_PDN ((1UL << 21)) /*!< ADC convert is operational */ +#define ADC_CR_START_MASK ((7UL << 24)) /*!< ADC start mask bits */ +#define ADC_CR_START_MODE_SEL(SEL) ((SEL << 24)) /*!< Select Start Mode */ +#define ADC_CR_START_NOW ((1UL << 24)) /*!< Start conversion now */ +#define ADC_CR_START_CTOUT15 ((2UL << 24)) /*!< Start conversion when the edge selected by bit 27 occurs on CTOUT_15 */ +#define ADC_CR_START_CTOUT8 ((3UL << 24)) /*!< Start conversion when the edge selected by bit 27 occurs on CTOUT_8 */ +#define ADC_CR_START_ADCTRIG0 ((4UL << 24)) /*!< Start conversion when the edge selected by bit 27 occurs on ADCTRIG0 */ +#define ADC_CR_START_ADCTRIG1 ((5UL << 24)) /*!< Start conversion when the edge selected by bit 27 occurs on ADCTRIG1 */ +#define ADC_CR_START_MCOA2 ((6UL << 24)) /*!< Start conversion when the edge selected by bit 27 occurs on Motocon PWM output MCOA2 */ +#define ADC_CR_EDGE ((1UL << 27)) /*!< Start conversion on a falling edge on the selected CAP/MAT signal */ +#define ADC_SAMPLE_RATE_CONFIG_MASK (ADC_CR_CLKDIV(0xFF) | ADC_CR_BITACC(0x07)) + +/** + * @brief ADC status register used for IP drivers + */ +typedef enum IP_ADC_STATUS { + ADC_DR_DONE_STAT, /*!< ADC data register staus */ + ADC_DR_OVERRUN_STAT,/*!< ADC data overrun staus */ + ADC_DR_ADINT_STAT /*!< ADC interrupt status */ +} ADC_STATUS_T; + +/** The channels on one ADC peripheral*/ +typedef enum CHIP_ADC_CHANNEL { + ADC_CH0 = 0, /**< ADC channel 0 */ + ADC_CH1, /**< ADC channel 1 */ + ADC_CH2, /**< ADC channel 2 */ + ADC_CH3, /**< ADC channel 3 */ + ADC_CH4, /**< ADC channel 4 */ + ADC_CH5, /**< ADC channel 5 */ + ADC_CH6, /**< ADC channel 6 */ + ADC_CH7, /**< ADC channel 7 */ +} ADC_CHANNEL_T; + +/** The number of bits of accuracy of the result in the LS bits of ADDR*/ +typedef enum CHIP_ADC_RESOLUTION { + ADC_10BITS = 0, /**< ADC 10 bits */ + ADC_9BITS, /**< ADC 9 bits */ + ADC_8BITS, /**< ADC 8 bits */ + ADC_7BITS, /**< ADC 7 bits */ + ADC_6BITS, /**< ADC 6 bits */ + ADC_5BITS, /**< ADC 5 bits */ + ADC_4BITS, /**< ADC 4 bits */ + ADC_3BITS, /**< ADC 3 bits */ +} ADC_RESOLUTION_T; + +/** Edge configuration, which controls rising or falling edge on the selected signal for the start of a conversion */ +typedef enum CHIP_ADC_EDGE_CFG { + ADC_TRIGGERMODE_RISING = 0, /**< Trigger event: rising edge */ + ADC_TRIGGERMODE_FALLING, /**< Trigger event: falling edge */ +} ADC_EDGE_CFG_T; + +/** Start mode, which controls the start of an A/D conversion when the BURST bit is 0. */ +typedef enum CHIP_ADC_START_MODE { + ADC_NO_START = 0, + ADC_START_NOW, /*!< Start conversion now */ + ADC_START_ON_CTOUT15, /*!< Start conversion when the edge selected by bit 27 occurs on CTOUT_15 */ + ADC_START_ON_CTOUT8, /*!< Start conversion when the edge selected by bit 27 occurs on CTOUT_8 */ + ADC_START_ON_ADCTRIG0, /*!< Start conversion when the edge selected by bit 27 occurs on ADCTRIG0 */ + ADC_START_ON_ADCTRIG1, /*!< Start conversion when the edge selected by bit 27 occurs on ADCTRIG1 */ + ADC_START_ON_MCOA2 /*!< Start conversion when the edge selected by bit 27 occurs on Motocon PWM output MCOA2 */ +} ADC_START_MODE_T; + +/** Clock setup structure for ADC controller passed to the initialize function */ +typedef struct { + uint32_t adcRate; /*!< ADC rate */ + uint8_t bitsAccuracy; /*!< ADC bit accuracy */ + bool burstMode; /*!< ADC Burt Mode */ +} ADC_CLOCK_SETUP_T; + +/** + * @brief Initialize the ADC peripheral and the ADC setup structure to default value + * @param pADC : The base of ADC peripheral on the chip + * @param ADCSetup : ADC setup structure to be set + * @return Nothing + * @note Default setting for ADC is 400kHz - 10bits + */ +void Chip_ADC_Init(LPC_ADC_T *pADC, ADC_CLOCK_SETUP_T *ADCSetup); + +/** + * @brief Shutdown ADC + * @param pADC : The base of ADC peripheral on the chip + * @return Nothing + */ +void Chip_ADC_DeInit(LPC_ADC_T *pADC); + +/** + * @brief Read the ADC value from a channel + * @param pADC : The base of ADC peripheral on the chip + * @param channel : ADC channel to read + * @param data : Pointer to where to put data + * @return SUCCESS or ERROR if no conversion is ready + */ +Status Chip_ADC_ReadValue(LPC_ADC_T *pADC, uint8_t channel, uint16_t *data); + +/** + * @brief Read the ADC value and convert it to 8bits value + * @param pADC : The base of ADC peripheral on the chip + * @param channel: selected channel + * @param data : Storage for data + * @return Status : ERROR or SUCCESS + */ +Status Chip_ADC_ReadByte(LPC_ADC_T *pADC, ADC_CHANNEL_T channel, uint8_t *data); + +/** + * @brief Read the ADC channel status + * @param pADC : The base of ADC peripheral on the chip + * @param channel : ADC channel to read + * @param StatusType : Status type of ADC_DR_* + * @return SET or RESET + */ +FlagStatus Chip_ADC_ReadStatus(LPC_ADC_T *pADC, uint8_t channel, uint32_t StatusType); + +/** + * @brief Enable/Disable interrupt for ADC channel + * @param pADC : The base of ADC peripheral on the chip + * @param channel : ADC channel to read + * @param NewState : New state, ENABLE or DISABLE + * @return SET or RESET + */ +void Chip_ADC_Int_SetChannelCmd(LPC_ADC_T *pADC, uint8_t channel, FunctionalState NewState); + +/** + * @brief Enable/Disable global interrupt for ADC channel + * @param pADC : The base of ADC peripheral on the chip + * @param NewState : New state, ENABLE or DISABLE + * @return Nothing + */ +STATIC INLINE void Chip_ADC_Int_SetGlobalCmd(LPC_ADC_T *pADC, FunctionalState NewState) +{ + Chip_ADC_Int_SetChannelCmd(pADC, 8, NewState); +} + +/** + * @brief Select the mode starting the AD conversion + * @param pADC : The base of ADC peripheral on the chip + * @param mode : Stating mode, should be : + * - ADC_NO_START : Must be set for Burst mode + * - ADC_START_NOW : Start conversion now + * - ADC_START_ON_CTOUT15 : Start conversion when the edge selected by bit 27 occurs on CTOUT_15 + * - ADC_START_ON_CTOUT8 : Start conversion when the edge selected by bit 27 occurs on CTOUT_8 + * - ADC_START_ON_ADCTRIG0 : Start conversion when the edge selected by bit 27 occurs on ADCTRIG0 + * - ADC_START_ON_ADCTRIG1 : Start conversion when the edge selected by bit 27 occurs on ADCTRIG1 + * - ADC_START_ON_MCOA2 : Start conversion when the edge selected by bit 27 occurs on Motocon PWM output MCOA2 + * @param EdgeOption : Stating Edge Condition, should be : + * - ADC_TRIGGERMODE_RISING : Trigger event on rising edge + * - ADC_TRIGGERMODE_FALLING : Trigger event on falling edge + * @return Nothing + */ +void Chip_ADC_SetStartMode(LPC_ADC_T *pADC, ADC_START_MODE_T mode, ADC_EDGE_CFG_T EdgeOption); + +/** + * @brief Set the ADC Sample rate + * @param pADC : The base of ADC peripheral on the chip + * @param ADCSetup : ADC setup structure to be modified + * @param rate : Sample rate, should be set so the clock for A/D converter is less than or equal to 4.5MHz. + * @return Nothing + */ +void Chip_ADC_SetSampleRate(LPC_ADC_T *pADC, ADC_CLOCK_SETUP_T *ADCSetup, uint32_t rate); + +/** + * @brief Set the ADC accuracy bits + * @param pADC : The base of ADC peripheral on the chip + * @param ADCSetup : ADC setup structure to be modified + * @param resolution : The resolution, should be ADC_10BITS -> ADC_3BITS + * @return Nothing + */ +void Chip_ADC_SetResolution(LPC_ADC_T *pADC, ADC_CLOCK_SETUP_T *ADCSetup, ADC_RESOLUTION_T resolution); + +/** + * @brief Enable or disable the ADC channel on ADC peripheral + * @param pADC : The base of ADC peripheral on the chip + * @param channel : Channel to be enable or disable + * @param NewState : New state, should be: + * - ENABLE + * - DISABLE + * @return Nothing + */ +void Chip_ADC_EnableChannel(LPC_ADC_T *pADC, ADC_CHANNEL_T channel, FunctionalState NewState); + +/** + * @brief Enable burst mode + * @param pADC : The base of ADC peripheral on the chip + * @param NewState : New state, should be: + * - ENABLE + * - DISABLE + * @return Nothing + */ +void Chip_ADC_SetBurstCmd(LPC_ADC_T *pADC, FunctionalState NewState); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(CHIP_LPC1125) */ + +#endif /* __ADC_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/ccand_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/ccand_11xx.h new file mode 100755 index 0000000..820d7c0 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/ccand_11xx.h @@ -0,0 +1,170 @@ +/* + * @brief LPC11xx CCAN ROM API declarations and functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CCAND_11XX_H_ +#define __CCAND_11XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup CCANROM_11XX CHIP: LPC11xx CCAN ROM Driver + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +/** + * CCAN ROM error status bits + */ +#define CAN_ERROR_NONE 0x00000000UL +#define CAN_ERROR_PASS 0x00000001UL +#define CAN_ERROR_WARN 0x00000002UL +#define CAN_ERROR_BOFF 0x00000004UL +#define CAN_ERROR_STUF 0x00000008UL +#define CAN_ERROR_FORM 0x00000010UL +#define CAN_ERROR_ACK 0x00000020UL +#define CAN_ERROR_BIT1 0x00000040UL +#define CAN_ERROR_BIT0 0x00000080UL +#define CAN_ERROR_CRC 0x00000100UL + +/** + * CCAN ROM control bits for CAN_MSG_OBJ.mode_id + */ +#define CAN_MSGOBJ_STD 0x00000000UL /* CAN 2.0a 11-bit ID */ +#define CAN_MSGOBJ_EXT 0x20000000UL /* CAN 2.0b 29-bit ID */ +#define CAN_MSGOBJ_DAT 0x00000000UL /* data frame */ +#define CAN_MSGOBJ_RTR 0x40000000UL /* rtr frame */ + +typedef struct CCAN_MSG_OBJ { + uint32_t mode_id; + uint32_t mask; + uint8_t data[8]; + uint8_t dlc; + uint8_t msgobj; +} CCAN_MSG_OBJ_T; + +/************************************************************************** + SDO Abort Codes +**************************************************************************/ +#define SDO_ABORT_TOGGLE 0x05030000UL // Toggle bit not alternated +#define SDO_ABORT_SDOTIMEOUT 0x05040000UL // SDO protocol timed out +#define SDO_ABORT_UNKNOWN_COMMAND 0x05040001UL // Client/server command specifier not valid or unknown +#define SDO_ABORT_UNSUPPORTED 0x06010000UL // Unsupported access to an object +#define SDO_ABORT_WRITEONLY 0x06010001UL // Attempt to read a write only object +#define SDO_ABORT_READONLY 0x06010002UL // Attempt to write a read only object +#define SDO_ABORT_NOT_EXISTS 0x06020000UL // Object does not exist in the object dictionary +#define SDO_ABORT_PARAINCOMP 0x06040043UL // General parameter incompatibility reason +#define SDO_ABORT_ACCINCOMP 0x06040047UL // General internal incompatibility in the device +#define SDO_ABORT_TYPEMISMATCH 0x06070010UL // Data type does not match, length of service parameter does not match +#define SDO_ABORT_UNKNOWNSUB 0x06090011UL // Sub-index does not exist +#define SDO_ABORT_VALUE_RANGE 0x06090030UL // Value range of parameter exceeded (only for write access) +#define SDO_ABORT_TRANSFER 0x08000020UL // Data cannot be transferred or stored to the application +#define SDO_ABORT_LOCAL 0x08000021UL // Data cannot be transferred or stored to the application because of local control +#define SDO_ABORT_DEVSTAT 0x08000022UL // Data cannot be transferred or stored to the application because of the present device state + +typedef struct CCAN_ODCONSTENTRY { + uint16_t index; + uint8_t subindex; + uint8_t len; + uint32_t val; +} CCAN_ODCONSTENTRY_T; + +// upper-nibble values for CAN_ODENTRY.entrytype_len +#define OD_NONE 0x00 // Object Dictionary entry doesn't exist +#define OD_EXP_RO 0x10 // Object Dictionary entry expedited, read-only +#define OD_EXP_WO 0x20 // Object Dictionary entry expedited, write-only +#define OD_EXP_RW 0x30 // Object Dictionary entry expedited, read-write +#define OD_SEG_RO 0x40 // Object Dictionary entry segmented, read-only +#define OD_SEG_WO 0x50 // Object Dictionary entry segmented, write-only +#define OD_SEG_RW 0x60 // Object Dictionary entry segmented, read-write + +typedef struct CCAN_ODENTRY { + uint16_t index; + uint8_t subindex; + uint8_t entrytype_len; + uint8_t *val; +} CCAN_ODENTRY_T; + +typedef struct CCAN_CANOPENCFG { + uint8_t node_id; + uint8_t msgobj_rx; + uint8_t msgobj_tx; + uint8_t isr_handled; + uint32_t od_const_num; + CCAN_ODCONSTENTRY_T *od_const_table; + uint32_t od_num; + CCAN_ODENTRY_T *od_table; +} CCAN_CANOPENCFG_T; + +// Return values for CANOPEN_sdo_req() callback +#define CAN_SDOREQ_NOTHANDLED 0 // process regularly, no impact +#define CAN_SDOREQ_HANDLED_SEND 1 // processed in callback, auto-send returned msg +#define CAN_SDOREQ_HANDLED_NOSEND 2 // processed in callback, don't send response + +// Values for CANOPEN_sdo_seg_read/write() callback 'openclose' parameter +#define CAN_SDOSEG_SEGMENT 0 // segment read/write +#define CAN_SDOSEG_OPEN 1 // channel is opened +#define CAN_SDOSEG_CLOSE 2 // channel is closed + +typedef struct CCAN_CALLBACKS { + void (*CAN_rx)(uint8_t msg_obj_num); + void (*CAN_tx)(uint8_t msg_obj_num); + void (*CAN_error)(uint32_t error_info); + uint32_t (*CANOPEN_sdo_read)(uint16_t index, uint8_t subindex); + uint32_t (*CANOPEN_sdo_write)(uint16_t index, uint8_t subindex, uint8_t *dat_ptr); + uint32_t (*CANOPEN_sdo_seg_read)(uint16_t index, uint8_t subindex, uint8_t openclose, uint8_t *length, + uint8_t *data, uint8_t *last); + uint32_t (*CANOPEN_sdo_seg_write)(uint16_t index, uint8_t subindex, uint8_t openclose, uint8_t length, + uint8_t *data, uint8_t *fast_resp); + uint8_t (*CANOPEN_sdo_req)(uint8_t length_req, uint8_t *req_ptr, uint8_t *length_resp, uint8_t *resp_ptr); +} CCAN_CALLBACKS_T; + +typedef struct CCAN_API { + void (*init_can)(uint32_t *can_cfg, uint8_t isr_ena); + void (*isr)(void); + void (*config_rxmsgobj)(CCAN_MSG_OBJ_T *msg_obj); + uint8_t (*can_receive)(CCAN_MSG_OBJ_T *msg_obj); + void (*can_transmit)(CCAN_MSG_OBJ_T *msg_obj); + void (*config_canopen)(CCAN_CANOPENCFG_T *canopen_cfg); + void (*canopen_handler)(void); + void (*config_calb)(CCAN_CALLBACKS_T *callback_cfg); +} CCAN_API_T; + +#define LPC_CCAN_API ((CCAN_API_T *) (LPC_ROM_API->candApiBase)) +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CCAND_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/chip.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/chip.h new file mode 100755 index 0000000..9d4951d --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/chip.h @@ -0,0 +1,309 @@ +/* + * @brief LPC11xx basic chip inclusion file + * + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CHIP_H_ +#define __CHIP_H_ + +#include "lpc_types.h" +#include "sys_config.h" +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CORE_M0 +#error CORE_M0 is not defined for the LPC11xx architecture +#error CORE_M0 should be defined as part of your compiler define list +#endif + +#if !defined(ENABLE_UNTESTED_CODE) +#if defined(CHIP_LPC110X) +#warning The LCP110X code has not been tested with a platform. This code should \ +build without errors but may not work correctly for the device. To disable this \ +#warning message, define ENABLE_UNTESTED_CODE. +#endif +#if defined(CHIP_LPC11XXLV) +#warning The LPC11XXLV code has not been tested with a platform. This code should \ +build without errors but may not work correctly for the device. To disable this \ +#warning message, define ENABLE_UNTESTED_CODE. +#endif +#if defined(CHIP_LPC11AXX) +#warning The LPC11AXX code has not been tested with a platform. This code should \ +build without errors but may not work correctly for the device. To disable this \ +#warning message, define ENABLE_UNTESTED_CODE. +#endif +#if defined(CHIP_LPC11EXX) +#warning The LPC11EXX code has not been tested with a platform. This code should \ +build without errors but may not work correctly for the device. To disable this \ +warning message, define ENABLE_UNTESTED_CODE. +#endif +#endif + +#if !defined(CHIP_LPC110X) && !defined(CHIP_LPC11XXLV) && !defined(CHIP_LPC11AXX) && \ + !defined(CHIP_LPC11CXX) && !defined(CHIP_LPC11EXX) && !defined(CHIP_LPC11UXX) && \ + !defined(CHIP_LPC1125) +#error CHIP_LPC110x/CHIP_LPC11XXLV/CHIP_LPC11AXX/CHIP_LPC11CXX/CHIP_LPC11EXX/CHIP_LPC11UXX/CHIP_LPC1125 is not defined! +#endif + +/* Peripheral mapping per device + Peripheral Device(s) + ---------------------------- ------------------------------------------------------------------------------------------------------------- + I2C(40000000) CHIP_LPC11XXLV/ CHIP_LPC11CXX/ CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX CHIP_LPC1125 + WDT(40004000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX/ CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX CHIP_LPC1125 + UART0(40008000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX CHIP_LPC1125 + UART1(40020000) CHIP_LPC1125 + UART2(40024000) CHIP_LPC1125 + USART/SMARTCARD(40008000) CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX + TIMER0_16(4000C000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX/ CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX CHIP_LPC1125 + TIMER1_16(40010000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX/ CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX CHIP_LPC1125 + TIMER0_32(40014000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX/ CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX CHIP_LPC1125 + TIMER1_32(40018000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX/ CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX CHIP_LPC1125 + ADC(4001C000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX/ CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX CHIP_LPC1125 + DAC(40024000) CHIP_LPC11AXX + ACMP(40028000) CHIP_LPC11AXX + PMU(40038000) CHIP_LPC110x/ CHIP_LPC11CXX/ CHIP_LPC11UXX/ CHIP_LPC11EXX CHIP_LPC1125 + FLASH_CTRL(4003C000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX/ CHIP_LPC11UXX CHIP_LPC1125 + FLASH_EEPROM(4003C000) CHIP_LPC11EXX/ CHIP_LPC11AXX + SPI0(40040000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX + SSP0(40040000) CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX CHIP_LPC1125 + IOCONF(40044000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX/ CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX CHIP_LPC1125 + SYSCON(40048000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX/ CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX CHIP_LPC1125 + GPIOINTS(4004C000) CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX + USB(40080000) CHIP_LPC11UXX + CCAN(40050000) CHIP_LPC11CXX + SPI1(40058000) CHIP_LPC11CXX + SSP1(40058000) CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX CHIP_LPC1125 + GPIO_GRP0_INT(4005C000) CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX + GPIO_GRP1_INT(40060000) CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX + GPIO_PORT(50000000) CHIP_LPC11UXX/ CHIP_LPC11EXX/ CHIP_LPC11AXX + GPIO_PIO0(50000000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX CHIP_LPC1125 + GPIO_PIO1(50010000) CHIP_LPC110x/ CHIP_LPC11XXLV/ CHIP_LPC11CXX CHIP_LPC1125 + GPIO_PIO2(50020000) CHIP_LPC11XXLV/ CHIP_LPC11CXX CHIP_LPC1125 + GPIO_PIO3(50030000) CHIP_LPC11XXLV/ CHIP_LPC11CXX CHIP_LPC1125 + */ + +/** @defgroup PERIPH_11XX_BASE CHIP: LPC11xx Peripheral addresses and register set declarations + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +#define LPC_I2C_BASE 0x40000000 +#define LPC_WWDT_BASE 0x40004000 +#define LPC_USART_BASE 0x40008000 +#define LPC_TIMER16_0_BASE 0x4000C000 +#define LPC_TIMER16_1_BASE 0x40010000 +#define LPC_TIMER32_0_BASE 0x40014000 +#define LPC_TIMER32_1_BASE 0x40018000 +#define LPC_ADC_BASE 0x4001C000 +#define LPC_DAC_BASE 0x40024000 +#define LPC_ACMP_BASE 0x40028000 +#define LPC_PMU_BASE 0x40038000 +#define LPC_FLASH_BASE 0x4003C000 +#define LPC_SSP0_BASE 0x40040000 +#define LPC_IOCON_BASE 0x40044000 +#define LPC_SYSCTL_BASE 0x40048000 +#define LPC_USB0_BASE 0x40080000 +#define LPC_CAN0_BASE 0x40050000 +#define LPC_SSP1_BASE 0x40058000 +#if defined(CHIP_LPC1125) +#define LPC_USART1_BASE 0x40020000 +#define LPC_USART2_BASE 0x40024000 +#endif +#if defined(CHIP_LPC11UXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11AXX) +#define LPC_GPIO_PIN_INT_BASE 0x4004C000 +#define LPC_GPIO_GROUP_INT0_BASE 0x4005C000 +#define LPC_GPIO_GROUP_INT1_BASE 0x40060000 +#define LPC_GPIO_PORT_BASE 0x50000000 +#else +#define LPC_GPIO_PORT0_BASE 0x50000000 +#define LPC_GPIO_PORT1_BASE 0x50010000 +#if defined(CHIP_LPC11XXLV) || defined(CHIP_LPC11CXX) || defined(CHIP_LPC1125) +#define LPC_GPIO_PORT2_BASE 0x50020000 +#define LPC_GPIO_PORT3_BASE 0x50030000 +#endif /* defined(CHIP_LPC11XXLV) || defined(CHIP_LPC11CXX) || defined(CHIP_LPC1125) */ +#endif /* defined(CHIP_LPC11UXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11AXX) */ +#define IAP_ENTRY_LOCATION 0X1FFF1FF1 +#define LPC_ROM_API_BASE_LOC 0x1FFF1FF8 + +#if !defined(CHIP_LPC110x) +#define LPC_I2C ((LPC_I2C_T *) LPC_I2C_BASE) +#endif + +#define LPC_WWDT ((LPC_WWDT_T *) LPC_WWDT_BASE) +#define LPC_USART ((LPC_USART_T *) LPC_USART_BASE) +#define LPC_TIMER16_0 ((LPC_TIMER_T *) LPC_TIMER16_0_BASE) +#define LPC_TIMER16_1 ((LPC_TIMER_T *) LPC_TIMER16_1_BASE) +#define LPC_TIMER32_0 ((LPC_TIMER_T *) LPC_TIMER32_0_BASE) +#define LPC_TIMER32_1 ((LPC_TIMER_T *) LPC_TIMER32_1_BASE) +#define LPC_ADC ((LPC_ADC_T *) LPC_ADC_BASE) + +#if defined(CHIP_LPC1125) +#define LPC_USART0 LPC_USART +#define LPC_USART1 ((LPC_USART_T *) LPC_USART1_BASE) +#define LPC_USART2 ((LPC_USART_T *) LPC_USART2_BASE) +#endif + +#if defined(CHIP_LPC11AXX) +#define LPC_DAC ((LPC_DAC_T *) LPC_DAC_BASE) +#define LPC_CMP ((LPC_CMP_T *) LPC_ACMP_BASE) +#endif + +#define LPC_PMU ((LPC_PMU_T *) LPC_PMU_BASE) +#define LPC_FMC ((LPC_FMC_T *) LPC_FLASH_BASE) +#define LPC_SSP0 ((LPC_SSP_T *) LPC_SSP0_BASE) +#define LPC_IOCON ((LPC_IOCON_T *) LPC_IOCON_BASE) +#define LPC_SYSCTL ((LPC_SYSCTL_T *) LPC_SYSCTL_BASE) +#if defined(CHIP_LPC11CXX) || defined(CHIP_LPC11UXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11AXX) || defined(CHIP_LPC1125) +#define LPC_SSP1 ((LPC_SSP_T *) LPC_SSP1_BASE) +#endif +#define LPC_USB ((LPC_USB_T *) LPC_USB0_BASE) + +#if defined(CHIP_LPC11UXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11AXX) +#define LPC_PININT ((LPC_PIN_INT_T *) LPC_GPIO_PIN_INT_BASE) +#define LPC_GPIOGROUP ((LPC_GPIOGROUPINT_T *) LPC_GPIO_GROUP_INT0_BASE) +#define LPC_GPIO ((LPC_GPIO_T *) LPC_GPIO_PORT_BASE) +#else +#define LPC_GPIO ((LPC_GPIO_T *) LPC_GPIO_PORT0_BASE) +#endif + +#define LPC_ROM_API (*((LPC_ROM_API_T * *) LPC_ROM_API_BASE_LOC)) + + +/** + * @} + */ + +/** @ingroup CHIP_11XX_DRIVER_OPTIONS + */ + +/** + * @brief System oscillator rate + * This value is defined externally to the chip layer and contains + * the value in Hz for the external oscillator for the board. If using the + * internal oscillator, this rate can be 0. + */ +extern const uint32_t OscRateIn; + +/** + * @} + */ + +/** @ingroup CHIP_11XX_DRIVER_OPTIONS + */ + +/** + * @brief Clock rate on the CLKIN pin + * This value is defined externally to the chip layer and contains + * the value in Hz for the CLKIN pin for the board. If this pin isn't used, + * this rate can be 0. + */ +extern const uint32_t ExtRateIn; + +/** + * @} + */ + +#include "pmu_11xx.h" +#include "fmc_11xx.h" +#include "sysctl_11xx.h" +#include "clock_11xx.h" +#include "iocon_11xx.h" +#include "timer_11xx.h" +#include "uart_11xx.h" +#include "wwdt_11xx.h" +#include "ssp_11xx.h" +#include "romapi_11xx.h" + +#if !defined(CHIP_LPC1125) +/* All LPC1xx devices except the LPC1125 */ +#include "adc_11xx.h" + +#else +/* LPC1125 has different IP than other LPC11xx devices */ +#include "adc_1125.h" +#endif + +/* Different GPIO/GPIOGROUP/PININT blocks for parts with similar numbers */ +#if defined(CHIP_LPC11CXX) || defined(CHIP_LPC110X) || defined(CHIP_LPC11XXLV) || defined(CHIP_LPC1125) +#include "gpio_11xx_2.h" +#else +#include "gpio_11xx_1.h" +#include "gpiogroup_11xx.h" +#include "pinint_11xx.h" +#endif + +/* Family specific drivers */ +#if defined(CHIP_LPC11AXX) +#include "acmp_11xx.h" +#include "dac_11xx.h" +#endif +#if !defined(CHIP_LPC110X) +#include "i2c_11xx.h" +#endif +#if defined(CHIP_LPC11CXX) +#include "ccand_11xx.h" +#endif +#if defined(CHIP_LPC11UXX) +#include "usbd_11xx.h" +#endif + +/** @defgroup SUPPORT_11XX_FUNC CHIP: LPC11xx support functions + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +/** + * @brief Current system clock rate, mainly used for sysTick + */ +extern uint32_t SystemCoreClock; + +/** + * @brief Update system core clock rate, should be called if the + * system has a clock rate change + * @return None + */ +void SystemCoreClockUpdate(void); + +/** + * @brief Set up and initialize hardware prior to call to main() + * @return None + * @note Chip_SystemInit() is called prior to the application and sets up + * system clocking prior to the application starting. + */ +void Chip_SystemInit(void); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CHIP_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/clock_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/clock_11xx.h new file mode 100755 index 0000000..e19ae6e --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/clock_11xx.h @@ -0,0 +1,547 @@ +/* + * @brief LPC11XX Clock control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CLOCK_11XX_H_ +#define __CLOCK_11XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup CLOCK_11XX CHIP: LPC11xx Clock Control block driver + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +/** Internal oscillator frequency */ +#define SYSCTL_IRC_FREQ (12000000) + +/** + * @brief Set System PLL divider values + * @param msel : PLL feedback divider value. M = msel + 1. + * @param psel : PLL post divider value. P = (1<SYSPLLCTRL = (msel & 0x1F) | ((psel & 0x3) << 5); +} + +/** + * @brief Read System PLL lock status + * @return true of the PLL is locked. false if not locked + */ +STATIC INLINE bool Chip_Clock_IsSystemPLLLocked(void) +{ + return (bool) ((LPC_SYSCTL->SYSPLLSTAT & 1) != 0); +} + +/** + * Clock sources for system and USB PLLs + */ +typedef enum CHIP_SYSCTL_PLLCLKSRC { + SYSCTL_PLLCLKSRC_IRC = 0, /*!< Internal oscillator in */ + SYSCTL_PLLCLKSRC_MAINOSC, /*!< Crystal (main) oscillator in */ +#if defined(CHIP_LPC11AXX) + SYSCTL_PLLCLKSRC_EXT_CLKIN, /*!< External clock in (11Axx only) */ +#else + SYSCTL_PLLCLKSRC_RESERVED1, /*!< Reserved */ +#endif + SYSCTL_PLLCLKSRC_RESERVED2, /*!< Reserved */ +} CHIP_SYSCTL_PLLCLKSRC_T; + +/** + * @brief Set System PLL clock source + * @param src : Clock source for system PLL + * @return Nothing + * @note This function will also toggle the clock source update register + * to update the clock source. + */ +void Chip_Clock_SetSystemPLLSource(CHIP_SYSCTL_PLLCLKSRC_T src); + +#if defined(CHIP_LPC11UXX) +/** + * @brief Set USB PLL divider values + * @param msel : PLL feedback divider value. M = msel + 1. + * @param psel : PLL post divider value. P = (1<USBPLLCTRL = (msel & 0x1F) | ((psel & 0x3) << 5); +} + +/** + * @brief Read USB PLL lock status + * @return true of the PLL is locked. false if not locked + */ +STATIC INLINE bool Chip_Clock_IsUSBPLLLocked(void) +{ + return (bool) ((LPC_SYSCTL->USBPLLSTAT & 1) != 0); +} + +/** + * @brief Set USB PLL clock source + * @param src : Clock source for USB PLL + * @return Nothing + * @note This function will also toggle the clock source update register + * to update the clock source. + */ +void Chip_Clock_SetUSBPLLSource(CHIP_SYSCTL_PLLCLKSRC_T src); + +#endif /*defined(CHIP_LPC11UXX)*/ + +/** + * @brief Bypass System Oscillator and set oscillator frequency range + * @param bypass : Flag to bypass oscillator + * @param highfr : Flag to set oscillator range from 15-25 MHz + * @return Nothing + * @note Sets the PLL input to bypass the oscillator. This would be + * used if an external clock that is not an oscillator is attached + * to the XTALIN pin. + */ +void Chip_Clock_SetPLLBypass(bool bypass, bool highfr); + +/** + * Watchdog and low frequency oscillator frequencies plus or minus 40% + */ +typedef enum CHIP_WDTLFO_OSC { + WDTLFO_OSC_ILLEGAL, + WDTLFO_OSC_0_60, /*!< 0.6 MHz watchdog/LFO rate */ + WDTLFO_OSC_1_05, /*!< 1.05 MHz watchdog/LFO rate */ + WDTLFO_OSC_1_40, /*!< 1.4 MHz watchdog/LFO rate */ + WDTLFO_OSC_1_75, /*!< 1.75 MHz watchdog/LFO rate */ + WDTLFO_OSC_2_10, /*!< 2.1 MHz watchdog/LFO rate */ + WDTLFO_OSC_2_40, /*!< 2.4 MHz watchdog/LFO rate */ + WDTLFO_OSC_2_70, /*!< 2.7 MHz watchdog/LFO rate */ + WDTLFO_OSC_3_00, /*!< 3.0 MHz watchdog/LFO rate */ + WDTLFO_OSC_3_25, /*!< 3.25 MHz watchdog/LFO rate */ + WDTLFO_OSC_3_50, /*!< 3.5 MHz watchdog/LFO rate */ + WDTLFO_OSC_3_75, /*!< 3.75 MHz watchdog/LFO rate */ + WDTLFO_OSC_4_00, /*!< 4.0 MHz watchdog/LFO rate */ + WDTLFO_OSC_4_20, /*!< 4.2 MHz watchdog/LFO rate */ + WDTLFO_OSC_4_40, /*!< 4.4 MHz watchdog/LFO rate */ + WDTLFO_OSC_4_60 /*!< 4.6 MHz watchdog/LFO rate */ +} CHIP_WDTLFO_OSC_T; + +/** + * @brief Setup Watchdog oscillator rate and divider + * @param wdtclk : Selected watchdog clock rate + * @param div : Watchdog divider value, even value between 2 and 64 + * @return Nothing + * @note Watchdog rate = selected rate divided by divider rate + */ +STATIC INLINE void Chip_Clock_SetWDTOSC(CHIP_WDTLFO_OSC_T wdtclk, uint8_t div) +{ + LPC_SYSCTL->WDTOSCCTRL = (((uint32_t) wdtclk) << 5) | ((div >> 1) - 1); +} + +#if defined(CHIP_LPC11AXX) +/** + * @brief Setup low frequency oscillator rate and divider + * @param lfoclk : Selected low frequency clock rate + * @param div : Low frequency divider value, even value between 2 and 64 + * @return Nothing + * @note Low frequency oscillator rate = selected rate divided by divider rate + */ +STATIC INLINE void Chip_Clock_SetLFOSC(CHIP_WDTLFO_OSC_T lfoclk, uint8_t div) +{ + LPC_SYSCTL->LFOSCCTRL = (((uint32_t) lfoclk) << 5) | ((div >> 1) - 1); +} + +#endif /*CHIP_LPC11AXX*/ + +/** + * Clock sources for main system clock + */ +typedef enum CHIP_SYSCTL_MAINCLKSRC { + SYSCTL_MAINCLKSRC_IRC = 0, /*!< Internal oscillator */ + SYSCTL_MAINCLKSRC_PLLIN, /*!< System PLL input */ + SYSCTL_MAINCLKSRC_LFOSC, /*!< LF oscillator rate (11Axx only) */ + SYSCTL_MAINCLKSRC_WDTOSC = SYSCTL_MAINCLKSRC_LFOSC, /*!< Watchdog oscillator rate */ + SYSCTL_MAINCLKSRC_PLLOUT, /*!< System PLL output */ +} CHIP_SYSCTL_MAINCLKSRC_T; + +/** + * @brief Set main system clock source + * @param src : Clock source for main system + * @return Nothing + * @note This function will also toggle the clock source update register + * to update the clock source. + */ +void Chip_Clock_SetMainClockSource(CHIP_SYSCTL_MAINCLKSRC_T src); + +/** + * @brief Returns the main clock source + * @return Which clock is used for the core clock source? + */ +STATIC INLINE CHIP_SYSCTL_MAINCLKSRC_T Chip_Clock_GetMainClockSource(void) +{ + return (CHIP_SYSCTL_MAINCLKSRC_T) (LPC_SYSCTL->MAINCLKSEL); +} + +/** + * @brief Set system clock divider + * @param div : divider for system clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The system clock + * rate is the main system clock divided by this value. + */ +STATIC INLINE void Chip_Clock_SetSysClockDiv(uint32_t div) +{ + LPC_SYSCTL->SYSAHBCLKDIV = div; +} + +/** + * System and peripheral clocks + */ +typedef enum CHIP_SYSCTL_CLOCK { + SYSCTL_CLOCK_SYS = 0, /*!< 0: System clock */ + SYSCTL_CLOCK_ROM, /*!<1: ROM clock */ + SYSCTL_CLOCK_RAM, /*!< 2: RAM clock */ + SYSCTL_CLOCK_FLASHREG, /*!< 3: FLASH register interface clock */ + SYSCTL_CLOCK_FLASHARRAY, /*!< 4: FLASH array access clock */ +#if defined(CHIP_LPC110X) + SYSCTL_CLOCK_RESERVED5, /*!< 5: Reserved */ +#else + SYSCTL_CLOCK_I2C, /*!< 5: I2C clock, not on LPC110x */ +#endif + SYSCTL_CLOCK_GPIO, /*!< 6: GPIO clock */ + SYSCTL_CLOCK_CT16B0, /*!< 7: 16-bit Counter/timer 0 clock */ + SYSCTL_CLOCK_CT16B1, /*!< 8: 16-bit Counter/timer 1 clock */ + SYSCTL_CLOCK_CT32B0, /*!< 9: 32-bit Counter/timer 0 clock */ + SYSCTL_CLOCK_CT32B1, /*!< 10: 32-bit Counter/timer 1 clock */ + SYSCTL_CLOCK_SSP0, /*!< 11: SSP0 clock */ + SYSCTL_CLOCK_UART0, /*!< 12: UART0 clock */ + SYSCTL_CLOCK_ADC, /*!< 13: ADC clock */ +#if defined(CHIP_LPC11UXX) + SYSCTL_CLOCK_USB, /*!< 14: USB clock, LPC11Uxx only */ +#else + SYSCTL_CLOCK_RESERVED14, /*!< 14: Reserved */ +#endif + SYSCTL_CLOCK_WDT, /*!< 15: Watchdog timer clock */ + SYSCTL_CLOCK_IOCON, /*!< 16: IOCON block clock */ +#if defined(CHIP_LPC11CXX) + SYSCTL_CLOCK_CAN, /*!< 17: CAN clock, LPC11Cxx only */ +#else + SYSCTL_CLOCK_RESERVED17, /*!< 17: Reserved */ +#endif +#if !(defined(CHIP_LPC110X) || defined(CHIP_LPC11XXLV)) + SYSCTL_CLOCK_SSP1, /*!< 18: SSP1 clock, LPC11A/C/E/Uxx//1125 only */ +#if !defined(CHIP_LPC11CXX) + SYSCTL_CLOCK_PINT, /*!< 19: GPIO Pin int register interface clock, LPC11A/E/Uxx only */ +#if defined(CHIP_LPC11AXX) + SYSCTL_CLOCK_ACOMP, /*!< 20: Analog comparator clock, LPC11Axx only */ + SYSCTL_CLOCK_DAC, /*!< 21: DAC clock, LPC11Axx only */ +#else + SYSCTL_CLOCK_RESERVED20, /*!< 20: Reserved */ + SYSCTL_CLOCK_RESERVED21, /*!< 21: Reserved */ +#endif + SYSCTL_CLOCK_RESERVED22, /*!< 22: Reserved */ + SYSCTL_CLOCK_P0INT, /*!< 23: GPIO GROUP1 interrupt register clock, LPC11Axx only */ + SYSCTL_CLOCK_GROUP0INT = SYSCTL_CLOCK_P0INT,/*!< 23: GPIO GROUP0 interrupt register interface clock, LPC11E/Uxx only */ + SYSCTL_CLOCK_P1INT, /*!< 24: GPIO GROUP1 interrupt register clock, LPC11Axx only */ + SYSCTL_CLOCK_GROUP1INT = SYSCTL_CLOCK_P1INT,/*!< 24: GPIO GROUP1 interrupt register interface clock, LPC11E/Uxx only */ + SYSCTL_CLOCK_RESERVED25, /*!< 25: Reserved */ +#if defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) + SYSCTL_CLOCK_RAM1, /*!< 26: SRAM block (0x20000000) clock, LPC11E/Uxx only */ +#else + SYSCTL_CLOCK_RESERVED26, /*!< 26: Reserved */ +#endif +#if defined(CHIP_LPC11UXX) + SYSCTL_CLOCK_USBRAM, /*!< 27: USB SRAM block clock, LPC11Uxx only */ +#else + SYSCTL_CLOCK_RESERVED27, /*!< 27: Reserved */ +#endif +#endif /* !defined(CHIP_LPC11CXX) */ +#endif /* !(defined(CHIP_LPC110X) || defined(CHIP_LPC11XXLV)) */ +} CHIP_SYSCTL_CLOCK_T; + +/** + * @brief Enable a system or peripheral clock + * @param clk : Clock to enable + * @return Nothing + */ +STATIC INLINE void Chip_Clock_EnablePeriphClock(CHIP_SYSCTL_CLOCK_T clk) +{ + LPC_SYSCTL->SYSAHBCLKCTRL |= (1 << clk); +} + +/** + * @brief Disable a system or peripheral clock + * @param clk : Clock to disable + * @return Nothing + */ +STATIC INLINE void Chip_Clock_DisablePeriphClock(CHIP_SYSCTL_CLOCK_T clk) +{ + LPC_SYSCTL->SYSAHBCLKCTRL &= ~(1 << clk); +} + +/** + * @brief Set SSP0 divider + * @param div : divider for SSP0 clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The SSP0 clock + * rate is the main system clock divided by this value. + */ +STATIC INLINE void Chip_Clock_SetSSP0ClockDiv(uint32_t div) +{ + LPC_SYSCTL->SSP0CLKDIV = div; +} + +/** + * @brief Return SSP0 divider + * @return divider for SSP0 clock + * @note A value of 0 means the clock is disabled. + */ +STATIC INLINE uint32_t Chip_Clock_GetSSP0ClockDiv(void) +{ + return LPC_SYSCTL->SSP0CLKDIV; +} + +/** + * @brief Set UART divider clock + * @param div : divider for UART clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The UART clock + * rate is the main system clock divided by this value. + */ +STATIC INLINE void Chip_Clock_SetUARTClockDiv(uint32_t div) +{ + LPC_SYSCTL->USARTCLKDIV = div; +} + +/** + * @brief Return UART divider + * @return divider for UART clock + * @note A value of 0 means the clock is disabled. + */ +STATIC INLINE uint32_t Chip_Clock_GetUARTClockDiv(void) +{ + return LPC_SYSCTL->USARTCLKDIV; +} + +#if defined(CHIP_LPC11CXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11AXX) || defined(CHIP_LPC11UXX) || defined(CHIP_LPC1125) +/** + * @brief Set SSP1 divider clock + * @param div : divider for SSP1 clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The SSP1 clock + * rate is the main system clock divided by this value. + */ +STATIC INLINE void Chip_Clock_SetSSP1ClockDiv(uint32_t div) +{ + LPC_SYSCTL->SSP1CLKDIV = div; +} + +/** + * @brief Return SSP1 divider + * @return divider for SSP1 clock + * @note A value of 0 means the clock is disabled. + */ +STATIC INLINE uint32_t Chip_Clock_GetSSP1ClockDiv(void) +{ + return LPC_SYSCTL->SSP1CLKDIV; +} + +#endif /*defined(CHIP_LPC11CXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11AXX) || defined(CHIP_LPC11UXX)*/ + +#if defined(CHIP_LPC11UXX) +/** + * Clock sources for USB + */ +typedef enum CHIP_SYSCTL_USBCLKSRC { + SYSCTL_USBCLKSRC_PLLOUT = 0, /*!< USB PLL out */ + SYSCTL_USBCLKSRC_MAINSYSCLK, /*!< Main system clock */ +} CHIP_SYSCTL_USBCLKSRC_T; + +/** + * @brief Set USB clock source and divider + * @param src : Clock source for USB + * @param div : divider for USB clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The USB clock + * rate is either the main system clock or USB PLL output clock divided + * by this value. This function will also toggle the clock source + * update register to update the clock source. + */ +void Chip_Clock_SetUSBClockSource(CHIP_SYSCTL_USBCLKSRC_T src, uint32_t div); + +#endif /*CHIP_LPC11UXX*/ + +#if defined(CHIP_LPC110X) || defined(CHIP_LPC11XXLV) || defined(CHIP_LPC11CXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC1125) +/** + * Clock sources for WDT + */ +typedef enum CHIP_SYSCTL_WDTCLKSRC { + SYSCTL_WDTCLKSRC_IRC = 0, /*!< Internal oscillator for watchdog clock */ + SYSCTL_WDTCLKSRC_MAINSYSCLK, /*!< Main system clock for watchdog clock */ + SYSCTL_WDTCLKSRC_WDTOSC, /*!< Watchdog oscillator for watchdog clock */ +} CHIP_SYSCTL_WDTCLKSRC_T; + +/** + * @brief Set WDT clock source and divider + * @param src : Clock source for WDT + * @param div : divider for WDT clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The WDT clock + * rate is the clock source divided by the divider. This function will + * also toggle the clock source update register to update the clock + * source. + */ +void Chip_Clock_SetWDTClockSource(CHIP_SYSCTL_WDTCLKSRC_T src, uint32_t div); + +#endif + +#if !defined(CHIP_LPC110X) +/** + * Clock sources for CLKOUT + */ +typedef enum CHIP_SYSCTL_CLKOUTSRC { + SYSCTL_CLKOUTSRC_IRC = 0, /*!< Internal oscillator for CLKOUT */ + SYSCTL_CLKOUTSRC_MAINOSC, /*!< Main oscillator for CLKOUT */ + SYSCTL_CLKOUTSRC_WDTOSC, /*!< Watchdog oscillator for CLKOUT */ + SYSCTL_CLKOUTSRC_LFOSC = SYSCTL_CLKOUTSRC_WDTOSC, /*!< LF oscillator rate (LPC11A/Exx only) for CLKOUT */ + SYSCTL_CLKOUTSRC_MAINSYSCLK, /*!< Main system clock for CLKOUT */ +} CHIP_SYSCTL_CLKOUTSRC_T; + +/** + * @brief Set CLKOUT clock source and divider + * @param src : Clock source for CLKOUT + * @param div : divider for CLKOUT clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The CLKOUT clock + * rate is the clock source divided by the divider. This function will + * also toggle the clock source update register to update the clock + * source. + */ +void Chip_Clock_SetCLKOUTSource(CHIP_SYSCTL_CLKOUTSRC_T src, uint32_t div); + +#endif + +/** + * @brief Returns the main oscillator clock rate + * @return main oscillator clock rate + */ +STATIC INLINE uint32_t Chip_Clock_GetMainOscRate(void) +{ + return OscRateIn; +} + +/** + * @brief Returns the internal oscillator (IRC) clock rate + * @return internal oscillator (IRC) clock rate + */ +STATIC INLINE uint32_t Chip_Clock_GetIntOscRate(void) +{ + return SYSCTL_IRC_FREQ; +} + +#if defined(CHIP_LPC11AXX) +/** + * @brief Returns the external clock input rate + * @return internal external clock input rate + * @note LPC11Axx devices only + */ +STATIC INLINE uint32_t Chip_Clock_GetExtClockInRate(void) +{ + return ExtRateIn; +} + +#endif + +/** + * @brief Return estimated watchdog oscillator rate + * @return Estimated watchdog oscillator rate + * @note This rate is accurate to plus or minus 40%. + */ +uint32_t Chip_Clock_GetWDTOSCRate(void); + +#if defined(CHIP_LPC11AXX) +/** + * @brief Return estimated low frequency oscillator rate + * @return Estimated low frequency oscillator rate + * @note This rate is accurate to plus or minus 40%. + */ +uint32_t Chip_Clock_GetLFOOSCRate(void); + +#endif + +/** + * @brief Return System PLL input clock rate + * @return System PLL input clock rate + */ +uint32_t Chip_Clock_GetSystemPLLInClockRate(void); + +/** + * @brief Return System PLL output clock rate + * @return System PLL output clock rate + */ +uint32_t Chip_Clock_GetSystemPLLOutClockRate(void); + +#if defined(CHIP_LPC11UXX) +/** + * @brief Return USB PLL input clock rate + * @return USB PLL input clock rate + */ +uint32_t Chip_Clock_GetUSBPLLInClockRate(void); + +/** + * @brief Return USB PLL output clock rate + * @return USB PLL output clock rate + */ +uint32_t Chip_Clock_GetUSBPLLOutClockRate(void); + +#endif + +/** + * @brief Return main clock rate + * @return main clock rate + */ +uint32_t Chip_Clock_GetMainClockRate(void); + +/** + * @brief Return system clock rate + * @return system clock rate + */ +uint32_t Chip_Clock_GetSystemClockRate(void); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CLOCK_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/cmsis.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/cmsis.h new file mode 100755 index 0000000..81300ff --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/cmsis.h @@ -0,0 +1,64 @@ +/* + * @brief LPC11xx selective CMSIS inclusion file + * + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CMSIS_H_ +#define __CMSIS_H_ + +#include "lpc_types.h" +#include "sys_config.h" + +/* Select correct CMSIS include file based on CHIP_* definition */ +#if defined(CHIP_LPC110X) +#include "cmsis_110x.h" +typedef LPC110X_IRQn_Type IRQn_Type; +#elif defined(CHIP_LPC1125) +#include "cmsis_1125.h" +typedef LPC1125_IRQn_Type IRQn_Type; +#elif defined(CHIP_LPC11AXX) +#include "cmsis_11axx.h" +typedef LPC11AXX_IRQn_Type IRQn_Type; +#elif defined(CHIP_LPC11CXX) +#include "cmsis_11cxx.h" +typedef LPC11CXX_IRQn_Type IRQn_Type; +#elif defined(CHIP_LPC11EXX) +#include "cmsis_11exx.h" +typedef LPC11EXX_IRQn_Type IRQn_Type; +#elif defined(CHIP_LPC11UXX) +#include "cmsis_11uxx.h" +typedef LPC11UXX_IRQn_Type IRQn_Type; +#elif defined(CHIP_LPC11XXLV) +#include "cmsis_11lvxx.h" +typedef LPC11XXLV_IRQn_Type IRQn_Type; +#else +#error "No CHIP_* definition is defined" +#endif + +/* Cortex-M0 processor and core peripherals */ +#include "core_cm0.h" + +#endif /* __CMSIS_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/cmsis_11cxx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/cmsis_11cxx.h new file mode 100755 index 0000000..b906346 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/cmsis_11cxx.h @@ -0,0 +1,152 @@ +/* + * @brief Basic CMSIS include file for LPC11CXX + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CMSIS_11CXX_H_ +#define __CMSIS_11CXX_H_ + +#include "lpc_types.h" +#include "sys_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup CMSIS_11CXX CHIP: LPC11Cxx CMSIS include file + * @ingroup CHIP_11XX_CMSIS_Drivers + * Applies to LPC1111, LPC1112, LPC1113, LPC1114, LPC11D14, LPC1115, + * LPC11C12, LPC11C13, LPC11C22, and LPC11C34 devices. + * @{ + */ + +#if defined(__ARMCC_VERSION) +// Kill warning "#pragma push with no matching #pragma pop" + #pragma diag_suppress 2525 + #pragma push + #pragma anon_unions +#elif defined(__CWCC__) + #pragma push + #pragma cpp_extensions on +#elif defined(__GNUC__) +/* anonymous unions are enabled by default */ +#elif defined(__IAR_SYSTEMS_ICC__) +// #pragma push // FIXME not usable for IAR + #pragma language=extended +#else + #error Not supported compiler type +#endif + +/* + * ========================================================================== + * ---------- Interrupt Number Definition ----------------------------------- + * ========================================================================== + */ + +#if !defined(CHIP_LPC11CXX) +#error Incorrect or missing device variant (CHIP_LPC11AXX) +#endif + +/** @defgroup CMSIS_11CXX_IRQ CHIP_LPC11CXX: LPC11CXX/LPC111X peripheral interrupt numbers + * @{ + */ + +typedef enum LPC11CXX_IRQn { + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Cortex-M0 Hard Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M0 SV Call Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M0 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M0 System Tick Interrupt */ + + PIO0_0_IRQn = 0, /*!< GPIO port 0, pin 0 Interrupt */ + PIO0_1_IRQn = 1, /*!< GPIO port 0, pin 1 Interrupt */ + PIO0_2_IRQn = 2, /*!< GPIO port 0, pin 2 Interrupt */ + PIO0_3_IRQn = 3, /*!< GPIO port 0, pin 3 Interrupt */ + PIO0_4_IRQn = 4, /*!< GPIO port 0, pin 4 Interrupt */ + PIO0_5_IRQn = 5, /*!< GPIO port 0, pin 5 Interrupt */ + PIO0_6_IRQn = 6, /*!< GPIO port 0, pin 6 Interrupt */ + PIO0_7_IRQn = 7, /*!< GPIO port 0, pin 7 Interrupt */ + PIO0_8_IRQn = 8, /*!< GPIO port 0, pin 8 Interrupt */ + PIO0_9_IRQn = 9, /*!< GPIO port 0, pin 9 Interrupt */ + PIO0_10_IRQn = 10, /*!< GPIO port 0, pin 10 Interrupt */ + PIO0_11_IRQn = 11, /*!< GPIO port 0, pin 11 Interrupt */ + PIO1_0_IRQn = 12, /*!< GPIO port 1, pin 0 Interrupt */ + CAN_IRQn = 13, /*!< CAN Interrupt */ + SSP1_IRQn = 14, /*!< SSP1 Interrupt */ + I2C0_IRQn = 15, /*!< I2C Interrupt */ + TIMER_16_0_IRQn = 16, /*!< 16-bit Timer0 Interrupt */ + TIMER_16_1_IRQn = 17, /*!< 16-bit Timer1 Interrupt */ + TIMER_32_0_IRQn = 18, /*!< 32-bit Timer0 Interrupt */ + TIMER_32_1_IRQn = 19, /*!< 32-bit Timer1 Interrupt */ + SSP0_IRQn = 20, /*!< SSP0 Interrupt */ + UART0_IRQn = 21, /*!< UART Interrupt */ + Reserved22_IRQn = 22, + Reserved23_IRQn = 23, + ADC_IRQn = 24, /*!< A/D Converter Interrupt */ + WDT_IRQn = 25, /*!< Watchdog timer Interrupt */ + BOD_IRQn = 26, /*!< Brown Out Detect(BOD) Interrupt */ + Reserved27_IRQn = 27, + EINT3_IRQn = 28, /*!< External Interrupt 3 Interrupt */ + EINT2_IRQn = 29, /*!< External Interrupt 2 Interrupt */ + EINT1_IRQn = 30, /*!< External Interrupt 1 Interrupt */ + EINT0_IRQn = 31, /*!< External Interrupt 0 Interrupt */ +} LPC11CXX_IRQn_Type; + +/** + * @} + */ + +/* + * ========================================================================== + * ----------- Processor and Core Peripheral Section ------------------------ + * ========================================================================== + */ + +/** @defgroup CMSIS_11CXX_COMMON CHIP: LPC11Cxx Cortex CMSIS definitions + * @{ + */ + +/* Configuration of the Cortex-M0 Processor and Core Peripherals */ +#define __MPU_PRESENT 0 /*!< MPU present or not */ +#define __NVIC_PRIO_BITS 2 /*!< Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CMSIS_11CXX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/core_cm0.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/core_cm0.h new file mode 100755 index 0000000..0d7cfd8 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/core_cm0.h @@ -0,0 +1,667 @@ +/**************************************************************************//** + * @file core_cm0.h + * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File + * @version V3.01 + * @date 13. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM0_H_GENERIC +#define __CORE_CM0_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M0 + @{ + */ + +/* CMSIS CM0 definitions */ +#define __CM0_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM0_CMSIS_VERSION_SUB (0x01) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16) | \ + __CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all +*/ +#define __FPU_USED 0 + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ + +#endif /* __CORE_CM0_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0_H_DEPENDANT +#define __CORE_CM0_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0_REV + #define __CM0_REV 0x0000 + #warning "__CM0_REV not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex_M0 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31]; + __IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31]; + __IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31]; + __IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31]; + uint32_t RESERVED4[64]; + __IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + uint32_t RESERVED0; + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IO uint32_t SHP[2]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) + are only accessible over DAP and not via processor. Therefore + they are not covered by the Cortex-M0 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M0 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 ) +#define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) ) +#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) ) + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) | + (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); } + else { + NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) | + (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); } +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M0 system interrupts */ + else { + return((uint32_t)((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#endif /* __CORE_CM0_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/core_cmFunc.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/core_cmFunc.h new file mode 100755 index 0000000..adb07b5 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/core_cmFunc.h @@ -0,0 +1,616 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) ); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) ); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) ); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) ); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) ); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) ); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) ); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all instrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +#endif /* __CORE_CMFUNC_H */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/core_cmInstr.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/core_cmInstr.h new file mode 100755 index 0000000..624c175 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/core_cmInstr.h @@ -0,0 +1,618 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.01 + * @date 06. March 2012 + * + * @note + * Copyright (C) 2009-2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ + uint32_t result; + + __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + + __ASM volatile ("ror %0, %0, %1" : "+r" (op1) : "r" (op2) ); + return(op1); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint8_t result; + + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint16_t result; + + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint8_t result; + + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/error.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/error.h new file mode 100755 index 0000000..be63f81 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/error.h @@ -0,0 +1,134 @@ +/* + * @brief Error code returned by Boot ROM drivers/library functions + * @ingroup Common + * + * This file contains unified error codes to be used across driver, + * middleware, applications, hal and demo software. + * + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __LPC_ERROR_H__ +#define __LPC_ERROR_H__ + +/** Error code returned by Boot ROM drivers/library functions +* +* Error codes are a 32-bit value with : +* - The 16 MSB contains the peripheral code number +* - The 16 LSB contains an error code number associated to that peripheral +* +*/ +typedef enum +{ + /**\b 0x00000000*/ LPC_OK=0, /**< enum value returned on Success */ + /**\b 0xFFFFFFFF*/ ERR_FAILED = -1, /**< enum value returned on general failure */ + /**\b 0xFFFFFFFE*/ ERR_TIME_OUT = -2, /**< enum value returned on general timeout */ + /**\b 0xFFFFFFFD*/ ERR_BUSY = -3, /**< enum value returned when resource is busy */ + + /* ISP related errors */ + ERR_ISP_BASE = 0x00000000, + /*0x00000001*/ ERR_ISP_INVALID_COMMAND = ERR_ISP_BASE + 1, + /*0x00000002*/ ERR_ISP_SRC_ADDR_ERROR, /* Source address not on word boundary */ + /*0x00000003*/ ERR_ISP_DST_ADDR_ERROR, /* Destination address not on word or 256 byte boundary */ + /*0x00000004*/ ERR_ISP_SRC_ADDR_NOT_MAPPED, + /*0x00000005*/ ERR_ISP_DST_ADDR_NOT_MAPPED, + /*0x00000006*/ ERR_ISP_COUNT_ERROR, /* Byte count is not multiple of 4 or is not a permitted value */ + /*0x00000007*/ ERR_ISP_INVALID_SECTOR, + /*0x00000008*/ ERR_ISP_SECTOR_NOT_BLANK, + /*0x00000009*/ ERR_ISP_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION, + /*0x0000000A*/ ERR_ISP_COMPARE_ERROR, + /*0x0000000B*/ ERR_ISP_BUSY, /* Flash programming hardware interface is busy */ + /*0x0000000C*/ ERR_ISP_PARAM_ERROR, /* Insufficient number of parameters */ + /*0x0000000D*/ ERR_ISP_ADDR_ERROR, /* Address not on word boundary */ + /*0x0000000E*/ ERR_ISP_ADDR_NOT_MAPPED, + /*0x0000000F*/ ERR_ISP_CMD_LOCKED, /* Command is locked */ + /*0x00000010*/ ERR_ISP_INVALID_CODE, /* Unlock code is invalid */ + /*0x00000011*/ ERR_ISP_INVALID_BAUD_RATE, + /*0x00000012*/ ERR_ISP_INVALID_STOP_BIT, + /*0x00000013*/ ERR_ISP_CODE_READ_PROTECTION_ENABLED, + + /* ROM API related errors */ + ERR_API_BASE = 0x00010000, + /**\b 0x00010001*/ ERR_API_INVALID_PARAMS = ERR_API_BASE + 1, /**< Invalid parameters*/ + /**\b 0x00010002*/ ERR_API_INVALID_PARAM1, /**< PARAM1 is invalid */ + /**\b 0x00010003*/ ERR_API_INVALID_PARAM2, /**< PARAM2 is invalid */ + /**\b 0x00010004*/ ERR_API_INVALID_PARAM3, /**< PARAM3 is invalid */ + /**\b 0x00010005*/ ERR_API_MOD_INIT, /**< API is called before module init */ + + /* SPIFI API related errors */ + ERR_SPIFI_BASE = 0x00020000, + /*0x00020001*/ ERR_SPIFI_DEVICE_ERROR =ERR_SPIFI_BASE+1, + /*0x00020002*/ ERR_SPIFI_INTERNAL_ERROR, + /*0x00020003*/ ERR_SPIFI_TIMEOUT, + /*0x00020004*/ ERR_SPIFI_OPERAND_ERROR, + /*0x00020005*/ ERR_SPIFI_STATUS_PROBLEM, + /*0x00020006*/ ERR_SPIFI_UNKNOWN_EXT, + /*0x00020007*/ ERR_SPIFI_UNKNOWN_ID, + /*0x00020008*/ ERR_SPIFI_UNKNOWN_TYPE, + /*0x00020009*/ ERR_SPIFI_UNKNOWN_MFG, + + /* Security API related errors */ + ERR_SEC_BASE = 0x00030000, + /*0x00030001*/ ERR_SEC_AES_WRONG_CMD=ERR_SEC_BASE+1, + /*0x00030002*/ ERR_SEC_AES_NOT_SUPPORTED, + /*0x00030003*/ ERR_SEC_AES_KEY_ALREADY_PROGRAMMED, + + + /* USB device stack related errors */ + ERR_USBD_BASE = 0x00040000, + /**\b 0x00040001*/ ERR_USBD_INVALID_REQ = ERR_USBD_BASE + 1, /**< invalid request */ + /**\b 0x00040002*/ ERR_USBD_UNHANDLED, /**< Callback did not process the event */ + /**\b 0x00040003*/ ERR_USBD_STALL, /**< Stall the endpoint on which the call back is called */ + /**\b 0x00040004*/ ERR_USBD_SEND_ZLP, /**< Send ZLP packet on the endpoint on which the call back is called */ + /**\b 0x00040005*/ ERR_USBD_SEND_DATA, /**< Send data packet on the endpoint on which the call back is called */ + /**\b 0x00040006*/ ERR_USBD_BAD_DESC, /**< Bad descriptor*/ + /**\b 0x00040007*/ ERR_USBD_BAD_CFG_DESC,/**< Bad config descriptor*/ + /**\b 0x00040008*/ ERR_USBD_BAD_INTF_DESC,/**< Bad interface descriptor*/ + /**\b 0x00040009*/ ERR_USBD_BAD_EP_DESC,/**< Bad endpoint descriptor*/ + /**\b 0x0004000a*/ ERR_USBD_BAD_MEM_BUF, /**< Bad alignment of buffer passed. */ + /**\b 0x0004000b*/ ERR_USBD_TOO_MANY_CLASS_HDLR, /**< Too many class handlers. */ + + /* CGU related errors */ + ERR_CGU_BASE = 0x00050000, + /*0x00050001*/ ERR_CGU_NOT_IMPL=ERR_CGU_BASE+1, + /*0x00050002*/ ERR_CGU_INVALID_PARAM, + /*0x00050003*/ ERR_CGU_INVALID_SLICE, + /*0x00050004*/ ERR_CGU_OUTPUT_GEN, + /*0x00050005*/ ERR_CGU_DIV_SRC, + /*0x00050006*/ ERR_CGU_DIV_VAL, + /*0x00050007*/ ERR_CGU_SRC + +} ErrorCode_t; + + + +//#define offsetof(s,m) (int)&(((s *)0)->m) +#define COMPILE_TIME_ASSERT(pred) switch(0){case 0:case pred:;} + +#endif /* __LPC_ERROR_H__ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/fmc_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/fmc_11xx.h new file mode 100755 index 0000000..c8ad69a --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/fmc_11xx.h @@ -0,0 +1,101 @@ +/* + * @brief FLASH Memory Controller (FMC) registers and control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __FMC_11XX_H_ +#define __FMC_11XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup FMC_11XX CHIP: LPC11xx FLASH Memory Controller driver + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +/** + * @brief FLASH Memory Controller Unit register block structure + */ +typedef struct {/*!< FMC Structure */ + __I uint32_t RESERVED1[4]; + __IO uint32_t FLASHTIM; + __I uint32_t RESERVED2[3]; + __IO uint32_t FMSSTART; + __IO uint32_t FMSSTOP; + __I uint32_t RESERVED3; + __I uint32_t FMSW[4]; + __I uint32_t RESERVED4[25]; +#if defined(CHIP_LPC1125) + __I uint32_t RESERVED5[977]; +#else + __IO uint32_t EEMSSTART; + __IO uint32_t EEMSSTOP; + __I uint32_t EEMSSIG; + __I uint32_t RESERVED5[974]; +#endif + __I uint32_t FMSTAT; + __I uint32_t RESERVED6; + __O uint32_t FMSTATCLR; +} LPC_FMC_T; + +/** + * @brief FLASH Access time definitions + */ +typedef enum { + FLASHTIM_20MHZ_CPU = 0, /*!< Flash accesses use 1 CPU clocks. Use for up to 20 MHz CPU clock*/ + FLASHTIM_40MHZ_CPU = 1, /*!< Flash accesses use 2 CPU clocks. Use for up to 40 MHz CPU clock*/ + FLASHTIM_50MHZ_CPU = 2, /*!< Flash accesses use 3 CPU clocks. Use for up to 50 MHz CPU clock*/ +} FMC_FLASHTIM_T; + +/** + * @brief Set FLASH access time in clocks + * @param clks : Clock cycles for FLASH access (minus 1) + * @return Nothing + * @note For CPU speed up to 20MHz, use a value of 0. For up to 40MHz, use + * a value of 1. For up to 50MHz, use a value of 2. + */ +STATIC INLINE void Chip_FMC_SetFLASHAccess(FMC_FLASHTIM_T clks) +{ + uint32_t tmp = LPC_FMC->FLASHTIM & (~(0x3)); + + /* Don't alter upper bits */ + LPC_FMC->FLASHTIM = tmp | clks; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __FMC_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/gpio_11xx_2.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/gpio_11xx_2.h new file mode 100755 index 0000000..c25f6d6 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/gpio_11xx_2.h @@ -0,0 +1,642 @@ +/* + * @brief LPC11xx GPIO driver for CHIP_LPC11CXX, CHIP_LPC110X, CHIP_LPC11XXLV, + * and CHIP_LPC1125 families only. + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __GPIO_11XX_2_H_ +#define __GPIO_11XX_2_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup GPIO_11XX_2 CHIP: LPC11xx GPIO driver for CHIP_LPC11CXX, CHIP_LPC110X, and CHIP_LPC11XXLV families + * @ingroup CHIP_11XX_Drivers + * For device familes identified with CHIP definitions CHIP_LPC11CXX, + * CHIP_LPC110X, and CHIP_LPC11XXLV only. + * @{ + */ + +#if defined(CHIP_LPC11CXX) || defined(CHIP_LPC110X) || defined(CHIP_LPC11XXLV) || defined(CHIP_LPC1125) + +/** + * @brief GPIO port register block structure + */ +typedef struct { /*!< GPIO_PORT Structure */ + __IO uint32_t DATA[4096]; /*!< Offset: 0x0000 to 0x3FFC Data address masking register (R/W) */ + uint32_t RESERVED1[4096]; + __IO uint32_t DIR; /*!< Offset: 0x8000 Data direction register (R/W) */ + __IO uint32_t IS; /*!< Offset: 0x8004 Interrupt sense register (R/W) */ + __IO uint32_t IBE; /*!< Offset: 0x8008 Interrupt both edges register (R/W) */ + __IO uint32_t IEV; /*!< Offset: 0x800C Interrupt event register (R/W) */ + __IO uint32_t IE; /*!< Offset: 0x8010 Interrupt mask register (R/W) */ + __I uint32_t RIS; /*!< Offset: 0x8014 Raw interrupt status register (R/ ) */ + __I uint32_t MIS; /*!< Offset: 0x8018 Masked interrupt status register (R/ ) */ + __O uint32_t IC; /*!< Offset: 0x801C Interrupt clear register (W) */ + uint32_t RESERVED2[8184]; /* Padding added for aligning contiguous GPIO blocks */ +} LPC_GPIO_T; + +/** + * @brief Initialize GPIO block + * @param pGPIO : The base of GPIO peripheral on the chip + * @return Nothing + */ +void Chip_GPIO_Init(LPC_GPIO_T *pGPIO); + +/** + * @brief De-Initialize GPIO block + * @param pGPIO : The base of GPIO peripheral on the chip + * @return Nothing + */ +void Chip_GPIO_DeInit(LPC_GPIO_T *pGPIO); + +/** + * @brief Set a GPIO port/bit state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO port to set + * @param bit : GPIO bit to set + * @param setting : true for high, false for low + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_WritePortBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t bit, bool setting) +{ + pGPIO[port].DATA[1 << bit] = setting << bit; +} + +/** + * @brief Set a GPIO pin state via the GPIO byte register + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pin : GPIO pin to set + * @param setting : true for high, false for low + * @return Nothing + * @note This function replaces Chip_GPIO_WritePortBit() + */ +STATIC INLINE void Chip_GPIO_SetPinState(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin, bool setting) +{ + pGPIO[port].DATA[1 << pin] = setting << pin; +} + +/** + * @brief Read a GPIO state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO port to read + * @param bit : GPIO bit to read + * @return true of the GPIO is high, false if low + * @note It is recommended to use the Chip_GPIO_GetPinState() function instead. + */ +STATIC INLINE bool Chip_GPIO_ReadPortBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t bit) +{ + return (bool) ((pGPIO[port].DATA[1 << bit] >> bit) & 1); +} + +/** + * @brief Get a GPIO pin state via the GPIO byte register + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pin : GPIO pin to get state for + * @return true if the GPIO is high, false if low + * @note This function replaces Chip_GPIO_ReadPortBit() + */ +STATIC INLINE bool Chip_GPIO_GetPinState(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + return (pGPIO[port].DATA[1 << pin]) != 0; +} + +/** + * @brief Seta GPIO direction + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO port to set + * @param bit : GPIO bit to set + * @param setting : true for output, false for input + * @return Nothing + * @note It is recommended to use the Chip_GPIO_SetPinDIROutput(), + * Chip_GPIO_SetPinDIRInput() or Chip_GPIO_SetPinDIR() functions instead + * of this function. + */ +void Chip_GPIO_WriteDirBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t bit, bool setting); + +/** + * @brief Set GPIO direction for a single GPIO pin to an output + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pin : GPIO pin to set direction on as output + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_SetPinDIROutput(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + pGPIO[port].DIR |= (1UL << pin); +} + +/** + * @brief Set GPIO direction for a single GPIO pin to an input + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pin : GPIO pin to set direction on as input + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_SetPinDIRInput(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + pGPIO[port].DIR &= ~(1UL << pin); +} + +/** + * @brief Set GPIO direction for a single GPIO pin + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pin : GPIO pin to set direction for + * @param output : true for output, false for input + * @return Nothing + */ +void Chip_GPIO_SetPinDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin, bool output); + +/** + * @brief Read a GPIO direction (out or in) + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO port to read + * @param bit : GPIO bit to read + * @return true of the GPIO is an output, false if input + * @note It is recommended to use the Chip_GPIO_GetPinDIR() function instead. + */ +STATIC INLINE bool Chip_GPIO_ReadDirBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t bit) +{ + return (bool) (((pGPIO[port].DIR) >> bit) & 1); +} + +/** + * @brief Get GPIO direction for a single GPIO pin + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pin : GPIO pin to get direction for + * @return true if the GPIO is an output, false if input + */ +STATIC INLINE bool Chip_GPIO_GetPinDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + return (bool) (pGPIO[port].DIR >> pin) & 1; +} + +/** + * @brief Set Direction for a GPIO port + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port Number + * @param bit : GPIO bit to set + * @param out : Direction value, 0 = input, !0 = output + * @return None + * @note Bits set to '0' are not altered. It is recommended to use the + * Chip_GPIO_SetPortDIR() function instead. + */ +void Chip_GPIO_SetDir(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t bit, uint8_t out); + +/** + * @brief Set GPIO direction for a all selected GPIO pins to an output + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pinMask : GPIO pin mask to set direction on as output (bits 0..n for pins 0..n) + * @return Nothing + * @note Sets multiple GPIO pins to the output direction, each bit's position that is + * high sets the corresponding pin number for that bit to an output. + */ +STATIC INLINE void Chip_GPIO_SetPortDIROutput(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinMask) +{ + pGPIO[port].DIR |= pinMask; +} + +/** + * @brief Set GPIO direction for a all selected GPIO pins to an input + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pinMask : GPIO pin mask to set direction on as input (bits 0..b for pins 0..n) + * @return Nothing + * @note Sets multiple GPIO pins to the input direction, each bit's position that is + * high sets the corresponding pin number for that bit to an input. + */ +STATIC INLINE void Chip_GPIO_SetPortDIRInput(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinMask) +{ + pGPIO[port].DIR &= ~pinMask; +} + +/** + * @brief Set GPIO direction for a all selected GPIO pins to an input or output + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pinMask : GPIO pin mask to set direction on (bits 0..b for pins 0..n) + * @param outSet : Direction value, false = set as inputs, true = set as outputs + * @return Nothing + * @note Sets multiple GPIO pins to the input direction, each bit's position that is + * high sets the corresponding pin number for that bit to an input. + */ +void Chip_GPIO_SetPortDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinMask, bool outSet); + +/** + * @brief Get GPIO direction for a all GPIO pins + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @return a bitfield containing the input and output states for each pin + * @note For pins 0..n, a high state in a bit corresponds to an output state for the + * same pin, while a low state corresponds to an input state. + */ +STATIC INLINE uint32_t Chip_GPIO_GetPortDIR(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO[port].DIR; +} + +/** + * @brief Set all GPIO raw pin states (regardless of masking) + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param value : Value to set all GPIO pin states (0..n) to + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_SetPortValue(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t value) +{ + pGPIO[port].DATA[0xFFF] = value; +} + +/** + * @brief Get all GPIO raw pin states (regardless of masking) + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @return Current (raw) state of all GPIO pins + */ +STATIC INLINE uint32_t Chip_GPIO_GetPortValue(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO[port].DATA[0xFFF]; +} + +/** + * @brief Set a GPIO port/bit to the high state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param bit : Bit(s) in the port to set high + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. It is recommended to use the + * Chip_GPIO_SetPortOutHigh() function instead. + */ +STATIC INLINE void Chip_GPIO_SetValue(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t bit) +{ + pGPIO[port].DATA[bit] = bit; +} + +/** + * @brief Set selected GPIO output pins to the high state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pins : pins (0..n) to set high + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_SetPortOutHigh(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pins) +{ + pGPIO[port].DATA[pins] = 0xFFF; +} + +/** + * @brief Set an individual GPIO output pin to the high state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pin : pin number (0..n) to set high + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_SetPinOutHigh(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + pGPIO[port].DATA[1 << pin] = (1 << pin); +} + +/** + * @brief Set a GPIO port/bit to the low state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param bit : Bit(s) in the port to set low + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_ClearValue(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t bit) +{ + pGPIO[port].DATA[bit] = ~bit; +} + +/** + * @brief Set selected GPIO output pins to the low state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pins : pins (0..n) to set low + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_SetPortOutLow(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pins) +{ + pGPIO[port].DATA[pins] = 0; +} + +/** + * @brief Set an individual GPIO output pin to the low state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pin : pin number (0..n) to set low + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_SetPinOutLow(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + pGPIO[port].DATA[1 << pin] = 0; +} + +/** + * @brief Toggle selected GPIO output pins to the opposite state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pins : pins (0..n) to toggle + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_SetPortToggle(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pins) +{ + pGPIO[port].DATA[pins] ^= 0xFFF; +} + +/** + * @brief Toggle an individual GPIO output pin to the opposite state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pin : pin number (0..n) to toggle + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_SetPinToggle(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + pGPIO[port].DATA[1 << pin] ^= (1 << pin); +} + +/** + * @brief Read current bit states for the selected port + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number to read + * @return Current value of GPIO port + * @note The current states of the bits for the port are read, regardless of + * whether the GPIO port bits are input or output. + */ +STATIC INLINE uint32_t Chip_GPIO_ReadValue(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO[port].DATA[4095]; +} + +/** + * @brief Configure the pins as edge sensitive for interrupts + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pinmask : Pins to set to edge mode (ORed value of bits 0..11) + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_SetPinModeEdge(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinmask) +{ + pGPIO[port].IS &= ~pinmask; +} + +/** + * @brief Configure the pins as level sensitive for interrupts + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pinmask : Pins to set to level mode (ORed value of bits 0..11) + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_SetPinModeLevel(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinmask) +{ + pGPIO[port].IS |= pinmask; +} + +/** + * @brief Returns current GPIO edge or high level interrupt configuration for all pins for a port + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @return A bifield containing the edge/level interrupt configuration for each + * pin for the selected port. Bit 0 = pin 0, 1 = pin 1. + * For each bit, a 0 means the edge interrupt is configured, while a 1 means a level + * interrupt is configured. Mask with this return value to determine the + * edge/level configuration for each pin in a port. + */ +STATIC INLINE uint32_t Chip_GPIO_IsLevelEnabled(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO[port].IS; +} + +/** + * @brief Sets GPIO interrupt configuration for both edges for selected pins + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pinmask : Pins to set to dual edge mode (ORed value of bits 0..11) + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_SetEdgeModeBoth(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinmask) +{ + pGPIO[port].IBE |= pinmask; +} + +/** + * @brief Sets GPIO interrupt configuration for a single edge for selected pins + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pinmask : Pins to set to single edge mode (ORed value of bits 0..11) + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_SetEdgeModeSingle(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinmask) +{ + pGPIO[port].IBE &= ~pinmask; +} + +/** + * @brief Returns current GPIO interrupt dual or single edge configuration for all pins for a port + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @return A bifield containing the single/dual interrupt configuration for each + * pin for the selected port. Bit 0 = pin 0, 1 = pin 1. + * For each bit, a 0 means the interrupt triggers on a single edge (use the + * Chip_GPIO_SetEdgeModeHigh() and Chip_GPIO_SetEdgeModeLow() functions to configure + * selected edge), while a 1 means the interrupt triggers on both edges. Mask + * with this return value to determine the edge/level configuration for each pin in + * a port. + */ +STATIC INLINE uint32_t Chip_GPIO_GetEdgeModeDir(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO[port].IBE; +} + +/** + * @brief Sets GPIO interrupt configuration when in single edge or level mode to high edge trigger or high level + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pinmask : Pins to set to high mode (ORed value of bits 0..11) + * @return Nothing + * @note Use this function to select high level or high edge interrupt mode + * for the selected pins on the selected port when not in dual edge mode. + */ +STATIC INLINE void Chip_GPIO_SetModeHigh(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinmask) +{ + pGPIO[port].IEV |= pinmask; +} + +/** + * @brief Sets GPIO interrupt configuration when in single edge or level mode to low edge trigger or low level + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pinmask : Pins to set to low mode (ORed value of bits 0..11) + * @return Nothing + * @note Use this function to select low level or low edge interrupt mode + * for the selected pins on the selected port when not in dual edge mode. + */ +STATIC INLINE void Chip_GPIO_SetModeLow(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinmask) +{ + pGPIO[port].IEV &= ~pinmask; +} + +/** + * @brief Returns current GPIO interrupt edge direction or level mode + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @return A bifield containing the low or high direction of the interrupt + * configuration for each pin for the selected port. Bit 0 = pin 0, 1 = pin 1. + * For each bit, a 0 means the interrupt triggers on a low level or edge, while a + * 1 means the interrupt triggers on a high level or edge. Mask with this + * return value to determine the high/low configuration for each pin in a port. + */ +STATIC INLINE uint32_t Chip_GPIO_GetModeHighLow(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO[port].IEV; +} + +/** + * @brief Enables interrupts for selected pins on a port + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pinmask : Pins to enable interrupts for (ORed value of bits 0..11) + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_EnableInt(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinmask) +{ + pGPIO[port].IE |= pinmask; +} + +/** + * @brief Disables interrupts for selected pins on a port + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pinmask : Pins to disable interrupts for (ORed value of bits 0..11) + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_DisableInt(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinmask) +{ + pGPIO[port].IE &= ~pinmask; +} + +/** + * @brief Returns current enable pin interrupts for a port + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @return A bifield containing the enabled pin interrupts (0..11) + */ +STATIC INLINE uint32_t Chip_GPIO_GetEnabledInts(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO[port].IE; +} + +/** + * @brief Returns raw interrupt pending status for pin interrupts for a port + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @return A bifield containing the raw pending interrupt states for each pin (0..11) on the port + */ +STATIC INLINE uint32_t Chip_GPIO_GetRawInts(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO[port].RIS; +} + +/** + * @brief Returns masked interrupt pending status for pin interrupts for a port + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @return A bifield containing the masked pending interrupt states for each pin (0..11) on the port + */ +STATIC INLINE uint32_t Chip_GPIO_GetMaskedInts(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO[port].MIS; +} + +/** + * @brief Clears pending interrupts for selected pins for a port + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pinmask : Pins to clear interrupts for (ORed value of bits 0..11) + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_ClearInts(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinmask) +{ + pGPIO[port].IC = pinmask; +} + +/** + * @brief GPIO interrupt mode definitions + */ +typedef enum { + GPIO_INT_ACTIVE_LOW_LEVEL = 0x0, /*!< Selects interrupt on pin to be triggered on LOW level */ + GPIO_INT_ACTIVE_HIGH_LEVEL = 0x1, /*!< Selects interrupt on pin to be triggered on HIGH level */ + GPIO_INT_FALLING_EDGE = 0x2, /*!< Selects interrupt on pin to be triggered on FALLING level */ + GPIO_INT_RISING_EDGE = 0x3, /*!< Selects interrupt on pin to be triggered on RISING level */ + GPIO_INT_BOTH_EDGES = 0x6 /*!< Selects interrupt on pin to be triggered on both edges */ +} GPIO_INT_MODE_T; + +/** + * @brief Composite function for setting up a full interrupt configuration for a single pin + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : Port number + * @param pin : Pin number (0..11) + * @param modeFlags : GPIO interrupt mode selection + * @return Nothing + */ +void Chip_GPIO_SetupPinInt(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin, GPIO_INT_MODE_T mode); + +#endif /* defined(CHIP_LPC11CXX) || defined(CHIP_LPC110X) || defined(CHIP_LPC11XXLV) || defined(CHIP_LPC1125) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __GPIO_11XX_2_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/gpiogroup_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/gpiogroup_11xx.h new file mode 100755 index 0000000..a04f63f --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/gpiogroup_11xx.h @@ -0,0 +1,212 @@ +/* + * @brief LPC11xx GPIO group driver for CHIP_LPC11AXX, CHIP_LPC11EXX, and + * CHIP_LPC11UXX families only. + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __GPIOGROUP_11XX_H_ +#define __GPIOGROUP_11XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup GPIOGP_11XX CHIP: LPC11xx GPIO group driver for CHIP_LPC11(A/E/U)XX families + * @ingroup CHIP_11XX_Drivers + * For device familes identified with CHIP definitions CHIP_LPC11AXX, + * CHIP_LPC11EXX, and CHIP_LPC11UXX only. + * @{ + */ + +#if defined(CHIP_LPC11AXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) + +/** + * @brief GPIO grouped interrupt register block structure + */ +typedef struct { /*!< GPIO_GROUP_INTn Structure */ + __IO uint32_t CTRL; /*!< GPIO grouped interrupt control register */ + __I uint32_t RESERVED0[7]; + __IO uint32_t PORT_POL[8]; /*!< GPIO grouped interrupt port polarity register */ + __IO uint32_t PORT_ENA[8]; /*!< GPIO grouped interrupt port m enable register */ + uint32_t RESERVED1[4072]; +} LPC_GPIOGROUPINT_T; + +/** + * LPC11xx GPIO group bit definitions + */ +#define GPIOGR_INT (1 << 0) /*!< GPIO interrupt pending/clear bit */ +#define GPIOGR_COMB (1 << 1) /*!< GPIO interrupt OR(0)/AND(1) mode bit */ +#define GPIOGR_TRIG (1 << 2) /*!< GPIO interrupt edge(0)/level(1) mode bit */ + +/** + * @brief Clear interrupt pending status for the selected group + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @return None + */ +STATIC INLINE void Chip_GPIOGP_ClearIntStatus(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group) +{ + uint32_t temp; + + temp = pGPIOGPINT[group].CTRL; + pGPIOGPINT[group].CTRL = temp | GPIOGR_INT; +} + +/** + * @brief Returns current GPIO group inetrrupt pending status + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @return true if the group interrupt is pending, otherwise false. + */ +STATIC INLINE bool Chip_GPIOGP_GetIntStatus(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group) +{ + return (bool) ((pGPIOGPINT[group].CTRL & GPIOGR_INT) != 0); +} + +/** + * @brief Selected GPIO group functionality for trigger on any pin in group (OR mode) + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @return None + */ +STATIC INLINE void Chip_GPIOGP_SelectOrMode(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group) +{ + pGPIOGPINT[group].CTRL &= ~GPIOGR_COMB; +} + +/** + * @brief Selected GPIO group functionality for trigger on all matching pins in group (AND mode) + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @return None + */ +STATIC INLINE void Chip_GPIOGP_SelectAndMode(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group) +{ + pGPIOGPINT[group].CTRL |= GPIOGR_COMB; +} + +/** + * @brief Selected GPIO group functionality edge trigger mode + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @return None + */ +STATIC INLINE void Chip_GPIOGP_SelectEdgeMode(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group) +{ + pGPIOGPINT[group].CTRL &= ~GPIOGR_TRIG; +} + +/** + * @brief Selected GPIO group functionality level trigger mode + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @return None + */ +STATIC INLINE void Chip_GPIOGP_SelectLevelMode(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group) +{ + pGPIOGPINT[group].CTRL |= GPIOGR_TRIG; +} + +/** + * @brief Set selected pins for the group and port to low level trigger + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @param port : GPIO port number + * @param pinMask : Or'ed value of pins to select for low level (bit 0 = pin 0, 1 = pin1, etc.) + * @return None + */ +STATIC INLINE void Chip_GPIOGP_SelectLowLevel(LPC_GPIOGROUPINT_T *pGPIOGPINT, + uint8_t group, + uint8_t port, + uint32_t pinMask) +{ + pGPIOGPINT[group].PORT_POL[port] &= ~pinMask; +} + +/** + * @brief Set selected pins for the group and port to high level trigger + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @param port : GPIO port number + * @param pinMask : Or'ed value of pins to select for high level (bit 0 = pin 0, 1 = pin1, etc.) + * @return None + */ +STATIC INLINE void Chip_GPIOGP_SelectHighLevel(LPC_GPIOGROUPINT_T *pGPIOGPINT, + uint8_t group, + uint8_t port, + uint32_t pinMask) +{ + pGPIOGPINT[group].PORT_POL[port] = pinMask; +} + +/** + * @brief Disabled selected pins for the group interrupt + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @param port : GPIO port number + * @param pinMask : Or'ed value of pins to disable interrupt for (bit 0 = pin 0, 1 = pin1, etc.) + * @return None + * @note Disabled pins do not contrinute to the group interrupt. + */ +STATIC INLINE void Chip_GPIOGP_DisableGroupPins(LPC_GPIOGROUPINT_T *pGPIOGPINT, + uint8_t group, + uint8_t port, + uint32_t pinMask) +{ + pGPIOGPINT[group].PORT_ENA[port] &= ~pinMask; +} + +/** + * @brief Enable selected pins for the group interrupt + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @param port : GPIO port number + * @param pinMask : Or'ed value of pins to enable interrupt for (bit 0 = pin 0, 1 = pin1, etc.) + * @return None + * @note Enables pins contrinute to the group interrupt. + */ +STATIC INLINE void Chip_GPIOGP_EnableGroupPins(LPC_GPIOGROUPINT_T *pGPIOGPINT, + uint8_t group, + uint8_t port, + uint32_t pinMask) +{ + pGPIOGPINT[group].PORT_ENA[port] = pinMask; +} + +#endif /* defined(CHIP_LPC11AXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __GPIOGROUP_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/i2c_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/i2c_11xx.h new file mode 100755 index 0000000..a657ad0 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/i2c_11xx.h @@ -0,0 +1,543 @@ +/* + * @brief LPC11xx I2C driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __I2C_11XX_H_ +#define __I2C_11XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup I2C_11XX CHIP: LPC11xx I2C driver + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +#if !defined(CHIP_LPC110X) + +/** + * @brief I2C register block structure + */ +typedef struct { /* I2C0 Structure */ + __IO uint32_t CONSET; /*!< I2C Control Set Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is set. Writing a zero has no effect on the corresponding bit in the I2C control register. */ + __I uint32_t STAT; /*!< I2C Status Register. During I2C operation, this register provides detailed status codes that allow software to determine the next action needed. */ + __IO uint32_t DAT; /*!< I2C Data Register. During master or slave transmit mode, data to be transmitted is written to this register. During master or slave receive mode, data that has been received may be read from this register. */ + __IO uint32_t ADR0; /*!< I2C Slave Address Register 0. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */ + __IO uint32_t SCLH; /*!< SCH Duty Cycle Register High Half Word. Determines the high time of the I2C clock. */ + __IO uint32_t SCLL; /*!< SCL Duty Cycle Register Low Half Word. Determines the low time of the I2C clock. SCLL and SCLH together determine the clock frequency generated by an I2C master and certain times used in slave mode. */ + __O uint32_t CONCLR; /*!< I2C Control Clear Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is cleared. Writing a zero has no effect on the corresponding bit in the I2C control register. */ + __IO uint32_t MMCTRL; /*!< Monitor mode control register. */ + __IO uint32_t ADR1; /*!< I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */ + __IO uint32_t ADR2; /*!< I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */ + __IO uint32_t ADR3; /*!< I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */ + __I uint32_t DATA_BUFFER; /*!< Data buffer register. The contents of the 8 MSBs of the DAT shift register will be transferred to the DATA_BUFFER automatically after every nine bits (8 bits of data plus ACK or NACK) has been received on the bus. */ + __IO uint32_t MASK[4]; /*!< I2C Slave address mask register */ +} LPC_I2C_T; + +/** + * @brief Return values for SLAVE handler + * @note + * Chip drivers will usally be designed to match their events with this value + */ +#define RET_SLAVE_TX 6 /**< Return value, when 1 byte TX'd successfully */ +#define RET_SLAVE_RX 5 /**< Return value, when 1 byte RX'd successfully */ +#define RET_SLAVE_IDLE 2 /**< Return value, when slave enter idle mode */ +#define RET_SLAVE_BUSY 0 /**< Return value, when slave is busy */ + +/** + * @brief I2C state handle return values + */ +#define I2C_STA_STO_RECV 0x20 + +/* + * @brief I2C Control Set register description + */ +#define I2C_I2CONSET_AA ((0x04))/*!< Assert acknowledge flag */ +#define I2C_I2CONSET_SI ((0x08))/*!< I2C interrupt flag */ +#define I2C_I2CONSET_STO ((0x10))/*!< STOP flag */ +#define I2C_I2CONSET_STA ((0x20))/*!< START flag */ +#define I2C_I2CONSET_I2EN ((0x40))/*!< I2C interface enable */ + +/* + * @brief I2C Control Clear register description + */ +#define I2C_I2CONCLR_AAC ((1 << 2)) /*!< Assert acknowledge Clear bit */ +#define I2C_I2CONCLR_SIC ((1 << 3)) /*!< I2C interrupt Clear bit */ +#define I2C_I2CONCLR_STOC ((1 << 4)) /*!< I2C STOP Clear bit */ +#define I2C_I2CONCLR_STAC ((1 << 5)) /*!< START flag Clear bit */ +#define I2C_I2CONCLR_I2ENC ((1 << 6)) /*!< I2C interface Disable bit */ + +/* + * @brief I2C Common Control register description + */ +#define I2C_CON_AA (1UL << 2) /*!< Assert acknowledge bit */ +#define I2C_CON_SI (1UL << 3) /*!< I2C interrupt bit */ +#define I2C_CON_STO (1UL << 4) /*!< I2C STOP bit */ +#define I2C_CON_STA (1UL << 5) /*!< START flag bit */ +#define I2C_CON_I2EN (1UL << 6) /*!< I2C interface bit */ + +/* + * @brief I2C Status Code definition (I2C Status register) + */ +#define I2C_STAT_CODE_BITMASK ((0xF8))/*!< Return Code mask in I2C status register */ +#define I2C_STAT_CODE_ERROR ((0xFF))/*!< Return Code error mask in I2C status register */ + +/* + * @brief I2C return status code definitions + */ +#define I2C_I2STAT_NO_INF ((0xF8))/*!< No relevant information */ +#define I2C_I2STAT_BUS_ERROR ((0x00))/*!< Bus Error */ + +/* + * @brief I2C Master transmit mode + */ +#define I2C_I2STAT_M_TX_START ((0x08))/*!< A start condition has been transmitted */ +#define I2C_I2STAT_M_TX_RESTART ((0x10))/*!< A repeat start condition has been transmitted */ +#define I2C_I2STAT_M_TX_SLAW_ACK ((0x18))/*!< SLA+W has been transmitted, ACK has been received */ +#define I2C_I2STAT_M_TX_SLAW_NACK ((0x20))/*!< SLA+W has been transmitted, NACK has been received */ +#define I2C_I2STAT_M_TX_DAT_ACK ((0x28))/*!< Data has been transmitted, ACK has been received */ +#define I2C_I2STAT_M_TX_DAT_NACK ((0x30))/*!< Data has been transmitted, NACK has been received */ +#define I2C_I2STAT_M_TX_ARB_LOST ((0x38))/*!< Arbitration lost in SLA+R/W or Data bytes */ + +/* + * @brief I2C Master receive mode + */ +#define I2C_I2STAT_M_RX_START ((0x08))/*!< A start condition has been transmitted */ +#define I2C_I2STAT_M_RX_RESTART ((0x10))/*!< A repeat start condition has been transmitted */ +#define I2C_I2STAT_M_RX_ARB_LOST ((0x38))/*!< Arbitration lost */ +#define I2C_I2STAT_M_RX_SLAR_ACK ((0x40))/*!< SLA+R has been transmitted, ACK has been received */ +#define I2C_I2STAT_M_RX_SLAR_NACK ((0x48))/*!< SLA+R has been transmitted, NACK has been received */ +#define I2C_I2STAT_M_RX_DAT_ACK ((0x50))/*!< Data has been received, ACK has been returned */ +#define I2C_I2STAT_M_RX_DAT_NACK ((0x58))/*!< Data has been received, NACK has been returned */ + +/* + * @brief I2C Slave receive mode + */ +#define I2C_I2STAT_S_RX_SLAW_ACK ((0x60))/*!< Own slave address has been received, ACK has been returned */ +#define I2C_I2STAT_S_RX_ARB_LOST_M_SLA ((0x68))/*!< Arbitration lost in SLA+R/W as master */ +// #define I2C_I2STAT_S_RX_SLAW_ACK ((0x68)) /*!< Own SLA+W has been received, ACK returned */ +#define I2C_I2STAT_S_RX_GENCALL_ACK ((0x70))/*!< General call address has been received, ACK has been returned */ +#define I2C_I2STAT_S_RX_ARB_LOST_M_GENCALL ((0x78))/*!< Arbitration lost in SLA+R/W (GENERAL CALL) as master */ +// #define I2C_I2STAT_S_RX_GENCALL_ACK ((0x78)) /*!< General call address has been received, ACK has been returned */ +#define I2C_I2STAT_S_RX_PRE_SLA_DAT_ACK ((0x80))/*!< Previously addressed with own SLA; Data has been received, ACK has been returned */ +#define I2C_I2STAT_S_RX_PRE_SLA_DAT_NACK ((0x88))/*!< Previously addressed with own SLA;Data has been received and NOT ACK has been returned */ +#define I2C_I2STAT_S_RX_PRE_GENCALL_DAT_ACK ((0x90))/*!< Previously addressed with General Call; Data has been received and ACK has been returned */ +#define I2C_I2STAT_S_RX_PRE_GENCALL_DAT_NACK ((0x98))/*!< Previously addressed with General Call; Data has been received and NOT ACK has been returned */ +#define I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX ((0xA0))/*!< A STOP condition or repeated START condition has been received while still addressed as SLV/REC (Slave Receive) or + SLV/TRX (Slave Transmit) */ + +/* + * @brief I2C Slave transmit mode + */ +#define I2C_I2STAT_S_TX_SLAR_ACK ((0xA8))/*!< Own SLA+R has been received, ACK has been returned */ +#define I2C_I2STAT_S_TX_ARB_LOST_M_SLA ((0xB0))/*!< Arbitration lost in SLA+R/W as master */ +// #define I2C_I2STAT_S_TX_SLAR_ACK ((0xB0)) /*!< Own SLA+R has been received, ACK has been returned */ +#define I2C_I2STAT_S_TX_DAT_ACK ((0xB8))/*!< Data has been transmitted, ACK has been received */ +#define I2C_I2STAT_S_TX_DAT_NACK ((0xC0))/*!< Data has been transmitted, NACK has been received */ +#define I2C_I2STAT_S_TX_LAST_DAT_ACK ((0xC8))/*!< Last data byte in I2DAT has been transmitted (AA = 0); ACK has been received */ +#define I2C_SLAVE_TIME_OUT 0x10000000UL/*!< Time out in case of using I2C slave mode */ + +/* + * @brief I2C Data register definition + */ +#define I2C_I2DAT_BITMASK ((0xFF))/*!< Mask for I2DAT register */ +#define I2C_I2DAT_IDLE_CHAR (0xFF) /*!< Idle data value will be send out in slave mode in case of the actual expecting data requested from the master is greater than + its sending data length that can be supported */ + +/* + * @brief I2C Monitor mode control register description + */ +#define I2C_I2MMCTRL_MM_ENA ((1 << 0)) /**< Monitor mode enable */ +#define I2C_I2MMCTRL_ENA_SCL ((1 << 1)) /**< SCL output enable */ +#define I2C_I2MMCTRL_MATCH_ALL ((1 << 2)) /**< Select interrupt register match */ +#define I2C_I2MMCTRL_BITMASK ((0x07)) /**< Mask for I2MMCTRL register */ + +/* + * @brief I2C Data buffer register description + */ +#define I2DATA_BUFFER_BITMASK ((0xFF))/*!< I2C Data buffer register bit mask */ + +/* + * @brief I2C Slave Address registers definition + */ +#define I2C_I2ADR_GC ((1 << 0)) /*!< General Call enable bit */ +#define I2C_I2ADR_BITMASK ((0xFF))/*!< I2C Slave Address registers bit mask */ + +/* + * @brief I2C Mask Register definition + */ +#define I2C_I2MASK_MASK(n) ((n & 0xFE))/*!< I2C Mask Register mask field */ + +/* + * @brief I2C SCL HIGH duty cycle Register definition + */ +#define I2C_I2SCLH_BITMASK ((0xFFFF)) /*!< I2C SCL HIGH duty cycle Register bit mask */ + +/* + * @brief I2C SCL LOW duty cycle Register definition + */ +#define I2C_I2SCLL_BITMASK ((0xFFFF)) /*!< I2C SCL LOW duty cycle Register bit mask */ + +/* + * @brief I2C status values + */ +#define I2C_SETUP_STATUS_ARBF (1 << 8) /**< Arbitration false */ +#define I2C_SETUP_STATUS_NOACKF (1 << 9) /**< No ACK returned */ +#define I2C_SETUP_STATUS_DONE (1 << 10) /**< Status DONE */ + +/* + * @brief I2C state handle return values + */ +#define I2C_OK 0x00 +#define I2C_BYTE_SENT 0x01 +#define I2C_BYTE_RECV 0x02 +#define I2C_LAST_BYTE_RECV 0x04 +#define I2C_SEND_END 0x08 +#define I2C_RECV_END 0x10 +#define I2C_STA_STO_RECV 0x20 + +#define I2C_ERR (0x10000000) +#define I2C_NAK_RECV (0x10000000 | 0x01) + +#define I2C_CheckError(ErrorCode) (ErrorCode & 0x10000000) + +/* + * @brief I2C monitor control configuration defines + */ +#define I2C_MONITOR_CFG_SCL_OUTPUT I2C_I2MMCTRL_ENA_SCL /**< SCL output enable */ +#define I2C_MONITOR_CFG_MATCHALL I2C_I2MMCTRL_MATCH_ALL /**< Select interrupt register match */ + +/** + * @brief I2C Slave Identifiers + */ +typedef enum { + I2C_SLAVE_GENERAL, /**< Slave ID for general calls */ + I2C_SLAVE_0, /**< Slave ID fo Slave Address 0 */ + I2C_SLAVE_1, /**< Slave ID fo Slave Address 1 */ + I2C_SLAVE_2, /**< Slave ID fo Slave Address 2 */ + I2C_SLAVE_3, /**< Slave ID fo Slave Address 3 */ + I2C_SLAVE_NUM_INTERFACE /**< Number of slave interfaces */ +} I2C_SLAVE_ID; + +/** + * @brief I2C transfer status + */ +typedef enum { + I2C_STATUS_DONE, /**< Transfer done successfully */ + I2C_STATUS_NAK, /**< NAK received during transfer */ + I2C_STATUS_ARBLOST, /**< Aribitration lost during transfer */ + I2C_STATUS_BUSERR, /**< Bus error in I2C transfer */ + I2C_STATUS_BUSY, /**< I2C is busy doing transfer */ +} I2C_STATUS_T; + +/** + * @brief Master transfer data structure definitions + */ +typedef struct { + uint8_t slaveAddr; /**< 7-bit I2C Slave address */ + const uint8_t *txBuff; /**< Pointer to array of bytes to be transmitted */ + int txSz; /**< Number of bytes in transmit array, + if 0 only receive transfer will be carried on */ + uint8_t *rxBuff; /**< Pointer memory where bytes received from I2C be stored */ + int rxSz; /**< Number of bytes to received, + if 0 only transmission we be carried on */ + I2C_STATUS_T status; /**< Status of the current I2C transfer */ +} I2C_XFER_T; + +/** + * @brief I2C interface IDs + * @note + * All Chip functions will take this as the first parameter, + * I2C_NUM_INTERFACE must never be used for calling any Chip + * functions, it is only used to find the number of interfaces + * available in the Chip. + */ +typedef enum I2C_ID { + I2C0, /**< ID I2C0 */ + I2C_NUM_INTERFACE /**< Number of I2C interfaces in the chip */ +} I2C_ID_T; + +/** + * @brief I2C master events + */ +typedef enum { + I2C_EVENT_WAIT = 1, /**< I2C Wait event */ + I2C_EVENT_DONE, /**< Done event that wakes up Wait event */ + I2C_EVENT_LOCK, /**< Re-entrency lock event for I2C transfer */ + I2C_EVENT_UNLOCK, /**< Re-entrency unlock event for I2C transfer */ + I2C_EVENT_SLAVE_RX, /**< Slave receive event */ + I2C_EVENT_SLAVE_TX, /**< Slave transmit event */ +} I2C_EVENT_T; + +/** + * @brief Event handler function type + */ +typedef void (*I2C_EVENTHANDLER_T)(I2C_ID_T, I2C_EVENT_T); + +/** + * @brief Initializes the LPC_I2C peripheral with specified parameter. + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return Nothing + */ +void Chip_I2C_Init(I2C_ID_T id); + +/** + * @brief De-initializes the I2C peripheral registers to their default reset values + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return Nothing + */ +void Chip_I2C_DeInit(I2C_ID_T id); + +/** + * @brief Set up clock rate for LPC_I2C peripheral. + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param clockrate : Target clock rate value to initialized I2C peripheral (Hz) + * @return Nothing + * @note + * Parameter @a clockrate for I2C0 should be from 1000 up to 1000000 + * (1 KHz to 1 MHz), as I2C0 support Fast Mode Plus. If the @a clockrate + * is more than 400 KHz (Fast Plus Mode) Board_I2C_EnableFastPlus() + * must be called prior to calling this function. + */ +void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate); + +/** + * @brief Get current clock rate for LPC_I2C peripheral. + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return The current I2C peripheral clock rate + */ +uint32_t Chip_I2C_GetClockRate(I2C_ID_T id); + +/** + * @brief Transmit and Receive data in master mode + * @param id : I2C peripheral selected (I2C0, I2C1 etc) + * @param xfer : Pointer to a I2C_XFER_T structure see notes below + * @return + * Any of #I2C_STATUS_T values, xfer->txSz will have number of bytes + * not sent due to error, xfer->rxSz will have the number of bytes yet + * to be received. + * @note + * The parameter @a xfer should have its member @a slaveAddr initialized + * to the 7-Bit slave address to which the master will do the xfer, Bit0 + * to bit6 should have the address and Bit8 is ignored. During the transfer + * no code (like event handler) must change the content of the memory + * pointed to by @a xfer. The member of @a xfer, @a txBuff and @a txSz be + * initialized to the memory from which the I2C must pick the data to be + * transfered to slave and the number of bytes to send respectively, similarly + * @a rxBuff and @a rxSz must have pointer to memroy where data received + * from slave be stored and the number of data to get from slave respectilvely. + */ +int Chip_I2C_MasterTransfer(I2C_ID_T id, I2C_XFER_T *xfer); + +/** + * @brief Transmit data to I2C slave using I2C Master mode + * @param id : I2C peripheral ID (I2C0, I2C1 .. etc) + * @param slaveAddr : Slave address to which the data be written + * @param buff : Pointer to buffer having the array of data + * @param len : Number of bytes to be transfered from @a buff + * @return Number of bytes successfully transfered + */ +int Chip_I2C_MasterSend(I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, uint8_t len); + +/** + * @brief Transfer a command to slave and receive data from slave after a repeated start + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param slaveAddr : Slave address of the I2C device + * @param cmd : Command (Address/Register) to be written + * @param buff : Pointer to memory that will hold the data received + * @param len : Number of bytes to receive + * @return Number of bytes successfully received + */ +int Chip_I2C_MasterCmdRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t cmd, uint8_t *buff, int len); + +/** + * @brief Get pointer to current function handling the events + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return Pointer to function handing events of I2C + */ +I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler(I2C_ID_T id); + +/** + * @brief Set function that must handle I2C events + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param event : Pointer to function that will handle the event (Should not be NULL) + * @return 1 when successful, 0 when a transfer is on going with its own event handler + */ +int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event); + +/** + * @brief Set function that must handle I2C events + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param slaveAddr : Slave address from which data be read + * @param buff : Pointer to memory where data read be stored + * @param len : Number of bytes to read from slave + * @return Number of bytes read successfully + */ +int Chip_I2C_MasterRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len); + +/** + * @brief Default event handler for polling operation + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param event : Event ID of the event that called the function + * @return Nothing + */ +void Chip_I2C_EventHandlerPolling(I2C_ID_T id, I2C_EVENT_T event); + +/** + * @brief Default event handler for interrupt base operation + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param event : Event ID of the event that called the function + * @return Nothing + */ +void Chip_I2C_EventHandler(I2C_ID_T id, I2C_EVENT_T event); + +/** + * @brief I2C Master transfer state change handler + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return Nothing + * @note Usually called from the appropriate Interrupt handler + */ +void Chip_I2C_MasterStateHandler(I2C_ID_T id); + +/** + * @brief Disable I2C peripheral's operation + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return Nothing + */ +void Chip_I2C_Disable(I2C_ID_T id); + +/** + * @brief Checks if master xfer in progress + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return 1 if master xfer in progress 0 otherwise + * @note + * This API is generally used in interrupt handler + * of the application to decide whether to call + * master state handler or to call slave state handler + */ +int Chip_I2C_IsMasterActive(I2C_ID_T id); + +/** + * @brief Setup a slave I2C device + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param sid : I2C Slave peripheral ID (I2C_SLAVE_0, I2C_SLAVE_1 etc) + * @param xfer : Pointer to transfer structure (see note below for more info) + * @param event : Event handler for slave transfers + * @param addrMask : Address mask to use along with slave address (see notes below for more info) + * @return Nothing + * @note + * Parameter @a xfer should point to a valid I2C_XFER_T structure object + * and must have @a slaveAddr initialized with 7bit Slave address (From Bit1 to Bit7), + * Bit0 when set enables general call handling, @a slaveAddr along with @a addrMask will + * be used to match the slave address. @a rxBuff and @a txBuff must point to valid buffers + * where slave can receive or send the data from, size of which will be provided by + * @a rxSz and @a txSz respectively. Function pointed to by @a event will be called + * for the following events #I2C_EVENT_SLAVE_RX (One byte of data received successfully + * from the master and stored inside memory pointed by xfer->rxBuff, incremented + * the pointer and decremented the @a xfer->rxSz), #I2C_EVENT_SLAVE_TX (One byte of + * data from xfer->txBuff was sent to master successfully, incremented the pointer + * and decremented xfer->txSz), #I2C_EVENT_DONE (Master is done doing its transfers + * with the slave).
+ *
Bit-0 of the parameter @a addrMask is reserved and should always be 0. Any bit (BIT1 + * to BIT7) set in @a addrMask will make the corresponding bit in *xfer->slaveAddr* as + * don't care. Thit is, if *xfer->slaveAddr* is (0x10 << 1) and @a addrMask is (0x03 << 1) then + * 0x10, 0x11, 0x12, 0x13 will all be considered as valid slave addresses for the registered + * slave. Upon receving any event *xfer->slaveAddr* (BIT1 to BIT7) will hold the actual + * address which was received from master.
+ *
General Call Handling
+ * Slave can receive data from master using general call address (0x00). General call + * handling must be setup as given below + * - Call Chip_I2C_SlaveSetup() with argument @a sid as I2C_SLAVE_GENERAL + * - xfer->slaveAddr ignored, argument @a addrMask ignored + * - function provided by @a event will registered to be called when slave received data using addr 0x00 + * - xfer->rxBuff and xfer->rxSz should be valid in argument @a xfer + * - To handle General Call only (No other slaves are configured) + * - Call Chip_I2C_SlaveSetup() with sid as I2C_SLAVE_X (X=0,1,2,3) + * - setup @a xfer with slaveAddr member set to 0, @a event is ignored hence can be NULL + * - provide @a addrMask (typically 0, if not you better be knowing what you are doing) + * - To handler General Call when other slave is active + * - Call Chip_I2C_SlaveSetup() with sid as I2C_SLAVE_X (X=0,1,2,3) + * - setup @a xfer with slaveAddr member set to 7-Bit Slave address [from Bit1 to 7] + * - Set Bit0 of @a xfer->slaveAddr as 1 + * - Provide appropriate @a addrMask + * - Argument @a event must point to function, that handles events from actual slaveAddress and not the GC + * @warning + * If the slave has only one byte in its txBuff, once that byte is transfered to master the event handler + * will be called for event #I2C_EVENT_DONE. If the master attempts to read more bytes in the same transfer + * then the slave hardware will send 0xFF to master till the end of transfer, event handler will not be + * called to notify this. For more info see section below
+ *
Last data handling in slave
+ * If the user wants to implement a slave which will read a byte from a specific location over and over + * again whenever master reads the slave. If the user initializes the xfer->txBuff as the location to read + * the byte from and xfer->txSz as 1, then say, if master reads one byte; slave will send the byte read from + * xfer->txBuff and will call the event handler with #I2C_EVENT_DONE. If the master attempts to read another + * byte instead of sending the byte read from xfer->txBuff the slave hardware will send 0xFF and no event will + * occur. To handle this issue, slave should set xfer->txSz to 2, in which case when master reads the byte + * event handler will be called with #I2C_EVENT_SLAVE_TX, in which the slave implementation can reset the buffer + * and size back to original location (i.e, xfer->txBuff--, xfer->txSz++), if the master reads another byte + * in the same transfer, byte read from xfer->txBuff will be sent and #I2C_EVENT_SLAVE_TX will be called again, and + * the process repeats. + */ +void Chip_I2C_SlaveSetup(I2C_ID_T id, + I2C_SLAVE_ID sid, + I2C_XFER_T *xfer, + I2C_EVENTHANDLER_T event, + uint8_t addrMask); + +/** + * @brief I2C Slave event handler + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return Nothing + */ +void Chip_I2C_SlaveStateHandler(I2C_ID_T id); + +/** + * @brief I2C peripheral state change checking + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return 1 if I2C peripheral @a id has changed its state, + * 0 if there is no state change + * @note + * This function must be used by the application when + * the polling has to be done based on state change. + */ +int Chip_I2C_IsStateChanged(I2C_ID_T id); + +#endif /* !defined(CHIP_LPC110X) */ + +/** + * @} + */ + + #ifdef __cplusplus +} +#endif + +#endif /* __I2C_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/iocon_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/iocon_11xx.h new file mode 100755 index 0000000..be83679 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/iocon_11xx.h @@ -0,0 +1,288 @@ +/* + * @brief IOCON registers and control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __IOCON_11XX_H_ +#define __IOCON_11XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup IOCON_11XX CHIP: LPC11xx IO Control driver + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +/** + * @brief IO Configuration Unit register block structure + */ +#if defined(CHIP_LPC11UXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11AXX) +typedef struct { /*!< LPC11AXX/LPC11UXX/LPC11EXX IOCON Structure */ + __IO uint32_t PIO0[24]; + __IO uint32_t PIO1[32]; +} LPC_IOCON_T; + +#else +/** + * @brief LPC11XX I/O Configuration register offset + */ +typedef enum CHIP_IOCON_PIO { + IOCON_PIO0_0 = (0x00C >> 2), + IOCON_PIO0_1 = (0x010 >> 2), + IOCON_PIO0_2 = (0x01C >> 2), + IOCON_PIO0_3 = (0x02C >> 2), + IOCON_PIO0_4 = (0x030 >> 2), + IOCON_PIO0_5 = (0x034 >> 2), + IOCON_PIO0_6 = (0x04C >> 2), + IOCON_PIO0_7 = (0x050 >> 2), + IOCON_PIO0_8 = (0x060 >> 2), + IOCON_PIO0_9 = (0x064 >> 2), + IOCON_PIO0_10 = (0x070 >> 2), + IOCON_PIO0_11 = (0x074 >> 2), + + IOCON_PIO1_0 = (0x078 >> 2), + IOCON_PIO1_1 = (0x07C >> 2), + IOCON_PIO1_2 = (0x080 >> 2), + IOCON_PIO1_3 = (0x090 >> 2), + IOCON_PIO1_4 = (0x094 >> 2), + IOCON_PIO1_5 = (0x0A0 >> 2), + IOCON_PIO1_6 = (0x0A4 >> 2), + IOCON_PIO1_7 = (0x0A8 >> 2), + IOCON_PIO1_8 = (0x014 >> 2), + IOCON_PIO1_9 = (0x038 >> 2), + IOCON_PIO1_10 = (0x06C >> 2), + IOCON_PIO1_11 = (0x098 >> 2), + + IOCON_PIO2_0 = (0x008 >> 2), + IOCON_PIO2_1 = (0x028 >> 2), + IOCON_PIO2_2 = (0x05C >> 2), + IOCON_PIO2_3 = (0x08C >> 2), + IOCON_PIO2_4 = (0x040 >> 2), + IOCON_PIO2_5 = (0x044 >> 2), + IOCON_PIO2_6 = (0x000 >> 2), + IOCON_PIO2_7 = (0x020 >> 2), + IOCON_PIO2_8 = (0x024 >> 2), + IOCON_PIO2_9 = (0x054 >> 2), + IOCON_PIO2_10 = (0x058 >> 2), +#if !defined(CHIP_LPC1125) + IOCON_PIO2_11 = (0x070 >> 2), +#endif + + IOCON_PIO3_0 = (0x084 >> 2), +#if !defined(CHIP_LPC1125) + IOCON_PIO3_1 = (0x088 >> 2), +#endif + IOCON_PIO3_2 = (0x09C >> 2), + IOCON_PIO3_3 = (0x0AC >> 2), + IOCON_PIO3_4 = (0x03C >> 2), + IOCON_PIO3_5 = (0x048 >> 2), +} CHIP_IOCON_PIO_T; + +/** + * @brief LPC11XX Pin location select + */ +typedef enum CHIP_IOCON_PIN_LOC { + IOCON_SCKLOC_PIO0_10 = (0xB0), /*!< Selects SCK0 function in pin location PIO0_10 */ +#if !defined(CHIP_LPC1125) + IOCON_SCKLOC_PIO2_11 = (0xB0 | 1), /*!< Selects SCK0 function in pin location PIO2_11 */ +#endif + IOCON_SCKLOC_PIO0_6 = (0xB0 | 2), /*!< Selects SCK0 function in pin location PIO0_6 */ + + IOCON_DSRLOC_PIO2_1 = (0xB4), /*!< Selects DSR function in pin location PIO2_1 */ +#if !defined(CHIP_LPC1125) + IOCON_DSRLOC_PIO3_1 = (0xB4 | 1), /*!< Selects DSR function in pin location PIO3_1 */ +#endif + + IOCON_DCDLOC_PIO2_2 = (0xB8), /*!< Selects DCD function in pin location PIO2_2 */ + IOCON_DCDLOC_PIO3_2 = (0xB8 | 1), /*!< Selects DCD function in pin location PIO3_2 */ + + IOCON_RILOC_PIO2_3 = (0xBC), /*!< Selects RI function in pin location PIO2_3 */ + IOCON_RILOC_PIO3_3 = (0xBC | 1), /*!< Selects Ri function in pin location PIO3_3 */ + +#if defined(CHIP_LPC1125) + IOCON_SSEL1_LOC_PIO2_2 = (0x18), /*!< Selects SSEL1 function in pin location PIO2_2 */ + IOCON_SSEL1_LOC_PIO2_4 = (0x18 | 1), /*!< Selects SSEL1 function in pin location PIO2_4 */ + + IOCON_CT16B0_CAP0_LOC_PIO0_2 = (0xC0), /*!< Selects SSEL1 CTB16B0_CAP0 function in pin location PIO0_2 */ + IOCON_CT16B0_CAP0_LOC_PIO3_3 = (0xC0 | 1), /*!< Selects SSEL1 CTB16B0_CAP0 function in pin location PIO3_3 */ + + IOCON_SCK1_LOC_PIO2_1 = (0xC4), /*!< Selects SCK1 function in pin location PIO2_1 */ + IOCON_SCK1_LOC_PIO3_2 = (0xC4 | 1), /*!< Selects SCK1 function in pin location PIO3_2 */ + + IOCON_MISO1_LOC_PIO2_2 = (0xC8), /*!< Selects MISO1 function in pin location PIO2_2 */ + IOCON_MISO1_LOC_PIO1_10 = (0xC8 | 1), /*!< Selects MISO1 function in pin location PIO1_10 */ + + IOCON_MOSI1_LOC_PIO2_3 = (0xCC), /*!< Selects MOSI1 function in pin location PIO2_3 */ + IOCON_MOSI1_LOC_PIO1_9 = (0xCC), /*!< Selects MOSI1 function in pin location PIO1_9 */ + + IOCON_CT326B0_CAP0_LOC_PIO1_5 = (0xD0), /*!< Selects CT32B0_CAP0 function in pin location PIO1_5 */ + IOCON_CT326B0_CAP0_LOC_PIO2_9 = (0xD0 | 1), /*!< Selects CT32B0_CAP0 function in pin location PIO2_9 */ + + IOCON_U0_RXD_LOC_PIO1_6 = (0xD4), /*!< Selects U0 RXD function in pin location PIO1_6 */ + IOCON_U0_RXD_LOC_PIO2_7 = (0xD4 | 1), /*!< Selects U0 RXD function in pin location PIO2_7 */ + IOCON_U0_RXD_LOC_PIO3_4 = (0xD4 | 3), /*!< Selects U0 RXD function in pin location PIO3_4 */ +#endif + +} CHIP_IOCON_PIN_LOC_T; + +typedef struct { /*!< LPC11XX/LPC11XXLV/LPC11UXX IOCON Structure */ + __IO uint32_t REG[48]; +} LPC_IOCON_T; +#endif + +/** + * IOCON function and mode selection definitions + * See the User Manual for specific modes and functions supported by the + * various LPC11xx devices. Functionality can vary per device. + */ +#define IOCON_FUNC0 0x0 /*!< Selects pin function 0 */ +#define IOCON_FUNC1 0x1 /*!< Selects pin function 1 */ +#define IOCON_FUNC2 0x2 /*!< Selects pin function 2 */ +#define IOCON_FUNC3 0x3 /*!< Selects pin function 3 */ +#define IOCON_FUNC4 0x4 /*!< Selects pin function 4 */ +#define IOCON_FUNC5 0x5 /*!< Selects pin function 5 */ +#define IOCON_FUNC6 0x6 /*!< Selects pin function 6 */ +#define IOCON_FUNC7 0x7 /*!< Selects pin function 7 */ +#define IOCON_MODE_INACT (0x0 << 3) /*!< No addition pin function */ +#define IOCON_MODE_PULLDOWN (0x1 << 3) /*!< Selects pull-down function */ +#define IOCON_MODE_PULLUP (0x2 << 3) /*!< Selects pull-up function */ +#define IOCON_MODE_REPEATER (0x3 << 3) /*!< Selects pin repeater function */ +#define IOCON_HYS_EN (0x1 << 5) /*!< Enables hysteresis */ +#define IOCON_INV_EN (0x1 << 6) /*!< Enables invert function on input */ +#define IOCON_ADMODE_EN (0x0 << 7) /*!< Enables analog input function (analog pins only) */ +#define IOCON_DIGMODE_EN (0x1 << 7) /*!< Enables digital function (analog pins only) */ +#define IOCON_SFI2C_EN (0x0 << 8) /*!< I2C standard mode/fast-mode */ +#define IOCON_STDI2C_EN (0x1 << 8) /*!< I2C standard I/O functionality */ +#define IOCON_FASTI2C_EN (0x2 << 8) /*!< I2C Fast-mode Plus */ +#define IOCON_FILT_DIS (0x1 << 8) /*!< Disables noise pulses filtering (10nS glitch filter) */ +#define IOCON_OPENDRAIN_EN (0x1 << 10) /*!< Enables open-drain function */ + +/** + * IOCON function and mode selection definitions (old) + * For backwards compatibility. + */ +#define MD_PLN (0x0 << 3) /*!< Disable pull-down and pull-up resistor at resistor at pad */ +#define MD_PDN (0x1 << 3) /*!< Enable pull-down resistor at pad */ +#define MD_PUP (0x2 << 3) /*!< Enable pull-up resistor at pad */ +#define MD_BUK (0x3 << 3) /*!< Enable pull-down and pull-up resistor at resistor at pad (repeater mode) */ +#define MD_HYS (0x1 << 5) /*!< Enable hysteresis */ +#define MD_INV (0x1 << 6) /*!< Invert enable */ +#define MD_ADMODE (0x0 << 7) /*!< Select analog mode */ +#define MD_DIGMODE (0x1 << 7) /*!< Select digitial mode */ +#define MD_DISFIL (0x0 << 8) /*!< Disable 10nS input glitch filter */ +#define MD_ENFIL (0x1 << 8) /*!< Enable 10nS input glitch filter */ +#define MD_SFI2C (0x0 << 8) /*!< I2C standard mode/fast-mode */ +#define MD_STDI2C (0x1 << 8) /*!< I2C standard I/O functionality */ +#define MD_FASTI2C (0x2 << 8) /*!< I2C Fast-mode Plus */ +#define MD_OPENDRAIN (0x1 << 10) /*!< Open drain mode bit */ +#define FUNC0 0x0 +#define FUNC1 0x1 +#define FUNC2 0x2 +#define FUNC3 0x3 +#define FUNC4 0x4 +#define FUNC5 0x5 +#define FUNC6 0x6 +#define FUNC7 0x7 + +#if defined(CHIP_LPC11UXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11AXX) +/** + * @brief Sets I/O Control pin mux + * @param pIOCON : The base of IOCON peripheral on the chip + * @param port : GPIO port to mux + * @param pin : GPIO pin to mux + * @param modefunc : OR'ed values or type IOCON_* + * @return Nothing + */ +void Chip_IOCON_PinMuxSet(LPC_IOCON_T *pIOCON, uint8_t port, uint8_t pin, uint32_t modefunc); + +/** + * @brief I/O Control pin mux + * @param pIOCON : The base of IOCON peripheral on the chip + * @param port : GPIO port to mux + * @param pin : GPIO pin to mux + * @param mode : OR'ed values or type IOCON_* + * @param func : Pin function, value of type IOCON_FUNC? + * @return Nothing + */ +STATIC INLINE void Chip_IOCON_PinMux(LPC_IOCON_T *pIOCON, uint8_t port, uint8_t pin, uint16_t mode, uint8_t func) +{ + Chip_IOCON_PinMuxSet(pIOCON, port, pin, (uint32_t) (mode | func)); +} + +#else + +/** + * @brief Sets I/O Control pin mux + * @param pIOCON : The base of IOCON peripheral on the chip + * @param pin : GPIO pin to mux + * @param modefunc : OR'ed values or type IOCON_* + * @return Nothing + */ +STATIC INLINE void Chip_IOCON_PinMuxSet(LPC_IOCON_T *pIOCON, CHIP_IOCON_PIO_T pin, uint32_t modefunc) +{ + pIOCON->REG[pin] = modefunc; +} + +/** + * @brief I/O Control pin mux + * @param pIOCON : The base of IOCON peripheral on the chip + * @param pin : GPIO pin to mux + * @param mode : OR'ed values or type IOCON_* + * @param func : Pin function, value of type IOCON_FUNC? + * @return Nothing + */ +STATIC INLINE void Chip_IOCON_PinMux(LPC_IOCON_T *pIOCON, CHIP_IOCON_PIO_T pin, uint16_t mode, uint8_t func) +{ + Chip_IOCON_PinMuxSet(pIOCON, pin, (uint32_t) (mode | func)); +} + +/** + * @brief Select pin location + * @param pIOCON : The base of IOCON peripheral on the chip + * @param sel : location selection + * @return Nothing + */ +STATIC INLINE void Chip_IOCON_PinLocSel(LPC_IOCON_T *pIOCON, CHIP_IOCON_PIN_LOC_T sel) +{ + pIOCON->REG[sel >> 2] = sel & 0x03; +} + +#endif /* defined(CHIP_LPC11UXX) || defined (CHIP_LPC11EXX) || defined (CHIP_LPC11AXX) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __IOCON_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/lpc_types.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/lpc_types.h new file mode 100755 index 0000000..772143e --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/lpc_types.h @@ -0,0 +1,216 @@ +/* + * @brief Common types used in LPC functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __LPC_TYPES_H_ +#define __LPC_TYPES_H_ + +#include +#include + +/** @defgroup LPC_Types CHIP: LPC Common Types + * @ingroup CHIP_Common + * @{ + */ + +/** @defgroup LPC_Types_Public_Types LPC Public Types + * @{ + */ + +/** + * @brief Boolean Type definition + */ +typedef enum {FALSE = 0, TRUE = !FALSE} Bool; + +/** + * @brief Boolean Type definition + */ +#if !defined(__cplusplus) +// typedef enum {false = 0, true = !false} bool; +#endif + +/** + * @brief Flag Status and Interrupt Flag Status type definition + */ +typedef enum {RESET = 0, SET = !RESET} FlagStatus, IntStatus, SetState; +#define PARAM_SETSTATE(State) ((State == RESET) || (State == SET)) + +/** + * @brief Functional State Definition + */ +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; +#define PARAM_FUNCTIONALSTATE(State) ((State == DISABLE) || (State == ENABLE)) + +/** + * @ Status type definition + */ +typedef enum {ERROR = 0, SUCCESS = !ERROR} Status; + +/** + * Read/Write transfer type mode (Block or non-block) + */ +typedef enum { + NONE_BLOCKING = 0, /**< None Blocking type */ + BLOCKING, /**< Blocking type */ +} TRANSFER_BLOCK_T; + +/** Pointer to Function returning Void (any number of parameters) */ +typedef void (*PFV)(); + +/** Pointer to Function returning int32_t (any number of parameters) */ +typedef int32_t (*PFI)(); + +/** + * @} + */ + +/** @defgroup LPC_Types_Public_Macros LPC Public Macros + * @{ + */ + +/* _BIT(n) sets the bit at position "n" + * _BIT(n) is intended to be used in "OR" and "AND" expressions: + * e.g., "(_BIT(3) | _BIT(7))". + */ +#undef _BIT +/* Set bit macro */ +#define _BIT(n) (1 << (n)) + +/* _SBF(f,v) sets the bit field starting at position "f" to value "v". + * _SBF(f,v) is intended to be used in "OR" and "AND" expressions: + * e.g., "((_SBF(5,7) | _SBF(12,0xF)) & 0xFFFF)" + */ +#undef _SBF +/* Set bit field macro */ +#define _SBF(f, v) ((v) << (f)) + +/* _BITMASK constructs a symbol with 'field_width' least significant + * bits set. + * e.g., _BITMASK(5) constructs '0x1F', _BITMASK(16) == 0xFFFF + * The symbol is intended to be used to limit the bit field width + * thusly: + * = (any_expression) & _BITMASK(x), where 0 < x <= 32. + * If "any_expression" results in a value that is larger than can be + * contained in 'x' bits, the bits above 'x - 1' are masked off. When + * used with the _SBF example above, the example would be written: + * a_reg = ((_SBF(5,7) | _SBF(12,0xF)) & _BITMASK(16)) + * This ensures that the value written to a_reg is no wider than + * 16 bits, and makes the code easier to read and understand. + */ +#undef _BITMASK +/* Bitmask creation macro */ +#define _BITMASK(field_width) ( _BIT(field_width) - 1) + +/* NULL pointer */ +#ifndef NULL +#define NULL ((void *) 0) +#endif + +/* Number of elements in an array */ +#define NELEMENTS(array) (sizeof(array) / sizeof(array[0])) + +/* Static data/function define */ +#define STATIC static +/* External data/function define */ +#define EXTERN extern + +#if !defined(MAX) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +#if !defined(MIN) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +/** + * @} + */ + +/* Old Type Definition compatibility */ +/** @addtogroup LPC_Types_Public_Types + * @{ + */ + +/** LPC type for character type */ +typedef char CHAR; + +/** LPC type for 8 bit unsigned value */ +typedef uint8_t UNS_8; + +/** LPC type for 8 bit signed value */ +typedef int8_t INT_8; + +/** LPC type for 16 bit unsigned value */ +typedef uint16_t UNS_16; + +/** LPC type for 16 bit signed value */ +typedef int16_t INT_16; + +/** LPC type for 32 bit unsigned value */ +typedef uint32_t UNS_32; + +/** LPC type for 32 bit signed value */ +typedef int32_t INT_32; + +/** LPC type for 64 bit signed value */ +typedef int64_t INT_64; + +/** LPC type for 64 bit unsigned value */ +typedef uint64_t UNS_64; + +#ifdef __CODE_RED +#define BOOL_32 bool +#define BOOL_16 bool +#define BOOL_8 bool +#else +/** 32 bit boolean type */ +typedef bool BOOL_32; + +/** 16 bit boolean type */ +typedef bool BOOL_16; + +/** 8 bit boolean type */ +typedef bool BOOL_8; +#endif + +#ifdef __CC_ARM +#define INLINE __inline +#else +#define INLINE inline +#endif + +/** + * @} + */ + +/** + * @} + */ + +#endif /* __LPC_TYPES_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/pinint_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/pinint_11xx.h new file mode 100755 index 0000000..680fa8e --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/pinint_11xx.h @@ -0,0 +1,257 @@ +/* + * @brief LPC11xx Pin Interrupt and Pattern Match Registers and driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __PININT_11XX_H_ +#define __PININT_11XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup PININT_11XX CHIP: LPC11xx Pin Interrupt and Pattern Match driver + * @ingroup CHIP_11XX_Drivers + * For device familes identified with CHIP definitions CHIP_LPC11AXX, + * CHIP_LPC11EXX, and CHIP_LPC11UXX only. + * @{ + */ + +#if defined(CHIP_LPC11AXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) + +/** + * @brief LPC11xx Pin Interrupt and Pattern Match register block structure + */ +typedef struct { /*!< PIN_INT Structure */ + __IO uint32_t ISEL; /*!< Pin Interrupt Mode register */ + __IO uint32_t IENR; /*!< Pin Interrupt Enable (Rising) register */ + __IO uint32_t SIENR; /*!< Set Pin Interrupt Enable (Rising) register */ + __IO uint32_t CIENR; /*!< Clear Pin Interrupt Enable (Rising) register */ + __IO uint32_t IENF; /*!< Pin Interrupt Enable Falling Edge / Active Level register */ + __IO uint32_t SIENF; /*!< Set Pin Interrupt Enable Falling Edge / Active Level register */ + __IO uint32_t CIENF; /*!< Clear Pin Interrupt Enable Falling Edge / Active Level address */ + __IO uint32_t RISE; /*!< Pin Interrupt Rising Edge register */ + __IO uint32_t FALL; /*!< Pin Interrupt Falling Edge register */ + __IO uint32_t IST; /*!< Pin Interrupt Status register */ +} LPC_PIN_INT_T; + +/** + * LPC11xx Pin Interrupt channel values + */ +#define PININTCH0 (1 << 0) +#define PININTCH1 (1 << 1) +#define PININTCH2 (1 << 2) +#define PININTCH3 (1 << 3) +#define PININTCH4 (1 << 4) +#define PININTCH5 (1 << 5) +#define PININTCH6 (1 << 6) +#define PININTCH7 (1 << 7) +#define PININTCH(ch) (1 << (ch)) + +/** + * @brief Initialize Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @return Nothing + * @note This function should be used after the Chip_GPIO_Init() function. + */ +STATIC INLINE void Chip_PININT_Init(LPC_PIN_INT_T *pPININT) {} + +/** + * @brief De-Initialize Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @return Nothing + */ +STATIC INLINE void Chip_PININT_DeInit(LPC_PIN_INT_T *pPININT) {} + +/** + * @brief Configure the pins as edge sensitive in Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_SetPinModeEdge(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->ISEL &= ~pins; +} + +/** + * @brief Configure the pins as level sensitive in Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_SetPinModeLevel(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->ISEL |= pins; +} + +/** + * @brief Return current PININT rising edge or high level interrupt enable state + * @param pPININT : The base address of Pin interrupt block + * @return A bifield containing the high edge/level interrupt enables for each + * interrupt. Bit 0 = PININT0, 1 = PININT1, etc. + * For each bit, a 0 means the high edge/level interrupt is disabled, while a 1 + * means it's enabled. + */ +STATIC INLINE uint32_t Chip_PININT_GetHighEnabled(LPC_PIN_INT_T *pPININT) +{ + return pPININT->IENR; +} + +/** + * @brief Enable high edge/level PININT interrupts for pins + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins to enable (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_EnableIntHigh(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->SIENR = pins; +} + +/** + * @brief Disable high edge/level PININT interrupts for pins + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins to disable (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_DisableIntHigh(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->CIENR = pins; +} + +/** + * @brief Return current PININT falling edge or low level interrupt enable state + * @param pPININT : The base address of Pin interrupt block + * @return A bifield containing the low edge/level interrupt enables for each + * interrupt. Bit 0 = PININT0, 1 = PININT1, etc. + * For each bit, a 0 means the low edge/level interrupt is disabled, while a 1 + * means it's enabled. + */ +STATIC INLINE uint32_t Chip_PININT_GetLowEnabled(LPC_PIN_INT_T *pPININT) +{ + return pPININT->IENF; +} + +/** + * @brief Enable low edge/level PININT interrupts for pins + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins to enable (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_EnableIntLow(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->SIENF = pins; +} + +/** + * @brief Disable low edge/level PININT interrupts for pins + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins to disable (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_DisableIntLow(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->CIENF = pins; +} + +/** + * @brief Return pin states that have a detected latched high edge (RISE) state + * @param pPININT : The base address of Pin interrupt block + * @return PININT states (bit n = high) with a latched rise state detected + */ +STATIC INLINE uint32_t Chip_PININT_GetRiseStates(LPC_PIN_INT_T *pPININT) +{ + return pPININT->RISE; +} + +/** + * @brief Clears pin states that had a latched high edge (RISE) state + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins with latched states to clear + * @return Nothing + */ +STATIC INLINE void Chip_PININT_ClearRiseStates(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->RISE = pins; +} + +/** + * @brief Return pin states that have a detected latched falling edge (FALL) state + * @param pPININT : The base address of Pin interrupt block + * @return PININT states (bit n = high) with a latched rise state detected + */ +STATIC INLINE uint32_t Chip_PININT_GetFallStates(LPC_PIN_INT_T *pPININT) +{ + return pPININT->FALL; +} + +/** + * @brief Clears pin states that had a latched falling edge (FALL) state + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins with latched states to clear + * @return Nothing + */ +STATIC INLINE void Chip_PININT_ClearFallStates(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->FALL = pins; +} + +/** + * @brief Get interrupt status from Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @return Interrupt status (bit n for PININTn = high means interrupt ie pending) + */ +STATIC INLINE uint32_t Chip_PININT_GetIntStatus(LPC_PIN_INT_T *pPININT) +{ + return pPININT->IST; +} + +/** + * @brief Clear interrupt status in Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pin interrupts to clear (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_ClearIntStatus(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->IST = pins; +} + +#endif /* defined(CHIP_LPC11AXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __PININT_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/pmu_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/pmu_11xx.h new file mode 100755 index 0000000..d08d8a5 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/pmu_11xx.h @@ -0,0 +1,201 @@ +/* + * @brief LPC11xx PMU chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __PMU_11XX_H_ +#define __PMU_11XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup PMU_11XX CHIP: LPC11xx Power Management Unit block driver + * @ingroup CHIP_11XX_Drivers + * This driver only applies to devices in the CHIP_LPC11AXX, CHIP_LPC11CXX, + * CHIP_LPC11EXX, CHIP_LPC11UXX, and CHIP_LPC1125 families. Note different + * families may have slightly different PMU support. + * @{ + */ + +#if defined(CHIP_LPC11AXX) || defined(CHIP_LPC11CXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) || defined(CHIP_LPC1125) +#if defined(CHIP_LPC1125) +#error "LPC1125 support for the PMU driver is not ready" +#endif + +/** + * @brief LPC11xx Power Management Unit register block structure + */ +typedef struct { + __IO uint32_t PCON; /*!< Offset: 0x000 Power control Register (R/W) */ + __IO uint32_t GPREG[4]; /*!< Offset: 0x004 General purpose Registers 0..3 (R/W) */ +} LPC_PMU_T; + +/** + * @brief LPC11xx low power mode type definitions + */ +typedef enum CHIP_PMU_MCUPOWER { + PMU_MCU_SLEEP = 0, /*!< Sleep mode */ +#if defined(CHIP_LPC11AXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) + PMU_MCU_DEEP_SLEEP, /*!< Deep Sleep mode */ + PMU_MCU_POWER_DOWN, /*!< Power down mode */ + PMU_MCU_DEEP_PWRDOWN /*!< Deep power down mode */ +#elif defined(CHIP_LPC11CXX) + PMU_MCU_DEEP_PWRDOWN = 3 /*!< Deep power down mode */ +#endif +} CHIP_PMU_MCUPOWER_T; + +/** + * PMU PCON register bit fields & masks + */ +#define PMU_PCON_PM_SLEEP (0x0) /*!< ARM WFI enter sleep mode */ +#if defined(CHIP_LPC11AXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) +#define PMU_PCON_PM_DEEPSLEEP (0x1) /*!< ARM WFI enter Deep-sleep mode */ +#define PMU_PCON_PM_POWERDOWN (0x2) /*!< ARM WFI enter Power-down mode */ +#define PMU_PCON_PM_DEEPPOWERDOWN (0x3) /*!< ARM WFI enter Deep Power-down mode */ +#elif defined(CHIP_LPC11CXX) +#define PMU_PCON_PM_DEEPPOWERDOWN (0x2) +#endif +#define PMU_PCON_SLEEPFLAG (1 << 8) /*!< Sleep mode flag */ +#define PMU_PCON_DPDFLAG (1 << 11) /*!< Deep power-down flag */ + +/** + * @brief Write a value to a GPREG register + * @param pPMU : Pointer to PMU register block + * @param regIndex : Register index to write to, must be 0..3 + * @param value : Value to write + * @return None + */ +STATIC INLINE void Chip_PMU_WriteGPREG(LPC_PMU_T *pPMU, uint8_t regIndex, uint32_t value) +{ + pPMU->GPREG[regIndex] = value; +} + +/** + * @brief Read a value to a GPREG register + * @param pPMU : Pointer to PMU register block + * @param regIndex : Register index to read from, must be 0..3 + * @return Value read from the GPREG register + */ +STATIC INLINE uint32_t Chip_PMU_ReadGPREG(LPC_PMU_T *pPMU, uint8_t regIndex) +{ + return pPMU->GPREG[regIndex]; +} + +/** + * @brief Enter MCU Sleep mode + * @param pPMU : Pointer to PMU register block + * @return None + * @note The sleep mode affects the ARM Cortex-M0+ core only. Peripherals + * and memories are active. + */ +void Chip_PMU_SleepState(LPC_PMU_T *pPMU); + +#if defined(CHIP_LPC11AXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) +/** + * @brief Enter MCU Deep Sleep mode + * @param pPMU : Pointer to PMU register block + * @return None + * @note In Deep-sleep mode, the peripherals receive no internal clocks. + * The flash is in stand-by mode. The SRAM memory and all peripheral registers + * as well as the processor maintain their internal states. The WWDT, WKT, + * and BOD can remain active to wake up the system on an interrupt. + */ +void Chip_PMU_DeepSleepState(LPC_PMU_T *pPMU); + +/** + * @brief Enter MCU Power down mode + * @param pPMU : Pointer to PMU register block + * @return None + * @note In Power-down mode, the peripherals receive no internal clocks. + * The internal SRAM memory and all peripheral registers as well as the + * processor maintain their internal states. The flash memory is powered + * down. The WWDT, WKT, and BOD can remain active to wake up the system + * on an interrupt. + */ +void Chip_PMU_PowerDownState(LPC_PMU_T *pPMU); +#endif + +/** + * @brief Enter MCU Deep Power down mode + * @param pPMU : Pointer to PMU register block + * @return None + * @note For maximal power savings, the entire system is shut down + * except for the general purpose registers in the PMU and the self + * wake-up timer. Only the general purpose registers in the PMU maintain + * their internal states. The part can wake up on a pulse on the WAKEUP + * pin or when the self wake-up timer times out. On wake-up, the part + * reboots. + */ +void Chip_PMU_DeepPowerDownState(LPC_PMU_T *pPMU); + +/** + * @brief Place the MCU in a low power state + * @param pPMU : Pointer to PMU register block + * @param SleepMode : Sleep mode + * @return None + */ +void Chip_PMU_Sleep(LPC_PMU_T *pPMU, CHIP_PMU_MCUPOWER_T SleepMode); + +/** + * @brief Returns sleep/power-down flags + * @param pPMU : Pointer to PMU register block + * @return Or'ed values of PMU_PCON_SLEEPFLAG and PMU_PCON_DPDFLAG + * @note These indicate that the PMU is setup for entry into a low + * power state on the next WFI() instruction. + */ +STATIC INLINE uint32_t Chip_PMU_GetSleepFlags(LPC_PMU_T *pPMU) +{ + return (pPMU->PCON & (PMU_PCON_SLEEPFLAG | PMU_PCON_DPDFLAG)); +} + +/** + * @brief Clears sleep/power-down flags + * @param pPMU : Pointer to PMU register block + * @param flags : Or'ed value of PMU_PCON_SLEEPFLAG and PMU_PCON_DPDFLAG + * @return Nothing + * @note Use this function to clear a low power state prior to calling + * WFI(). + */ +STATIC INLINE void Chip_PMU_ClearSleepFlags(LPC_PMU_T *pPMU, uint32_t flags) +{ + pPMU->PCON &= ~flags; +} + +#endif /* defined(CHIP_LPC11AXX) || defined(CHIP_LPC11CXX) || ... */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __PMU_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/ring_buffer.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/ring_buffer.h new file mode 100755 index 0000000..30412d9 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/ring_buffer.h @@ -0,0 +1,188 @@ +/* + * @brief Common ring buffer support functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __RING_BUFFER_H_ +#define __RING_BUFFER_H_ + +#include "lpc_types.h" + +/** @defgroup Ring_Buffer CHIP: Simple ring buffer implementation + * @ingroup CHIP_Common + * @{ + */ + +/** + * @brief Ring buffer structure + */ +typedef struct { + void *data; + int count; + int itemSz; + uint32_t head; + uint32_t tail; +} RINGBUFF_T; + +/** + * @def RB_VHEAD(rb) + * volatile typecasted head index + */ +#define RB_VHEAD(rb) (*(volatile uint32_t *) &(rb)->head) + +/** + * @def RB_VTAIL(rb) + * volatile typecasted tail index + */ +#define RB_VTAIL(rb) (*(volatile uint32_t *) &(rb)->tail) + +/** + * @brief Initialize ring buffer + * @param RingBuff : Pointer to ring buffer to initialize + * @param buffer : Pointer to buffer to associate with RingBuff + * @param itemSize : Size of each buffer item size + * @param count : Size of ring buffer + * @note Memory pointed by @a buffer must have correct alignment of + * @a itemSize, and @a count must be a power of 2 and must at + * least be 2 or greater. + * @return Nothing + */ +int RingBuffer_Init(RINGBUFF_T *RingBuff, void *buffer, int itemSize, int count); + +/** + * @brief Resets the ring buffer to empty + * @param RingBuff : Pointer to ring buffer + * @return Nothing + */ +STATIC INLINE void RingBuffer_Flush(RINGBUFF_T *RingBuff) +{ + RingBuff->head = RingBuff->tail = 0; +} + +/** + * @brief Return size the ring buffer + * @param RingBuff : Pointer to ring buffer + * @return Size of the ring buffer in bytes + */ +STATIC INLINE int RingBuffer_GetSize(RINGBUFF_T *RingBuff) +{ + return RingBuff->count; +} + +/** + * @brief Return number of items in the ring buffer + * @param RingBuff : Pointer to ring buffer + * @return Number of items in the ring buffer + */ +STATIC INLINE int RingBuffer_GetCount(RINGBUFF_T *RingBuff) +{ + return RB_VHEAD(RingBuff) - RB_VTAIL(RingBuff); +} + +/** + * @brief Return number of free items in the ring buffer + * @param RingBuff : Pointer to ring buffer + * @return Number of free items in the ring buffer + */ +STATIC INLINE int RingBuffer_GetFree(RINGBUFF_T *RingBuff) +{ + return RingBuff->count - RingBuffer_GetCount(RingBuff); +} + +/** + * @brief Return number of items in the ring buffer + * @param RingBuff : Pointer to ring buffer + * @return 1 if the ring buffer is full, otherwise 0 + */ +STATIC INLINE int RingBuffer_IsFull(RINGBUFF_T *RingBuff) +{ + return (RingBuffer_GetCount(RingBuff) >= RingBuff->count); +} + +/** + * @brief Return empty status of ring buffer + * @param RingBuff : Pointer to ring buffer + * @return 1 if the ring buffer is empty, otherwise 0 + */ +STATIC INLINE int RingBuffer_IsEmpty(RINGBUFF_T *RingBuff) +{ + return RB_VHEAD(RingBuff) == RB_VTAIL(RingBuff); +} + +/** + * @brief Insert a single item into ring buffer + * @param RingBuff : Pointer to ring buffer + * @param data : pointer to item + * @return 1 when successfully inserted, + * 0 on error (Buffer not initialized using + * RingBuffer_Init() or attempted to insert + * when buffer is full) + */ +int RingBuffer_Insert(RINGBUFF_T *RingBuff, const void *data); + +/** + * @brief Insert an array of items into ring buffer + * @param RingBuff : Pointer to ring buffer + * @param data : Pointer to first element of the item array + * @param num : Number of items in the array + * @return number of items successfully inserted, + * 0 on error (Buffer not initialized using + * RingBuffer_Init() or attempted to insert + * when buffer is full) + */ +int RingBuffer_InsertMult(RINGBUFF_T *RingBuff, const void *data, int num); + +/** + * @brief Pop an item from the ring buffer + * @param RingBuff : Pointer to ring buffer + * @param data : Pointer to memory where popped item be stored + * @return 1 when item popped successfuly onto @a data, + * 0 When error (Buffer not initialized using + * RingBuffer_Init() or attempted to pop item when + * the buffer is empty) + */ +int RingBuffer_Pop(RINGBUFF_T *RingBuff, void *data); + +/** + * @brief Pop an array of items from the ring buffer + * @param RingBuff : Pointer to ring buffer + * @param data : Pointer to memory where popped items be stored + * @param num : Max number of items array @a data can hold + * @return Number of items popped onto @a data, + * 0 on error (Buffer not initialized using RingBuffer_Init() + * or attempted to pop when the buffer is empty) + */ +int RingBuffer_PopMult(RINGBUFF_T *RingBuff, void *data, int num); + + +/** + * @} + */ + +#endif /* __RING_BUFFER_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/romapi_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/romapi_11xx.h new file mode 100755 index 0000000..2ca6cc4 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/romapi_11xx.h @@ -0,0 +1,78 @@ +/* + * @brief LPC11xx ROM API declarations and functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __ROMAPI_11XX_H_ +#define __ROMAPI_11XX_H_ + +#include "error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup ROMAPI_11XX CHIP: LPC11XX ROM API declarations and functions + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +/** + * @brief LPC11XX High level ROM API structure + */ +typedef struct { + const uint32_t usbdApiBase; /*!< USBD API function table base address */ + const uint32_t reserved0; /*!< Reserved */ + const uint32_t candApiBase; /*!< CAN API function table base address */ + const uint32_t pwrApiBase; /*!< Power API function table base address */ + const uint32_t reserved1; /*!< Reserved */ + const uint32_t reserved2; /*!< Reserved */ + const uint32_t reserved3; /*!< Reserved */ + const uint32_t reserved4; /*!< Reserved */ +} LPC_ROM_API_T; + +/** + * @brief LPC11XX IAP_ENTRY API function type + */ +typedef void (*IAP_ENTRY_T)(unsigned int[], unsigned int[]); + +static INLINE void iap_entry(unsigned int cmd_param[], unsigned int status_result[]) +{ + ((IAP_ENTRY_T) IAP_ENTRY_LOCATION)(cmd_param, status_result); +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ROMAPI_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/ssp_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/ssp_11xx.h new file mode 100755 index 0000000..4fe1181 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/ssp_11xx.h @@ -0,0 +1,571 @@ +/* + * @brief LPC11xx SSP Registers and control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __SSP_11XX_H_ +#define __SSP_11XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup SSP_11XX CHIP: LPC11xx SSP register block and driver + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +/** + * @brief SSP register block structure + */ +typedef struct { /*!< SSPn Structure */ + __IO uint32_t CR0; /*!< Control Register 0. Selects the serial clock rate, bus type, and data size. */ + __IO uint32_t CR1; /*!< Control Register 1. Selects master/slave and other modes. */ + __IO uint32_t DR; /*!< Data Register. Writes fill the transmit FIFO, and reads empty the receive FIFO. */ + __I uint32_t SR; /*!< Status Register */ + __IO uint32_t CPSR; /*!< Clock Prescale Register */ + __IO uint32_t IMSC; /*!< Interrupt Mask Set and Clear Register */ + __I uint32_t RIS; /*!< Raw Interrupt Status Register */ + __I uint32_t MIS; /*!< Masked Interrupt Status Register */ + __O uint32_t ICR; /*!< SSPICR Interrupt Clear Register */ +} LPC_SSP_T; + +/** + * Macro defines for CR0 register + */ + +/** SSP data size select, must be 4 bits to 16 bits */ +#define SSP_CR0_DSS(n) ((uint32_t) ((n) & 0xF)) +/** SSP control 0 Motorola SPI mode */ +#define SSP_CR0_FRF_SPI ((uint32_t) (0 << 4)) +/** SSP control 0 TI synchronous serial mode */ +#define SSP_CR0_FRF_TI ((uint32_t) (1 << 4)) +/** SSP control 0 National Micro-wire mode */ +#define SSP_CR0_FRF_MICROWIRE ((uint32_t) (2 << 4)) +/** SPI clock polarity bit (used in SPI mode only), (1) = maintains the + bus clock high between frames, (0) = low */ +#define SSP_CR0_CPOL_LO ((uint32_t) (0)) +#define SSP_CR0_CPOL_HI ((uint32_t) (1 << 6)) +/** SPI clock out phase bit (used in SPI mode only), (1) = captures data + on the second clock transition of the frame, (0) = first */ +#define SSP_CR0_CPHA_FIRST ((uint32_t) (0)) +#define SSP_CR0_CPHA_SECOND ((uint32_t) (1 << 7)) +/** SSP serial clock rate value load macro, divider rate is + PERIPH_CLK / (cpsr * (SCR + 1)) */ +#define SSP_CR0_SCR(n) ((uint32_t) ((n & 0xFF) << 8)) +/** SSP CR0 bit mask */ +#define SSP_CR0_BITMASK ((uint32_t) (0xFFFF)) +/** SSP CR0 bit mask */ +#define SSP_CR0_BITMASK ((uint32_t) (0xFFFF)) +/** SSP serial clock rate value load macro, divider rate is + PERIPH_CLK / (cpsr * (SCR + 1)) */ +#define SSP_CR0_SCR(n) ((uint32_t) ((n & 0xFF) << 8)) + +/** + * Macro defines for CR1 register + */ + +/** SSP control 1 loopback mode enable bit */ +#define SSP_CR1_LBM_EN ((uint32_t) (1 << 0)) +/** SSP control 1 enable bit */ +#define SSP_CR1_SSP_EN ((uint32_t) (1 << 1)) +/** SSP control 1 slave enable */ +#define SSP_CR1_SLAVE_EN ((uint32_t) (1 << 2)) +#define SSP_CR1_MASTER_EN ((uint32_t) (0)) +/** SSP control 1 slave out disable bit, disables transmit line in slave + mode */ +#define SSP_CR1_SO_DISABLE ((uint32_t) (1 << 3)) +/** SSP CR1 bit mask */ +#define SSP_CR1_BITMASK ((uint32_t) (0x0F)) + +/** SSP CPSR bit mask */ +#define SSP_CPSR_BITMASK ((uint32_t) (0xFF)) +/** + * Macro defines for DR register + */ + +/** SSP data bit mask */ +#define SSP_DR_BITMASK(n) ((n) & 0xFFFF) + +/** + * Macro defines for SR register + */ + +/** SSP SR bit mask */ +#define SSP_SR_BITMASK ((uint32_t) (0x1F)) + +/** ICR bit mask */ +#define SSP_ICR_BITMASK ((uint32_t) (0x03)) + +/** + * @brief SSP Type of Status + */ +typedef enum _SSP_STATUS { + SSP_STAT_TFE = ((uint32_t)(1 << 0)),/**< TX FIFO Empty */ + SSP_STAT_TNF = ((uint32_t)(1 << 1)),/**< TX FIFO not full */ + SSP_STAT_RNE = ((uint32_t)(1 << 2)),/**< RX FIFO not empty */ + SSP_STAT_RFF = ((uint32_t)(1 << 3)),/**< RX FIFO full */ + SSP_STAT_BSY = ((uint32_t)(1 << 4)),/**< SSP Busy */ +} SSP_STATUS_T; + +/** + * @brief SSP Type of Interrupt Mask + */ +typedef enum _SSP_INTMASK { + SSP_RORIM = ((uint32_t)(1 << 0)), /**< Overun */ + SSP_RTIM = ((uint32_t)(1 << 1)),/**< TimeOut */ + SSP_RXIM = ((uint32_t)(1 << 2)),/**< Rx FIFO is at least half full */ + SSP_TXIM = ((uint32_t)(1 << 3)),/**< Tx FIFO is at least half empty */ + SSP_INT_MASK_BITMASK = ((uint32_t)(0xF)), +} SSP_INTMASK_T; + +/** + * @brief SSP Type of Mask Interrupt Status + */ +typedef enum _SSP_MASKINTSTATUS { + SSP_RORMIS = ((uint32_t)(1 << 0)), /**< Overun */ + SSP_RTMIS = ((uint32_t)(1 << 1)), /**< TimeOut */ + SSP_RXMIS = ((uint32_t)(1 << 2)), /**< Rx FIFO is at least half full */ + SSP_TXMIS = ((uint32_t)(1 << 3)), /**< Tx FIFO is at least half empty */ + SSP_MASK_INT_STAT_BITMASK = ((uint32_t)(0xF)), +} SSP_MASKINTSTATUS_T; + +/** + * @brief SSP Type of Raw Interrupt Status + */ +typedef enum _SSP_RAWINTSTATUS { + SSP_RORRIS = ((uint32_t)(1 << 0)), /**< Overun */ + SSP_RTRIS = ((uint32_t)(1 << 1)), /**< TimeOut */ + SSP_RXRIS = ((uint32_t)(1 << 2)), /**< Rx FIFO is at least half full */ + SSP_TXRIS = ((uint32_t)(1 << 3)), /**< Tx FIFO is at least half empty */ + SSP_RAW_INT_STAT_BITMASK = ((uint32_t)(0xF)), +} SSP_RAWINTSTATUS_T; + +typedef enum _SSP_INTCLEAR { + SSP_RORIC = 0x0, + SSP_RTIC = 0x1, + SSP_INT_CLEAR_BITMASK = 0x3, +} SSP_INTCLEAR_T; + +/* + * @brief SSP clock format + */ +typedef enum CHIP_SSP_CLOCK_FORMAT { + SSP_CLOCK_CPHA0_CPOL0 = (0 << 6), /**< CPHA = 0, CPOL = 0 */ + SSP_CLOCK_CPHA0_CPOL1 = (1u << 6), /**< CPHA = 0, CPOL = 1 */ + SSP_CLOCK_CPHA1_CPOL0 = (2u << 6), /**< CPHA = 1, CPOL = 0 */ + SSP_CLOCK_CPHA1_CPOL1 = (3u << 6), /**< CPHA = 1, CPOL = 1 */ + SSP_CLOCK_MODE0 = SSP_CLOCK_CPHA0_CPOL0,/**< alias */ + SSP_CLOCK_MODE1 = SSP_CLOCK_CPHA1_CPOL0,/**< alias */ + SSP_CLOCK_MODE2 = SSP_CLOCK_CPHA0_CPOL1,/**< alias */ + SSP_CLOCK_MODE3 = SSP_CLOCK_CPHA1_CPOL1,/**< alias */ +} CHIP_SSP_CLOCK_MODE_T; + +/* + * @brief SSP frame format + */ +typedef enum CHIP_SSP_FRAME_FORMAT { + SSP_FRAMEFORMAT_SPI = (0 << 4), /**< Frame format: SPI */ + CHIP_SSP_FRAME_FORMAT_TI = (1u << 4), /**< Frame format: TI SSI */ + SSP_FRAMEFORMAT_MICROWIRE = (2u << 4), /**< Frame format: Microwire */ +} CHIP_SSP_FRAME_FORMAT_T; + +/* + * @brief Number of bits per frame + */ +typedef enum CHIP_SSP_BITS { + SSP_BITS_4 = (3u << 0), /*!< 4 bits/frame */ + SSP_BITS_5 = (4u << 0), /*!< 5 bits/frame */ + SSP_BITS_6 = (5u << 0), /*!< 6 bits/frame */ + SSP_BITS_7 = (6u << 0), /*!< 7 bits/frame */ + SSP_BITS_8 = (7u << 0), /*!< 8 bits/frame */ + SSP_BITS_9 = (8u << 0), /*!< 9 bits/frame */ + SSP_BITS_10 = (9u << 0), /*!< 10 bits/frame */ + SSP_BITS_11 = (10u << 0), /*!< 11 bits/frame */ + SSP_BITS_12 = (11u << 0), /*!< 12 bits/frame */ + SSP_BITS_13 = (12u << 0), /*!< 13 bits/frame */ + SSP_BITS_14 = (13u << 0), /*!< 14 bits/frame */ + SSP_BITS_15 = (14u << 0), /*!< 15 bits/frame */ + SSP_BITS_16 = (15u << 0), /*!< 16 bits/frame */ +} CHIP_SSP_BITS_T; + +/* + * @brief SSP config format + */ +typedef struct SSP_ConfigFormat { + CHIP_SSP_BITS_T bits; /*!< Format config: bits/frame */ + CHIP_SSP_CLOCK_MODE_T clockMode; /*!< Format config: clock phase/polarity */ + CHIP_SSP_FRAME_FORMAT_T frameFormat; /*!< Format config: SPI/TI/Microwire */ +} SSP_ConfigFormat; + +/** + * @brief Enable SSP operation + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + */ +STATIC INLINE void Chip_SSP_Enable(LPC_SSP_T *pSSP) +{ + pSSP->CR1 |= SSP_CR1_SSP_EN; +} + +/** + * @brief Disable SSP operation + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + */ +STATIC INLINE void Chip_SSP_Disable(LPC_SSP_T *pSSP) +{ + pSSP->CR1 &= (~SSP_CR1_SSP_EN) & SSP_CR1_BITMASK; +} + +/** + * @brief Enable loopback mode + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + * @note Serial input is taken from the serial output (MOSI or MISO) rather + * than the serial input pin + */ +STATIC INLINE void Chip_SSP_EnableLoopBack(LPC_SSP_T *pSSP) +{ + pSSP->CR1 |= SSP_CR1_LBM_EN; +} + +/** + * @brief Disable loopback mode + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + * @note Serial input is taken from the serial output (MOSI or MISO) rather + * than the serial input pin + */ +STATIC INLINE void Chip_SSP_DisableLoopBack(LPC_SSP_T *pSSP) +{ + pSSP->CR1 &= (~SSP_CR1_LBM_EN) & SSP_CR1_BITMASK; +} + +/** + * @brief Get the current status of SSP controller + * @param pSSP : The base of SSP peripheral on the chip + * @param Stat : Type of status, should be : + * - SSP_STAT_TFE + * - SSP_STAT_TNF + * - SSP_STAT_RNE + * - SSP_STAT_RFF + * - SSP_STAT_BSY + * @return SSP controller status, SET or RESET + */ +STATIC INLINE FlagStatus Chip_SSP_GetStatus(LPC_SSP_T *pSSP, SSP_STATUS_T Stat) +{ + return (pSSP->SR & Stat) ? SET : RESET; +} + +/** + * @brief Get the masked interrupt status + * @param pSSP : The base of SSP peripheral on the chip + * @return SSP Masked Interrupt Status Register value + * @note The return value contains a 1 for each interrupt condition that is asserted and enabled (masked) + */ +STATIC INLINE uint32_t Chip_SSP_GetIntStatus(LPC_SSP_T *pSSP) +{ + return pSSP->MIS; +} + +/** + * @brief Get the raw interrupt status + * @param pSSP : The base of SSP peripheral on the chip + * @param RawInt : Interrupt condition to be get status, shoud be : + * - SSP_RORRIS + * - SSP_RTRIS + * - SSP_RXRIS + * - SSP_TXRIS + * @return Raw interrupt status corresponding to interrupt condition , SET or RESET + * @note Get the status of each interrupt condition ,regardless of whether or not the interrupt is enabled + */ +STATIC INLINE IntStatus Chip_SSP_GetRawIntStatus(LPC_SSP_T *pSSP, SSP_RAWINTSTATUS_T RawInt) +{ + return (pSSP->RIS & RawInt) ? SET : RESET; +} + +/** + * @brief Get the number of bits transferred in each frame + * @param pSSP : The base of SSP peripheral on the chip + * @return the number of bits transferred in each frame minus one + * @note The return value is 0x03 -> 0xF corresponding to 4bit -> 16bit transfer + */ +STATIC INLINE uint8_t Chip_SSP_GetDataSize(LPC_SSP_T *pSSP) +{ + return SSP_CR0_DSS(pSSP->CR0); +} + +/** + * @brief Clear the corresponding interrupt condition(s) in the SSP controller + * @param pSSP : The base of SSP peripheral on the chip + * @param IntClear: Type of cleared interrupt, should be : + * - SSP_RORIC + * - SSP_RTIC + * @return Nothing + * @note Software can clear one or more interrupt condition(s) in the SSP controller + */ +STATIC INLINE void Chip_SSP_ClearIntPending(LPC_SSP_T *pSSP, SSP_INTCLEAR_T IntClear) +{ + pSSP->ICR = IntClear; +} + +/** + * @brief Enable interrupt for the SSP + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + */ +STATIC INLINE void Chip_SSP_Int_Enable(LPC_SSP_T *pSSP) +{ + pSSP->IMSC |= SSP_TXIM; +} + +/** + * @brief Disable interrupt for the SSP + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + */ +STATIC INLINE void Chip_SSP_Int_Disable(LPC_SSP_T *pSSP) +{ + pSSP->IMSC &= (~SSP_TXIM); +} + +/** + * @brief Get received SSP data + * @param pSSP : The base of SSP peripheral on the chip + * @return SSP 16-bit data received + */ +STATIC INLINE uint16_t Chip_SSP_ReceiveFrame(LPC_SSP_T *pSSP) +{ + return (uint16_t) (SSP_DR_BITMASK(pSSP->DR)); +} + +/** + * @brief Send SSP 16-bit data + * @param pSSP : The base of SSP peripheral on the chip + * @param tx_data : SSP 16-bit data to be transmited + * @return Nothing + */ +STATIC INLINE void Chip_SSP_SendFrame(LPC_SSP_T *pSSP, uint16_t tx_data) +{ + pSSP->DR = SSP_DR_BITMASK(tx_data); +} + +/** + * @brief Set up output clocks per bit for SSP bus + * @param pSSP : The base of SSP peripheral on the chip + * @param clk_rate fs: The number of prescaler-output clocks per bit on the bus, minus one + * @param prescale : The factor by which the Prescaler divides the SSP peripheral clock PCLK + * @return Nothing + * @note The bit frequency is PCLK / (prescale x[clk_rate+1]) + */ +void Chip_SSP_SetClockRate(LPC_SSP_T *pSSP, uint32_t clk_rate, uint32_t prescale); + +/** + * @brief Set up the SSP frame format + * @param pSSP : The base of SSP peripheral on the chip + * @param bits : The number of bits transferred in each frame, should be SSP_BITS_4 to SSP_BITS_16 + * @param frameFormat : Frame format, should be : + * - SSP_FRAMEFORMAT_SPI + * - SSP_FRAME_FORMAT_TI + * - SSP_FRAMEFORMAT_MICROWIRE + * @param clockMode : Select Clock polarity and Clock phase, should be : + * - SSP_CLOCK_CPHA0_CPOL0 + * - SSP_CLOCK_CPHA0_CPOL1 + * - SSP_CLOCK_CPHA1_CPOL0 + * - SSP_CLOCK_CPHA1_CPOL1 + * @return Nothing + * @note Note: The clockFormat is only used in SPI mode + */ +STATIC INLINE void Chip_SSP_SetFormat(LPC_SSP_T *pSSP, uint32_t bits, uint32_t frameFormat, uint32_t clockMode) +{ + pSSP->CR0 = (pSSP->CR0 & ~0xFF) | bits | frameFormat | clockMode; +} + +/** + * @brief Set the SSP working as master or slave mode + * @param pSSP : The base of SSP peripheral on the chip + * @param mode : Operating mode, should be + * - SSP_MODE_MASTER + * - SSP_MODE_SLAVE + * @return Nothing + */ +STATIC INLINE void Chip_SSP_Set_Mode(LPC_SSP_T *pSSP, uint32_t mode) +{ + pSSP->CR1 = (pSSP->CR1 & ~(1 << 2)) | mode; +} + +/* + * @brief SSP mode + */ +typedef enum CHIP_SSP_MODE { + SSP_MODE_MASTER = (0 << 2), /**< Master mode */ + SSP_MODE_SLAVE = (1u << 2), /**< Slave mode */ +} CHIP_SSP_MODE_T; + +/* + * @brief SPI address + */ +typedef struct { + uint8_t port; /*!< Port Number */ + uint8_t pin; /*!< Pin number */ +} SPI_Address_t; + +/* + * @brief SSP data setup structure + */ +typedef struct { + void *tx_data; /*!< Pointer to transmit data */ + uint32_t tx_cnt; /*!< Transmit counter */ + void *rx_data; /*!< Pointer to transmit data */ + uint32_t rx_cnt; /*!< Receive counter */ + uint32_t length; /*!< Length of transfer data */ +} Chip_SSP_DATA_SETUP_T; + +/** SSP configuration parameter defines */ +/** Clock phase control bit */ +#define SSP_CPHA_FIRST SSP_CR0_CPHA_FIRST +#define SSP_CPHA_SECOND SSP_CR0_CPHA_SECOND + +/** Clock polarity control bit */ +/* There's no bug here!!! + * - If bit[6] in SSPnCR0 is 0: SSP controller maintains the bus clock low between frames. + * That means the active clock is in HI state. + * - If bit[6] in SSPnCR0 is 1 (SSP_CR0_CPOL_HI): SSP controller maintains the bus clock + * high between frames. That means the active clock is in LO state. + */ +#define SSP_CPOL_HI SSP_CR0_CPOL_LO +#define SSP_CPOL_LO SSP_CR0_CPOL_HI + +/** SSP master mode enable */ +#define SSP_SLAVE_MODE SSP_CR1_SLAVE_EN +#define SSP_MASTER_MODE SSP_CR1_MASTER_EN + +/** + * @brief Clean all data in RX FIFO of SSP + * @param pSSP : The base SSP peripheral on the chip + * @return Nothing + */ +void Chip_SSP_Int_FlushData(LPC_SSP_T *pSSP); + +/** + * @brief SSP Interrupt Read/Write with 8-bit frame width + * @param pSSP : The base SSP peripheral on the chip + * @param xf_setup : Pointer to a SSP_DATA_SETUP_T structure that contains specified + * information about transmit/receive data configuration + * @return SUCCESS or ERROR + */ +Status Chip_SSP_Int_RWFrames8Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup); + +/** + * @brief SSP Interrupt Read/Write with 16-bit frame width + * @param pSSP : The base SSP peripheral on the chip + * @param xf_setup : Pointer to a SSP_DATA_SETUP_T structure that contains specified + * information about transmit/receive data configuration + * @return SUCCESS or ERROR + */ +Status Chip_SSP_Int_RWFrames16Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup); + +/** + * @brief SSP Polling Read/Write in blocking mode + * @param pSSP : The base SSP peripheral on the chip + * @param xf_setup : Pointer to a SSP_DATA_SETUP_T structure that contains specified + * information about transmit/receive data configuration + * @return Actual data length has been transferred + * @note + * This function can be used in both master and slave mode. It starts with writing phase and after that, + * a reading phase is generated to read any data available in RX_FIFO. All needed information is prepared + * through xf_setup param. + */ +uint32_t Chip_SSP_RWFrames_Blocking(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup); + +/** + * @brief SSP Polling Write in blocking mode + * @param pSSP : The base SSP peripheral on the chip + * @param buffer : Buffer address + * @param buffer_len : Buffer length + * @return Actual data length has been transferred + * @note + * This function can be used in both master and slave mode. First, a writing operation will send + * the needed data. After that, a dummy reading operation is generated to clear data buffer + */ +uint32_t Chip_SSP_WriteFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len); + +/** + * @brief SSP Polling Read in blocking mode + * @param pSSP : The base SSP peripheral on the chip + * @param buffer : Buffer address + * @param buffer_len : The length of buffer + * @return Actual data length has been transferred + * @note + * This function can be used in both master and slave mode. First, a dummy writing operation is generated + * to clear data buffer. After that, a reading operation will receive the needed data + */ +uint32_t Chip_SSP_ReadFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len); + +/** + * @brief Initialize the SSP + * @param pSSP : The base SSP peripheral on the chip + * @return Nothing + */ +void Chip_SSP_Init(LPC_SSP_T *pSSP); + +/** + * @brief Deinitialise the SSP + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + * @note The SSP controller is disabled + */ +void Chip_SSP_DeInit(LPC_SSP_T *pSSP); + +/** + * @brief Set the SSP operating modes, master or slave + * @param pSSP : The base SSP peripheral on the chip + * @param master : 1 to set master, 0 to set slave + * @return Nothing + */ +void Chip_SSP_SetMaster(LPC_SSP_T *pSSP, bool master); + +/** + * @brief Set the clock frequency for SSP interface + * @param pSSP : The base SSP peripheral on the chip + * @param bitRate : The SSP bit rate + * @return Nothing + */ +void Chip_SSP_SetBitRate(LPC_SSP_T *pSSP, uint32_t bitRate); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __SSP_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/sys_config.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/sys_config.h new file mode 100755 index 0000000..c6e4aea --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/sys_config.h @@ -0,0 +1,33 @@ +/* + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __SYS_CONFIG_H_ +#define __SYS_CONFIG_H_ + +#endif /* __SYS_CONFIG_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/sysctl_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/sysctl_11xx.h new file mode 100755 index 0000000..6c61a10 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/sysctl_11xx.h @@ -0,0 +1,687 @@ +/* + * @brief LPC11XX System Control registers and control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __SYSCTL_11XX_H_ +#define __SYSCTL_11XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup SYSCTL_11XX CHIP: LPC11xx System Control block driver + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +/** + * @brief LPC11XX System Control block structure + */ +typedef struct { /*!< SYSCTL Structure */ + __IO uint32_t SYSMEMREMAP; /*!< System Memory remap register */ + __IO uint32_t PRESETCTRL; /*!< Peripheral reset Control register */ + __IO uint32_t SYSPLLCTRL; /*!< System PLL control register */ + __I uint32_t SYSPLLSTAT; /*!< System PLL status register */ + __IO uint32_t USBPLLCTRL; /*!< USB PLL control register, LPC11UXX only*/ + __I uint32_t USBPLLSTAT; /*!< USB PLL status register, LPC11UXX only */ + __I uint32_t RESERVED1[2]; + __IO uint32_t SYSOSCCTRL; /*!< System Oscillator control register */ + __IO uint32_t WDTOSCCTRL; /*!< Watchdog Oscillator control register */ + __IO uint32_t IRCCTRL; /*!< IRC control register, not on LPC11UXX and LPC11EXX */ + __IO uint32_t LFOSCCTRL; /*!< LF oscillator control, LPC11AXX only */ + __IO uint32_t SYSRSTSTAT; /*!< System Reset Status register */ + __I uint32_t RESERVED2[3]; + __IO uint32_t SYSPLLCLKSEL; /*!< System PLL clock source select register */ + __IO uint32_t SYSPLLCLKUEN; /*!< System PLL clock source update enable register*/ + __IO uint32_t USBPLLCLKSEL; /*!< USB PLL clock source select register, LPC11UXX only */ + __IO uint32_t USBPLLCLKUEN; /*!< USB PLL clock source update enable register, LPC11UXX only */ + __I uint32_t RESERVED3[8]; + __IO uint32_t MAINCLKSEL; /*!< Main clock source select register */ + __IO uint32_t MAINCLKUEN; /*!< Main clock source update enable register */ + __IO uint32_t SYSAHBCLKDIV; /*!< System Clock divider register */ + __I uint32_t RESERVED4; + __IO uint32_t SYSAHBCLKCTRL; /*!< System clock control register */ + __I uint32_t RESERVED5[4]; + __IO uint32_t SSP0CLKDIV; /*!< SSP0 clock divider register */ + __IO uint32_t USARTCLKDIV; /*!< UART clock divider register */ + __IO uint32_t SSP1CLKDIV; /*!< SSP1 clock divider register, not on CHIP_LPC110X, CHIP_LPC11XXLV */ + __I uint32_t RESERVED6[8]; + __IO uint32_t USBCLKSEL; /*!< USB clock source select register, LPC11UXX only */ + __IO uint32_t USBCLKUEN; /*!< USB clock source update enable register, LPC11UXX only */ + __IO uint32_t USBCLKDIV; /*!< USB clock source divider register, LPC11UXX only */ + __I uint32_t RESERVED7; + __IO uint32_t WDTCLKSEL; /*!< WDT clock source select register, some parts only */ + __IO uint32_t WDTCLKUEN; /*!< WDT clock source update enable register, some parts only */ + __IO uint32_t WDTCLKDIV; /*!< WDT clock divider register, some parts only */ + __I uint32_t RESERVED8; + __IO uint32_t CLKOUTSEL; /*!< Clock out source select register, not on LPC1102/04 */ + __IO uint32_t CLKOUTUEN; /*!< Clock out source update enable register, not on LPC1102/04 */ + __IO uint32_t CLKOUTDIV; /*!< Clock out divider register, not on LPC1102/04 */ + __I uint32_t RESERVED9[5]; + __I uint32_t PIOPORCAP[2];/*!< POR captured PIO status registers, index 1 on LPC1102/04 */ + __I uint32_t RESERVED10[18]; + __IO uint32_t BODCTRL; /*!< Brown Out Detect register */ + __IO uint32_t SYSTCKCAL; /*!< System tick counter calibration register */ + __I uint32_t RESERVED11[6]; + __IO uint32_t IRQLATENCY; /*!< IRQ delay register, on LPC11UXX and LPC11EXX only */ + __IO uint32_t NMISRC; /*!< NMI source control register,some parts only */ + __IO uint32_t PINTSEL[8]; /*!< GPIO pin interrupt select register 0-7, not on CHIP_LPC110X, CHIP_LPC11XXLV, CHIP_LPC11CXX */ + __IO uint32_t USBCLKCTRL; /*!< USB clock control register, LPC11UXX only */ + __I uint32_t USBCLKST; /*!< USB clock status register, LPC11UXX only */ + __I uint32_t RESERVED12[24]; + __IO uint32_t STARTAPRP0; /*!< Start loigc 0 interrupt wake up enable register 0, on CHIP_LPC110X, CHIP_LPC11XXLV, CHIP_LPC11CXX */ + __IO uint32_t STARTERP0; /*!< Start loigc signal enable register 0, not on LPC11AXX */ + __IO uint32_t STARTRSRP0CLR; /*!< Start loigc reset register 0, on CHIP_LPC110X, CHIP_LPC11XXLV, CHIP_LPC11CXX */ + __IO uint32_t STARTSRP0; /*!< Start loigc status register 0, on CHIP_LPC110X, CHIP_LPC11XXLV, CHIP_LPC11CXX */ + __I uint32_t RESERVED13; + __IO uint32_t STARTERP1; /*!< Start logic 1 interrupt wake up enable register 1, on LPC11UXX and LPC11EXX only */ + __I uint32_t RESERVED14[6]; + __IO uint32_t PDSLEEPCFG; /*!< Power down states in deep sleep mode register, not on LPC11AXX */ + __IO uint32_t PDWAKECFG; /*!< Power down states in wake up from deep sleep register, not on LPC11AXX */ + __IO uint32_t PDRUNCFG; /*!< Power configuration register*/ + __I uint32_t RESERVED15[110]; + __I uint32_t DEVICEID; /*!< Device ID register */ +} LPC_SYSCTL_T; + +/** + * System memory remap modes used to remap interrupt vectors + */ +typedef enum CHIP_SYSCTL_BOOT_MODE_REMAP { + REMAP_BOOT_LOADER_MODE, /*!< Interrupt vectors are re-mapped to Boot ROM */ + REMAP_USER_RAM_MODE, /*!< Interrupt vectors are re-mapped to Static RAM */ + REMAP_USER_FLASH_MODE /*!< Interrupt vectors are not re-mapped and reside in Flash */ +} CHIP_SYSCTL_BOOT_MODE_REMAP_T; + +/** + * @brief Re-map interrupt vectors + * @param remap : system memory map value + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_Map(CHIP_SYSCTL_BOOT_MODE_REMAP_T remap) +{ + LPC_SYSCTL->SYSMEMREMAP = (uint32_t) remap; +} + +/** + * Peripheral reset identifiers, not available on all devices + */ +typedef enum { + RESET_SSP0, /*!< SSP0 reset control */ + RESET_I2C0, /*!< I2C0 reset control */ + RESET_SSP1, /*!< SSP1 reset control */ +#if !defined(CHIP_LPC1125) + RESET_CAN0, /*!< CAN0 reset control */ + RESET_UART0, /*!< UART0 reset control */ + RESET_TIMER0_16, /*!< 16-bit Timer 0 reset control */ + RESET_TIMER1_16, /*!< 16-bit Timer 1 reset control */ + RESET_TIMER0_32, /*!< 32-bit Timer 0 reset control */ + RESET_TIMER1_32, /*!< 32-bit Timer 1 reset control */ + RESET_ACMP, /*!< Analog comparator reset control */ + RESET_DAC0, /*!< DAC reset control */ + RESET_ADC0 /*!< ADC reset control */ +#endif +} CHIP_SYSCTL_PERIPH_RESET_T; + +/** + * @brief Assert reset for a peripheral + * @param periph : Peripheral to assert reset for + * @return Nothing + * @note The peripheral will stay in reset until reset is de-asserted. Call + * Chip_SYSCTL_DeassertPeriphReset() to de-assert the reset. + */ +STATIC INLINE void Chip_SYSCTL_AssertPeriphReset(CHIP_SYSCTL_PERIPH_RESET_T periph) +{ + LPC_SYSCTL->PRESETCTRL &= ~(1 << (uint32_t) periph); +} + +/** + * @brief De-assert reset for a peripheral + * @param periph : Peripheral to de-assert reset for + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_DeassertPeriphReset(CHIP_SYSCTL_PERIPH_RESET_T periph) +{ + LPC_SYSCTL->PRESETCTRL |= (1 << (uint32_t) periph); +} + +/** + * @brief Resets a peripheral + * @param periph : Peripheral to reset + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_PeriphReset(CHIP_SYSCTL_PERIPH_RESET_T periph) +{ + Chip_SYSCTL_AssertPeriphReset(periph); + Chip_SYSCTL_DeassertPeriphReset(periph); +} + +/** + * System reset status + */ +#define SYSCTL_RST_POR (1 << 0) /*!< POR reset status */ +#define SYSCTL_RST_EXTRST (1 << 1) /*!< External reset status */ +#define SYSCTL_RST_WDT (1 << 2) /*!< Watchdog reset status */ +#define SYSCTL_RST_BOD (1 << 3) /*!< Brown-out detect reset status */ +#define SYSCTL_RST_SYSRST (1 << 4) /*!< software system reset status */ + +/** + * Non-Maskable Interrupt Enable/Disable value + */ +#define SYSCTL_NMISRC_ENABLE ((uint32_t) 1 << 31) /*!< Enable the Non-Maskable Interrupt (NMI) source */ + +/** + * @brief Get system reset status + * @return An Or'ed value of SYSCTL_RST_* + * @note This function returns the detected reset source(s). + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetSystemRSTStatus(void) +{ + return LPC_SYSCTL->SYSRSTSTAT; +} + +/** + * @brief Clear system reset status + * @param reset : An Or'ed value of SYSCTL_RST_* status to clear + * @return Nothing + * @note This function returns the detected reset source(s). + */ +STATIC INLINE void Chip_SYSCTL_ClearSystemRSTStatus(uint32_t reset) +{ + LPC_SYSCTL->SYSRSTSTAT = reset; +} + +/** + * @brief Read POR captured PIO status + * @param index : POR register index, 0 or 1 + * @return captured POR PIO status + * @note Some devices only support index 0. + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetPORPIOStatus(int index) +{ + return LPC_SYSCTL->PIOPORCAP[index]; +} + +/** + * Brown-out detector reset level + */ +typedef enum CHIP_SYSCTL_BODRSTLVL { +#if defined(CHIP_LPC11CXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) || defined(CHIP_LPC11XXLV) || defined(CHIP_LPC1125) + SYSCTL_BODRSTLVL_1_46V, /*!< Brown-out reset at 1.46v */ +#else + SYSCTL_BODRSTLVL_RESERVED1, /*!< Only possible value for LPC11A/02/XXLV */ +#endif +#if defined(CHIP_LPC11XXLV) + SYSCTL_BODRSTLVL_RESERVED1, + SYSCTL_BODRSTLVL_RESERVED2, + SYSCTL_BODRSTLVL_RESERVED3, +#elif defined(CHIP_LPC11AXX) + SYSCTL_BODRSTLVL_RESERVED2, + SYSCTL_BODRSTLVL_2_52V, /*!< Brown-out reset at 2.52v */ + SYSCTL_BODRSTLVL_2_80V, /*!< Brown-out reset at 2.80v */ +#else + SYSCTL_BODRSTLVL_2_06V, /*!< Brown-out reset at 2.06v */ + SYSCTL_BODRSTLVL_2_35V, /*!< Brown-out reset at 2.35v */ + SYSCTL_BODRSTLVL_2_63V, /*!< Brown-out reset at 2.63v */ +#endif +} CHIP_SYSCTL_BODRSTLVL_T; + +/** + * Brown-out detector interrupt level + */ +typedef enum CHIP_SYSCTL_BODRINTVAL { + SYSCTL_BODINTVAL_RESERVED1, +#if defined(CHIP_LPC110X) || defined(CHIP_LPC11CXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) || defined(CHIP_LPC1125) + SYSCTL_BODINTVAL_2_22V, /*!< Brown-out interrupt at 2.22v */ + SYSCTL_BODINTVAL_2_52V, /*!< Brown-out interrupt at 2.52v */ + SYSCTL_BODINTVAL_2_80V, /*!< Brown-out interrupt at 2.8v */ +#endif +} CHIP_SYSCTL_BODRINTVAL_T; + +/** + * @brief Set brown-out detection interrupt and reset levels + * @param rstlvl : Brown-out detector reset level + * @param intlvl : Brown-out interrupt level + * @return Nothing + * @note Brown-out detection reset will be disabled upon exiting this function. + * Use Chip_SYSCTL_EnableBODReset() to re-enable. + */ +STATIC INLINE void Chip_SYSCTL_SetBODLevels(CHIP_SYSCTL_BODRSTLVL_T rstlvl, + CHIP_SYSCTL_BODRINTVAL_T intlvl) +{ + LPC_SYSCTL->BODCTRL = ((uint32_t) rstlvl) | (((uint32_t) intlvl) << 2); +} + +#if defined(CHIP_LPC11AXX) +/** + * @brief Returns brown-out detection interrupt status + * @return true if the BOD interrupt is pending, otherwise false + */ +STATIC INLINE bool Chip_SYSCTL_GetBODIntStatus(void) +{ + return (bool) ((LPC_SYSCTL->BODCTRL & (1 << 6)) != 0); +} + +#else +/** + * @brief Enable brown-out detection reset + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_EnableBODReset(void) +{ + LPC_SYSCTL->BODCTRL |= (1 << 4); +} + +/** + * @brief Disable brown-out detection reset + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_DisableBODReset(void) +{ + LPC_SYSCTL->BODCTRL &= ~(1 << 4); +} + +#endif + +/** + * @brief Set System tick timer calibration value + * @param sysCalVal : System tick timer calibration value + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_SetSYSTCKCAL(uint32_t sysCalVal) +{ + LPC_SYSCTL->SYSTCKCAL = sysCalVal; +} + +#if defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) || defined(CHIP_LPC1125) +/** + * @brief Set System IRQ latency + * @param latency : Latency in clock ticks + * @return Nothing + * @note Sets the IRQ latency, a value between 0 and 255 clocks. Lower + * values allow better latency. + */ +STATIC INLINE void Chip_SYSCTL_SetIRQLatency(uint32_t latency) +{ + LPC_SYSCTL->IRQLATENCY = latency; +} + +/** + * @brief Get System IRQ latency + * @return Latency in clock ticks + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetIRQLatency(void) +{ + return LPC_SYSCTL->IRQLATENCY; +} + +#endif + +#if defined(CHIP_LPC11AXX) || defined(CHIP_LPC11CXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) || defined(CHIP_LPC1125) +/** + * @brief Set source for non-maskable interrupt (NMI) + * @param intsrc : IRQ number to assign to the NMI + * @return Nothing + * @note The NMI source will be disabled upon exiting this function. use the + * Chip_SYSCTL_EnableNMISource() function to enable the NMI source. + */ +STATIC INLINE void Chip_SYSCTL_SetNMISource(uint32_t intsrc) +{ + LPC_SYSCTL->NMISRC = intsrc; +} + +/** + * @brief Enable interrupt used for NMI source + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_EnableNMISource(void) +{ + LPC_SYSCTL->NMISRC |= SYSCTL_NMISRC_ENABLE; +} + +/** + * @brief Disable interrupt used for NMI source + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_DisableNMISource(void) +{ + LPC_SYSCTL->NMISRC &= ~(SYSCTL_NMISRC_ENABLE); +} + +#endif + +#if defined(CHIP_LPC11AXX) +/** + * @brief Setup a pin source for the pin interrupts (0-7) + * @param intno : IRQ number + * @param port : port number 0/1) + * @param pin : pin number (0->31) + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_SetPinInterrupt(uint32_t intno, uint8_t port, uint8_t pin) +{ + LPC_SYSCTL->PINTSEL[intno] = (uint32_t) ((port << 5) | pin); +} + +#elif defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) +/** + * @brief Setup a pin source for the pin interrupts (0-7) + * @param intno : IRQ number + * @param port : port number 0/1) + * @param pin : pin number (0->23 for GPIO Port 0 and 0->31 for GPIO Port 1) + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_SetPinInterrupt(uint32_t intno, uint8_t port, uint8_t pin) +{ + LPC_SYSCTL->PINTSEL[intno] = (uint32_t) (port * 24 + pin); +} + +#endif + +#if defined(CHIP_LPC11UXX) +/** + * @brief Setup USB clock control + * @param ap_clk : USB need_clock signal control (0 or 1) + * @param pol_clk : USB need_clock polarity for triggering the USB wake-up interrupt (0 or 1) + * @return Nothing + * @note See the USBCLKCTRL register in the user manual for these settings. + */ +STATIC INLINE void Chip_SYSCTL_SetUSBCLKCTRL(uint32_t ap_clk, uint32_t pol_clk) +{ + LPC_SYSCTL->USBCLKCTRL = ap_clk | (pol_clk << 1); +} + +/** + * @brief Returns the status of the USB need_clock signal + * @return true if USB need_clock statis is high, otherwise false + */ +STATIC INLINE bool Chip_SYSCTL_GetUSBCLKStatus(void) +{ + return (bool) ((LPC_SYSCTL->USBCLKST & 0x1) != 0); +} + +#endif + +#if defined(CHIP_LPC110X) || defined(CHIP_LPC11XXLV) || defined(CHIP_LPC11CXX) || defined(CHIP_LPC1125) +/** + * @brief Set edge for PIO start logic + * @param pin : PIO pin number + * @param edge : 0 for falling edge, 1 for rising edge + * @return Nothing + * @note Different devices support different pins, see the user manual for supported pins. + */ +STATIC INLINE void Chip_SYSCTL_SetStartPin(uint32_t pin, uint32_t edge) +{ + if (edge) { + LPC_SYSCTL->STARTAPRP0 |= (1 << pin); + } + else { + LPC_SYSCTL->STARTAPRP0 &= ~(1 << pin); + } +} + +/** + * @brief Enable PIO start logic for a pin + * @param pin : PIO pin number + * @return Nothing + * @note Different devices support different pins, see the user manual for supported pins. + */ +STATIC INLINE void Chip_SYSCTL_EnableStartPin(uint32_t pin) +{ + LPC_SYSCTL->STARTERP0 |= (1 << pin); +} + +/** + * @brief Disable PIO start logic for a pin + * @param pin : PIO pin number + * @return Nothing + * @note Different devices support different pins, see the user manual for supported pins. + */ +STATIC INLINE void Chip_SYSCTL_DisableStartPin(uint32_t pin) +{ + LPC_SYSCTL->STARTERP0 &= ~(1 << pin); +} + +/** + * @brief Clear PIO start logic state + * @param pin : PIO pin number + * @return Nothing + * @note Different devices support different pins, see the user manual for supported pins. + */ +STATIC INLINE void Chip_SYSCTL_ResetStartPin(uint32_t pin) +{ + LPC_SYSCTL->STARTRSRP0CLR = (1 << pin); +} + +/** + * @brief Returns status of pin wakeup + * @param pin : PIO pin number + * @return true if a pin start signal is pending, otherwise false + * @note Different devices support different pins, see the user manual for supported pins. + */ +STATIC INLINE bool Chip_SYSCTL_GetStartPinStatus(uint32_t pin) +{ + return (bool) ((LPC_SYSCTL->STARTSRP0 & (1 << pin)) != 0); +} + +#endif + +#if defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) +/** + * @brief Enables a pin's (PINT) wakeup logic + * @param pin : pin number + * @return Nothing + * @note Different devices support different pins, see the user manual for supported pins. + */ +STATIC INLINE void Chip_SYSCTL_EnablePINTWakeup(uint32_t pin) +{ + LPC_SYSCTL->STARTERP0 |= (1 << pin); +} + +/** + * @brief Disables a pin's (PINT) wakeup logic + * @param pin : pin number + * @return Nothing + * @note Different devices support different pins, see the user manual for supported pins. + */ +STATIC INLINE void Chip_SYSCTL_DisablePINTWakeup(uint32_t pin) +{ + LPC_SYSCTL->STARTERP0 &= ~(1 << pin); +} + +/** + * Peripheral interrupt wakeup events, LPC11E/Uxx only + */ +#define SYSCTL_WAKEUP_WWDTINT (1 << 12) /*!< WWDT interrupt wake-up */ +#define SYSCTL_WAKEUP_BODINT (1 << 13) /*!< Brown Out Detect (BOD) interrupt wake-up */ +#define SYSCTL_WAKEUP_USB_WAKEUP (1 << 19) /*!< USB need_clock signal wake-up, LPC11Uxx only */ +#define SYSCTL_WAKEUP_GPIOINT0 (1 << 20) /*!< GPIO GROUP0 interrupt wake-up */ +#define SYSCTL_WAKEUP_GPIOINT1 (1 << 21) /*!< GPIO GROUP1 interrupt wake-up */ + +/** + * @brief Enables a peripheral's wakeup logic + * @param periphmask : OR'ed values of SYSCTL_WAKEUP_* for wakeup + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_EnablePeriphWakeup(uint32_t periphmask) +{ + LPC_SYSCTL->STARTERP1 |= periphmask; +} + +/** + * @brief Disables a peripheral's wakeup logic + * @param periphmask : OR'ed values of SYSCTL_WAKEUP_* for wakeup + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_DisablePeriphWakeup(uint32_t periphmask) +{ + LPC_SYSCTL->STARTERP1 &= ~periphmask; +} + +#endif + +#if !defined(LPC11AXX) +/** + * Deep sleep setup values + */ +#define SYSCTL_DEEPSLP_BOD_PD (1 << 3) /*!< BOD power-down control in Deep-sleep mode, powered down */ +#define SYSCTL_DEEPSLP_WDTOSC_PD (1 << 6) /*!< Watchdog oscillator power control in Deep-sleep, powered down */ +#if defined(CHIP_LPC11XXLV) +#define SYSCTL_DEEPSLP_IRCOUT_PD (1 << 0) /*!< IRC oscillator output in Deep-sleep mode, powered down */ +#define SYSCTL_DEEPSLP_IRC_PD (1 << 1) /*!< IRC oscillator in Deep-sleep, powered down */ +#endif + +/** + * @brief Setup deep sleep behaviour for power down + * @param sleepmask : OR'ed values of SYSCTL_DEEPSLP_* values (high to powerdown on deepsleep) + * @return Nothing + * @note This must be setup prior to using deep sleep. See the user manual + ***(PDSLEEPCFG register) for more info on setting this up. This function selects + * which peripherals are powered down on deep sleep. + * This function should only be called once with all options for power-down + * in that call. + */ +void Chip_SYSCTL_SetDeepSleepPD(uint32_t sleepmask); + +/** + * @brief Returns current deep sleep mask + * @return OR'ed values of SYSCTL_DEEPSLP_* values + * @note A high bit indicates the peripheral will power down on deep sleep. + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetDeepSleepPD(void) +{ + return LPC_SYSCTL->PDSLEEPCFG; +} + +/** + * Deep sleep to wakeup setup values + */ +#define SYSCTL_SLPWAKE_IRCOUT_PD (1 << 0) /*!< IRC oscillator output wake-up configuration */ +#define SYSCTL_SLPWAKE_IRC_PD (1 << 1) /*!< IRC oscillator power-down wake-up configuration */ +#define SYSCTL_SLPWAKE_FLASH_PD (1 << 2) /*!< Flash wake-up configuration */ +#define SYSCTL_SLPWAKE_BOD_PD (1 << 3) /*!< BOD wake-up configuration */ +#define SYSCTL_SLPWAKE_ADC_PD (1 << 4) /*!< ADC wake-up configuration */ +#define SYSCTL_SLPWAKE_SYSOSC_PD (1 << 5) /*!< System oscillator wake-up configuration */ +#define SYSCTL_SLPWAKE_WDTOSC_PD (1 << 6) /*!< Watchdog oscillator wake-up configuration */ +#define SYSCTL_SLPWAKE_SYSPLL_PD (1 << 7) /*!< System PLL wake-up configuration */ +#if defined(CHIP_LPC11UXX) +#define SYSCTL_SLPWAKE_USBPLL_PD (1 << 8) /*!< USB PLL wake-up configuration */ +#define SYSCTL_SLPWAKE_USBPAD_PD (1 << 10) /*!< USB transceiver wake-up configuration */ +#endif + +/** + * @brief Setup wakeup behaviour from deep sleep + * @param wakeupmask : OR'ed values of SYSCTL_SLPWAKE_* values (high is powered down) + * @return Nothing + * @note This must be setup prior to using deep sleep. See the user manual + * (PDWAKECFG register) for more info on setting this up. This function selects + * which peripherals are powered up on exit from deep sleep. + * This function should only be called once with all options for wakeup + * in that call. + */ +void Chip_SYSCTL_SetWakeup(uint32_t wakeupmask); + +/** + * @brief Return current wakeup mask + * @return OR'ed values of SYSCTL_SLPWAKE_* values + * @note A high state indicates the peripehral will powerup on wakeup. + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetWakeup(void) +{ + return LPC_SYSCTL->PDWAKECFG; +} + +#endif + +/** + * Power down configuration values + */ +#define SYSCTL_POWERDOWN_IRCOUT_PD (1 << 0) /*!< IRC oscillator output power down */ +#define SYSCTL_POWERDOWN_IRC_PD (1 << 1) /*!< IRC oscillator power-down */ +#define SYSCTL_POWERDOWN_FLASH_PD (1 << 2) /*!< Flash power down */ +#if !defined(CHIP_LPC11AXX) +#define SYSCTL_POWERDOWN_BOD_PD (1 << 3) /*!< BOD power down */ +#endif +#define SYSCTL_POWERDOWN_ADC_PD (1 << 4) /*!< ADC power down */ +#define SYSCTL_POWERDOWN_SYSOSC_PD (1 << 5) /*!< System oscillator power down */ +#define SYSCTL_POWERDOWN_WDTOSC_PD (1 << 6) /*!< Watchdog oscillator power down */ +#define SYSCTL_POWERDOWN_SYSPLL_PD (1 << 7) /*!< System PLL power down */ +#if defined(CHIP_LPC11UXX) +#define SYSCTL_POWERDOWN_USBPLL_PD (1 << 8) /*!< USB PLL power-down */ +#define SYSCTL_POWERDOWN_USBPAD_PD (1 << 10)/*!< USB transceiver power-down */ +#endif +#if defined(CHIP_LPC11AXX) +#define SYSCTL_POWERDOWN_LFOSC_PD (1 << 13) /*!< Low frequency oscillator power-down */ +#define SYSCTL_POWERDOWN_DAC_PD (1 << 14) /*!< DAC power-down */ +#define SYSCTL_POWERDOWN_TS_PD (1 << 15) /*!< Temperature Sensor power-down */ +#define SYSCTL_POWERDOWN_ACOMP_PD (1 << 16) /*!< Analog Comparator power-down */ +#endif + +/** + * @brief Power down one or more blocks or peripherals + * @param powerdownmask : OR'ed values of SYSCTL_POWERDOWN_* values + * @return Nothing + */ +void Chip_SYSCTL_PowerDown(uint32_t powerdownmask); + +/** + * @brief Power up one or more blocks or peripherals + * @param powerupmask : OR'ed values of SYSCTL_POWERDOWN_* values + * @return Nothing + */ +void Chip_SYSCTL_PowerUp(uint32_t powerupmask); + +/** + * @brief Get power status + * @return OR'ed values of SYSCTL_POWERDOWN_* values + * @note A high state indicates the peripheral is powered down. + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetPowerStates(void) +{ + return LPC_SYSCTL->PDRUNCFG; +} + +/** + * @brief Return the device ID + * @return the device ID + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetDeviceID(void) +{ + return LPC_SYSCTL->DEVICEID; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*!< __SYSCTL_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/timer_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/timer_11xx.h new file mode 100755 index 0000000..ad1c5c3 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/timer_11xx.h @@ -0,0 +1,446 @@ +/* + * @brief LPC11xx 16/32-bit Timer/PWM control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __TIMER_11XX_H_ +#define __TIMER_11XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup TIMER_11XX CHIP: LPC11xx 16/32-bit Timer driver + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +/** + * @brief 32-bit Standard timer register block structure + */ +typedef struct { /*!< TIMERn Structure */ + __IO uint32_t IR; /*!< Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */ + __IO uint32_t TCR; /*!< Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */ + __IO uint32_t TC; /*!< Timer Counter. The 32 bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */ + __IO uint32_t PR; /*!< Prescale Register. The Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */ + __IO uint32_t PC; /*!< Prescale Counter. The 32 bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */ + __IO uint32_t MCR; /*!< Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */ + __IO uint32_t MR[4]; /*!< Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */ + __IO uint32_t CCR; /*!< Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */ + __IO uint32_t CR[4]; /*!< Capture Register. CR is loaded with the value of TC when there is an event on the CAPn.0 input. */ + __IO uint32_t EMR; /*!< External Match Register. The EMR controls the external match pins MATn.0-3 (MAT0.0-3 and MAT1.0-3 respectively). */ + __I uint32_t RESERVED0[12]; + __IO uint32_t CTCR; /*!< Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */ + __IO uint32_t PWMC; +} LPC_TIMER_T; + +/** Macro to clear interrupt pending */ +#define TIMER_IR_CLR(n) _BIT(n) + +/** Macro for getting a timer match interrupt bit */ +#define TIMER_MATCH_INT(n) (_BIT((n) & 0x0F)) +/** Macro for getting a capture event interrupt bit */ +#define TIMER_CAP_INT(n) (_BIT((((n) & 0x0F) + 4))) + +/** Timer/counter enable bit */ +#define TIMER_ENABLE ((uint32_t) (1 << 0)) +/** Timer/counter reset bit */ +#define TIMER_RESET ((uint32_t) (1 << 1)) + +/** Bit location for interrupt on MRx match, n = 0 to 3 */ +#define TIMER_INT_ON_MATCH(n) (_BIT(((n) * 3))) +/** Bit location for reset on MRx match, n = 0 to 3 */ +#define TIMER_RESET_ON_MATCH(n) (_BIT((((n) * 3) + 1))) +/** Bit location for stop on MRx match, n = 0 to 3 */ +#define TIMER_STOP_ON_MATCH(n) (_BIT((((n) * 3) + 2))) + +/** Bit location for CAP.n on CRx rising edge, n = 0 to 3 */ +#define TIMER_CAP_RISING(n) (_BIT(((n) * 3))) +/** Bit location for CAP.n on CRx falling edge, n = 0 to 3 */ +#define TIMER_CAP_FALLING(n) (_BIT((((n) * 3) + 1))) +/** Bit location for CAP.n on CRx interrupt enable, n = 0 to 3 */ +#define TIMER_INT_ON_CAP(n) (_BIT((((n) * 3) + 2))) + +/** + * @brief Initialize a timer + * @param pTMR : Pointer to timer IP register address + * @return Nothing + */ +void Chip_TIMER_Init(LPC_TIMER_T *pTMR); + +/** + * @brief Shutdown a timer + * @param pTMR : Pointer to timer IP register address + * @return Nothing + */ +void Chip_TIMER_DeInit(LPC_TIMER_T *pTMR); + +/** + * @brief Determine if a match interrupt is pending + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match interrupt number to check + * @return false if the interrupt is not pending, otherwise true + * @note Determine if the match interrupt for the passed timer and match + * counter is pending. + */ +STATIC INLINE bool Chip_TIMER_MatchPending(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + return (bool) ((pTMR->IR & TIMER_MATCH_INT(matchnum)) != 0); +} + +/** + * @brief Determine if a capture interrupt is pending + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture interrupt number to check + * @return false if the interrupt is not pending, otherwise true + * @note Determine if the capture interrupt for the passed capture pin is + * pending. + */ +STATIC INLINE bool Chip_TIMER_CapturePending(LPC_TIMER_T *pTMR, int8_t capnum) +{ + return (bool) ((pTMR->IR & TIMER_CAP_INT(capnum)) != 0); +} + +/** + * @brief Clears a (pending) match interrupt + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match interrupt number to clear + * @return Nothing + * @note Clears a pending timer match interrupt. + */ +STATIC INLINE void Chip_TIMER_ClearMatch(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->IR = TIMER_IR_CLR(matchnum); +} + +/** + * @brief Clears a (pending) capture interrupt + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture interrupt number to clear + * @return Nothing + * @note Clears a pending timer capture interrupt. + */ +STATIC INLINE void Chip_TIMER_ClearCapture(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->IR = (0x10 << capnum); +} + +/** + * @brief Enables the timer (starts count) + * @param pTMR : Pointer to timer IP register address + * @return Nothing + * @note Enables the timer to start counting. + */ +STATIC INLINE void Chip_TIMER_Enable(LPC_TIMER_T *pTMR) +{ + pTMR->TCR |= TIMER_ENABLE; +} + +/** + * @brief Disables the timer (stops count) + * @param pTMR : Pointer to timer IP register address + * @return Nothing + * @note Disables the timer to stop counting. + */ +STATIC INLINE void Chip_TIMER_Disable(LPC_TIMER_T *pTMR) +{ + pTMR->TCR &= ~TIMER_ENABLE; +} + +/** + * @brief Returns the current timer count + * @param pTMR : Pointer to timer IP register address + * @return Current timer terminal count value + * @note Returns the current timer terminal count. + */ +STATIC INLINE uint32_t Chip_TIMER_ReadCount(LPC_TIMER_T *pTMR) +{ + return pTMR->TC; +} + +/** + * @brief Returns the current prescale count + * @param pTMR : Pointer to timer IP register address + * @return Current timer prescale count value + * @note Returns the current prescale count. + */ +STATIC INLINE uint32_t Chip_TIMER_ReadPrescale(LPC_TIMER_T *pTMR) +{ + return pTMR->PC; +} + +/** + * @brief Sets the prescaler value + * @param pTMR : Pointer to timer IP register address + * @param prescale : Prescale value to set the prescale register to + * @return Nothing + * @note Sets the prescale count value. + */ +STATIC INLINE void Chip_TIMER_PrescaleSet(LPC_TIMER_T *pTMR, uint32_t prescale) +{ + pTMR->PR = prescale; +} + +/** + * @brief Sets a timer match value + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer to set match count for + * @param matchval : Match value for the selected match count + * @return Nothing + * @note Sets one of the timer match values. + */ +STATIC INLINE void Chip_TIMER_SetMatch(LPC_TIMER_T *pTMR, int8_t matchnum, uint32_t matchval) +{ + pTMR->MR[matchnum] = matchval; +} + +/** + * @brief Reads a capture register + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture register to read + * @return The selected capture register value + * @note Returns the selected capture register value. + */ +STATIC INLINE uint32_t Chip_TIMER_ReadCapture(LPC_TIMER_T *pTMR, int8_t capnum) +{ + return pTMR->CR[capnum]; +} + +/** + * @brief Resets the timer terminal and prescale counts to 0 + * @param pTMR : Pointer to timer IP register address + * @return Nothing + */ +void Chip_TIMER_Reset(LPC_TIMER_T *pTMR); + +/** + * @brief Enables a match interrupt that fires when the terminal count + * matches the match counter value. + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer, 0 to 3 + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_MatchEnableInt(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->MCR |= TIMER_INT_ON_MATCH(matchnum); +} + +/** + * @brief Disables a match interrupt for a match counter. + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer, 0 to 3 + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_MatchDisableInt(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->MCR &= ~TIMER_INT_ON_MATCH(matchnum); +} + +/** + * @brief For the specific match counter, enables reset of the terminal count register when a match occurs + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer, 0 to 3 + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_ResetOnMatchEnable(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->MCR |= TIMER_RESET_ON_MATCH(matchnum); +} + +/** + * @brief For the specific match counter, disables reset of the terminal count register when a match occurs + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer, 0 to 3 + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_ResetOnMatchDisable(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->MCR &= ~TIMER_RESET_ON_MATCH(matchnum); +} + +/** + * @brief Enable a match timer to stop the terminal count when a + * match count equals the terminal count. + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer, 0 to 3 + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_StopOnMatchEnable(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->MCR |= TIMER_STOP_ON_MATCH(matchnum); +} + +/** + * @brief Disable stop on match for a match timer. Disables a match timer + * to stop the terminal count when a match count equals the terminal count. + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer, 0 to 3 + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_StopOnMatchDisable(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->MCR &= ~TIMER_STOP_ON_MATCH(matchnum); +} + +/** + * @brief Enables capture on on rising edge of selected CAP signal for the + * selected capture register, enables the selected CAPn.capnum signal to load + * the capture register with the terminal coount on a rising edge. + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture signal/register to use + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_CaptureRisingEdgeEnable(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->CCR |= TIMER_CAP_RISING(capnum); +} + +/** + * @brief Disables capture on on rising edge of selected CAP signal. For the + * selected capture register, disables the selected CAPn.capnum signal to load + * the capture register with the terminal coount on a rising edge. + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture signal/register to use + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_CaptureRisingEdgeDisable(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->CCR &= ~TIMER_CAP_RISING(capnum); +} + +/** + * @brief Enables capture on on falling edge of selected CAP signal. For the + * selected capture register, enables the selected CAPn.capnum signal to load + * the capture register with the terminal coount on a falling edge. + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture signal/register to use + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_CaptureFallingEdgeEnable(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->CCR |= TIMER_CAP_FALLING(capnum); +} + +/** + * @brief Disables capture on on falling edge of selected CAP signal. For the + * selected capture register, disables the selected CAPn.capnum signal to load + * the capture register with the terminal coount on a falling edge. + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture signal/register to use + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_CaptureFallingEdgeDisable(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->CCR &= ~TIMER_CAP_FALLING(capnum); +} + +/** + * @brief Enables interrupt on capture of selected CAP signal. For the + * selected capture register, an interrupt will be generated when the enabled + * rising or falling edge on CAPn.capnum is detected. + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture signal/register to use + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_CaptureEnableInt(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->CCR |= TIMER_INT_ON_CAP(capnum); +} + +/** + * @brief Disables interrupt on capture of selected CAP signal + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture signal/register to use + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_CaptureDisableInt(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->CCR &= ~TIMER_INT_ON_CAP(capnum); +} + +/** + * @brief Standard timer initial match pin state and change state + */ +typedef enum IP_TIMER_PIN_MATCH_STATE { + TIMER_EXTMATCH_DO_NOTHING = 0, /*!< Timer match state does nothing on match pin */ + TIMER_EXTMATCH_CLEAR = 1, /*!< Timer match state sets match pin low */ + TIMER_EXTMATCH_SET = 2, /*!< Timer match state sets match pin high */ + TIMER_EXTMATCH_TOGGLE = 3 /*!< Timer match state toggles match pin */ +} TIMER_PIN_MATCH_STATE_T; + +/** + * @brief Sets external match control (MATn.matchnum) pin control. For the pin + * selected with matchnum, sets the function of the pin that occurs on + * a terminal count match for the match count. + * @param pTMR : Pointer to timer IP register address + * @param initial_state : Initial state of the pin, high(1) or low(0) + * @param matchState : Selects the match state for the pin + * @param matchnum : MATn.matchnum signal to use + * @return Nothing + * @note For the pin selected with matchnum, sets the function of the pin that occurs on + * a terminal count match for the match count. + */ +void Chip_TIMER_ExtMatchControlSet(LPC_TIMER_T *pTMR, int8_t initial_state, + TIMER_PIN_MATCH_STATE_T matchState, int8_t matchnum); + +/** + * @brief Standard timer clock and edge for count source + */ +typedef enum IP_TIMER_CAP_SRC_STATE { + TIMER_CAPSRC_RISING_PCLK = 0, /*!< Timer ticks on PCLK rising edge */ + TIMER_CAPSRC_RISING_CAPN = 1, /*!< Timer ticks on CAPn.x rising edge */ + TIMER_CAPSRC_FALLING_CAPN = 2, /*!< Timer ticks on CAPn.x falling edge */ + TIMER_CAPSRC_BOTH_CAPN = 3 /*!< Timer ticks on CAPn.x both edges */ +} TIMER_CAP_SRC_STATE_T; + +/** + * @brief Sets timer count source and edge with the selected passed from CapSrc. + * If CapSrc selected a CAPn pin, select the specific CAPn pin with the capnum value. + * @param pTMR : Pointer to timer IP register address + * @param capSrc : timer clock source and edge + * @param capnum : CAPn.capnum pin to use (if used) + * @return Nothing + * @note If CapSrc selected a CAPn pin, select the specific CAPn pin with the capnum value. + */ +STATIC INLINE void Chip_TIMER_TIMER_SetCountClockSrc(LPC_TIMER_T *pTMR, + TIMER_CAP_SRC_STATE_T capSrc, + int8_t capnum) +{ + pTMR->CTCR = (uint32_t) capSrc | ((uint32_t) capnum) << 2; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIMER_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/uart_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/uart_11xx.h new file mode 100755 index 0000000..8c15b24 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/uart_11xx.h @@ -0,0 +1,787 @@ +/* + * @brief LPC11xx UART chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __UART_11XX_H_ +#define __UART_11XX_H_ + +#include "ring_buffer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup UART_11XX CHIP: LPC11xx UART driver + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +/** + * @brief USART register block structure + */ +typedef struct { /*!< USARTn Structure */ + + union { + __IO uint32_t DLL; /*!< Divisor Latch LSB. Least significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider (DLAB = 1). */ + __O uint32_t THR; /*!< Transmit Holding Register. The next character to be transmitted is written here (DLAB = 0). */ + __I uint32_t RBR; /*!< Receiver Buffer Register. Contains the next received character to be read (DLAB = 0). */ + }; + + union { + __IO uint32_t IER; /*!< Interrupt Enable Register. Contains individual interrupt enable bits for the 7 potential UART interrupts (DLAB = 0). */ + __IO uint32_t DLM; /*!< Divisor Latch MSB. Most significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider (DLAB = 1). */ + }; + + union { + __O uint32_t FCR; /*!< FIFO Control Register. Controls UART FIFO usage and modes. */ + __I uint32_t IIR; /*!< Interrupt ID Register. Identifies which interrupt(s) are pending. */ + }; + + __IO uint32_t LCR; /*!< Line Control Register. Contains controls for frame formatting and break generation. */ + __IO uint32_t MCR; /*!< Modem Control Register. Only present on USART ports with full modem support. */ + __I uint32_t LSR; /*!< Line Status Register. Contains flags for transmit and receive status, including line errors. */ + __I uint32_t MSR; /*!< Modem Status Register. Only present on USART ports with full modem support. */ + __IO uint32_t SCR; /*!< Scratch Pad Register. Eight-bit temporary storage for software. */ + __IO uint32_t ACR; /*!< Auto-baud Control Register. Contains controls for the auto-baud feature. */ + __IO uint32_t ICR; /*!< IrDA control register (not all UARTS) */ + __IO uint32_t FDR; /*!< Fractional Divider Register. Generates a clock input for the baud rate divider. */ + __IO uint32_t OSR; /*!< Oversampling Register. Controls the degree of oversampling during each bit time. Only on some UARTS. */ + __IO uint32_t TER1; /*!< Transmit Enable Register. Turns off USART transmitter for use with software flow control. */ + uint32_t RESERVED0[3]; + __IO uint32_t HDEN; /*!< Half-duplex enable Register- only on some UARTs */ + __I uint32_t RESERVED1[1]; + __IO uint32_t SCICTRL; /*!< Smart card interface control register- only on some UARTs */ + + __IO uint32_t RS485CTRL; /*!< RS-485/EIA-485 Control. Contains controls to configure various aspects of RS-485/EIA-485 modes. */ + __IO uint32_t RS485ADRMATCH; /*!< RS-485/EIA-485 address match. Contains the address match value for RS-485/EIA-485 mode. */ + __IO uint32_t RS485DLY; /*!< RS-485/EIA-485 direction control delay. */ + + union { + __IO uint32_t SYNCCTRL; /*!< Synchronous mode control register. Only on USARTs. */ + __I uint32_t FIFOLVL; /*!< FIFO Level register. Provides the current fill levels of the transmit and receive FIFOs. */ + }; + + __IO uint32_t TER2; /*!< Transmit Enable Register. Only on LPC177X_8X UART4 and LPC18XX/43XX USART0/2/3. */ +} LPC_USART_T; + + +/** + * @brief Macro defines for UART Receive Buffer register + */ +#define UART_RBR_MASKBIT (0xFF) /*!< UART Received Buffer mask bit (8 bits) */ + +/** + * @brief Macro defines for UART Divisor Latch LSB register + */ +#define UART_LOAD_DLL(div) ((div) & 0xFF) /*!< Macro for loading LSB of divisor */ +#define UART_DLL_MASKBIT (0xFF) /*!< Divisor latch LSB bit mask */ + +/** + * @brief Macro defines for UART Divisor Latch MSB register + */ +#define UART_LOAD_DLM(div) (((div) >> 8) & 0xFF) /*!< Macro for loading MSB of divisors */ +#define UART_DLM_MASKBIT (0xFF) /*!< Divisor latch MSB bit mask */ + +/** + * @brief Macro defines for UART Interrupt Enable Register + */ +#define UART_IER_RBRINT (1 << 0) /*!< RBR Interrupt enable */ +#define UART_IER_THREINT (1 << 1) /*!< THR Interrupt enable */ +#define UART_IER_RLSINT (1 << 2) /*!< RX line status interrupt enable */ +#define UART_IER_MSINT (1 << 3) /*!< Modem status interrupt enable - valid for 11xx, 17xx/40xx UART1, 18xx/43xx UART1 only */ +#define UART_IER_CTSINT (1 << 7) /*!< CTS signal transition interrupt enable - valid for 17xx/40xx UART1, 18xx/43xx UART1 only */ +#define UART_IER_ABEOINT (1 << 8) /*!< Enables the end of auto-baud interrupt */ +#define UART_IER_ABTOINT (1 << 9) /*!< Enables the auto-baud time-out interrupt */ +#define UART_IER_BITMASK (0x307) /*!< UART interrupt enable register bit mask - valid for 13xx, 17xx/40xx UART0/2/3, 18xx/43xx UART0/2/3 only*/ +#define UART1_IER_BITMASK (0x30F) /*!< UART1 interrupt enable register bit mask - valid for 11xx only */ +#define UART2_IER_BITMASK (0x38F) /*!< UART2 interrupt enable register bit mask - valid for 17xx/40xx UART1, 18xx/43xx UART1 only */ + +/** + * @brief Macro defines for UART Interrupt Identification Register + */ +#define UART_IIR_INTSTAT_PEND (1 << 0) /*!< Interrupt pending status - Active low */ +#define UART_IIR_FIFO_EN (3 << 6) /*!< These bits are equivalent to FCR[0] */ +#define UART_IIR_ABEO_INT (1 << 8) /*!< End of auto-baud interrupt */ +#define UART_IIR_ABTO_INT (1 << 9) /*!< Auto-baud time-out interrupt */ +#define UART_IIR_BITMASK (0x3CF) /*!< UART interrupt identification register bit mask */ + +/* Interrupt ID bit definitions */ +#define UART_IIR_INTID_MASK (7 << 1) /*!< Interrupt identification: Interrupt ID mask */ +#define UART_IIR_INTID_RLS (3 << 1) /*!< Interrupt identification: Receive line interrupt */ +#define UART_IIR_INTID_RDA (2 << 1) /*!< Interrupt identification: Receive data available interrupt */ +#define UART_IIR_INTID_CTI (6 << 1) /*!< Interrupt identification: Character time-out indicator interrupt */ +#define UART_IIR_INTID_THRE (1 << 1) /*!< Interrupt identification: THRE interrupt */ +#define UART_IIR_INTID_MODEM (0 << 1) /*!< Interrupt identification: Modem interrupt */ + +/** + * @brief Macro defines for UART FIFO Control Register + */ +#define UART_FCR_FIFO_EN (1 << 0) /*!< UART FIFO enable */ +#define UART_FCR_RX_RS (1 << 1) /*!< UART RX FIFO reset */ +#define UART_FCR_TX_RS (1 << 2) /*!< UART TX FIFO reset */ +#define UART_FCR_DMAMODE_SEL (1 << 3) /*!< UART DMA mode selection - valid for 17xx/40xx, 18xx/43xx only */ +#define UART_FCR_BITMASK (0xCF) /*!< UART FIFO control bit mask */ + +#define UART_TX_FIFO_SIZE (16) + +/* FIFO trigger level bit definitions */ +#define UART_FCR_TRG_LEV0 (0) /*!< UART FIFO trigger level 0: 1 character */ +#define UART_FCR_TRG_LEV1 (1 << 6) /*!< UART FIFO trigger level 1: 4 character */ +#define UART_FCR_TRG_LEV2 (2 << 6) /*!< UART FIFO trigger level 2: 8 character */ +#define UART_FCR_TRG_LEV3 (3 << 6) /*!< UART FIFO trigger level 3: 14 character */ + +/** + * @brief Macro defines for UART Line Control Register + */ +/* UART word length select bit definitions */ +#define UART_LCR_WLEN_MASK (3 << 0) /*!< UART word length select bit mask */ +#define UART_LCR_WLEN5 (0 << 0) /*!< UART word length select: 5 bit data mode */ +#define UART_LCR_WLEN6 (1 << 0) /*!< UART word length select: 6 bit data mode */ +#define UART_LCR_WLEN7 (2 << 0) /*!< UART word length select: 7 bit data mode */ +#define UART_LCR_WLEN8 (3 << 0) /*!< UART word length select: 8 bit data mode */ + +/* UART Stop bit select bit definitions */ +#define UART_LCR_SBS_MASK (1 << 2) /*!< UART stop bit select: bit mask */ +#define UART_LCR_SBS_1BIT (0 << 2) /*!< UART stop bit select: 1 stop bit */ +#define UART_LCR_SBS_2BIT (1 << 2) /*!< UART stop bit select: 2 stop bits (in 5 bit data mode, 1.5 stop bits) */ + +/* UART Parity enable bit definitions */ +#define UART_LCR_PARITY_EN (1 << 3) /*!< UART Parity Enable */ +#define UART_LCR_PARITY_DIS (0 << 3) /*!< UART Parity Disable */ +#define UART_LCR_PARITY_ODD (0 << 4) /*!< UART Parity select: Odd parity */ +#define UART_LCR_PARITY_EVEN (1 << 4) /*!< UART Parity select: Even parity */ +#define UART_LCR_PARITY_F_1 (2 << 4) /*!< UART Parity select: Forced 1 stick parity */ +#define UART_LCR_PARITY_F_0 (3 << 4) /*!< UART Parity select: Forced 0 stick parity */ +#define UART_LCR_BREAK_EN (1 << 6) /*!< UART Break transmission enable */ +#define UART_LCR_DLAB_EN (1 << 7) /*!< UART Divisor Latches Access bit enable */ +#define UART_LCR_BITMASK (0xFF) /*!< UART line control bit mask */ + +/** + * @brief Macro defines for UART Modem Control Register + */ +#define UART_MCR_DTR_CTRL (1 << 0) /*!< Source for modem output pin DTR */ +#define UART_MCR_RTS_CTRL (1 << 1) /*!< Source for modem output pin RTS */ +#define UART_MCR_LOOPB_EN (1 << 4) /*!< Loop back mode select */ +#define UART_MCR_AUTO_RTS_EN (1 << 6) /*!< Enable Auto RTS flow-control */ +#define UART_MCR_AUTO_CTS_EN (1 << 7) /*!< Enable Auto CTS flow-control */ +#define UART_MCR_BITMASK (0xD3) /*!< UART bit mask value */ + +/** + * @brief Macro defines for UART Line Status Register + */ +#define UART_LSR_RDR (1 << 0) /*!< Line status: Receive data ready */ +#define UART_LSR_OE (1 << 1) /*!< Line status: Overrun error */ +#define UART_LSR_PE (1 << 2) /*!< Line status: Parity error */ +#define UART_LSR_FE (1 << 3) /*!< Line status: Framing error */ +#define UART_LSR_BI (1 << 4) /*!< Line status: Break interrupt */ +#define UART_LSR_THRE (1 << 5) /*!< Line status: Transmit holding register empty */ +#define UART_LSR_TEMT (1 << 6) /*!< Line status: Transmitter empty */ +#define UART_LSR_RXFE (1 << 7) /*!< Line status: Error in RX FIFO */ +#define UART_LSR_TXFE (1 << 8) /*!< Line status: Error in RX FIFO */ +#define UART_LSR_BITMASK (0xFF) /*!< UART Line status bit mask */ +#define UART1_LSR_BITMASK (0x1FF) /*!< UART1 Line status bit mask - valid for 11xx, 18xx/43xx UART0/2/3 only */ + +/** + * @brief Macro defines for UART Modem Status Register + */ +#define UART_MSR_DELTA_CTS (1 << 0) /*!< Modem status: State change of input CTS */ +#define UART_MSR_DELTA_DSR (1 << 1) /*!< Modem status: State change of input DSR */ +#define UART_MSR_LO2HI_RI (1 << 2) /*!< Modem status: Low to high transition of input RI */ +#define UART_MSR_DELTA_DCD (1 << 3) /*!< Modem status: State change of input DCD */ +#define UART_MSR_CTS (1 << 4) /*!< Modem status: Clear To Send State */ +#define UART_MSR_DSR (1 << 5) /*!< Modem status: Data Set Ready State */ +#define UART_MSR_RI (1 << 6) /*!< Modem status: Ring Indicator State */ +#define UART_MSR_DCD (1 << 7) /*!< Modem status: Data Carrier Detect State */ +#define UART_MSR_BITMASK (0xFF) /*!< Modem status: MSR register bit-mask value */ + +/** + * @brief Macro defines for UART Auto baudrate control register + */ +#define UART_ACR_START (1 << 0) /*!< UART Auto-baud start */ +#define UART_ACR_MODE (1 << 1) /*!< UART Auto baudrate Mode 1 */ +#define UART_ACR_AUTO_RESTART (1 << 2) /*!< UART Auto baudrate restart */ +#define UART_ACR_ABEOINT_CLR (1 << 8) /*!< UART End of auto-baud interrupt clear */ +#define UART_ACR_ABTOINT_CLR (1 << 9) /*!< UART Auto-baud time-out interrupt clear */ +#define UART_ACR_BITMASK (0x307) /*!< UART Auto Baudrate register bit mask */ + +/** + * @brief Macro defines for UART RS485 Control register + */ +#define UART_RS485CTRL_NMM_EN (1 << 0) /*!< RS-485/EIA-485 Normal Multi-drop Mode (NMM) is disabled */ +#define UART_RS485CTRL_RX_DIS (1 << 1) /*!< The receiver is disabled */ +#define UART_RS485CTRL_AADEN (1 << 2) /*!< Auto Address Detect (AAD) is enabled */ +#define UART_RS485CTRL_SEL_DTR (1 << 3) /*!< If direction control is enabled (bit DCTRL = 1), pin DTR is + used for direction control */ +#define UART_RS485CTRL_DCTRL_EN (1 << 4) /*!< Enable Auto Direction Control */ +#define UART_RS485CTRL_OINV_1 (1 << 5) /*!< This bit reverses the polarity of the direction + control signal on the RTS (or DTR) pin. The direction control pin + will be driven to logic "1" when the transmitter has data to be sent */ +#define UART_RS485CTRL_BITMASK (0x3F) /*!< RS485 control bit-mask value */ + +/** + * @brief Macro defines for UART IrDA Control Register - valid for 11xx, 17xx/40xx UART0/2/3, 18xx/43xx UART3 only + */ +#define UART_ICR_IRDAEN (1 << 0) /*!< IrDA mode enable */ +#define UART_ICR_IRDAINV (1 << 1) /*!< IrDA serial input inverted */ +#define UART_ICR_FIXPULSE_EN (1 << 2) /*!< IrDA fixed pulse width mode */ +#define UART_ICR_PULSEDIV(n) ((n & 0x07) << 3) /*!< PulseDiv - Configures the pulse when FixPulseEn = 1 */ +#define UART_ICR_BITMASK (0x3F) /*!< UART IRDA bit mask */ + +/** + * @brief Macro defines for UART half duplex register - ???? + */ +#define UART_HDEN_HDEN ((1 << 0)) /*!< enable half-duplex mode*/ + +/** + * @brief Macro defines for UART Smart card interface Control Register - valid for 11xx, 18xx/43xx UART0/2/3 only + */ +#define UART_SCICTRL_SCIEN (1 << 0) /*!< enable asynchronous half-duplex smart card interface*/ +#define UART_SCICTRL_NACKDIS (1 << 1) /*!< NACK response is inhibited*/ +#define UART_SCICTRL_PROTSEL_T1 (1 << 2) /*!< ISO7816-3 protocol T1 is selected*/ +#define UART_SCICTRL_TXRETRY(n) ((n & 0x07) << 5) /*!< number of retransmission*/ +#define UART_SCICTRL_GUARDTIME(n) ((n & 0xFF) << 8) /*!< Extra guard time*/ + +/** + * @brief Macro defines for UART Fractional Divider Register + */ +#define UART_FDR_DIVADDVAL(n) (n & 0x0F) /*!< Baud-rate generation pre-scaler divisor */ +#define UART_FDR_MULVAL(n) ((n << 4) & 0xF0) /*!< Baud-rate pre-scaler multiplier value */ +#define UART_FDR_BITMASK (0xFF) /*!< UART Fractional Divider register bit mask */ + +/** + * @brief Macro defines for UART Tx Enable Register + */ +#define UART_TER1_TXEN (1 << 7) /*!< Transmit enable bit - valid for 11xx, 13xx, 17xx/40xx only */ +#define UART_TER2_TXEN (1 << 0) /*!< Transmit enable bit - valid for 18xx/43xx only */ + +/** + * @brief Macro defines for UART Synchronous Control Register - 11xx, 18xx/43xx UART0/2/3 only + */ +#define UART_SYNCCTRL_SYNC (1 << 0) /*!< enable synchronous mode*/ +#define UART_SYNCCTRL_CSRC_MASTER (1 << 1) /*!< synchronous master mode*/ +#define UART_SYNCCTRL_FES (1 << 2) /*!< sample on falling edge*/ +#define UART_SYNCCTRL_TSBYPASS (1 << 3) /*!< to be defined*/ +#define UART_SYNCCTRL_CSCEN (1 << 4) /*!< Continuous running clock enable (master mode only)*/ +#define UART_SYNCCTRL_STARTSTOPDISABLE (1 << 5) /*!< Do not send start/stop bit*/ +#define UART_SYNCCTRL_CCCLR (1 << 6) /*!< stop continuous clock*/ + +/** + * @brief Enable transmission on UART TxD pin + * @param pUART : Pointer to selected pUART peripheral + * @return Nothing + */ +STATIC INLINE void Chip_UART_TXEnable(LPC_USART_T *pUART) +{ + pUART->TER1 = UART_TER1_TXEN; +} + +/** + * @brief Disable transmission on UART TxD pin + * @param pUART : Pointer to selected pUART peripheral + * @return Nothing + */ +STATIC INLINE void Chip_UART_TXDisable(LPC_USART_T *pUART) +{ + pUART->TER1 = 0; +} + +/** + * @brief Transmit a single data byte through the UART peripheral + * @param pUART : Pointer to selected UART peripheral + * @param data : Byte to transmit + * @return Nothing + * @note This function attempts to place a byte into the UART transmit + * FIFO or transmit hold register regard regardless of UART state + */ +STATIC INLINE void Chip_UART_SendByte(LPC_USART_T *pUART, uint8_t data) +{ + pUART->THR = (uint32_t) data; +} + +/** + * @brief Read a single byte data from the UART peripheral + * @param pUART : Pointer to selected UART peripheral + * @return A single byte of data read + * @note This function reads a byte from the UART receive FIFO or + * receive hold register regard regardless of UART state. The + * FIFO status should be read first prior to using this function + */ +STATIC INLINE uint8_t Chip_UART_ReadByte(LPC_USART_T *pUART) +{ + return (uint8_t) (pUART->RBR & UART_RBR_MASKBIT); +} + +/** + * @brief Enable UART interrupts + * @param pUART : Pointer to selected UART peripheral + * @param intMask : OR'ed Interrupts to enable in the Interrupt Enable Register (IER) + * @return Nothing + * @note Use an OR'ed value of UART_IER_* definitions with this function + * to enable specific UART interrupts. The Divisor Latch Access Bit + * (DLAB) in LCR must be cleared in order to access the IER register. + * This function doesn't alter the DLAB state + */ +STATIC INLINE void Chip_UART_IntEnable(LPC_USART_T *pUART, uint32_t intMask) +{ + pUART->IER |= intMask; +} + +/** + * @brief Disable UART interrupts + * @param pUART : Pointer to selected UART peripheral + * @param intMask : OR'ed Interrupts to disable in the Interrupt Enable Register (IER) + * @return Nothing + * @note Use an OR'ed value of UART_IER_* definitions with this function + * to disable specific UART interrupts. The Divisor Latch Access Bit + * (DLAB) in LCR must be cleared in order to access the IER register. + * This function doesn't alter the DLAB state + */ +STATIC INLINE void Chip_UART_IntDisable(LPC_USART_T *pUART, uint32_t intMask) +{ + pUART->IER &= ~intMask; +} + +/** + * @brief Returns UART interrupts that are enabled + * @param pUART : Pointer to selected UART peripheral + * @return Returns the enabled UART interrupts + * @note Use an OR'ed value of UART_IER_* definitions with this function + * to determine which interrupts are enabled. You can check + * for multiple enabled bits if needed. + */ +STATIC INLINE uint32_t Chip_UART_GetIntsEnabled(LPC_USART_T *pUART) +{ + return pUART->IER; +} + +/** + * @brief Read the Interrupt Identification Register (IIR) + * @param pUART : Pointer to selected UART peripheral + * @return Current pending interrupt status per the IIR register + */ +STATIC INLINE uint32_t Chip_UART_ReadIntIDReg(LPC_USART_T *pUART) +{ + return pUART->IIR; +} + +/** + * @brief Setup the UART FIFOs + * @param pUART : Pointer to selected UART peripheral + * @param fcr : FIFO control register setup OR'ed flags + * @return Nothing + * @note Use OR'ed value of UART_FCR_* definitions with this function + * to select specific options. For example, to enable the FIFOs + * with a RX trip level of 8 characters, use something like + * (UART_FCR_FIFO_EN | UART_FCR_TRG_LEV2) + */ +STATIC INLINE void Chip_UART_SetupFIFOS(LPC_USART_T *pUART, uint32_t fcr) +{ + pUART->FCR = fcr; +} + +/** + * @brief Configure data width, parity and stop bits + * @param pUART : Pointer to selected pUART peripheral + * @param config : UART configuration, OR'ed values of UART_LCR_* defines + * @return Nothing + * @note Select OR'ed config options for the UART from the UART_LCR_* + * definitions. For example, a configuration of 8 data bits, 1 + * stop bit, and even (enabled) parity would be + * (UART_LCR_WLEN8 | UART_LCR_SBS_1BIT | UART_LCR_PARITY_EN | UART_LCR_PARITY_EVEN) + */ +STATIC INLINE void Chip_UART_ConfigData(LPC_USART_T *pUART, uint32_t config) +{ + pUART->LCR = config; +} + +/** + * @brief Enable access to Divisor Latches + * @param pUART : Pointer to selected UART peripheral + * @return Nothing + */ +STATIC INLINE void Chip_UART_EnableDivisorAccess(LPC_USART_T *pUART) +{ + pUART->LCR |= UART_LCR_DLAB_EN; +} + +/** + * @brief Disable access to Divisor Latches + * @param pUART : Pointer to selected UART peripheral + * @return Nothing + */ +STATIC INLINE void Chip_UART_DisableDivisorAccess(LPC_USART_T *pUART) +{ + pUART->LCR &= ~UART_LCR_DLAB_EN; +} + +/** + * @brief Set LSB and MSB divisor latch registers + * @param pUART : Pointer to selected UART peripheral + * @param dll : Divisor Latch LSB value + * @param dlm : Divisor Latch MSB value + * @return Nothing + * @note The Divisor Latch Access Bit (DLAB) in LCR must be set in + * order to access the USART Divisor Latches. This function + * doesn't alter the DLAB state. + */ +STATIC INLINE void Chip_UART_SetDivisorLatches(LPC_USART_T *pUART, uint8_t dll, uint8_t dlm) +{ + pUART->DLL = (uint32_t) dll; + pUART->DLM = (uint32_t) dlm; +} + +/** + * @brief Return modem control register/status + * @param pUART : Pointer to selected UART peripheral + * @return Modem control register (status) + * @note Mask bits of the returned status value with UART_MCR_* + * definitions for specific statuses. + */ +STATIC INLINE uint32_t Chip_UART_ReadModemControl(LPC_USART_T *pUART) +{ + return pUART->MCR; +} + +/** + * @brief Set modem control register/status + * @param pUART : Pointer to selected UART peripheral + * @param mcr : Modem control register flags to set + * @return Nothing + * @note Use an Or'ed value of UART_MCR_* definitions with this + * call to set specific options. + */ +STATIC INLINE void Chip_UART_SetModemControl(LPC_USART_T *pUART, uint32_t mcr) +{ + pUART->MCR |= mcr; +} + +/** + * @brief Clear modem control register/status + * @param pUART : Pointer to selected UART peripheral + * @param mcr : Modem control register flags to clear + * @return Nothing + * @note Use an Or'ed value of UART_MCR_* definitions with this + * call to clear specific options. + */ +STATIC INLINE void Chip_UART_ClearModemControl(LPC_USART_T *pUART, uint32_t mcr) +{ + pUART->MCR &= ~mcr; +} + +/** + * @brief Return Line Status register/status (LSR) + * @param pUART : Pointer to selected UART peripheral + * @return Line Status register (status) + * @note Mask bits of the returned status value with UART_LSR_* + * definitions for specific statuses. + */ +STATIC INLINE uint32_t Chip_UART_ReadLineStatus(LPC_USART_T *pUART) +{ + return pUART->LSR; +} + +/** + * @brief Return Modem Status register/status (MSR) + * @param pUART : Pointer to selected UART peripheral + * @return Modem Status register (status) + * @note Mask bits of the returned status value with UART_MSR_* + * definitions for specific statuses. + */ +STATIC INLINE uint32_t Chip_UART_ReadModemStatus(LPC_USART_T *pUART) +{ + return pUART->MSR; +} + +/** + * @brief Write a byte to the scratchpad register + * @param pUART : Pointer to selected UART peripheral + * @param data : Byte value to write + * @return Nothing + */ +STATIC INLINE void Chip_UART_SetScratch(LPC_USART_T *pUART, uint8_t data) +{ + pUART->SCR = (uint32_t) data; +} + +/** + * @brief Returns current byte value in the scratchpad register + * @param pUART : Pointer to selected UART peripheral + * @return Byte value read from scratchpad register + */ +STATIC INLINE uint8_t Chip_UART_ReadScratch(LPC_USART_T *pUART) +{ + return (uint8_t) (pUART->SCR & 0xFF); +} + +/** + * @brief Set autobaud register options + * @param pUART : Pointer to selected UART peripheral + * @param acr : Or'ed values to set for ACR register + * @return Nothing + * @note Use an Or'ed value of UART_ACR_* definitions with this + * call to set specific options. + */ +STATIC INLINE void Chip_UART_SetAutoBaudReg(LPC_USART_T *pUART, uint32_t acr) +{ + pUART->ACR |= acr; +} + +/** + * @brief Clear autobaud register options + * @param pUART : Pointer to selected UART peripheral + * @param acr : Or'ed values to clear for ACR register + * @return Nothing + * @note Use an Or'ed value of UART_ACR_* definitions with this + * call to clear specific options. + */ +STATIC INLINE void Chip_UART_ClearAutoBaudReg(LPC_USART_T *pUART, uint32_t acr) +{ + pUART->ACR &= ~acr; +} + +/** + * @brief Set RS485 control register options + * @param pUART : Pointer to selected UART peripheral + * @param ctrl : Or'ed values to set for RS485 control register + * @return Nothing + * @note Use an Or'ed value of UART_RS485CTRL_* definitions with this + * call to set specific options. + */ +STATIC INLINE void Chip_UART_SetRS485Flags(LPC_USART_T *pUART, uint32_t ctrl) +{ + pUART->RS485CTRL |= ctrl; +} + +/** + * @brief Clear RS485 control register options + * @param pUART : Pointer to selected UART peripheral + * @param ctrl : Or'ed values to clear for RS485 control register + * @return Nothing + * @note Use an Or'ed value of UART_RS485CTRL_* definitions with this + * call to clear specific options. + */ +STATIC INLINE void Chip_UART_ClearRS485Flags(LPC_USART_T *pUART, uint32_t ctrl) +{ + pUART->RS485CTRL &= ~ctrl; +} + +/** + * @brief Set RS485 address match value + * @param pUART : Pointer to selected UART peripheral + * @param addr : Address match value for RS-485/EIA-485 mode + * @return Nothing + */ +STATIC INLINE void Chip_UART_SetRS485Addr(LPC_USART_T *pUART, uint8_t addr) +{ + pUART->RS485ADRMATCH = (uint32_t) addr; +} + +/** + * @brief Read RS485 address match value + * @param pUART : Pointer to selected UART peripheral + * @return Address match value for RS-485/EIA-485 mode + */ +STATIC INLINE uint8_t Chip_UART_GetRS485Addr(LPC_USART_T *pUART) +{ + return (uint8_t) (pUART->RS485ADRMATCH & 0xFF); +} + +/** + * @brief Set RS485 direction control (RTS or DTR) delay value + * @param pUART : Pointer to selected UART peripheral + * @param dly : direction control (RTS or DTR) delay value + * @return Nothing + * @note This delay time is in periods of the baud clock. Any delay + * time from 0 to 255 bit times may be programmed. + */ +STATIC INLINE void Chip_UART_SetRS485Delay(LPC_USART_T *pUART, uint8_t dly) +{ + pUART->RS485DLY = (uint32_t) dly; +} + +/** + * @brief Read RS485 direction control (RTS or DTR) delay value + * @param pUART : Pointer to selected UART peripheral + * @return direction control (RTS or DTR) delay value + * @note This delay time is in periods of the baud clock. Any delay + * time from 0 to 255 bit times may be programmed. + */ +STATIC INLINE uint8_t Chip_UART_GetRS485Delay(LPC_USART_T *pUART) +{ + return (uint8_t) (pUART->RS485DLY & 0xFF); +} + +/** + * @brief Initializes the pUART peripheral + * @param pUART : Pointer to selected pUART peripheral + * @return Nothing + */ +void Chip_UART_Init(LPC_USART_T *pUART); + +/** + * @brief De-initializes the pUART peripheral. + * @param pUART : Pointer to selected pUART peripheral + * @return Nothing + */ +void Chip_UART_DeInit(LPC_USART_T *pUART); + +/** + * @brief Transmit a byte array through the UART peripheral (non-blocking) + * @param pUART : Pointer to selected UART peripheral + * @param data : Pointer to bytes to transmit + * @param numBytes : Number of bytes to transmit + * @return The actual number of bytes placed into the FIFO + * @note This function places data into the transmit FIFO until either + * all the data is in the FIFO or the FIFO is full. This function + * will not block in the FIFO is full. The actual number of bytes + * placed into the FIFO is returned. This function ignores errors. + */ +int Chip_UART_Send(LPC_USART_T *pUART, const void *data, int numBytes); + +/** + * @brief Read data through the UART peripheral (non-blocking) + * @param pUART : Pointer to selected UART peripheral + * @param data : Pointer to bytes array to fill + * @param numBytes : Size of the passed data array + * @return The actual number of bytes read + * @note This function reads data from the receive FIFO until either + * all the data has been read or the passed buffer is completely full. + * This function will not block. This function ignores errors. + */ +int Chip_UART_Read(LPC_USART_T *pUART, void *data, int numBytes); + +/** + * @brief Sets best dividers to get a target bit rate (without fractional divider) + * @param pUART : Pointer to selected UART peripheral + * @param baudrate : Target baud rate (baud rate = bit rate) + * @return The actual baud rate, or 0 if no rate can be found + */ +uint32_t Chip_UART_SetBaud(LPC_USART_T *pUART, uint32_t baudrate); + +/** + * @brief Sets best dividers to get a target bit rate (with fractional divider) + * @param pUART : Pointer to selected UART peripheral + * @param baudrate : Target baud rate (baud rate = bit rate) + * @return The actual baud rate, or 0 if no rate can be found + */ +uint32_t Chip_UART_SetBaudFDR(LPC_USART_T *pUART, uint32_t baudrate); + +/** + * @brief Transmit a byte array through the UART peripheral (blocking) + * @param pUART : Pointer to selected UART peripheral + * @param data : Pointer to data to transmit + * @param numBytes : Number of bytes to transmit + * @return The number of bytes transmitted + * @note This function will send or place all bytes into the transmit + * FIFO. This function will block until the last bytes are in the FIFO. + */ +int Chip_UART_SendBlocking(LPC_USART_T *pUART, const void *data, int numBytes); + +/** + * @brief Read data through the UART peripheral (blocking) + * @param pUART : Pointer to selected UART peripheral + * @param data : Pointer to data array to fill + * @param numBytes : Size of the passed data array + * @return The size of the dat array + * @note This function reads data from the receive FIFO until the passed + * buffer is completely full. The function will block until full. + * This function ignores errors. + */ +int Chip_UART_ReadBlocking(LPC_USART_T *pUART, void *data, int numBytes); + +/** + * @brief UART receive-only interrupt handler for ring buffers + * @param pUART : Pointer to selected UART peripheral + * @param pRB : Pointer to ring buffer structure to use + * @return Nothing + * @note If ring buffer support is desired for the receive side + * of data transfer, the UART interrupt should call this + * function for a receive based interrupt status. + */ +void Chip_UART_RXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB); + +/** + * @brief UART transmit-only interrupt handler for ring buffers + * @param pUART : Pointer to selected UART peripheral + * @param pRB : Pointer to ring buffer structure to use + * @return Nothing + * @note If ring buffer support is desired for the transmit side + * of data transfer, the UART interrupt should call this + * function for a transmit based interrupt status. + */ +void Chip_UART_TXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB); + +/** + * @brief Populate a transmit ring buffer and start UART transmit + * @param pUART : Pointer to selected UART peripheral + * @param pRB : Pointer to ring buffer structure to use + * @param data : Pointer to buffer to move to ring buffer + * @param bytes : Number of bytes to move + * @return The number of bytes placed into the ring buffer + * @note Will move the data into the TX ring buffer and start the + * transfer. If the number of bytes returned is less than the + * number of bytes to send, the ring buffer is considered full. + */ +uint32_t Chip_UART_SendRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, const void *data, int bytes); + +/** + * @brief Copy data from a receive ring buffer + * @param pUART : Pointer to selected UART peripheral + * @param pRB : Pointer to ring buffer structure to use + * @param data : Pointer to buffer to fill from ring buffer + * @param bytes : Size of the passed buffer in bytes + * @return The number of bytes placed into the ring buffer + * @note Will move the data from the RX ring buffer up to the + * the maximum passed buffer size. Returns 0 if there is + * no data in the ring buffer. + */ +int Chip_UART_ReadRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, void *data, int bytes); + +/** + * @brief UART receive/transmit interrupt handler for ring buffers + * @param pUART : Pointer to selected UART peripheral + * @param pRXRB : Pointer to transmit ring buffer + * @param pTXRB : Pointer to receive ring buffer + * @return Nothing + * @note This provides a basic implementation of the UART IRQ + * handler for support of a ring buffer implementation for + * transmit and receive. + */ +void Chip_UART_IRQRBHandler(LPC_USART_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __UART_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/wwdt_11xx.h b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/wwdt_11xx.h new file mode 100755 index 0000000..9dfdff8 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/inc/wwdt_11xx.h @@ -0,0 +1,266 @@ +/* + * @brief LPC11xx WWDT chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __WWDT_11XX_H_ +#define __WWDT_11XX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup WWDT_11XX CHIP: LPC11xx Windowed Watchdog driver + * @ingroup CHIP_11XX_Drivers + * @{ + */ + +#if !defined(CHIP_LPC11CXX) || defined(CHIP_LPC1125) +#define WATCHDOG_WINDOW_SUPPORT +#endif + +#if defined(CHIP_LPC11AXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC11UXX) +#define WATCHDOG_CLKSEL_SUPPORT +#endif + +/** + * @brief Windowed Watchdog register block structure + */ +typedef struct { /*!< WWDT Structure */ + __IO uint32_t MOD; /*!< Watchdog mode register. This register contains the basic mode and status of the Watchdog Timer. */ + __IO uint32_t TC; /*!< Watchdog timer constant register. This register determines the time-out value. */ + __O uint32_t FEED; /*!< Watchdog feed sequence register. Writing 0xAA followed by 0x55 to this register reloads the Watchdog timer with the value contained in WDTC. */ + __I uint32_t TV; /*!< Watchdog timer value register. This register reads out the current value of the Watchdog timer. */ +#ifdef WATCHDOG_CLKSEL_SUPPORT + __IO uint32_t CLKSEL; /*!< Watchdog clock select register. */ +#else + __I uint32_t RESERVED0; +#endif +#ifdef WATCHDOG_WINDOW_SUPPORT + __IO uint32_t WARNINT; /*!< Watchdog warning interrupt register. This register contains the Watchdog warning interrupt compare value. */ + __IO uint32_t WINDOW; /*!< Watchdog timer window register. This register contains the Watchdog window value. */ +#endif +} LPC_WWDT_T; + +/** + * @brief Watchdog Mode register definitions + */ +/** Watchdog Mode Bitmask */ +#define WWDT_WDMOD_BITMASK ((uint32_t) 0x1F) +/** WWDT interrupt enable bit */ +#define WWDT_WDMOD_WDEN ((uint32_t) (1 << 0)) +/** WWDT interrupt enable bit */ +#define WWDT_WDMOD_WDRESET ((uint32_t) (1 << 1)) +/** WWDT time out flag bit */ +#define WWDT_WDMOD_WDTOF ((uint32_t) (1 << 2)) +/** WDT Time Out flag bit */ +#define WWDT_WDMOD_WDINT ((uint32_t) (1 << 3)) +/** WWDT Protect flag bit */ +#define WWDT_WDMOD_WDPROTECT ((uint32_t) (1 << 4)) + +/** + * @brief Initialize the Watchdog timer + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @return None + */ +void Chip_WWDT_Init(LPC_WWDT_T *pWWDT); + +/** + * @brief Shutdown the Watchdog timer + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @return None + */ +void Chip_WWDT_DeInit(LPC_WWDT_T *pWWDT); + +/** + * @brief Set WDT timeout constant value used for feed + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param timeout : WDT timeout in ticks, between WWDT_TICKS_MIN and WWDT_TICKS_MAX + * @return none + */ +STATIC INLINE void Chip_WWDT_SetTimeOut(LPC_WWDT_T *pWWDT, uint32_t timeout) +{ + pWWDT->TC = timeout; +} + +/** + * @brief Feed watchdog timer + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @return None + * @note If this function isn't called, a watchdog timer warning will occur. + * After the warning, a timeout will occur if a feed has happened. + */ +STATIC INLINE void Chip_WWDT_Feed(LPC_WWDT_T *pWWDT) +{ + pWWDT->FEED = 0xAA; + pWWDT->FEED = 0x55; +} + +#if defined(WATCHDOG_WINDOW_SUPPORT) +/** + * @brief Set WWDT warning interrupt + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param timeout : WDT warning in ticks, between 0 and 1023 + * @return None + * @note This is the number of ticks after the watchdog interrupt that the + * warning interrupt will be generated. + */ +STATIC INLINE void Chip_WWDT_SetWarning(LPC_WWDT_T *pWWDT, uint32_t timeout) +{ + pWWDT->WARNINT = timeout; +} + +/** + * @brief Set WWDT window time + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param timeout : WDT timeout in ticks, between WWDT_TICKS_MIN and WWDT_TICKS_MAX + * @return None + * @note The watchdog timer must be fed between the timeout from the Chip_WWDT_SetTimeOut() + * function and this function, with this function defining the last tick before the + * watchdog window interrupt occurs. + */ +STATIC INLINE void Chip_WWDT_SetWindow(LPC_WWDT_T *pWWDT, uint32_t timeout) +{ + pWWDT->WINDOW = timeout; +} + +#endif + +/** + * @brief Enable watchdog timer options + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param options : An or'ed set of options of values + * WWDT_WDMOD_WDEN, WWDT_WDMOD_WDRESET, and WWDT_WDMOD_WDPROTECT + * @return None + * @note You can enable more than one option at once (ie, WWDT_WDMOD_WDRESET | + * WWDT_WDMOD_WDPROTECT), but use the WWDT_WDMOD_WDEN after all other options + * are set (or unset) with no other options. If WWDT_WDMOD_LOCK is used, it cannot + * be unset. + */ +STATIC INLINE void Chip_WWDT_SetOption(LPC_WWDT_T *pWWDT, uint32_t options) +{ + pWWDT->MOD |= options; +} + +/** + * @brief Disable/clear watchdog timer options + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param options : An or'ed set of options of values + * WWDT_WDMOD_WDEN, WWDT_WDMOD_WDRESET, and WWDT_WDMOD_WDPROTECT + * @return None + * @note You can disable more than one option at once (ie, WWDT_WDMOD_WDRESET | + * WWDT_WDMOD_WDTOF). + */ +STATIC INLINE void Chip_WWDT_UnsetOption(LPC_WWDT_T *pWWDT, uint32_t options) +{ + pWWDT->MOD &= (~options) & WWDT_WDMOD_BITMASK; +} + +/** + * @brief Enable WWDT activity + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @return None + */ +STATIC INLINE void Chip_WWDT_Start(LPC_WWDT_T *pWWDT) +{ + Chip_WWDT_SetOption(pWWDT, WWDT_WDMOD_WDEN); + Chip_WWDT_Feed(pWWDT); +} + +/** + * @brief Read WWDT status flag + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @return Watchdog status, an Or'ed value of WWDT_WDMOD_* + */ +STATIC INLINE uint32_t Chip_WWDT_GetStatus(LPC_WWDT_T *pWWDT) +{ + return pWWDT->MOD; +} + +/** + * @brief Clear WWDT interrupt status flags + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param status : Or'ed value of status flag(s) that you want to clear, should be: + * - WWDT_WDMOD_WDTOF: Clear watchdog timeout flag + * - WWDT_WDMOD_WDINT: Clear watchdog warning flag + * @return None + */ +void Chip_WWDT_ClearStatusFlag(LPC_WWDT_T *pWWDT, uint32_t status); + +/** + * @brief Get the current value of WDT + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @return current value of WDT + */ +STATIC INLINE uint32_t Chip_WWDT_GetCurrentCount(LPC_WWDT_T *pWWDT) +{ + return pWWDT->TV; +} + +#if defined(WATCHDOG_CLKSEL_SUPPORT) +/** + * @brief Watchdog Timer Clock Source Selection register definitions + */ +/** Clock source select bitmask */ +#define WWDT_CLKSEL_BITMASK ((uint32_t) 0x10000003) +/** Clock source select */ +#define WWDT_CLKSEL_SOURCE(n) ((uint32_t) (n & 0x03)) +/** Lock the clock source selection */ +#define WWDT_CLKSEL_LOCK ((uint32_t) (1 << 31)) + +/** + * @brief Watchdog Clock Source definitions + */ +typedef enum { + WWDT_CLKSRC_IRC = WWDT_CLKSEL_SOURCE(0), /*!< Internal RC oscillator */ + WWDT_CLKSRC_WATCHDOG_WDOSC = WWDT_CLKSEL_SOURCE(1), /*!< Watchdog oscillator (WDOSC) */ +} CHIP_WWDT_CLK_SRC_T; + +/** + * @brief Get the current value of WDT + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param wdtClkSrc : Selected watchdog clock source + * @return Nothing + */ +STATIC INLINE void Chip_WWDT_SelClockSource(LPC_WWDT_T *pWWDT, CHIP_WWDT_CLK_SRC_T wdtClkSrc) +{ + pWWDT->CLKSEL = wdtClkSrc & WWDT_CLKSEL_BITMASK; +} + +#endif + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __WWDT_11XX_H_ */ diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/src/clock_11xx.c b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/src/clock_11xx.c new file mode 100755 index 0000000..bd6b953 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/src/clock_11xx.c @@ -0,0 +1,285 @@ +/* + * @brief LPC11XX System clock control functions + * + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/* Inprecise clock rates for the watchdog oscillator */ +STATIC const uint32_t wdtOSCRate[WDTLFO_OSC_4_60 + 1] = { + 0, /* WDT_OSC_ILLEGAL */ + 600000, /* WDT_OSC_0_60 */ + 1050000, /* WDT_OSC_1_05 */ + 1400000, /* WDT_OSC_1_40 */ + 1750000, /* WDT_OSC_1_75 */ + 2100000, /* WDT_OSC_2_10 */ + 2400000, /* WDT_OSC_2_40 */ + 2700000, /* WDT_OSC_2_70 */ + 3000000, /* WDT_OSC_3_00 */ + 3250000, /* WDT_OSC_3_25 */ + 3500000, /* WDT_OSC_3_50 */ + 3750000, /* WDT_OSC_3_75 */ + 4000000, /* WDT_OSC_4_00 */ + 4200000, /* WDT_OSC_4_20 */ + 4400000, /* WDT_OSC_4_40 */ + 4600000 /* WDT_OSC_4_60 */ +}; + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/* Compute a WDT or LFO rate */ +STATIC uint32_t Chip_Clock_GetWDTLFORate(uint32_t reg) +{ + uint32_t div; + CHIP_WDTLFO_OSC_T clk; + + /* Get WDT oscillator settings */ + clk = (CHIP_WDTLFO_OSC_T) ((reg >> 5) & 0xF); + div = reg & 0x1F; + + /* Compute clock rate and divided by divde value */ + return wdtOSCRate[clk] / ((div + 1) << 1); +} + +/* Compute a PLL frequency */ +STATIC uint32_t Chip_Clock_GetPLLFreq(uint32_t PLLReg, uint32_t inputRate) +{ + uint32_t msel = ((PLLReg & 0x1F) + 1); + + return inputRate * msel; +} + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Set System PLL clock source */ +void Chip_Clock_SetSystemPLLSource(CHIP_SYSCTL_PLLCLKSRC_T src) +{ + LPC_SYSCTL->SYSPLLCLKSEL = (uint32_t) src; + LPC_SYSCTL->SYSPLLCLKUEN = 0; + LPC_SYSCTL->SYSPLLCLKUEN = 1; +} + +/* Bypass System Oscillator and set oscillator frequency range */ +void Chip_Clock_SetPLLBypass(bool bypass, bool highfr) +{ + uint32_t ctrl = 0; + + if (bypass) { + ctrl |= (1 << 0); + } + if (highfr) { + ctrl |= (1 << 1); + } + + LPC_SYSCTL->SYSOSCCTRL = ctrl; +} + +#if defined(CHIP_LPC11UXX) +/* Set USB PLL clock source */ +void Chip_Clock_SetUSBPLLSource(CHIP_SYSCTL_PLLCLKSRC_T src) +{ + LPC_SYSCTL->USBPLLCLKSEL = (uint32_t) src; + LPC_SYSCTL->USBPLLCLKUEN = 0; + LPC_SYSCTL->USBPLLCLKUEN = 1; +} + +#endif + +/* Set main system clock source */ +void Chip_Clock_SetMainClockSource(CHIP_SYSCTL_MAINCLKSRC_T src) +{ + LPC_SYSCTL->MAINCLKSEL = (uint32_t) src; + LPC_SYSCTL->MAINCLKUEN = 0; + LPC_SYSCTL->MAINCLKUEN = 1; +} + +#if defined(CHIP_LPC11UXX) +/* Set USB clock source and divider */ +void Chip_Clock_SetUSBClockSource(CHIP_SYSCTL_USBCLKSRC_T src, uint32_t div) +{ + LPC_SYSCTL->USBCLKSEL = (uint32_t) src; + LPC_SYSCTL->USBCLKUEN = 0; + LPC_SYSCTL->USBCLKUEN = 1; + LPC_SYSCTL->USBCLKDIV = div; +} + +#endif /*CHIP_LPC11UXX*/ + +#if defined(CHIP_LPC110X) || defined(CHIP_LPC11XXLV) || defined(CHIP_LPC11CXX) || defined(CHIP_LPC11EXX) || defined(CHIP_LPC1125) +/* Set WDT clock source and divider */ +void Chip_Clock_SetWDTClockSource(CHIP_SYSCTL_WDTCLKSRC_T src, uint32_t div) +{ + LPC_SYSCTL->WDTCLKSEL = (uint32_t) src; + LPC_SYSCTL->WDTCLKUEN = 0; + LPC_SYSCTL->WDTCLKUEN = 1; + LPC_SYSCTL->WDTCLKDIV = div; +} + +#endif + +#if !defined(CHIP_LPC110X) +/* Set CLKOUT clock source and divider */ +void Chip_Clock_SetCLKOUTSource(CHIP_SYSCTL_CLKOUTSRC_T src, uint32_t div) +{ + LPC_SYSCTL->CLKOUTSEL = (uint32_t) src; + LPC_SYSCTL->CLKOUTUEN = 0; + LPC_SYSCTL->CLKOUTUEN = 1; + LPC_SYSCTL->CLKOUTDIV = div; +} + +#endif + +/* Return estimated watchdog oscillator rate */ +uint32_t Chip_Clock_GetWDTOSCRate(void) +{ + return Chip_Clock_GetWDTLFORate(LPC_SYSCTL->WDTOSCCTRL); +} + +#if defined(CHIP_LPC11AXX) +/* Return estimated low frequency oscillator rate */ +uint32_t Chip_Clock_GetLFOOSCRate(void) +{ + return Chip_Clock_GetWDTLFORate(LPC_SYSCTL->LFOSCCTRL); +} + +#endif + +/* Return System PLL input clock rate */ +uint32_t Chip_Clock_GetSystemPLLInClockRate(void) +{ + uint32_t clkRate; + + switch ((CHIP_SYSCTL_PLLCLKSRC_T) (LPC_SYSCTL->SYSPLLCLKSEL & 0x3)) { + case SYSCTL_PLLCLKSRC_IRC: + clkRate = Chip_Clock_GetIntOscRate(); + break; + + case SYSCTL_PLLCLKSRC_MAINOSC: + clkRate = Chip_Clock_GetMainOscRate(); + break; + +#if defined(CHIP_LPC11AXX) + case SYSCTL_PLLCLKSRC_EXT_CLKIN: + clkRate = Chip_Clock_GetExtClockInRate(); + break; +#endif + + default: + clkRate = 0; + } + + return clkRate; +} + +/* Return System PLL output clock rate */ +uint32_t Chip_Clock_GetSystemPLLOutClockRate(void) +{ + return Chip_Clock_GetPLLFreq(LPC_SYSCTL->SYSPLLCTRL, + Chip_Clock_GetSystemPLLInClockRate()); +} + +#if defined(CHIP_LPC11UXX) +/* Return USB PLL input clock rate */ +uint32_t Chip_Clock_GetUSBPLLInClockRate(void) +{ + uint32_t clkRate; + + switch ((CHIP_SYSCTL_PLLCLKSRC_T) (LPC_SYSCTL->USBPLLCLKSEL & 0x3)) { + case SYSCTL_PLLCLKSRC_IRC: + clkRate = Chip_Clock_GetIntOscRate(); + break; + + case SYSCTL_PLLCLKSRC_MAINOSC: + clkRate = Chip_Clock_GetMainOscRate(); + break; + + default: + clkRate = 0; + } + + return clkRate; +} + +/* Return USB PLL output clock rate */ +uint32_t Chip_Clock_GetUSBPLLOutClockRate(void) +{ + return Chip_Clock_GetPLLFreq(LPC_SYSCTL->USBPLLCTRL, + Chip_Clock_GetUSBPLLInClockRate()); +} + +#endif + +/* Return main clock rate */ +uint32_t Chip_Clock_GetMainClockRate(void) +{ + uint32_t clkRate = 0; + + switch ((CHIP_SYSCTL_MAINCLKSRC_T) (LPC_SYSCTL->MAINCLKSEL & 0x3)) { + case SYSCTL_MAINCLKSRC_IRC: + clkRate = Chip_Clock_GetIntOscRate(); + break; + + case SYSCTL_MAINCLKSRC_PLLIN: + clkRate = Chip_Clock_GetSystemPLLInClockRate(); + break; + +#if defined(CHIP_LPC11AXX) + case SYSCTL_MAINCLKSRC_LFOSC: + clkRate = Chip_Clock_GetLFOOSCRate(); + break; + +#else + case SYSCTL_MAINCLKSRC_WDTOSC: + clkRate = Chip_Clock_GetWDTOSCRate(); + break; +#endif + + case SYSCTL_MAINCLKSRC_PLLOUT: + clkRate = Chip_Clock_GetSystemPLLOutClockRate(); + break; + } + + return clkRate; +} + +/* Return system clock rate */ +uint32_t Chip_Clock_GetSystemClockRate(void) +{ + /* No point in checking for divide by 0 */ + return Chip_Clock_GetMainClockRate() / LPC_SYSCTL->SYSAHBCLKDIV; +} diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/src/uart_11xx.c b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/src/uart_11xx.c new file mode 100644 index 0000000..ae404b0 --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/src/uart_11xx.c @@ -0,0 +1,289 @@ +/* + * @brief LPC11xx UART chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +#if __GNUC__ +# pragma GCC diagnostic ignored "-Wsign-conversion" +# pragma GCC diagnostic ignored "-Wconversion" +# pragma GCC diagnostic ignored "-Wmissing-declarations" +# pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initializes the pUART peripheral */ +void Chip_UART_Init(LPC_USART_T *pUART) +{ + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_UART0); + Chip_Clock_SetUARTClockDiv(1); + + /* Enable FIFOs by default, reset them */ + Chip_UART_SetupFIFOS(pUART, (UART_FCR_FIFO_EN | UART_FCR_RX_RS | UART_FCR_TX_RS)); + + /* Default 8N1, with DLAB disabled */ + Chip_UART_ConfigData(pUART, (UART_LCR_WLEN8 | UART_LCR_SBS_1BIT | UART_LCR_PARITY_DIS)); + + /* Disable fractional divider */ + pUART->FDR = 0x10; +} + +/* De-initializes the pUART peripheral */ +void Chip_UART_DeInit(LPC_USART_T *pUART) +{ + Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_UART0); +} + +/* Transmit a byte array through the UART peripheral (non-blocking) */ +int Chip_UART_Send(LPC_USART_T *pUART, const void *data, int numBytes) +{ + int sent = 0; + uint8_t *p8 = (uint8_t *) data; + + /* Send until the transmit FIFO is full or out of bytes */ + while ((sent < numBytes) && + ((Chip_UART_ReadLineStatus(pUART) & UART_LSR_THRE) != 0)) { + Chip_UART_SendByte(pUART, *p8); + p8++; + sent++; + } + + return sent; +} + +/* Transmit a byte array through the UART peripheral (blocking) */ +int Chip_UART_SendBlocking(LPC_USART_T *pUART, const void *data, int numBytes) +{ + int pass, sent = 0; + uint8_t *p8 = (uint8_t *) data; + + while (numBytes > 0) { + pass = Chip_UART_Send(pUART, p8, numBytes); + numBytes -= pass; + sent += pass; + p8 += pass; + } + + return sent; +} + +/* Read data through the UART peripheral (non-blocking) */ +int Chip_UART_Read(LPC_USART_T *pUART, void *data, int numBytes) +{ + int readBytes = 0; + uint8_t *p8 = (uint8_t *) data; + + /* Send until the transmit FIFO is full or out of bytes */ + while ((readBytes < numBytes) && + ((Chip_UART_ReadLineStatus(pUART) & UART_LSR_RDR) != 0)) { + *p8 = Chip_UART_ReadByte(pUART); + p8++; + readBytes++; + } + + return readBytes; +} + +/* Read data through the UART peripheral (blocking) */ +int Chip_UART_ReadBlocking(LPC_USART_T *pUART, void *data, int numBytes) +{ + int pass, readBytes = 0; + uint8_t *p8 = (uint8_t *) data; + + while (readBytes < numBytes) { + pass = Chip_UART_Read(pUART, p8, numBytes); + numBytes -= pass; + readBytes += pass; + p8 += pass; + } + + return readBytes; +} + +/* Determines and sets best dividers to get a target bit rate */ +uint32_t Chip_UART_SetBaud(LPC_USART_T *pUART, uint32_t baudrate) +{ + uint32_t div, divh, divl, clkin; + + /* Determine UART clock in rate without FDR */ + clkin = Chip_Clock_GetMainClockRate(); + div = clkin / (baudrate * 16); + + /* High and low halves of the divider */ + divh = div / 256; + divl = div - (divh * 256); + + Chip_UART_EnableDivisorAccess(pUART); + Chip_UART_SetDivisorLatches(pUART, divl, divh); + Chip_UART_DisableDivisorAccess(pUART); + + /* Fractional FDR alreadt setup for 1 in UART init */ + + return clkin / div; +} + +/* UART receive-only interrupt handler for ring buffers */ +void Chip_UART_RXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB) +{ + /* New data will be ignored if data not popped in time */ + while (Chip_UART_ReadLineStatus(pUART) & UART_LSR_RDR) { + uint8_t ch = Chip_UART_ReadByte(pUART); + RingBuffer_Insert(pRB, &ch); + } +} + +/* UART transmit-only interrupt handler for ring buffers */ +void Chip_UART_TXIntHandlerRB(LPC_USART_T *pUART, RINGBUFF_T *pRB) +{ + uint8_t ch; + + /* Fill FIFO until full or until TX ring buffer is empty */ + while ((Chip_UART_ReadLineStatus(pUART) & UART_LSR_THRE) != 0 && + RingBuffer_Pop(pRB, &ch)) { + Chip_UART_SendByte(pUART, ch); + } +} + +/* Populate a transmit ring buffer and start UART transmit */ +uint32_t Chip_UART_SendRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, const void *data, int bytes) +{ + uint32_t ret; + uint8_t *p8 = (uint8_t *) data; + + /* Don't let UART transmit ring buffer change in the UART IRQ handler */ + Chip_UART_IntDisable(pUART, UART_IER_THREINT); + + /* Move as much data as possible into transmit ring buffer */ + ret = RingBuffer_InsertMult(pRB, p8, bytes); + Chip_UART_TXIntHandlerRB(pUART, pRB); + + /* Add additional data to transmit ring buffer if possible */ + ret += RingBuffer_InsertMult(pRB, (p8 + ret), (bytes - ret)); + + /* Enable UART transmit interrupt */ + Chip_UART_IntEnable(pUART, UART_IER_THREINT); + + return ret; +} + +/* Copy data from a receive ring buffer */ +int Chip_UART_ReadRB(LPC_USART_T *pUART, RINGBUFF_T *pRB, void *data, int bytes) +{ + (void) pUART; + + return RingBuffer_PopMult(pRB, (uint8_t *) data, bytes); +} + +/* UART receive/transmit interrupt handler for ring buffers */ +void Chip_UART_IRQRBHandler(LPC_USART_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB) +{ + /* Handle transmit interrupt if enabled */ + if (pUART->IER & UART_IER_THREINT) { + Chip_UART_TXIntHandlerRB(pUART, pTXRB); + + /* Disable transmit interrupt if the ring buffer is empty */ + if (RingBuffer_IsEmpty(pTXRB)) { + Chip_UART_IntDisable(pUART, UART_IER_THREINT); + } + } + + /* Handle receive interrupt */ + Chip_UART_RXIntHandlerRB(pUART, pRXRB); +} + +/* Determines and sets best dividers to get a target baud rate */ +uint32_t Chip_UART_SetBaudFDR(LPC_USART_T *pUART, uint32_t baudrate) + +{ + uint32_t uClk = 0; + uint32_t dval = 0; + uint32_t mval = 0; + uint32_t dl = 0; + uint32_t rate16 = 16 * baudrate; + uint32_t actualRate = 0; + + /* Get Clock rate */ + uClk = Chip_Clock_GetMainClockRate(); + + /* The fractional is calculated as (PCLK % (16 * Baudrate)) / (16 * Baudrate) + * Let's make it to be the ratio DivVal / MulVal + */ + dval = uClk % rate16; + + /* The PCLK / (16 * Baudrate) is fractional + * => dval = pclk % rate16 + * mval = rate16; + * now mormalize the ratio + * dval / mval = 1 / new_mval + * new_mval = mval / dval + * new_dval = 1 + */ + if (dval > 0) { + mval = rate16 / dval; + dval = 1; + + /* In case mval still bigger then 4 bits + * no adjustment require + */ + if (mval > 12) { + dval = 0; + } + } + dval &= 0xf; + mval &= 0xf; + dl = uClk / (rate16 + rate16 *dval / mval); + + /* Update UART registers */ + Chip_UART_EnableDivisorAccess(pUART); + Chip_UART_SetDivisorLatches(pUART, UART_LOAD_DLL(dl), UART_LOAD_DLM(dl)); + Chip_UART_DisableDivisorAccess(pUART); + + /* Set best fractional divider */ + pUART->FDR = (UART_FDR_MULVAL(mval) | UART_FDR_DIVADDVAL(dval)); + + /* Return actual baud rate */ + actualRate = uClk / (16 * dl + 16 * dl * dval / mval); + return actualRate; +} diff --git a/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/src/wwdt_11xx.c b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/src/wwdt_11xx.c new file mode 100755 index 0000000..c78656d --- /dev/null +++ b/test_olimex_lpc_p11c24/lpc_chip_11cxx_lib/src/wwdt_11xx.c @@ -0,0 +1,86 @@ +/* + * @brief LPC11xx WWDT chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +/* + * Compiler warning fixes + * Pavel Kirienko, 2014 + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initialize the Watchdog timer */ +void Chip_WWDT_Init(LPC_WWDT_T *pWWDT) +{ + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_WDT); + + /* Disable watchdog */ + pWWDT->MOD = 0; + pWWDT->TC = 0xFF; +#if defined(WATCHDOG_WINDOW_SUPPORT) + pWWDT->WARNINT = 0xFFFF; + pWWDT->WINDOW = 0xFFFFFF; +#endif +} + +/* Shutdown the Watchdog timer */ +void Chip_WWDT_DeInit(LPC_WWDT_T *pWWDT) +{ + (void)pWWDT; + Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_WDT); +} + +/* Clear WWDT interrupt status flags */ +void Chip_WWDT_ClearStatusFlag(LPC_WWDT_T *pWWDT, uint32_t status) +{ + if (status & WWDT_WDMOD_WDTOF) { + pWWDT->MOD &= (~WWDT_WDMOD_WDTOF) & WWDT_WDMOD_BITMASK; + } + + if (status & WWDT_WDMOD_WDINT) { + pWWDT->MOD |= WWDT_WDMOD_WDINT; + } +} diff --git a/test_olimex_lpc_p11c24/src/main.cpp b/test_olimex_lpc_p11c24/src/main.cpp new file mode 100644 index 0000000..9f81263 --- /dev/null +++ b/test_olimex_lpc_p11c24/src/main.cpp @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * GCC 4.9 cannot generate a working binary with higher optimization levels, although + * rest of the firmware can be compiled with -Os. + * GCC 4.8 and earlier don't work at all on this firmware. + */ +#if __GNUC__ +# pragma GCC optimize 1 +#endif + +/** + * This function re-defines the standard ::rand(), which is used by the class uavcan::DynamicNodeIDClient. + * Redefinition is normally not needed, but GCC 4.9 tends to generate broken binaries if it is not redefined. + */ +int rand() +{ + static int x = 1; + x = x * 48271 % 2147483647; + return x; +} + +namespace +{ + +static constexpr unsigned NodeMemoryPoolSize = 2800; + +/** + * This is a compact, reentrant and thread-safe replacement to standard llto(). + * It returns the string by value, no extra storage is needed. + */ +typename uavcan::MakeString<22>::Type intToString(long long n) +{ + char buf[24] = {}; + const short sign = (n < 0) ? -1 : 1; + if (sign < 0) + { + n = -n; + } + unsigned pos = 0; + do + { + buf[pos++] = char(n % 10 + '0'); + } + while ((n /= 10) > 0); + if (sign < 0) + { + buf[pos++] = '-'; + } + buf[pos] = '\0'; + for (unsigned i = 0, j = pos - 1U; i < j; i++, j--) + { + std::swap(buf[i], buf[j]); + } + return static_cast(buf); +} + +uavcan::Node& getNode() +{ + static uavcan::Node node(uavcan_lpc11c24::CanDriver::instance(), + uavcan_lpc11c24::SystemClock::instance()); + return node; +} + +uavcan::GlobalTimeSyncSlave& getTimeSyncSlave() +{ + static uavcan::GlobalTimeSyncSlave tss(getNode()); + return tss; +} + +uavcan::Logger& getLogger() +{ + static uavcan::Logger logger(getNode()); + return logger; +} + +uavcan::NodeID performDynamicNodeIDAllocation() +{ + uavcan::DynamicNodeIDClient client(getNode()); + + const int client_start_res = client.start(getNode().getHardwareVersion().unique_id); + if (client_start_res < 0) + { + board::die(); + } + + while (!client.isAllocationComplete()) + { + board::resetWatchdog(); + (void)getNode().spin(uavcan::MonotonicDuration::fromMSec(100)); + } + + return client.getAllocatedNodeID(); +} + +void init() +{ + board::resetWatchdog(); + board::syslog("Boot\r\n"); + + board::setErrorLed(false); + board::setStatusLed(true); + + /* + * Configuring the clock - this must be done before the CAN controller is initialized + */ + uavcan_lpc11c24::clock::init(); + + /* + * Configuring the CAN controller + */ + std::uint32_t bit_rate = 0; + while (bit_rate == 0) + { + board::syslog("CAN auto bitrate...\r\n"); + bit_rate = uavcan_lpc11c24::CanDriver::detectBitRate(&board::resetWatchdog); + } + board::syslog("Bitrate: "); + board::syslog(intToString(bit_rate).c_str()); + board::syslog("\r\n"); + + if (uavcan_lpc11c24::CanDriver::instance().init(bit_rate) < 0) + { + board::die(); + } + + board::syslog("CAN init ok\r\n"); + + board::resetWatchdog(); + + /* + * Configuring the node + */ + getNode().setName("org.uavcan.lpc11c24_test"); + + uavcan::protocol::SoftwareVersion swver; + swver.major = FW_VERSION_MAJOR; + swver.minor = FW_VERSION_MINOR; + swver.vcs_commit = GIT_HASH; + swver.optional_field_flags = swver.OPTIONAL_FIELD_FLAG_VCS_COMMIT; + getNode().setSoftwareVersion(swver); + + uavcan::protocol::HardwareVersion hwver; + std::uint8_t uid[board::UniqueIDSize] = {}; + board::readUniqueID(uid); + std::copy(std::begin(uid), std::end(uid), std::begin(hwver.unique_id)); + getNode().setHardwareVersion(hwver); + + board::resetWatchdog(); + + /* + * Starting the node and performing dynamic node ID allocation + */ + if (getNode().start() < 0) + { + board::die(); + } + + board::syslog("Node ID allocation...\r\n"); + + getNode().setNodeID(performDynamicNodeIDAllocation()); + + board::syslog("Node ID "); + board::syslog(intToString(getNode().getNodeID().get()).c_str()); + board::syslog("\r\n"); + + board::resetWatchdog(); + + /* + * Example filter configuration. + * Can be removed safely. + */ + { + constexpr unsigned NumFilters = 3; + uavcan::CanFilterConfig filters[NumFilters]; + + // Acepting all service transfers addressed to us + filters[0].id = (unsigned(getNode().getNodeID().get()) << 8) | (1U << 7) | uavcan::CanFrame::FlagEFF; + filters[0].mask = 0x7F80 | uavcan::CanFrame::FlagEFF; + + // Accepting time sync messages + filters[1].id = (4U << 8) | uavcan::CanFrame::FlagEFF; + filters[1].mask = 0xFFFF80 | uavcan::CanFrame::FlagEFF; + + // Accepting zero CAN ID (just for the sake of testing) + filters[2].id = 0 | uavcan::CanFrame::FlagEFF; + filters[2].mask = uavcan::CanFrame::MaskExtID | uavcan::CanFrame::FlagEFF; + + if (uavcan_lpc11c24::CanDriver::instance().configureFilters(filters, NumFilters) < 0) + { + board::syslog("Filter init failed\r\n"); + board::die(); + } + } + + /* + * Initializing other libuavcan-related objects + */ + if (getTimeSyncSlave().start() < 0) + { + board::die(); + } + + if (getLogger().init() < 0) + { + board::die(); + } + + getLogger().setLevel(uavcan::protocol::debug::LogLevel::DEBUG); + + board::resetWatchdog(); +} + +} + +int main() +{ + init(); + + getNode().setModeOperational(); + + uavcan::MonotonicTime prev_log_at; + + while (true) + { + const int res = getNode().spin(uavcan::MonotonicDuration::fromMSec(25)); + board::setErrorLed(res < 0); + board::setStatusLed(uavcan_lpc11c24::CanDriver::instance().hadActivity()); + + const auto ts = uavcan_lpc11c24::clock::getMonotonic(); + if ((ts - prev_log_at).toMSec() >= 1000) + { + prev_log_at = ts; + + /* + * CAN bus off state monitoring + */ + if (uavcan_lpc11c24::CanDriver::instance().isInBusOffState()) + { + board::syslog("CAN BUS OFF\r\n"); + } + + /* + * CAN error counter, for debugging purposes + */ + board::syslog("CAN errors: "); + board::syslog(intToString(static_cast(uavcan_lpc11c24::CanDriver::instance().getErrorCount())).c_str()); + board::syslog(" "); + board::syslog(intToString(uavcan_lpc11c24::CanDriver::instance().getRxQueueOverflowCount()).c_str()); + board::syslog("\r\n"); + + /* + * We don't want to use formatting functions provided by libuavcan because they rely on std::snprintf(), + * so we need to construct the message manually: + */ + uavcan::protocol::debug::LogMessage logmsg; + logmsg.level.value = uavcan::protocol::debug::LogLevel::INFO; + logmsg.source = "app"; + logmsg.text = intToString(uavcan_lpc11c24::clock::getPrevUtcAdjustment().toUSec()).c_str(); + (void)getLogger().log(logmsg); + } + + board::resetWatchdog(); + } +} diff --git a/test_olimex_lpc_p11c24/src/sys/board.cpp b/test_olimex_lpc_p11c24/src/sys/board.cpp new file mode 100644 index 0000000..b342984 --- /dev/null +++ b/test_olimex_lpc_p11c24/src/sys/board.cpp @@ -0,0 +1,195 @@ +/* + * Pavel Kirienko, 2014 + * Board initialization for Olimex LPC11C24 + */ + +#include "board.hpp" +#include +#include +#include +#include + +static constexpr unsigned long PDRUNCFGUSEMASK = 0x0000ED00U; +static constexpr unsigned long PDRUNCFGMASKTMP = 0x000000FFU; + +const std::uint32_t OscRateIn = 12000000; ///< External crystal +const std::uint32_t ExtRateIn = 0; + +std::uint32_t SystemCoreClock = 12000000; ///< Initialized to default clock value, will be changed on init + +namespace board +{ +namespace +{ + +constexpr unsigned TargetSystemCoreClock = 48000000; + +constexpr unsigned ErrorLedPort = 1; +constexpr unsigned ErrorLedPin = 10; + +constexpr unsigned StatusLedPort = 1; +constexpr unsigned StatusLedPin = 11; + +struct PinMuxGroup +{ + unsigned pin : 8; + unsigned modefunc : 24; +}; + +constexpr PinMuxGroup pinmux[] = +{ + { IOCON_PIO1_10, IOCON_FUNC0 | IOCON_MODE_INACT }, // Error LED + { IOCON_PIO1_11, IOCON_FUNC0 | IOCON_MODE_INACT }, // Status LED + { IOCON_PIO1_7, IOCON_FUNC1 | IOCON_HYS_EN | IOCON_MODE_PULLUP }, // UART_TXD +}; + + +void sysctlPowerDown(unsigned long powerdownmask) +{ + unsigned long pdrun = LPC_SYSCTL->PDRUNCFG & PDRUNCFGMASKTMP; + pdrun |= (powerdownmask & PDRUNCFGMASKTMP); + LPC_SYSCTL->PDRUNCFG = pdrun | PDRUNCFGUSEMASK; +} + +void sysctlPowerUp(unsigned long powerupmask) +{ + unsigned long pdrun = LPC_SYSCTL->PDRUNCFG & PDRUNCFGMASKTMP; + pdrun &= ~(powerupmask & PDRUNCFGMASKTMP); + LPC_SYSCTL->PDRUNCFG = pdrun | PDRUNCFGUSEMASK; +} + +void initWatchdog() +{ + Chip_WWDT_Init(LPC_WWDT); // Initialize watchdog + sysctlPowerUp(SYSCTL_POWERDOWN_WDTOSC_PD); // Enable watchdog oscillator + Chip_Clock_SetWDTOSC(WDTLFO_OSC_0_60, 4); // WDT osc rate 0.6 MHz / 4 = 150 kHz + Chip_Clock_SetWDTClockSource(SYSCTL_WDTCLKSRC_WDTOSC, 1); // Clocking watchdog from its osc, div rate 1 + Chip_WWDT_SetTimeOut(LPC_WWDT, 37500); // 1 sec (hardcoded to reduce code size) + Chip_WWDT_SetOption(LPC_WWDT, WWDT_WDMOD_WDRESET); // Mode: reset on timeout + Chip_WWDT_Start(LPC_WWDT); // Go +} + +void initClock() +{ + sysctlPowerUp(SYSCTL_POWERDOWN_SYSOSC_PD); // Enable system oscillator + for (volatile int i = 0; i < 1000; i++) { } + + Chip_Clock_SetSystemPLLSource(SYSCTL_PLLCLKSRC_MAINOSC); + sysctlPowerDown(SYSCTL_POWERDOWN_SYSPLL_PD); + + /* + * Setup PLL for main oscillator rate (FCLKIN = 12MHz) * 4 = 48MHz + * MSEL = 3 (this is pre-decremented), PSEL = 1 (for P = 2) + * FCLKOUT = FCLKIN * (MSEL + 1) = 12MHz * 4 = 48MHz + * FCCO = FCLKOUT * 2 * P = 48MHz * 2 * 2 = 192MHz (within FCCO range) + */ + Chip_Clock_SetupSystemPLL(3, 1); + sysctlPowerUp(SYSCTL_POWERDOWN_SYSPLL_PD); + while (!Chip_Clock_IsSystemPLLLocked()) { } + + Chip_Clock_SetSysClockDiv(1); + + Chip_FMC_SetFLASHAccess(FLASHTIM_50MHZ_CPU); + + Chip_Clock_SetMainClockSource(SYSCTL_MAINCLKSRC_PLLOUT); + + SystemCoreClock = Chip_Clock_GetSystemClockRate(); + + while (SystemCoreClock != TargetSystemCoreClock) { } // Loop forever if the clock failed to initialize properly +} + +void initGpio() +{ + LPC_SYSCTL->SYSAHBCLKCTRL |= 1 << SYSCTL_CLOCK_IOCON; + LPC_SYSCTL->SYSAHBCLKCTRL |= 1 << SYSCTL_CLOCK_GPIO; + + for (unsigned i = 0; i < (sizeof(pinmux) / sizeof(PinMuxGroup)); i++) + { + LPC_IOCON->REG[pinmux[i].pin] = pinmux[i].modefunc; + } + + LPC_GPIO[ErrorLedPort].DIR |= 1 << ErrorLedPin; + LPC_GPIO[StatusLedPort].DIR |= 1 << StatusLedPin; +} + +void initUart() +{ + Chip_UART_Init(LPC_USART); + Chip_UART_SetBaud(LPC_USART, 115200); + Chip_UART_TXEnable(LPC_USART); +} + +void init() +{ + Chip_SYSCTL_SetBODLevels(SYSCTL_BODRSTLVL_2_06V, SYSCTL_BODINTVAL_RESERVED1); + Chip_SYSCTL_EnableBODReset(); + + initWatchdog(); + initClock(); + initGpio(); + initUart(); + + resetWatchdog(); +} + +} // namespace + +void die() +{ + static const volatile unsigned& DHCSR = *reinterpret_cast(0xE000EDF0U); + + syslog("FATAL\r\n"); + + while (true) + { + if ((DHCSR & 1U) != 0) + { + __asm volatile ("bkpt #0\n"); // Break into the debugger + } + } +} + +#if __GNUC__ +__attribute__((optimize(0))) // Optimization must be disabled lest it hardfaults in the IAP call +#endif +void readUniqueID(std::uint8_t out_uid[UniqueIDSize]) +{ + unsigned aligned_array[5] = {}; // out_uid may be unaligned, so we need to use temp array + unsigned iap_command = 58; + reinterpret_cast(0x1FFF1FF1)(&iap_command, aligned_array); + std::memcpy(out_uid, &aligned_array[1], 16); +} + +void setStatusLed(bool state) +{ + LPC_GPIO[StatusLedPort].DATA[1 << StatusLedPin] = static_cast(!state) << StatusLedPin; +} + +void setErrorLed(bool state) +{ + LPC_GPIO[ErrorLedPort].DATA[1 << ErrorLedPin] = static_cast(!state) << ErrorLedPin; +} + +void resetWatchdog() +{ + Chip_WWDT_Feed(LPC_WWDT); +} + +void syslog(const char* msg) +{ + Chip_UART_SendBlocking(LPC_USART, msg, static_cast(std::strlen(msg))); +} + +} // namespace board + +extern "C" +{ + +void SystemInit(); + +void SystemInit() +{ + board::init(); +} + +} diff --git a/test_olimex_lpc_p11c24/src/sys/board.hpp b/test_olimex_lpc_p11c24/src/sys/board.hpp new file mode 100644 index 0000000..21a64c4 --- /dev/null +++ b/test_olimex_lpc_p11c24/src/sys/board.hpp @@ -0,0 +1,32 @@ +/* + * Pavel Kirienko, 2014 + */ + +#include + +namespace board +{ + +#if __GNUC__ +__attribute__((noreturn)) +#endif +void die(); + +static constexpr unsigned UniqueIDSize = 16; + +/** + * Reads the globally unique 128-bit hardware ID from the MCU. + */ +void readUniqueID(std::uint8_t out_uid[UniqueIDSize]); + +void setStatusLed(bool state); +void setErrorLed(bool state); + +void resetWatchdog(); + +/** + * Sends the string to UART. + */ +void syslog(const char* msg); + +} diff --git a/test_olimex_lpc_p11c24/src/sys/crt0.c b/test_olimex_lpc_p11c24/src/sys/crt0.c new file mode 100644 index 0000000..c0de66a --- /dev/null +++ b/test_olimex_lpc_p11c24/src/sys/crt0.c @@ -0,0 +1,223 @@ +/* + * Pavel Kirienko, 2014 + * ARM Cortex-M0(+)/M1/M3 startup file. + */ + +typedef void (*funptr_t)(void); + +#define fill32(start, end, filler) { \ + unsigned *p1 = start; \ + const unsigned * const p2 = end; \ + while (p1 < p2) \ + *p1++ = filler; \ +} + +extern const unsigned _etext; + +extern unsigned _data; +extern unsigned _edata; + +extern unsigned _bss; +extern unsigned _ebss; + +extern funptr_t __init_array_start; +extern funptr_t __init_array_end; + +__attribute__((noreturn)) +extern int main(void); + +extern void SystemInit(void); + +#pragma GCC optimize 1 + +/** + * Prototypes for the functions below + */ +void Reset_Handler(void); +void Default_Handler(void); +void NMI_Handler(void); +void HardFault_Handler(void); +void SVC_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); + +/** + * Firmware entry point + */ +__attribute__((naked, noreturn)) +void Reset_Handler(void) +{ + // Data section + { + const unsigned* tp = &_etext; + unsigned* dp = &_data; + while (dp < &_edata) + { + *dp++ = *tp++; + } + } + + // BSS section + fill32(&_bss, &_ebss, 0); + + SystemInit(); + + // Constructors + { + funptr_t* fpp = &__init_array_start; + while (fpp < &__init_array_end) + { + (*fpp)(); + fpp++; + } + } + + (void)main(); + + while (1) { } +} + +/** + * Default handlers + */ +__attribute__((weak)) +void Default_Handler(void) +{ + while(1) { } +} + +__attribute__((weak)) +void NMI_Handler(void) +{ + while(1) { } +} + +__attribute__((weak)) +void HardFault_Handler(void) +{ + while(1) { } +} + +__attribute__((weak)) +void SVC_Handler(void) +{ + while(1) { } +} + +__attribute__((weak)) +void PendSV_Handler(void) +{ + while(1) { } +} + +__attribute__((weak)) +void SysTick_Handler(void) +{ + while(1) { } +} + +/** + * Default vectors for LPC11C24, to be overriden by the firmware as needed + */ +#define ALIAS(f) __attribute__ ((weak, alias (#f))) + +void CAN_IRQHandler(void) ALIAS(Default_Handler); +void SSP1_IRQHandler(void) ALIAS(Default_Handler); +void I2C_IRQHandler(void) ALIAS(Default_Handler); +void TIMER16_0_IRQHandler(void) ALIAS(Default_Handler); +void TIMER16_1_IRQHandler(void) ALIAS(Default_Handler); +void TIMER32_0_IRQHandler(void) ALIAS(Default_Handler); +void TIMER32_1_IRQHandler(void) ALIAS(Default_Handler); +void SSP0_IRQHandler(void) ALIAS(Default_Handler); +void UART_IRQHandler(void) ALIAS(Default_Handler); +void ADC_IRQHandler(void) ALIAS(Default_Handler); +void WDT_IRQHandler(void) ALIAS(Default_Handler); +void BOD_IRQHandler(void) ALIAS(Default_Handler); +void PIOINT3_IRQHandler(void) ALIAS(Default_Handler); +void PIOINT2_IRQHandler(void) ALIAS(Default_Handler); +void PIOINT1_IRQHandler(void) ALIAS(Default_Handler); +void PIOINT0_IRQHandler(void) ALIAS(Default_Handler); +void WAKEUP_IRQHandler(void) ALIAS(Default_Handler); + +/** + * Refer to the linker script + */ +extern void __stack_end(void); + +/** + * Vector table for LPC11Cxx + * Must be explicitly defined 'used', otherwise LTO optimizer will discard it. + */ +__attribute__ ((used, section("vectors"))) +void (* const VectorTable[64])(void) = +{ + __stack_end, // The initial stack pointer + Reset_Handler, // The reset handler + NMI_Handler, // The NMI handler + HardFault_Handler, // The hard fault handler + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + SVC_Handler, // SVCall handler + 0, // Reserved + 0, // Reserved + PendSV_Handler, // The PendSV handler + SysTick_Handler, // The SysTick handler + + WAKEUP_IRQHandler, // PIO0_0 Wakeup + WAKEUP_IRQHandler, // PIO0_1 Wakeup + WAKEUP_IRQHandler, // PIO0_2 Wakeup + WAKEUP_IRQHandler, // PIO0_3 Wakeup + WAKEUP_IRQHandler, // PIO0_4 Wakeup + WAKEUP_IRQHandler, // PIO0_5 Wakeup + WAKEUP_IRQHandler, // PIO0_6 Wakeup + WAKEUP_IRQHandler, // PIO0_7 Wakeup + WAKEUP_IRQHandler, // PIO0_8 Wakeup + WAKEUP_IRQHandler, // PIO0_9 Wakeup + WAKEUP_IRQHandler, // PIO0_10 Wakeup + WAKEUP_IRQHandler, // PIO0_11 Wakeup + WAKEUP_IRQHandler, // PIO1_0 Wakeup + + CAN_IRQHandler, // C_CAN Interrupt + SSP1_IRQHandler, // SPI/SSP1 Interrupt + I2C_IRQHandler, // I2C0 + TIMER16_0_IRQHandler, // CT16B0 (16-bit Timer 0) + TIMER16_1_IRQHandler, // CT16B1 (16-bit Timer 1) + TIMER32_0_IRQHandler, // CT32B0 (32-bit Timer 0) + TIMER32_1_IRQHandler, // CT32B1 (32-bit Timer 1) + SSP0_IRQHandler, // SPI/SSP0 Interrupt + UART_IRQHandler, // UART0 + + 0, // Reserved + 0, // Reserved + + ADC_IRQHandler, // ADC (A/D Converter) + WDT_IRQHandler, // WDT (Watchdog Timer) + BOD_IRQHandler, // BOD (Brownout Detect) + 0, // Reserved + PIOINT3_IRQHandler, // PIO INT3 + PIOINT2_IRQHandler, // PIO INT2 + PIOINT1_IRQHandler, // PIO INT1 + PIOINT0_IRQHandler, // PIO INT0 + + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 +}; diff --git a/test_olimex_lpc_p11c24/src/sys/libstubs.cpp b/test_olimex_lpc_p11c24/src/sys/libstubs.cpp new file mode 100644 index 0000000..ca63b91 --- /dev/null +++ b/test_olimex_lpc_p11c24/src/sys/libstubs.cpp @@ -0,0 +1,148 @@ +/* + * Pavel Kirienko, 2014 + * Standard library stubs + */ + +#include +#include +#include + +#if __GNUC__ +# pragma GCC diagnostic ignored "-Wmissing-declarations" +#endif + +void* __dso_handle; + +void* operator new(std::size_t) +{ + std::abort(); + return reinterpret_cast(0xFFFFFFFF); +} + +void* operator new[](std::size_t) +{ + std::abort(); + return reinterpret_cast(0xFFFFFFFF); +} + +void operator delete(void*) +{ + std::abort(); +} + +void operator delete[](void*) +{ + std::abort(); +} + +namespace __gnu_cxx +{ + +void __verbose_terminate_handler() +{ + std::abort(); +} + +} + +/* + * libstdc++ stubs + */ +extern "C" +{ + +int __aeabi_atexit(void*, void(*)(void*), void*) +{ + return 0; +} + +__extension__ typedef int __guard __attribute__((mode (__DI__))); + +void __cxa_atexit(void(*)(void *), void*, void*) +{ +} + +int __cxa_guard_acquire(__guard* g) +{ + return !*g; +} + +void __cxa_guard_release (__guard* g) +{ + *g = 1; +} + +void __cxa_guard_abort (__guard*) +{ +} + +void __cxa_pure_virtual() +{ + std::abort(); +} + +} + +/* + * stdio + */ +extern "C" +{ + +__attribute__((used)) +void abort() +{ + while (true) { } +} + +int _read_r(struct _reent*, int, char*, int) +{ + return -1; +} + +int _lseek_r(struct _reent*, int, int, int) +{ + return -1; +} + +int _write_r(struct _reent*, int, char*, int) +{ + return -1; +} + +int _close_r(struct _reent*, int) +{ + return -1; +} + +__attribute__((used)) +caddr_t _sbrk_r(struct _reent*, int) +{ + return 0; +} + +int _fstat_r(struct _reent*, int, struct stat*) +{ + return -1; +} + +int _isatty_r(struct _reent*, int) +{ + return -1; +} + +void _exit(int) +{ + abort(); +} + +pid_t _getpid(void) +{ + return 1; +} + +void _kill(pid_t) +{ +} + +}