diff options
Diffstat (limited to 'tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX')
18 files changed, 2407 insertions, 0 deletions
diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/PeripheralNames.h b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/PeripheralNames.h new file mode 100644 index 0000000000..742d7a7818 --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/PeripheralNames.h @@ -0,0 +1,60 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_PERIPHERALNAMES_H +#define MBED_PERIPHERALNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ADC0_0 = 0, + ADC0_1, + ADC0_2, + ADC0_3, + ADC0_4, + ADC0_5, + ADC0_6, + ADC0_7, + ADC0_8, + ADC0_9, + ADC0_10, + ADC0_11, + ADC1_0, + ADC1_1, + ADC1_2, + ADC1_3, + ADC1_4, + ADC1_5, + ADC1_6, + ADC1_7, + ADC1_8, + ADC1_9, + ADC1_10, + ADC1_11, +} ADCName; + +typedef enum { + DAC0_0 = 0, +} DACName; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/PinNames.h b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/PinNames.h new file mode 100644 index 0000000000..664d9b7161 --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/PinNames.h @@ -0,0 +1,103 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2014 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_PINNAMES_H +#define MBED_PINNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +typedef enum { + // LPC Pin Names + P0_0 = 0, + P0_1, P0_2, P0_3, P0_4, P0_5, P0_6, P0_7, P0_8, P0_9, P0_10, P0_11, P0_12, P0_13, P0_14, P0_15, P0_16, P0_17, P0_18, P0_19, P0_20, P0_21, P0_22, P0_23, P0_24, P0_25, P0_26, P0_27, P0_28, P0_29, P0_30, P0_31, + P1_0, P1_1, P1_2, P1_3, P1_4, P1_5, P1_6, P1_7, P1_8, P1_9, P1_10, P1_11, P1_12, P1_13, P1_14, P1_15, P1_16, P1_17, P1_18, P1_19, P1_20, P1_21, P1_22, P1_23, P1_24, P1_25, P1_26, P1_27, P1_28, P1_29, P1_30, P1_31, + P2_0, P2_1, P2_2, P2_3, P2_4, P2_5, P2_6, P2_7, P2_8, P2_9, P2_10, P2_11, P2_12, + + LED_RED = P0_25, + LED_GREEN = P0_3, + LED_BLUE = P1_1, + + // mbed original LED naming + LED1 = LED_RED, + LED2 = LED_GREEN, + LED3 = LED_BLUE, + LED4 = LED_BLUE, + + // Serial to USB pins + USBTX = P0_18, + USBRX = P0_13, + + // Arduino Shield Receptacles Names + D0 = P0_13, + D1 = P0_18, + D2 = P0_29, + D3 = P0_9, + D4 = P0_10, + D5 = P0_16, // same port as D13 + D6 = P1_3, + D7 = P0_0, + D8 = P0_24, + D9 = P1_0, + D10= P0_27, + D11= P0_28, + D12= P0_12, + D13= P0_16, // same port as D5 + D14= P0_23, + D15= P0_22, + + A0 = P0_8, + A1 = P0_7, + A2 = P0_6, + A3 = P0_5, + A4 = P0_23, // same port as SDA + A5 = P0_22, // same port as SCL + SDA= P0_23, // same port as A4 + SCL= P0_22, // same port as A5 + + // Not connected + NC = (int)0xFFFFFFFF, +} PinName; + +typedef enum { + PullUp = 2, + PullDown = 1, + PullNone = 0, + Repeater = 3, + OpenDrain = 4, + PullDefault = PullDown +} PinMode; + +#define STDIO_UART_TX USBTX +#define STDIO_UART_RX USBRX + +typedef struct { + unsigned char n; + unsigned char offset; +} SWM_Map; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/PortNames.h b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/PortNames.h new file mode 100644 index 0000000000..f332b05544 --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/PortNames.h @@ -0,0 +1,32 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2014 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_PORTNAMES_H +#define MBED_PORTNAMES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + Port0 = 0, + Port1 = 1, + Port2 = 2 +} PortName; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/analogin_api.c b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/analogin_api.c new file mode 100644 index 0000000000..da3bcef999 --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/analogin_api.c @@ -0,0 +1,158 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include "analogin_api.h" +#include "cmsis.h" +#include "pinmap.h" + +#define ANALOGIN_MEDIAN_FILTER 1 + +#define ADC_10BIT_RANGE 0x3FF +#define ADC_12BIT_RANGE 0xFFF + +#define ADC_RANGE ADC_12BIT_RANGE + +static const PinMap PinMap_ADC[] = { + {P0_8 , ADC0_0, 0}, + {P0_7 , ADC0_1, 0}, + {P0_6 , ADC0_2, 0}, + {P0_5 , ADC0_3, 0}, + {P0_4 , ADC0_4, 0}, + {P0_3 , ADC0_5, 0}, + {P0_2 , ADC0_6, 0}, + {P0_1 , ADC0_7, 0}, + {P1_0 , ADC0_8, 0}, + {P0_31, ADC0_9, 0}, + {P0_0 , ADC0_10,0}, + {P0_30, ADC0_11,0}, + {P1_1 , ADC1_0, 0}, + {P0_9 , ADC1_1, 0}, + {P0_10, ADC1_2, 0}, + {P0_11, ADC1_3, 0}, + {P1_2 , ADC1_4, 0}, + {P1_3 , ADC1_5, 0}, + {P0_13, ADC1_6, 0}, + {P0_14, ADC1_7, 0}, + {P0_15, ADC1_8, 0}, + {P0_16, ADC1_9, 0}, + {P1_4 , ADC1_10,0}, + {P1_5 , ADC1_11,0}, +}; + +void analogin_init(analogin_t *obj, PinName pin) { + obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC); + MBED_ASSERT(obj->adc != (ADCName)NC); + + uint32_t port = (pin >> 5); + // enable clock for GPIOx + LPC_SYSCON->SYSAHBCLKCTRL0 |= (1UL << (14 + port)); + // pin enable + LPC_SWM->PINENABLE0 &= ~(1UL << obj->adc); + // configure GPIO as input + LPC_GPIO_PORT->DIR[port] &= ~(1UL << (pin & 0x1F)); + + // power up ADC + if (obj->adc < ADC1_0) + { + // ADC0 + LPC_SYSCON->PDRUNCFG &= ~(1 << 10); + LPC_SYSCON->SYSAHBCLKCTRL0 |= (1 << 27); + } + else { + // ADC1 + LPC_SYSCON->PDRUNCFG &= ~(1 << 11); + LPC_SYSCON->SYSAHBCLKCTRL0 |= (1 << 28); + } + + // select IRC as asynchronous clock, divided by 1 + LPC_SYSCON->ADCASYNCCLKSEL = 0; + LPC_SYSCON->ADCASYNCCLKDIV = 1; + + __IO LPC_ADC0_Type *adc_reg = (obj->adc < ADC1_0) ? (__IO LPC_ADC0_Type*)(LPC_ADC0) : (__IO LPC_ADC0_Type*)(LPC_ADC1); + + // determine the system clock divider for a 500kHz ADC clock during calibration + uint32_t clkdiv = (SystemCoreClock / 500000) - 1; + + // perform a self-calibration + adc_reg->CTRL = (1UL << 30) | (clkdiv & 0xFF); + while ((adc_reg->CTRL & (1UL << 30)) != 0); + + // switch to asynchronous mode + adc_reg->CTRL = (1UL << 8); +} + +static inline uint32_t adc_read(analogin_t *obj) { + uint32_t channels; + + __IO LPC_ADC0_Type *adc_reg = (obj->adc < ADC1_0) ? (__IO LPC_ADC0_Type*)(LPC_ADC0) : (__IO LPC_ADC0_Type*)(LPC_ADC1); + + if (obj->adc >= ADC1_0) + channels = ((obj->adc - ADC1_0) & 0x1F); + else + channels = (obj->adc & 0x1F); + + // select channel + adc_reg->SEQA_CTRL &= ~(0xFFF); + adc_reg->SEQA_CTRL |= (1UL << channels); + + // start conversion and sequence enable + adc_reg->SEQA_CTRL |= ((1UL << 26) | (1UL << 31)); + + // Repeatedly get the sample data until DONE bit + volatile uint32_t data; + do { + data = adc_reg->SEQA_GDAT; + } while ((data & (1UL << 31)) == 0); + + // Stop conversion + adc_reg->SEQA_CTRL &= ~(1UL << 31); + + return ((data >> 4) & ADC_RANGE); +} + +static inline void order(uint32_t *a, uint32_t *b) { + if (*a > *b) { + uint32_t t = *a; + *a = *b; + *b = t; + } +} + +static inline uint32_t adc_read_u32(analogin_t *obj) { + uint32_t value; +#if ANALOGIN_MEDIAN_FILTER + uint32_t v1 = adc_read(obj); + uint32_t v2 = adc_read(obj); + uint32_t v3 = adc_read(obj); + order(&v1, &v2); + order(&v2, &v3); + order(&v1, &v2); + value = v2; +#else + value = adc_read(obj); +#endif + return value; +} + +uint16_t analogin_read_u16(analogin_t *obj) { + uint32_t value = adc_read_u32(obj); + return (value << 4) | ((value >> 8) & 0x000F); // 12 bit +} + +float analogin_read(analogin_t *obj) { + uint32_t value = adc_read_u32(obj); + return (float)value * (1.0f / (float)ADC_RANGE); +} diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/analogout_api.c b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/analogout_api.c new file mode 100644 index 0000000000..5c9d57a1b8 --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/analogout_api.c @@ -0,0 +1,71 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include "analogout_api.h" +#include "cmsis.h" +#include "pinmap.h" + +void analogout_init(dac_t *obj, PinName pin) { + MBED_ASSERT(pin == P0_12); + + LPC_SYSCON->SYSAHBCLKCTRL0 |= (1 << 29); + LPC_SYSCON->PDRUNCFG &= ~(1 << 12); + LPC_IOCON->PIO0_12 = 0; + LPC_SWM->PINENABLE0 &= ~(1 << 24); + LPC_DAC->CTRL = 0; + + analogout_write_u16(obj, 0); +} + +void analogout_free(dac_t *obj) +{ + LPC_SYSCON->SYSAHBCLKCTRL0 &= ~(1 << 29); + LPC_SWM->PINENABLE0 |= (1 << 24); +} + +static inline void dac_write(int value) { + value &= 0xFFF; // 12-bit + + // Set the DAC output + LPC_DAC->VAL = (value << 4); +} + +static inline int dac_read() { + return ((LPC_DAC->VAL >> 4) & 0xFFF); +} + +void analogout_write(dac_t *obj, float value) { + if (value < 0.0f) { + dac_write(0); + } else if (value > 1.0f) { + dac_write(0xFFF); + } else { + dac_write((uint32_t)(value * (float)0xFFF)); + } +} + +void analogout_write_u16(dac_t *obj, uint16_t value) { + dac_write(value); +} + +float analogout_read(dac_t *obj) { + uint32_t value = dac_read(); + return (float)value * (1.0f / (float)0xFFF); +} + +uint16_t analogout_read_u16(dac_t *obj) { + return (uint16_t)dac_read(); +} diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/can_api.c b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/can_api.c new file mode 100644 index 0000000000..bb738dbf2b --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/can_api.c @@ -0,0 +1,437 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "can_api.h" + +#include "cmsis.h" +#include "mbed_error.h" + +#include <math.h> +#include <string.h> + +/* Handy defines */ +#define MSG_OBJ_MAX 32 +#define DLC_MAX 8 + +#define ID_STD_MASK 0x07FF +#define ID_EXT_MASK 0x1FFFFFFF +#define DLC_MASK 0x0F + +#define CANIFn_ARB2_DIR (1UL << 13) +#define CANIFn_ARB2_XTD (1UL << 14) +#define CANIFn_ARB2_MSGVAL (1UL << 15) +#define CANIFn_MSK2_MXTD (1UL << 15) +#define CANIFn_MSK2_MDIR (1UL << 14) +#define CANIFn_MCTRL_EOB (1UL << 7) +#define CANIFn_MCTRL_TXRQST (1UL << 8) +#define CANIFn_MCTRL_RMTEN (1UL << 9) +#define CANIFn_MCTRL_RXIE (1UL << 10) +#define CANIFn_MCTRL_TXIE (1UL << 11) +#define CANIFn_MCTRL_UMASK (1UL << 12) +#define CANIFn_MCTRL_INTPND (1UL << 13) +#define CANIFn_MCTRL_MSGLST (1UL << 14) +#define CANIFn_MCTRL_NEWDAT (1UL << 15) +#define CANIFn_CMDMSK_DATA_B (1UL << 0) +#define CANIFn_CMDMSK_DATA_A (1UL << 1) +#define CANIFn_CMDMSK_TXRQST (1UL << 2) +#define CANIFn_CMDMSK_NEWDAT (1UL << 2) +#define CANIFn_CMDMSK_CLRINTPND (1UL << 3) +#define CANIFn_CMDMSK_CTRL (1UL << 4) +#define CANIFn_CMDMSK_ARB (1UL << 5) +#define CANIFn_CMDMSK_MASK (1UL << 6) +#define CANIFn_CMDMSK_WR (1UL << 7) +#define CANIFn_CMDMSK_RD (0UL << 7) +#define CANIFn_CMDREQ_BUSY (1UL << 15) + +static uint32_t can_irq_id = 0; +static can_irq_handler irq_handler; + +static inline void can_disable(can_t *obj) { + LPC_C_CAN0->CANCNTL |= 0x1; +} + +static inline void can_enable(can_t *obj) { + if (LPC_C_CAN0->CANCNTL & 0x1) { + LPC_C_CAN0->CANCNTL &= ~(0x1); + } +} + +int can_mode(can_t *obj, CanMode mode) { + return 0; // not implemented +} + +int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) { + uint16_t i; + + // Find first free message object + if (handle == 0) { + uint32_t msgval = LPC_C_CAN0->CANMSGV1 | (LPC_C_CAN0->CANMSGV2 << 16); + + // Find first free messagebox + for (i = 0; i < 32; i++) { + if ((msgval & (1 << i)) == 0) { + handle = i+1; + break; + } + } + } + + if (handle > 0 && handle < 32) { + if (format == CANExtended) { + // Mark message valid, Direction = TX, Extended Frame, Set Identifier and mask everything + LPC_C_CAN0->CANIF1_ARB1 = (id & 0xFFFF); + LPC_C_CAN0->CANIF1_ARB2 = CANIFn_ARB2_MSGVAL | CANIFn_ARB2_XTD | ((id >> 16) & 0x1FFF); + LPC_C_CAN0->CANIF1_MSK1 = (mask & 0xFFFF); + LPC_C_CAN0->CANIF1_MSK2 = CANIFn_MSK2_MXTD /*| CANIFn_MSK2_MDIR*/ | ((mask >> 16) & 0x1FFF); + } else { + // Mark message valid, Direction = TX, Set Identifier and mask everything + LPC_C_CAN0->CANIF1_ARB2 = CANIFn_ARB2_MSGVAL | ((id << 2) & 0x1FFF); + LPC_C_CAN0->CANIF1_MSK2 = /*CANIFn_MSK2_MDIR |*/ ((mask << 2) & 0x1FFF); + } + + // Use mask, single message object and set DLC + LPC_C_CAN0->CANIF1_MCTRL = CANIFn_MCTRL_UMASK | CANIFn_MCTRL_EOB | CANIFn_MCTRL_RXIE | (DLC_MAX & 0xF); + + // Transfer all fields to message object + LPC_C_CAN0->CANIF1_CMDMSK_W = CANIFn_CMDMSK_WR | CANIFn_CMDMSK_MASK | CANIFn_CMDMSK_ARB | CANIFn_CMDMSK_CTRL; + + // Start Transfer to given message number + LPC_C_CAN0->CANIF1_CMDREQ = (handle & 0x3F); + + // Wait until transfer to message ram complete - TODO: maybe not block?? + while ( LPC_C_CAN0->CANIF1_CMDREQ & CANIFn_CMDREQ_BUSY ); + } + + return handle; +} + +static inline void can_irq() { + irq_handler(can_irq_id, IRQ_RX); +} + +// Register CAN object's irq handler +void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id) { + irq_handler = handler; + can_irq_id = id; +} + +// Unregister CAN object's irq handler +void can_irq_free(can_t *obj) { + LPC_C_CAN0->CANCNTL &= ~(1UL << 1); // Disable Interrupts :) + can_irq_id = 0; + NVIC_DisableIRQ(C_CAN0_IRQn); +} + +// Clear or set a irq +void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) { + // Put CAN in Reset Mode and enable interrupt + can_disable(obj); + if (enable == 0) { + LPC_C_CAN0->CANCNTL &= ~(1UL << 1 | 1UL << 2); + } else { + LPC_C_CAN0->CANCNTL |= 1UL << 1 | 1UL << 2; + } + // Take it out of reset... + can_enable(obj); + + // Enable NVIC if at least 1 interrupt is active + NVIC_SetVector(C_CAN0_IRQn, (uint32_t) &can_irq); + NVIC_EnableIRQ(C_CAN0_IRQn); +} + +// This table has the sampling points as close to 75% as possible. The first +// value is TSEG1, the second TSEG2. +static const int timing_pts[23][2] = { + {0x0, 0x0}, // 2, 50% + {0x1, 0x0}, // 3, 67% + {0x2, 0x0}, // 4, 75% + {0x3, 0x0}, // 5, 80% + {0x3, 0x1}, // 6, 67% + {0x4, 0x1}, // 7, 71% + {0x5, 0x1}, // 8, 75% + {0x6, 0x1}, // 9, 78% + {0x6, 0x2}, // 10, 70% + {0x7, 0x2}, // 11, 73% + {0x8, 0x2}, // 12, 75% + {0x9, 0x2}, // 13, 77% + {0x9, 0x3}, // 14, 71% + {0xA, 0x3}, // 15, 73% + {0xB, 0x3}, // 16, 75% + {0xC, 0x3}, // 17, 76% + {0xD, 0x3}, // 18, 78% + {0xD, 0x4}, // 19, 74% + {0xE, 0x4}, // 20, 75% + {0xF, 0x4}, // 21, 76% + {0xF, 0x5}, // 22, 73% + {0xF, 0x6}, // 23, 70% + {0xF, 0x7}, // 24, 67% +}; + +static unsigned int can_speed(unsigned int sclk, unsigned int cclk, unsigned char psjw) { + uint32_t btr; + uint32_t clkdiv = 1; + uint16_t brp = 0; + uint32_t calcbit; + uint32_t bitwidth; + int hit = 0; + int bits = 0; + + bitwidth = sclk / cclk; + + brp = bitwidth / 0x18; + while ((!hit) && (brp < bitwidth / 4)) { + brp++; + for (bits = 22; bits > 0; bits--) { + calcbit = (bits + 3) * (brp + 1); + if (calcbit == bitwidth) { + hit = 1; + break; + } + } + } + + clkdiv = clkdiv - 1; + + if (hit) { + btr = (timing_pts[bits][1] & 0x7) << 12 + | (timing_pts[bits][0] & 0xf) << 8 + | (psjw & 0x3) << 6 + | (brp & 0x3F); + btr = btr | (clkdiv << 16); + } else { + btr = 0; + } + + return btr; +} + + +int can_config_rxmsgobj(can_t *obj) { + uint16_t i = 0; + + // Make sure the interface is available + while ( LPC_C_CAN0->CANIF1_CMDREQ & CANIFn_CMDREQ_BUSY ); + + // Mark message valid, Direction = RX, Don't care about anything else + LPC_C_CAN0->CANIF1_ARB1 = 0; + LPC_C_CAN0->CANIF1_ARB2 = 0; + LPC_C_CAN0->CANIF1_MCTRL = 0; + + for ( i = 0; i < MSG_OBJ_MAX; i++ ) { + // Transfer arb and control fields to message object + LPC_C_CAN0->CANIF1_CMDMSK_W = CANIFn_CMDMSK_WR | CANIFn_CMDMSK_ARB | CANIFn_CMDMSK_CTRL | CANIFn_CMDMSK_TXRQST; + + // Start Transfer to given message number + LPC_C_CAN0->CANIF1_CMDREQ = (i & 0x3F); + + // Wait until transfer to message ram complete - TODO: maybe not block?? + while ( LPC_C_CAN0->CANIF1_CMDREQ & CANIFn_CMDREQ_BUSY ); + } + + // Accept all messages + can_filter(obj, 0, 0, CANStandard, 1); + + return 1; +} + + +void can_init(can_t *obj, PinName rd, PinName td) { + // Enable power and clock + LPC_SYSCON->SYSAHBCLKCTRL1 |= (1UL << 7); + LPC_SYSCON->PRESETCTRL1 |= (1UL << 7); + LPC_SYSCON->PRESETCTRL1 &= ~(1UL << 7); + + // Enable Initialization mode + if (!(LPC_C_CAN0->CANCNTL & (1UL << 0))) { + LPC_C_CAN0->CANCNTL |= (1UL << 0); + } + + LPC_SWM->PINASSIGN[6] &= ~(0x00FFFF00L); + LPC_SWM->PINASSIGN[6] |= (rd << 16) | (td << 8); + + can_frequency(obj, 100000); + + // Resume operation + LPC_C_CAN0->CANCNTL &= ~(1UL << 0); + while ( LPC_C_CAN0->CANCNTL & (1UL << 0) ); + + // Initialize RX message object + can_config_rxmsgobj(obj); +} + +void can_free(can_t *obj) { + LPC_SYSCON->SYSAHBCLKCTRL1 &= ~(1UL << 7); + LPC_SYSCON->PRESETCTRL1 &= ~(1UL << 7); +} + +int can_frequency(can_t *obj, int f) { + int btr = can_speed(SystemCoreClock, (unsigned int)f, 1); + int clkdiv = (btr >> 16) & 0x0F; + btr = btr & 0xFFFF; + + if (btr > 0) { + // Set the bit clock + LPC_C_CAN0->CANCNTL |= (1UL << 6 | 1UL << 0); // set CCE and INIT + LPC_C_CAN0->CANCLKDIV = clkdiv; + LPC_C_CAN0->CANBT = btr; + LPC_C_CAN0->CANBRPE = 0x0000; + LPC_C_CAN0->CANCNTL &= ~(1UL << 6 | 1UL << 0); // clear CCE and INIT + return 1; + } + return 0; +} + +int can_write(can_t *obj, CAN_Message msg, int cc) { + uint16_t msgnum = 0; + + // Make sure controller is enabled + can_enable(obj); + + // Make sure the interface is available + while ( LPC_C_CAN0->CANIF1_CMDREQ & CANIFn_CMDREQ_BUSY ); + + // Set the direction bit based on the message type + uint32_t direction = 0; + if (msg.type == CANData) { + direction = CANIFn_ARB2_DIR; + } + + if (msg.format == CANExtended) { + // Mark message valid, Extended Frame, Set Identifier and mask everything + LPC_C_CAN0->CANIF1_ARB1 = (msg.id & 0xFFFF); + LPC_C_CAN0->CANIF1_ARB2 = CANIFn_ARB2_MSGVAL | CANIFn_ARB2_XTD | direction | ((msg.id >> 16) & 0x1FFFF); + LPC_C_CAN0->CANIF1_MSK1 = (ID_EXT_MASK & 0xFFFF); + LPC_C_CAN0->CANIF1_MSK2 = CANIFn_MSK2_MXTD | CANIFn_MSK2_MDIR | ((ID_EXT_MASK >> 16) & 0x1FFF); + } else { + // Mark message valid, Set Identifier and mask everything + LPC_C_CAN0->CANIF1_ARB2 = CANIFn_ARB2_MSGVAL | direction | ((msg.id << 2) & 0x1FFF); + LPC_C_CAN0->CANIF1_MSK2 = CANIFn_MSK2_MDIR | ((ID_STD_MASK << 2) & 0x1FFF); + } + + // Use mask, request transmission, single message object and set DLC + LPC_C_CAN0->CANIF1_MCTRL = CANIFn_MCTRL_UMASK | CANIFn_MCTRL_TXRQST | CANIFn_MCTRL_EOB | (msg.len & 0xF); + + LPC_C_CAN0->CANIF1_DA1 = ((msg.data[1] & 0xFF) << 8) | (msg.data[0] & 0xFF); + LPC_C_CAN0->CANIF1_DA2 = ((msg.data[3] & 0xFF) << 8) | (msg.data[2] & 0xFF); + LPC_C_CAN0->CANIF1_DB1 = ((msg.data[5] & 0xFF) << 8) | (msg.data[4] & 0xFF); + LPC_C_CAN0->CANIF1_DB2 = ((msg.data[7] & 0xFF) << 8) | (msg.data[6] & 0xFF); + + // Transfer all fields to message object + LPC_C_CAN0->CANIF1_CMDMSK_W = CANIFn_CMDMSK_WR | CANIFn_CMDMSK_MASK | CANIFn_CMDMSK_ARB | CANIFn_CMDMSK_CTRL | CANIFn_CMDMSK_TXRQST | CANIFn_CMDMSK_DATA_A | CANIFn_CMDMSK_DATA_B; + + // Start Transfer to given message number + LPC_C_CAN0->CANIF1_CMDREQ = (msgnum & 0x3F); + + // Wait until transfer to message ram complete - TODO: maybe not block?? + while ( LPC_C_CAN0->CANIF1_CMDREQ & CANIFn_CMDREQ_BUSY); + + // Wait until TXOK is set, then clear it - TODO: maybe not block + //while ( !(LPC_C_CAN0->STAT & CANSTAT_TXOK) ); + LPC_C_CAN0->CANSTAT &= ~(1UL << 3); + + return 1; +} + +int can_read(can_t *obj, CAN_Message *msg, int handle) { + uint16_t i; + + // Make sure controller is enabled + can_enable(obj); + + // Find first message object with new data + if (handle == 0) { + uint32_t newdata = LPC_C_CAN0->CANND1 | (LPC_C_CAN0->CANND2 << 16); + // Find first free messagebox + for (i = 0; i < 32; i++) { + if (newdata & (1 << i)) { + handle = i+1; + break; + } + } + } + + if (handle > 0 && handle < 32) { + // Wait until message interface is free + while ( LPC_C_CAN0->CANIF2_CMDREQ & CANIFn_CMDREQ_BUSY ); + + // Transfer all fields to message object + LPC_C_CAN0->CANIF2_CMDMSK_W = CANIFn_CMDMSK_RD | CANIFn_CMDMSK_MASK | CANIFn_CMDMSK_ARB | CANIFn_CMDMSK_CTRL | CANIFn_CMDMSK_CLRINTPND | CANIFn_CMDMSK_TXRQST | CANIFn_CMDMSK_DATA_A | CANIFn_CMDMSK_DATA_B; + + // Start Transfer from given message number + LPC_C_CAN0->CANIF2_CMDREQ = (handle & 0x3F); + + // Wait until transfer to message ram complete + while ( LPC_C_CAN0->CANIF2_CMDREQ & CANIFn_CMDREQ_BUSY ); + + if (LPC_C_CAN0->CANIF2_ARB2 & CANIFn_ARB2_XTD) { + msg->format = CANExtended; + msg->id = (LPC_C_CAN0->CANIF2_ARB1 & 0x1FFF) << 16; + msg->id |= (LPC_C_CAN0->CANIF2_ARB2 & 0x1FFF); + } else { + msg->format = CANStandard; + msg->id = (LPC_C_CAN0->CANIF2_ARB2 & 0x1FFF) >> 2; + } + + if (LPC_C_CAN0->CANIF2_ARB2 & CANIFn_ARB2_DIR) { + msg->type = CANRemote; + } + else { + msg->type = CANData; + } + + msg->len = (LPC_C_CAN0->CANIF2_MCTRL & 0xF); // TODO: If > 8, len = 8 + msg->data[0] = ((LPC_C_CAN0->CANIF2_DA1 >> 0) & 0xFF); + msg->data[1] = ((LPC_C_CAN0->CANIF2_DA1 >> 8) & 0xFF); + msg->data[2] = ((LPC_C_CAN0->CANIF2_DA2 >> 0) & 0xFF); + msg->data[3] = ((LPC_C_CAN0->CANIF2_DA2 >> 8) & 0xFF); + msg->data[4] = ((LPC_C_CAN0->CANIF2_DB1 >> 0) & 0xFF); + msg->data[5] = ((LPC_C_CAN0->CANIF2_DB1 >> 8) & 0xFF); + msg->data[6] = ((LPC_C_CAN0->CANIF2_DB2 >> 0) & 0xFF); + msg->data[7] = ((LPC_C_CAN0->CANIF2_DB2 >> 8) & 0xFF); + + LPC_C_CAN0->CANSTAT &= ~(1UL << 4); + return 1; + } + return 0; +} + +void can_reset(can_t *obj) { + LPC_SYSCON->PRESETCTRL1 &= ~(1UL << 7); + LPC_C_CAN0->CANSTAT = 0; + can_config_rxmsgobj(obj); +} + +unsigned char can_rderror(can_t *obj) { + return ((LPC_C_CAN0->CANEC >> 8) & 0x7F); +} + +unsigned char can_tderror(can_t *obj) { + return (LPC_C_CAN0->CANEC & 0xFF); +} + +void can_monitor(can_t *obj, int silent) { + if (silent) { + LPC_C_CAN0->CANCNTL |= (1UL << 7); + LPC_C_CAN0->CANTEST |= (1UL << 3); + } else { + LPC_C_CAN0->CANCNTL &= ~(1UL << 7); + LPC_C_CAN0->CANTEST &= ~(1UL << 3); + } + + if (!(LPC_C_CAN0->CANCNTL & (1UL << 0))) { + LPC_C_CAN0->CANCNTL |= (1UL << 0); + } +} diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/device.h b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/device.h new file mode 100644 index 0000000000..1ef3bcbb3e --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/device.h @@ -0,0 +1,58 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2014 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_DEVICE_H +#define MBED_DEVICE_H + +#define DEVICE_PORTIN 0 +#define DEVICE_PORTOUT 0 +#define DEVICE_PORTINOUT 0 + +#define DEVICE_INTERRUPTIN 1 + +#define DEVICE_ANALOGIN 1 +#define DEVICE_ANALOGOUT 1 + +#define DEVICE_SERIAL 1 +#define DEVICE_SERIAL_FC 1 + +#define DEVICE_I2C 1 +#define DEVICE_I2CSLAVE 0 + +#define DEVICE_SPI 1 +#define DEVICE_SPISLAVE 1 + +#define DEVICE_CAN 1 + +#define DEVICE_RTC 1 + +#define DEVICE_ETHERNET 0 + +#define DEVICE_PWMOUT 1 + +#define DEVICE_SEMIHOST 0 +#define DEVICE_LOCALFILESYSTEM 0 + +#define DEVICE_SLEEP 0 + +#define DEVICE_DEBUG_AWARENESS 0 + +#define DEVICE_STDIO_MESSAGES 0 + +#define DEVICE_ERROR_RED 0 + +#include "objects.h" + +#endif diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/gpio_api.c b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/gpio_api.c new file mode 100644 index 0000000000..624a4d76b5 --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/gpio_api.c @@ -0,0 +1,66 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2014 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include "gpio_api.h" +#include "pinmap.h" + +static int gpio_enabled = 0; + +static void gpio_enable(void) { + gpio_enabled = 1; + + /* Enable AHB clock to the GPIO0/1/2 and IOCON domain. */ + LPC_SYSCON->SYSAHBCLKCTRL0 |= (0xFUL << 13); +} + +uint32_t gpio_set(PinName pin) { + MBED_ASSERT(pin != (PinName)NC); + if (!gpio_enabled) + gpio_enable(); + + return (1UL << ((int)pin & 0x1f)); +} + +void gpio_init(gpio_t *obj, PinName pin) { + obj->pin = pin; + if (pin == (PinName)NC) + return; + + obj->mask = gpio_set(pin); + + unsigned int port = (unsigned int)(pin >> 5); + + obj->reg_set = &LPC_GPIO_PORT->SET[port]; + obj->reg_clr = &LPC_GPIO_PORT->CLR[port]; + obj->reg_in = &LPC_GPIO_PORT->PIN[port]; + obj->reg_dir = &LPC_GPIO_PORT->DIR[port]; +} + +void gpio_mode(gpio_t *obj, PinMode mode) { + pin_mode(obj->pin, mode); +} + +void gpio_dir(gpio_t *obj, PinDirection direction) { + MBED_ASSERT(obj->pin != (PinName)NC); + switch (direction) { + case PIN_INPUT : + *obj->reg_dir &= ~obj->mask; + break; + case PIN_OUTPUT: + *obj->reg_dir |= obj->mask; + break; + } +} diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/gpio_irq_api.c b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/gpio_irq_api.c new file mode 100644 index 0000000000..f4b379295a --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/gpio_irq_api.c @@ -0,0 +1,139 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <stddef.h> + +#include "cmsis.h" +#include "gpio_irq_api.h" +#include "mbed_error.h" + +#define CHANNEL_NUM 8 +#define LPC_GPIO_X LPC_PINT +#define PININT_IRQ PIN_INT0_IRQn + +static uint32_t channel_ids[CHANNEL_NUM] = {0}; +static gpio_irq_handler irq_handler; + +static inline void handle_interrupt_in(uint32_t channel) { + uint32_t ch_bit = (1 << channel); + // Return immediately if: + // * The interrupt was already served + // * There is no user handler + // * It is a level interrupt, not an edge interrupt + if ( ((LPC_GPIO_X->IST & ch_bit) == 0) || + (channel_ids[channel] == 0 ) || + (LPC_GPIO_X->ISEL & ch_bit ) ) return; + + if ((LPC_GPIO_X->IENR & ch_bit) && (LPC_GPIO_X->RISE & ch_bit)) { + irq_handler(channel_ids[channel], IRQ_RISE); + LPC_GPIO_X->RISE = ch_bit; + } + if ((LPC_GPIO_X->IENF & ch_bit) && (LPC_GPIO_X->FALL & ch_bit)) { + irq_handler(channel_ids[channel], IRQ_FALL); + LPC_GPIO_X->FALL = ch_bit; + } + LPC_GPIO_X->IST = ch_bit; +} + +void gpio_irq0(void) {handle_interrupt_in(0);} +void gpio_irq1(void) {handle_interrupt_in(1);} +void gpio_irq2(void) {handle_interrupt_in(2);} +void gpio_irq3(void) {handle_interrupt_in(3);} +void gpio_irq4(void) {handle_interrupt_in(4);} +void gpio_irq5(void) {handle_interrupt_in(5);} +void gpio_irq6(void) {handle_interrupt_in(6);} +void gpio_irq7(void) {handle_interrupt_in(7);} + +int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) { + // PINT only supprt GPIO port 0 and 1 interrupt + if (pin >= P2_0) return -1; + + irq_handler = handler; + + int found_free_channel = 0; + int i = 0; + for (i=0; i<CHANNEL_NUM; i++) { + if (channel_ids[i] == 0) { + channel_ids[i] = id; + obj->ch = i; + found_free_channel = 1; + break; + } + } + if (!found_free_channel) return -1; + + /* Enable AHB clock to the PIN, GPIO0/1, IOCON and MUX domain. */ + LPC_SYSCON->SYSAHBCLKCTRL0 |= ((1 << 18) | (0x1D << 11)); + + LPC_INMUX->PINTSEL[obj->ch] = pin; + + // Interrupt Wake-Up Enable + LPC_SYSCON->STARTERP0 |= (1 << (obj->ch + 5)); + + LPC_GPIO_PORT->DIR[pin >> 5] &= ~(1 << (pin & 0x1F)); + + void (*channels_irq)(void) = NULL; + switch (obj->ch) { + case 0: channels_irq = &gpio_irq0; break; + case 1: channels_irq = &gpio_irq1; break; + case 2: channels_irq = &gpio_irq2; break; + case 3: channels_irq = &gpio_irq3; break; + case 4: channels_irq = &gpio_irq4; break; + case 5: channels_irq = &gpio_irq5; break; + case 6: channels_irq = &gpio_irq6; break; + case 7: channels_irq = &gpio_irq7; break; + } + NVIC_SetVector((IRQn_Type)(PININT_IRQ + obj->ch), (uint32_t)channels_irq); + NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ + obj->ch)); + + return 0; +} + +void gpio_irq_free(gpio_irq_t *obj) { + channel_ids[obj->ch] = 0; + LPC_SYSCON->STARTERP0 &= ~(1 << (obj->ch + 5)); +} + +void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) { + unsigned int ch_bit = (1 << obj->ch); + + // Clear interrupt + if (!(LPC_GPIO_X->ISEL & ch_bit)) + LPC_GPIO_X->IST = ch_bit; + + // Edge trigger + LPC_GPIO_X->ISEL &= ~ch_bit; + if (event == IRQ_RISE) { + if (enable) { + LPC_GPIO_X->IENR |= ch_bit; + } else { + LPC_GPIO_X->IENR &= ~ch_bit; + } + } else { + if (enable) { + LPC_GPIO_X->IENF |= ch_bit; + } else { + LPC_GPIO_X->IENF &= ~ch_bit; + } + } +} + +void gpio_irq_enable(gpio_irq_t *obj) { + NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ + obj->ch)); +} + +void gpio_irq_disable(gpio_irq_t *obj) { + NVIC_DisableIRQ((IRQn_Type)(PININT_IRQ + obj->ch)); +} diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/gpio_object.h b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/gpio_object.h new file mode 100644 index 0000000000..0252448103 --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/gpio_object.h @@ -0,0 +1,57 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_GPIO_OBJECT_H +#define MBED_GPIO_OBJECT_H + +#include "mbed_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + PinName pin; + uint32_t mask; + + __IO uint32_t *reg_dir; + __IO uint32_t *reg_set; + __IO uint32_t *reg_clr; + __I uint32_t *reg_in; +} gpio_t; + +static inline void gpio_write(gpio_t *obj, int value) { + MBED_ASSERT(obj->pin != (PinName)NC); + + if (value) + *obj->reg_set = obj->mask; + else + *obj->reg_clr = obj->mask; +} + +static inline int gpio_read(gpio_t *obj) { + MBED_ASSERT(obj->pin != (PinName)NC); + return ((*obj->reg_in & obj->mask) ? 1 : 0); +} + +static inline int gpio_is_connected(const gpio_t *obj) { + return obj->pin != (PinName)NC; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/i2c_api.c b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/i2c_api.c new file mode 100644 index 0000000000..0ca7c7dccf --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/i2c_api.c @@ -0,0 +1,217 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include "i2c_api.h" +#include "cmsis.h" +#include "pinmap.h" + +static uint8_t repeated_start = 0; + +#define I2C_STAT(x) ((LPC_I2C0->STAT >> 1) & (0x07)) + +static inline int i2c_status(i2c_t *obj) { + return I2C_STAT(obj); +} + +// Wait until the Serial Interrupt (SI) is set +static int i2c_wait_SI(i2c_t *obj) { + volatile int timeout = 0; + while (!(LPC_I2C0->STAT & (1 << 0))) { + timeout++; + if (timeout > 100000) return -1; + } + return 0; +} + +static inline void i2c_interface_enable(i2c_t *obj) { + LPC_I2C0->CFG |= (1 << 0); +} + +void i2c_init(i2c_t *obj, PinName sda, PinName scl) { + MBED_ASSERT((sda == P0_23) && (scl == P0_22)); + + // Enables clock for I2C0 + LPC_SYSCON->SYSAHBCLKCTRL1 |= (1 << 13); + + LPC_SYSCON->PRESETCTRL1 |= (1 << 13); + LPC_SYSCON->PRESETCTRL1 &= ~(1 << 13); + + // pin enable + LPC_SWM->PINENABLE1 &= ~(0x3 << 3); + + // set default frequency at 100kHz + i2c_frequency(obj, 100000); + i2c_interface_enable(obj); +} + +inline int i2c_start(i2c_t *obj) { + int status = 0; + if (repeated_start) { + LPC_I2C0->MSTCTL = (1 << 1) | (1 << 0); + repeated_start = 0; + } else { + LPC_I2C0->MSTCTL = (1 << 1); + } + return status; +} + +inline int i2c_stop(i2c_t *obj) { + volatile int timeout = 0; + + LPC_I2C0->MSTCTL = (1 << 2) | (1 << 0); + while ((LPC_I2C0->STAT & ((1 << 0) | (7 << 1))) != ((1 << 0) | (0 << 1))) { + timeout ++; + if (timeout > 100000) return 1; + } + + return 0; +} + + +static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr) { + // write the data + LPC_I2C0->MSTDAT = value; + + if (!addr) + LPC_I2C0->MSTCTL = (1 << 0); + + // wait and return status + i2c_wait_SI(obj); + return i2c_status(obj); +} + +static inline int i2c_do_read(i2c_t *obj, int last) { + // wait for it to arrive + i2c_wait_SI(obj); + if (!last) + LPC_I2C0->MSTCTL = (1 << 0); + + // return the data + return (LPC_I2C0->MSTDAT & 0xFF); +} + +void i2c_frequency(i2c_t *obj, int hz) { + // No peripheral clock divider on the M0 + uint32_t PCLK = SystemCoreClock; + uint32_t clkdiv = PCLK / (hz * 4) - 1; + + LPC_I2C0->DIV = clkdiv; + LPC_I2C0->MSTTIME = 0; +} + +int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { + int count, status; + + i2c_start(obj); + + LPC_I2C0->MSTDAT = (address | 0x01); + LPC_I2C0->MSTCTL |= 0x20; + if (i2c_wait_SI(obj) == -1) + return -1; + + status = ((LPC_I2C0->STAT >> 1) & (0x07)); + if (status != 0x01) { + i2c_stop(obj); + return I2C_ERROR_NO_SLAVE; + } + + // Read in all except last byte + for (count = 0; count < (length - 1); count++) { + if (i2c_wait_SI(obj) == -1) + return -1; + LPC_I2C0->MSTCTL = (1 << 0); + data[count] = (LPC_I2C0->MSTDAT & 0xFF); + status = ((LPC_I2C0->STAT >> 1) & (0x07)); + if (status != 0x01) { + i2c_stop(obj); + return count; + } + } + + // read in last byte + if (i2c_wait_SI(obj) == -1) + return -1; + + data[count] = (LPC_I2C0->MSTDAT & 0xFF); + status = i2c_status(obj); + if (status != 0x01) { + i2c_stop(obj); + return length - 1; + } + // If not repeated start, send stop. + if (stop) { + i2c_stop(obj); + } else { + repeated_start = 1; + } + + return length; +} + +int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { + int i, status; + + i2c_start(obj); + + LPC_I2C0->MSTDAT = (address & 0xFE); + LPC_I2C0->MSTCTL |= 0x20; + if (i2c_wait_SI(obj) == -1) + return -1; + + status = ((LPC_I2C0->STAT >> 1) & (0x07)); + if (status != 0x02) { + i2c_stop(obj); + return I2C_ERROR_NO_SLAVE; + } + + for (i=0; i<length; i++) { + LPC_I2C0->MSTDAT = data[i]; + LPC_I2C0->MSTCTL = (1 << 0); + if (i2c_wait_SI(obj) == -1) + return -1; + + status = ((LPC_I2C0->STAT >> 1) & (0x07)); + if (status != 0x02) { + i2c_stop(obj); + return i; + } + } + + // If not repeated start, send stop. + if (stop) { + i2c_stop(obj); + } else { + repeated_start = 1; + } + + return length; +} + +void i2c_reset(i2c_t *obj) { + i2c_stop(obj); +} + +int i2c_byte_read(i2c_t *obj, int last) { + return (i2c_do_read(obj, last) & 0xFF); +} + +int i2c_byte_write(i2c_t *obj, int data) { + if (i2c_do_write(obj, (data & 0xFF), 0) == 2) { + return 1; + } else { + return 0; + } +} diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/objects.h b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/objects.h new file mode 100644 index 0000000000..621419bce7 --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/objects.h @@ -0,0 +1,69 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_OBJECTS_H +#define MBED_OBJECTS_H + +#include "cmsis.h" +#include "PortNames.h" +#include "PeripheralNames.h" +#include "PinNames.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct gpio_irq_s { + uint32_t ch; +}; + +struct pwmout_s { + LPC_SCT0_Type* pwm; + uint32_t pwm_ch; +}; + +struct serial_s { + LPC_USART0_Type *uart; + unsigned char index; +}; + +struct analogin_s { + ADCName adc; +}; + +struct dac_s { + DACName dac; +}; + +struct i2c_s { + LPC_I2C0_Type *i2c; +}; + +struct spi_s { + LPC_SPI0_Type *spi; + unsigned char spi_n; +}; + +struct can_s { + int index; +}; + +#include "gpio_object.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/pinmap.c b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/pinmap.c new file mode 100644 index 0000000000..c466534cf9 --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/pinmap.c @@ -0,0 +1,41 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include "pinmap.h" +#include "mbed_error.h" + +void pin_function(PinName pin, int function) { +} + +void pin_mode(PinName pin, PinMode mode) { + MBED_ASSERT(pin != (PinName)NC); + + if ((pin == P0_22) || (pin == P0_23)) { + // The true open-drain pins PIO0_22 and PIO0_23 can be configured for different I2C-bus speeds. + return; + } + + __IO uint32_t *reg = (__IO uint32_t*)(LPC_IOCON_BASE + (pin * 4)); + + if (mode == OpenDrain) { + *reg |= (1 << 10); + } else { + uint32_t tmp = *reg; + tmp &= ~(0x3 << 3); + tmp |= (mode & 0x3) << 3; + *reg = tmp; + } +} diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/pwmout_api.c b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/pwmout_api.c new file mode 100644 index 0000000000..8a17f4be48 --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/pwmout_api.c @@ -0,0 +1,170 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include "pwmout_api.h" +#include "cmsis.h" +#include "pinmap.h" +#include "mbed_error.h" + +static LPC_SCT0_Type *SCTs[4] = { + (LPC_SCT0_Type*)LPC_SCT0, + (LPC_SCT0_Type*)LPC_SCT1, + (LPC_SCT0_Type*)LPC_SCT2, + (LPC_SCT0_Type*)LPC_SCT3, +}; + +// bit flags for used SCTs +static unsigned char sct_used = 0; +static int get_available_sct(void) { + int i; + for (i=0; i<4; i++) { + if ((sct_used & (1 << i)) == 0) + return i; + } + return -1; +} + +void pwmout_init(pwmout_t* obj, PinName pin) { + MBED_ASSERT(pin != (uint32_t)NC); + + int sct_n = get_available_sct(); + if (sct_n == -1) { + error("No available SCT"); + } + + sct_used |= (1 << sct_n); + obj->pwm = SCTs[sct_n]; + obj->pwm_ch = sct_n; + + LPC_SCT0_Type* pwm = obj->pwm; + + // Enable the SCT clock + LPC_SYSCON->SYSAHBCLKCTRL1 |= (1 << (obj->pwm_ch + 2)); + + // Clear peripheral reset the SCT: + LPC_SYSCON->PRESETCTRL1 |= (1 << (obj->pwm_ch + 2)); + LPC_SYSCON->PRESETCTRL1 &= ~(1 << (obj->pwm_ch + 2)); + + switch(obj->pwm_ch) { + case 0: + // SCT0_OUT0 + LPC_SWM->PINASSIGN[7] &= ~0x0000FF00; + LPC_SWM->PINASSIGN[7] |= (pin << 8); + break; + case 1: + // SCT1_OUT0 + LPC_SWM->PINASSIGN[8] &= ~0x000000FF; + LPC_SWM->PINASSIGN[8] |= (pin); + break; + case 2: + // SCT2_OUT0 + LPC_SWM->PINASSIGN[8] &= ~0xFF000000; + LPC_SWM->PINASSIGN[8] |= (pin << 24); + break; + case 3: + // SCT3_OUT0 + LPC_SWM->PINASSIGN[9] &= ~0x00FF0000; + LPC_SWM->PINASSIGN[9] |= (pin << 16); + break; + default: + break; + } + + // Unified 32-bit counter, autolimit + pwm->CONFIG |= ((0x3 << 17) | 0x01); + + // halt and clear the counter + pwm->CTRL |= (1 << 2) | (1 << 3); + + // System Clock -> us_ticker (1)MHz + pwm->CTRL &= ~(0x7F << 5); + pwm->CTRL |= (((SystemCoreClock/1000000 - 1) & 0x7F) << 5); + + // Match reload register + pwm->MATCHREL0 = 20000; // 20ms + pwm->MATCHREL1 = (pwm->MATCHREL0 / 4); // 50% duty + + pwm->OUT0_SET = (1 << 0); // event 0 + pwm->OUT0_CLR = (1 << 1); // event 1 + + pwm->EV0_CTRL = (1 << 12); + pwm->EV0_STATE = 0xFFFFFFFF; + pwm->EV1_CTRL = (1 << 12) | (1 << 0); + pwm->EV1_STATE = 0xFFFFFFFF; + + // unhalt the counter: + // - clearing bit 2 of the CTRL register + pwm->CTRL &= ~(1 << 2); + + // default to 20ms: standard for servos, and fine for e.g. brightness control + pwmout_period_ms(obj, 20); + pwmout_write (obj, 0); +} + +void pwmout_free(pwmout_t* obj) { + // Disable the SCT clock + LPC_SYSCON->SYSAHBCLKCTRL1 &= ~(1 << (obj->pwm_ch + 2)); + sct_used &= ~(1 << obj->pwm_ch); +} + +void pwmout_write(pwmout_t* obj, float value) { + LPC_SCT0_Type* pwm = obj->pwm; + if (value < 0.0f) { + value = 0.0; + } else if (value > 1.0f) { + value = 1.0; + } + uint32_t t_on = (uint32_t)((float)(pwm->MATCHREL0) * value); + pwm->MATCHREL1 = t_on; +} + +float pwmout_read(pwmout_t* obj) { + uint32_t t_off = obj->pwm->MATCHREL0; + uint32_t t_on = obj->pwm->MATCHREL1; + float v = (float)t_on/(float)t_off; + return (v > 1.0f) ? (1.0f) : (v); +} + +void pwmout_period(pwmout_t* obj, float seconds) { + pwmout_period_us(obj, seconds * 1000000.0f); +} + +void pwmout_period_ms(pwmout_t* obj, int ms) { + pwmout_period_us(obj, ms * 1000); +} + +// Set the PWM period, keeping the duty cycle the same. +void pwmout_period_us(pwmout_t* obj, int us) { + LPC_SCT0_Type* pwm = obj->pwm; + uint32_t t_off = pwm->MATCHREL0; + uint32_t t_on = pwm->MATCHREL1; + float v = (float)t_on/(float)t_off; + pwm->MATCHREL0 = (uint32_t)us; + pwm->MATCHREL1 = (uint32_t)((float)us * (float)v); +} + +void pwmout_pulsewidth(pwmout_t* obj, float seconds) { + pwmout_pulsewidth_us(obj, seconds * 1000000.0f); +} + +void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) { + pwmout_pulsewidth_us(obj, ms * 1000); +} + +void pwmout_pulsewidth_us(pwmout_t* obj, int us) { + obj->pwm->MATCHREL1 = (uint32_t)us; +} + diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/rtc_api.c b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/rtc_api.c new file mode 100644 index 0000000000..120652672c --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/rtc_api.c @@ -0,0 +1,64 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "rtc_api.h" + +#if DEVICE_RTC + +void rtc_init(void) +{ + // Enables clock for RTC + LPC_SYSCON->SYSAHBCLKCTRL0 |= (1 << 23); + + // Software reset + LPC_RTC->CTRL |= 1; + + LPC_RTC->COUNT = 0; + + // Enabled RTC + LPC_RTC->CTRL |= (1 << 7); + // clear reset + LPC_RTC->CTRL &= ~1; +} + +void rtc_free(void) +{ + LPC_SYSCON->SYSAHBCLKCTRL0 &= ~(1 << 23); + LPC_RTC->CTRL &= ~(1 << 7); +} + +int rtc_isenabled(void) +{ + return (((LPC_RTC->CTRL) & 0x80) != 0); +} + +time_t rtc_read(void) +{ + return (time_t)LPC_RTC->COUNT; +} + +void rtc_write(time_t t) +{ + // Disabled RTC + LPC_RTC->CTRL &= ~(1 << 7); + + // Set count + LPC_RTC->COUNT = t; + + //Enabled RTC + LPC_RTC->CTRL |= (1 << 7); +} + +#endif diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/serial_api.c b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/serial_api.c new file mode 100644 index 0000000000..ab06380329 --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/serial_api.c @@ -0,0 +1,316 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// math.h required for floating point operations for baud rate calculation +#include "mbed_assert.h" +#include <math.h> +#include <string.h> + +#include "serial_api.h" +#include "cmsis.h" +#include "pinmap.h" +#include "mbed_error.h" + +/****************************************************************************** + * INITIALIZATION + ******************************************************************************/ +#define UART_NUM 3 + +static const SWM_Map SWM_UART_TX[] = { + {0, 0}, // Pin assign register0, 7:0bit + {1, 8}, // Pin assign register1, 15:8bit + {2, 16}, // Pin assign register2, 23:16bit +}; + +static const SWM_Map SWM_UART_RX[] = { + {0, 8}, + {1, 16}, + {2, 24}, +}; + +static const SWM_Map SWM_UART_RTS[] = { + {0, 16}, + {1, 24}, + {3, 0}, // not available +}; + +static const SWM_Map SWM_UART_CTS[] = { + {0, 24}, + {2, 0}, + {3, 8} // not available +}; + +// bit flags for used UARTs +static unsigned char uart_used = 0; +static int get_available_uart(void) { + int i; + for (i=0; i<3; i++) { + if ((uart_used & (1 << i)) == 0) + return i; + } + return -1; +} + +#define UART_EN (0x01<<0) + +#define CTS_DELTA (0x01<<5) +#define RXBRK (0x01<<10) +#define DELTA_RXBRK (0x01<<11) + +#define RXRDY (0x01<<0) +#define TXRDY (0x01<<2) + +#define TXBRKEN (0x01<<1) +#define CTSEN (0x01<<9) + +static uint32_t UARTSysClk; + +static uint32_t serial_irq_ids[UART_NUM] = {0}; +static uart_irq_handler irq_handler; + +int stdio_uart_inited = 0; +serial_t stdio_uart; + +static void switch_pin(const SWM_Map *swm, PinName pn) +{ + uint32_t regVal; + if (pn != NC) + { + // check if we have any function mapped to this pin already and remove it + for (uint32_t n = 0; n < sizeof(LPC_SWM->PINASSIGN)/sizeof(*LPC_SWM->PINASSIGN); n ++) { + regVal = LPC_SWM->PINASSIGN[n]; + for (uint32_t j = 0; j <= 24; j += 8) { + if (((regVal >> j) & 0xFF) == (uint32_t)pn) + regVal |= (0xFF << j); + } + LPC_SWM->PINASSIGN[n] = regVal; + } + } + // now map it + regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); + LPC_SWM->PINASSIGN[swm->n] = regVal | (pn << swm->offset); +} + +void serial_init(serial_t *obj, PinName tx, PinName rx) { + int is_stdio_uart = 0; + + int uart_n = get_available_uart(); + if (uart_n == -1) { + error("No available UART"); + } + obj->index = uart_n; + switch (uart_n) { + case 0: obj->uart = (LPC_USART0_Type *)LPC_USART0_BASE; break; + case 1: obj->uart = (LPC_USART0_Type *)LPC_USART1_BASE; break; + case 2: obj->uart = (LPC_USART0_Type *)LPC_USART2_BASE; break; + } + uart_used |= (1 << uart_n); + + switch_pin(&SWM_UART_TX[uart_n], tx); + switch_pin(&SWM_UART_RX[uart_n], rx); + + /* uart clock divided by 6 */ + LPC_SYSCON->UARTCLKDIV =6; + + /* disable uart interrupts */ + NVIC_DisableIRQ((IRQn_Type)(UART0_IRQn + uart_n)); + + /* Enable UART clock */ + LPC_SYSCON->SYSAHBCLKCTRL1 |= (1 << (17 + uart_n)); + + /* Peripheral reset control to UART, a "1" bring it out of reset. */ + LPC_SYSCON->PRESETCTRL1 |= (0x1 << (17 + uart_n)); + LPC_SYSCON->PRESETCTRL1 &= ~(0x1 << (17 + uart_n)); + + UARTSysClk = SystemCoreClock / LPC_SYSCON->UARTCLKDIV; + + // set default baud rate and format + serial_baud (obj, 9600); + serial_format(obj, 8, ParityNone, 1); + + /* Clear all status bits. */ + obj->uart->STAT = CTS_DELTA | DELTA_RXBRK; + + /* enable uart interrupts */ + NVIC_EnableIRQ((IRQn_Type)(UART0_IRQn + uart_n)); + + /* Enable UART */ + obj->uart->CFG |= UART_EN; + + is_stdio_uart = ((tx == USBTX) && (rx == USBRX)); + + if (is_stdio_uart) { + stdio_uart_inited = 1; + memcpy(&stdio_uart, obj, sizeof(serial_t)); + } +} + +void serial_free(serial_t *obj) { + uart_used &= ~(1 << obj->index); + serial_irq_ids[obj->index] = 0; +} + +// serial_baud +// set the baud rate, taking in to account the current SystemFrequency +void serial_baud(serial_t *obj, int baudrate) { + /* Integer divider: + BRG = UARTSysClk/(Baudrate * 16) - 1 + + Frational divider: + FRG = ((UARTSysClk / (Baudrate * 16 * (BRG + 1))) - 1) + + where + FRG = (LPC_SYSCON->UARTFRDADD + 1) / (LPC_SYSCON->UARTFRDSUB + 1) + + (1) The easiest way is set SUB value to 256, -1 encoded, thus SUB + register is 0xFF. + (2) In ADD register value, depending on the value of UartSysClk, + baudrate, BRG register value, and SUB register value, be careful + about the order of multiplier and divider and make sure any + multiplier doesn't exceed 32-bit boundary and any divider doesn't get + down below one(integer 0). + (3) ADD should be always less than SUB. + */ + obj->uart->BRG = UARTSysClk / 16 / baudrate - 1; + + // To use of the fractional baud rate generator, you must write 0xFF to the DIV + // value to yield a denominator value of 256. All other values are not supported. + LPC_SYSCON->FRGCTRL = 0xFF; + + LPC_SYSCON->FRGCTRL |= ( ( ((UARTSysClk / 16) * (0xFF + 1)) / + (baudrate * (obj->uart->BRG + 1)) + ) - (0xFF + 1) ) << 8; + +} + +void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) { + MBED_ASSERT((stop_bits == 1) || (stop_bits == 2)); // 0: 1 stop bits, 1: 2 stop bits + MBED_ASSERT((data_bits > 6) && (data_bits < 10)); // 0: 7 data bits ... 2: 9 data bits + MBED_ASSERT((parity == ParityNone) || (parity == ParityEven) || (parity == ParityOdd)); + + stop_bits -= 1; + data_bits -= 7; + + int paritysel; + switch (parity) { + case ParityNone: paritysel = 0; break; + case ParityEven: paritysel = 2; break; + case ParityOdd : paritysel = 3; break; + default: + break; + } + + // First disable the the usart as described in documentation and then enable while updating CFG + + // 24.6.1 USART Configuration register + // Remark: If software needs to change configuration values, the following sequence should + // be used: 1) Make sure the USART is not currently sending or receiving data. 2) Disable + // the USART by writing a 0 to the Enable bit (0 may be written to the entire register). 3) + // Write the new configuration value, with the ENABLE bit set to 1. + obj->uart->CFG &= ~(1 << 0); + + obj->uart->CFG = (1 << 0) // this will enable the usart + | (data_bits << 2) + | (paritysel << 4) + | (stop_bits << 6); +} + +/****************************************************************************** + * INTERRUPTS HANDLING + ******************************************************************************/ +static inline void uart_irq(SerialIrq irq_type, uint32_t index) { + if (serial_irq_ids[index] != 0) + irq_handler(serial_irq_ids[index], irq_type); +} + +void uart0_irq() {uart_irq((LPC_USART0->INTSTAT & 1) ? RxIrq : TxIrq, 0);} +void uart1_irq() {uart_irq((LPC_USART1->INTSTAT & 1) ? RxIrq : TxIrq, 1);} +void uart2_irq() {uart_irq((LPC_USART2->INTSTAT & 1) ? RxIrq : TxIrq, 2);} + +void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { + irq_handler = handler; + serial_irq_ids[obj->index] = id; +} + +void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) { + IRQn_Type irq_n = (IRQn_Type)0; + uint32_t vector = 0; + switch ((int)obj->uart) { + case LPC_USART0_BASE: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break; + case LPC_USART1_BASE: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break; + case LPC_USART2_BASE: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break; + } + + if (enable) { + NVIC_DisableIRQ(irq_n); + obj->uart->INTENSET |= (1 << ((irq == RxIrq) ? 0 : 2)); + NVIC_SetVector(irq_n, vector); + NVIC_EnableIRQ(irq_n); + } else { // disable + int all_disabled = 0; + SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq); + obj->uart->INTENCLR |= (1 << ((irq == RxIrq) ? 0 : 2)); // disable the interrupt + all_disabled = (obj->uart->INTENSET & (1 << ((other_irq == RxIrq) ? 0 : 2))) == 0; + if (all_disabled) + NVIC_DisableIRQ(irq_n); + } +} + +/****************************************************************************** + * READ/WRITE + ******************************************************************************/ +int serial_getc(serial_t *obj) { + while (!serial_readable(obj)); + return obj->uart->RXDATA; +} + +void serial_putc(serial_t *obj, int c) { + while (!serial_writable(obj)); + obj->uart->TXDATA = c; +} + +int serial_readable(serial_t *obj) { + return obj->uart->STAT & RXRDY; +} + +int serial_writable(serial_t *obj) { + return obj->uart->STAT & TXRDY; +} + +void serial_clear(serial_t *obj) { + // [TODO] +} + +void serial_pinout_tx(PinName tx) { + +} + +void serial_break_set(serial_t *obj) { + obj->uart->CTRL |= TXBRKEN; +} + +void serial_break_clear(serial_t *obj) { + obj->uart->CTRL &= ~TXBRKEN; +} + +void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) { + if ((FlowControlNone == type || FlowControlRTS == type)) txflow = NC; + if ((FlowControlNone == type || FlowControlCTS == type)) rxflow = NC; + switch_pin(&SWM_UART_RTS[obj->index], rxflow); + switch_pin(&SWM_UART_CTS[obj->index], txflow); + if (txflow == NC) obj->uart->CFG &= ~CTSEN; + else obj->uart->CFG |= CTSEN; +} + diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/spi_api.c b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/spi_api.c new file mode 100644 index 0000000000..79d1d2aeef --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/spi_api.c @@ -0,0 +1,276 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include <math.h> + +#include "spi_api.h" +#include "cmsis.h" +#include "pinmap.h" +#include "mbed_error.h" + +static const SWM_Map SWM_SPI_SSEL[] = { + {4, 0}, + {5, 24}, +}; + +static const SWM_Map SWM_SPI_SCLK[] = { + {3, 8}, + {5, 0}, +}; + +static const SWM_Map SWM_SPI_MOSI[] = { + {3, 16}, + {5, 8}, +}; + +static const SWM_Map SWM_SPI_MISO[] = { + {3, 24}, + {5, 16}, +}; + +// bit flags for used SPIs +static unsigned char spi_used = 0; +static int get_available_spi(PinName mosi, PinName miso, PinName sclk, PinName ssel) +{ + if (spi_used == 0) { + return 0; // The first user + } + + const SWM_Map *swm; + uint32_t regVal; + + // Investigate if same pins as the used SPI0/1 - to be able to reuse it + for (int spi_n = 0; spi_n < 2; spi_n++) { + if (spi_used & (1<<spi_n)) { + if (sclk != NC) { + swm = &SWM_SPI_SCLK[spi_n]; + regVal = LPC_SWM->PINASSIGN[swm->n] & (0xFF << swm->offset); + if (regVal != (sclk << swm->offset)) { + // Existing pin is not the same as the one we want + continue; + } + } + + if (mosi != NC) { + swm = &SWM_SPI_MOSI[spi_n]; + regVal = LPC_SWM->PINASSIGN[swm->n] & (0xFF << swm->offset); + if (regVal != (mosi << swm->offset)) { + // Existing pin is not the same as the one we want + continue; + } + } + + if (miso != NC) { + swm = &SWM_SPI_MISO[spi_n]; + regVal = LPC_SWM->PINASSIGN[swm->n] & (0xFF << swm->offset); + if (regVal != (miso << swm->offset)) { + // Existing pin is not the same as the one we want + continue; + } + } + + if (ssel != NC) { + swm = &SWM_SPI_SSEL[spi_n]; + regVal = LPC_SWM->PINASSIGN[swm->n] & (0xFF << swm->offset); + if (regVal != (ssel << swm->offset)) { + // Existing pin is not the same as the one we want + continue; + } + } + + // The pins for the currently used SPIx are the same as the + // ones we want so we will reuse it + return spi_n; + } + } + + // None of the existing SPIx pin setups match the pins we want + // so the last hope is to select one unused SPIx + if ((spi_used & 1) == 0) { + return 0; + } else if ((spi_used & 2) == 0) { + return 1; + } + + // No matching setup and no free SPIx + return -1; +} + +static inline void spi_disable(spi_t *obj); +static inline void spi_enable(spi_t *obj); + +void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) +{ + int spi_n = get_available_spi(mosi, miso, sclk, ssel); + if (spi_n == -1) { + error("No available SPI"); + } + + obj->spi_n = spi_n; + spi_used |= (1 << spi_n); + + obj->spi = (spi_n) ? (LPC_SPI0_Type *)(LPC_SPI1_BASE) : (LPC_SPI0_Type *)(LPC_SPI0_BASE); + + const SWM_Map *swm; + uint32_t regVal; + + if (sclk != NC) { + swm = &SWM_SPI_SCLK[obj->spi_n]; + regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); + LPC_SWM->PINASSIGN[swm->n] = regVal | (sclk << swm->offset); + } + + if (mosi != NC) { + swm = &SWM_SPI_MOSI[obj->spi_n]; + regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); + LPC_SWM->PINASSIGN[swm->n] = regVal | (mosi << swm->offset); + } + + if (miso != NC) { + swm = &SWM_SPI_MISO[obj->spi_n]; + regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); + LPC_SWM->PINASSIGN[swm->n] = regVal | (miso << swm->offset); + } + + if (ssel != NC) { + swm = &SWM_SPI_SSEL[obj->spi_n]; + regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); + LPC_SWM->PINASSIGN[swm->n] = regVal | (ssel << swm->offset); + } + + // clear interrupts + obj->spi->INTENCLR = 0x3f; + + // enable power and clocking + LPC_SYSCON->SYSAHBCLKCTRL1 |= (0x1 << (obj->spi_n + 9)); + LPC_SYSCON->PRESETCTRL1 |= (0x1 << (obj->spi_n + 9)); + LPC_SYSCON->PRESETCTRL1 &= ~(0x1 << (obj->spi_n + 9)); + + // set default format and frequency + if (ssel == NC) { + spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master + } else { + spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave + } + spi_frequency(obj, 1000000); + + // enable the spi channel + spi_enable(obj); +} + +void spi_free(spi_t *obj) +{ +} + +void spi_format(spi_t *obj, int bits, int mode, int slave) +{ + spi_disable(obj); + MBED_ASSERT((bits >= 1 && bits <= 16) && (mode >= 0 && mode <= 3)); + + int polarity = (mode & 0x2) ? 1 : 0; + int phase = (mode & 0x1) ? 1 : 0; + + // set it up + int LEN = bits - 1; // LEN - Data Length + int CPOL = (polarity) ? 1 : 0; // CPOL - Clock Polarity select + int CPHA = (phase) ? 1 : 0; // CPHA - Clock Phase select + + uint32_t tmp = obj->spi->CFG; + tmp &= ~((1 << 5) | (1 << 4) | (1 << 2)); + tmp |= (CPOL << 5) | (CPHA << 4) | ((slave ? 0 : 1) << 2); + obj->spi->CFG = tmp; + + // select frame length + tmp = obj->spi->TXCTL; + tmp &= ~(0xf << 24); + tmp |= (LEN << 24); + obj->spi->TXCTL = tmp; + + spi_enable(obj); +} + +void spi_frequency(spi_t *obj, int hz) +{ + spi_disable(obj); + + // rise DIV value if it cannot be divided + obj->spi->DIV = (SystemCoreClock + (hz - 1))/hz - 1; + obj->spi->DLY = 0; + + spi_enable(obj); +} + +static inline void spi_disable(spi_t *obj) +{ + obj->spi->CFG &= ~(1 << 0); +} + +static inline void spi_enable(spi_t *obj) +{ + obj->spi->CFG |= (1 << 0); +} + +static inline int spi_readable(spi_t *obj) +{ + return obj->spi->STAT & (1 << 0); +} + +static inline int spi_writeable(spi_t *obj) +{ + return obj->spi->STAT & (1 << 1); +} + +static inline void spi_write(spi_t *obj, int value) +{ + while (!spi_writeable(obj)); + // end of transfer + obj->spi->TXCTL |= (1 << 20); + obj->spi->TXDAT = (value & 0xffff); +} + +static inline int spi_read(spi_t *obj) +{ + while (!spi_readable(obj)); + return obj->spi->RXDAT & 0xffff; // Only the lower 16 bits contain data +} + +int spi_busy(spi_t *obj) +{ + // checking RXOV(Receiver Overrun interrupt flag) + return obj->spi->STAT & (1 << 2); +} + +int spi_master_write(spi_t *obj, int value) +{ + spi_write(obj, value); + return spi_read(obj); +} + +int spi_slave_receive(spi_t *obj) +{ + return (spi_readable(obj) && !spi_busy(obj)) ? (1) : (0); +} + +int spi_slave_read(spi_t *obj) +{ + return obj->spi->RXDAT & 0xffff; // Only the lower 16 bits contain data +} + +void spi_slave_write(spi_t *obj, int value) +{ + while (spi_writeable(obj) == 0) ; + obj->spi->TXDAT = value; +} diff --git a/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/us_ticker.c b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/us_ticker.c new file mode 100644 index 0000000000..a4ad2d0039 --- /dev/null +++ b/tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/us_ticker.c @@ -0,0 +1,73 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <stddef.h> +#include "us_ticker_api.h" +#include "PeripheralNames.h" + +#define US_TICKER_TIMER_IRQn RIT_IRQn + +int us_ticker_inited = 0; + +void us_ticker_init(void) { + if (us_ticker_inited) return; + us_ticker_inited = 1; + + // Enable the RIT clock + LPC_SYSCON->SYSAHBCLKCTRL1 |= (1 << 1); + + // Clear peripheral reset the RIT + LPC_SYSCON->PRESETCTRL1 |= (1 << 1); + LPC_SYSCON->PRESETCTRL1 &= ~(1 << 1); + + LPC_RIT->MASK = 0; + LPC_RIT->MASK_H = 0; + + LPC_RIT->COUNTER = 0; + LPC_RIT->COUNTER_H = 0; + + LPC_RIT->COMPVAL = 0xffffffff; + LPC_RIT->COMPVAL_H = 0x0000ffff; + + // Timer enable, enable for debug + LPC_RIT->CTRL = 0xC; + + NVIC_SetVector(US_TICKER_TIMER_IRQn, (uint32_t)us_ticker_irq_handler); + NVIC_EnableIRQ(US_TICKER_TIMER_IRQn); +} + +uint32_t us_ticker_read() { + if (!us_ticker_inited) + us_ticker_init(); + + uint64_t temp; + temp = LPC_RIT->COUNTER | ((uint64_t)LPC_RIT->COUNTER_H << 32); + temp /= (SystemCoreClock/1000000); + return (uint32_t)temp; +} + +void us_ticker_set_interrupt(timestamp_t timestamp) { + uint64_t temp = ((uint64_t)timestamp * (SystemCoreClock/1000000)); + LPC_RIT->COMPVAL = (temp & 0xFFFFFFFFL); + LPC_RIT->COMPVAL_H = ((temp >> 32)& 0x0000FFFFL); +} + +void us_ticker_disable_interrupt(void) { + LPC_RIT->CTRL |= (1 << 3); +} + +void us_ticker_clear_interrupt(void) { + LPC_RIT->CTRL |= (1 << 0); +} |