[BEETLE] Add initial Beetle HAL files

This patch adds support for BEETLE SoC Target into the HAL layer.
It contains:
* Beetle Platform Configuration
* I2C API
* SPI API
* Serial API
* Port API
* us Ticker API

Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
pull/1852/head
Vincenzo Frascino 2016-05-11 16:02:24 +01:00
parent 44be0626a6
commit 09b5551d41
19 changed files with 2743 additions and 0 deletions

View File

@ -0,0 +1,82 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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"
#include "i2c_def.h"
#include "spi_def.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
UART_0 = (int)CMSDK_UART0_BASE,
UART_1 = (int)CMSDK_UART1_BASE
} UARTName;
typedef enum {
I2C_0 = (int)I2C0_BASE,
I2C_1 = (int)I2C1_BASE
} I2CName;
typedef enum {
ADC0_0 = 0,
ADC0_1,
ADC0_2,
ADC0_3,
ADC0_4,
ADC0_5
} ADCName;
typedef enum {
SPI_0 = (int)SPI0_BASE,
SPI_1 = (int)SPI1_BASE
} SPIName;
typedef enum {
PWM_1 = 0,
PWM_2,
PWM_3,
PWM_4,
PWM_5,
PWM_6,
PWM_7,
PWM_8,
PWM_9,
PWM_10,
PWM_11
} PWMName;
#define STDIO_UART_TX UART_TX1
#define STDIO_UART_RX UART_RX1
#define STDIO_UART UART_1
#define MBED_UART0 UART_TX0, UART_RX0
#define MBED_UART1 UART_TX1, UART_RX1
#define MBED_UARTUSB UART_TX1, UART_RX1
//USB UART
#define USBTX UART_TX1
#define USBRX UART_RX1
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,151 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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;
#define PORT_SHIFT 5
typedef enum {
/* BEETLE Pin Names */
/* GPIO0 */
P0_0 = 0,
P0_1 = 1,
P0_2 = 2,
P0_3 = 3,
P0_4 = 4,
P0_5 = 5,
P0_6 = 6,
P0_7 = 7,
P0_8 = 8,
P0_9 = 9,
P0_10 = 10,
P0_11 = 11,
P0_12 = 12,
P0_13 = 13,
P0_14 = 14,
P0_15 = 15,
/* GPIO1 */
P1_0 = 16,
P1_1 = 17,
P1_2 = 18,
P1_3 = 19,
P1_4 = 20,
P1_5 = 21,
P1_6 = 22,
P1_7 = 23,
P1_8 = 24,
P1_9 = 25,
P1_10 = 26,
P1_11 = 27,
P1_12 = 28,
P1_13 = 29,
P1_14 = 30,
P1_15 = 31,
/* Arduino Connector Namings */
A0 = 600,
A1 = 601,
A2 = 602,
A3 = 603,
A4 = 604,
A5 = 605,
D0 = P0_0,
D1 = P0_1,
D2 = P0_2,
D3 = P0_3,
D4 = P0_4,
D5 = P0_5,
D6 = P0_6,
D7 = P0_7,
D8 = P0_8,
D9 = P0_9,
D10 = P0_10,
D11 = P0_11,
D12 = P0_12,
D13 = P0_13,
D14 = P0_14,
D15 = P0_15,
/* TRACE Ports */
TRACECLK = P0_2,
TRACED0 = P0_6,
TRACED1 = P0_7,
TRACED2 = P0_8,
TRACED3 = P0_9,
/* Other BEETLE Pin Names */
//Shield SPI
SHIELD_SPI_SCK = 320,
SHIELD_SPI_MOSI = 321,
SHIELD_SPI_MISO = 322,
SHIELD_SPI_nCS = 323,
//ADC SPI
ADC_SPI_MOSI = 650,
ADC_SPI_MISO = 651,
ADC_SPI_SCK = 652,
ADC_SPI_nCS = 653,
//Uart
UART_TX0 = 400,
UART_RX0 = 401,
UART_TX1 = 402,
UART_RX1 = 403,
//Shield I2C
SHIELD_SDA = 504,
SHIELD_SCL = 505,
// Internal I2C for temperature and acceleromter sensor
SENSOR_SDA = 506,
SENSOR_SCL = 507,
// Not connected
NC = (int)0xFFFFFFFF,
// LEDS not connected
LED1 = NC,
LED2 = NC,
LED3 = NC,
LED4 = NC,
} PinName;
typedef enum {
PullUp = 2,
PullDown = 1,
PullNone = 0,
Repeater = 3,
OpenDrain = 4,
PullDefault = PullDown
} PinMode;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,32 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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
} PortName;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,148 @@
/*
* PackageLicenseDeclared: Apache-2.0
* Copyright (c) 2016 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cmsis.h"
#include "mbed_assert.h"
#include "wait_api.h"
#include "analogin_api.h"
#include "gpio_api.h"
#include "spi_api.h"
#include "pinmap.h"
#if DEVICE_ANALOGIN
/*
* Channel Address for the next acquisition:
* XXAAAXXX XXXXXXXX
*/
#define ADC_SPI_ADDRESS 11
/* ADC Resolution */
#define ADC_RESOLUTION 0xFFF
/* ADC Voltage Divider */
#define ADC_DIV 819.0
/* PinMap structure for ADC IN */
static const PinMap PinMap_ADC[] = {
{A0, ADC0_0, 0},
{A1, ADC0_1, 0},
{A2, ADC0_2, 0},
{A3, ADC0_3, 0},
{A4, ADC0_4, 0},
{A5, ADC0_5, 0},
{NC, NC, 0}
};
/* ADC SPI Private Data */
typedef struct {
/* ADC SPI */
spi_t analogin_spi;
/* ADC SPI CS */
gpio_t adc_spi_cs_gpio;
/* ADC SPI State */
uint32_t analog_spi_inited;
} analogin_spi_t;
/* ADC SPI Device */
static analogin_spi_t analogin_spi_dev;
/*
* ADC SPI CS
*/
#define ADC_SPI_CS P1_2
/*
* Initialize the analogin peripheral
* Configures the pin used by analogin.
* obj: The analogin object to initialize
* pin: The analogin pin name
*/
void analogin_init(analogin_t *obj, PinName pin)
{
/* Initialize ADC Pin */
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
/* Verify if pin is valid */
MBED_ASSERT(obj->adc != (ADCName)NC);
/* Initialize the ADC SPI */
if(analogin_spi_dev.analog_spi_inited == 0){
/* Initialize SPI for ADC */
spi_init(&(analogin_spi_dev.analogin_spi), ADC_SPI_MOSI,
ADC_SPI_MISO, ADC_SPI_SCK, ADC_SPI_nCS);
spi_format(&(analogin_spi_dev.analogin_spi), 16, 3, 0);
/* Set SPI to MAX Freq */
spi_frequency(&(analogin_spi_dev.analogin_spi), 0);
/* Initialize CS GPIO */
gpio_init_out(&(analogin_spi_dev.adc_spi_cs_gpio), ADC_SPI_CS);
analogin_spi_dev.analog_spi_inited = 1;
}
/* If pin is valid assign it to the ADC data structure */
obj->pin = pin;
obj->pin_number = pin-600;
obj->address = (0x0000 | (pin-600));
/* Configure the pinout */
pinmap_pinout(pin, PinMap_ADC);
}
/*
* Read the value from analogin pin, represented as an unsigned 16bit value
* obj: The analogin object
* @return: An unsigned 16bit value representing the current input voltage
*/
uint16_t analogin_read_u16(analogin_t *obj)
{
uint16_t result = 0;
/*
* The ADC SPI hw is 8 bit format, 16 bit emulation is required
* in the SPI driver.
*/
/* CS = 1 */
gpio_write(&(analogin_spi_dev.adc_spi_cs_gpio), 1);
/* Do the first read */
(void)spi_master_write(&(analogin_spi_dev.analogin_spi),
((obj->pin_number) << ADC_SPI_ADDRESS));
/* CS = 0 */
gpio_write(&(analogin_spi_dev.adc_spi_cs_gpio), 0);
/* Wait 50 us */
wait_us(50);
/* CS = 1 */
gpio_write(&(analogin_spi_dev.adc_spi_cs_gpio), 1);
/* The second read provides the result */
result = spi_master_write(&(analogin_spi_dev.analogin_spi),
((obj->pin_number) << ADC_SPI_ADDRESS));
/* CS = 0 */
gpio_write(&(analogin_spi_dev.adc_spi_cs_gpio), 0);
return result;
}
/*
* Read the input voltage, represented as a float in the range [0.0, 1.0]
* obj: The analogin object
* @return: A floating value representing the current input voltage
*/
float analogin_read(analogin_t *obj)
{
uint16_t result = analogin_read_u16(obj);
return (float)((result & ADC_RESOLUTION) * 1.0f) / ADC_DIV;
}
#endif

View File

@ -0,0 +1,21 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_DEVICE_H
#define MBED_DEVICE_H
#include "objects.h"
#endif

View File

@ -0,0 +1,86 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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 "gpio_api.h"
#include "pinmap.h"
// function to enable the GPIO pin
uint32_t gpio_set(PinName pin) {
uint32_t pin_value = 0;
if(pin <= 15) {
pin_value = pin;
} else if (pin >= 16 && pin <= 31) {
pin_value = pin-16;
}
pin_function(pin, 0);
return (1 << pin_value);
}
//function to initialise the gpio pin
// this links the board control bits for each pin
// with the object created for the pin
void gpio_init(gpio_t *obj, PinName pin) {
if (pin == NC) {
return;
} else {
int pin_value = 0;
obj->pin = pin;
if (pin <=15) {
pin_value = pin;
} else if (pin >= 16 && pin <= 31) {
pin_value = pin-16;
}
obj->mask = 0x1 << pin_value;
obj->pin_number = pin;
if (pin <=15) {
obj->reg_data = &CMSDK_GPIO0->DATAOUT;
obj->reg_in = &CMSDK_GPIO0->DATA;
obj->reg_dir = &CMSDK_GPIO0->OUTENABLESET;
obj->reg_dirclr = &CMSDK_GPIO0->OUTENABLECLR;
} else if (pin >= 16 && pin <= 31) {
obj->reg_data = &CMSDK_GPIO1->DATAOUT;
obj->reg_in = &CMSDK_GPIO1->DATA;
obj->reg_dir = &CMSDK_GPIO1->OUTENABLESET;
obj->reg_dirclr = &CMSDK_GPIO1->OUTENABLECLR;
}
}
}
void gpio_mode(gpio_t *obj, PinMode mode) {
pin_mode(obj->pin, mode);
}
void gpio_dir(gpio_t *obj, PinDirection direction) {
if(obj->pin >= 0 && obj->pin <= 31) {
switch (direction) {
case PIN_INPUT : *obj->reg_dirclr = obj->mask; break;
case PIN_OUTPUT: *obj->reg_dir |= obj->mask; break;
}
} else {
return;
}
}
int gpio_is_connected(const gpio_t *obj){
if(obj->pin != (PinName)NC){
return 1;
} else {
return 0;
}
}

View File

@ -0,0 +1,399 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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 32
#define CMSDK_GPIO_0 CMSDK_GPIO0
#define CMSDK_GPIO_1 CMSDK_GPIO1
#define PININT_IRQ 0
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 (ch_bit <16){
if (((CMSDK_GPIO_0->INTSTATUS) == 0) || (channel_ids[channel] == 0)
|| ((CMSDK_GPIO_0->INTTYPESET) == 0))
return;
if ((CMSDK_GPIO_0->INTTYPESET & ch_bit)
&& (CMSDK_GPIO_0->INTPOLSET & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_RISE);
CMSDK_GPIO_0->INTPOLSET = ch_bit;
}
if ((CMSDK_GPIO_0->INTTYPESET & ch_bit)
&& ~(CMSDK_GPIO_0->INTPOLSET & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_FALL);
}
CMSDK_GPIO_0->INTCLEAR = ch_bit;
}
if (ch_bit>=16) {
if (((CMSDK_GPIO_1->INTSTATUS) == 0) || (channel_ids[channel] == 0)
|| ((CMSDK_GPIO_1->INTTYPESET) == 0))
return;
if ((CMSDK_GPIO_1->INTTYPESET & ch_bit)
&& (CMSDK_GPIO_1->INTPOLSET & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_RISE);
CMSDK_GPIO_1->INTPOLSET = ch_bit;
}
if ((CMSDK_GPIO_1->INTTYPESET & ch_bit)
&& ~(CMSDK_GPIO_1->INTPOLSET & ch_bit)) {
irq_handler(channel_ids[channel], IRQ_FALL);
}
CMSDK_GPIO_1->INTCLEAR = ch_bit;
}
}
void gpio0_irq0(void) {
handle_interrupt_in(0);
}
void gpio0_irq1(void) {
handle_interrupt_in(1);
}
void gpio0_irq2(void) {
handle_interrupt_in(2);
}
void gpio0_irq3(void) {
handle_interrupt_in(3);
}
void gpio0_irq4(void) {
handle_interrupt_in(4);
}
void gpio0_irq5(void) {
handle_interrupt_in(5);
}
void gpio0_irq6(void) {
handle_interrupt_in(6);
}
void gpio0_irq7(void) {
handle_interrupt_in(7);
}
void gpio0_irq8(void) {
handle_interrupt_in(8);
}
void gpio0_irq9(void) {
handle_interrupt_in(9);
}
void gpio0_irq10(void) {
handle_interrupt_in(10);
}
void gpio0_irq11(void) {
handle_interrupt_in(11);
}
void gpio0_irq12(void) {
handle_interrupt_in(12);
}
void gpio0_irq13(void) {
handle_interrupt_in(13);
}
void gpio0_irq14(void) {
handle_interrupt_in(14);
}
void gpio0_irq15(void) {
handle_interrupt_in(15);
}
void gpio1_irq0(void) {
handle_interrupt_in(16);
}
void gpio1_irq1(void) {
handle_interrupt_in(17);
}
void gpio1_irq2(void) {
handle_interrupt_in(18);
}
void gpio1_irq3(void) {
handle_interrupt_in(19);
}
void gpio1_irq4(void) {
handle_interrupt_in(20);
}
void gpio1_irq5(void) {
handle_interrupt_in(21);
}
void gpio1_irq6(void) {
handle_interrupt_in(22);
}
void gpio1_irq7(void) {
handle_interrupt_in(23);
}
void gpio1_irq8(void) {
handle_interrupt_in(24);
}
void gpio1_irq9(void) {
handle_interrupt_in(25);
}
void gpio1_irq10(void) {
handle_interrupt_in(26);
}
void gpio1_irq11(void) {
handle_interrupt_in(27);
}
void gpio1_irq12(void) {
handle_interrupt_in(28);
}
void gpio1_irq13(void) {
handle_interrupt_in(29);
}
void gpio1_irq14(void) {
handle_interrupt_in(30);
}
void gpio1_irq15(void) {
handle_interrupt_in(31);
}
int gpio_irq_init(gpio_irq_t *obj, PinName pin,
gpio_irq_handler handler, uint32_t id) {
if (pin == NC) {return -1;}
else {
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;
/* To select a pin for any of the eight pin interrupts, write the pin number
* as 0 to 23 for pins PIO0_0 to PIO0_23 and 24 to 55.
* @see: mbed_capi/PinNames.h
*/
if (pin <16) {
CMSDK_GPIO_0->INTENSET |= (0x1 << pin);
}
if (pin >= 16) {
CMSDK_GPIO_1->INTENSET |= (0x1 << pin);
}
void (*channels_irq)(void) = NULL;
switch (obj->ch) {
case 0:
channels_irq = &gpio0_irq0;
break;
case 1:
channels_irq = &gpio0_irq1;
break;
case 2:
channels_irq = &gpio0_irq2;
break;
case 3:
channels_irq = &gpio0_irq3;
break;
case 4:
channels_irq = &gpio0_irq4;
break;
case 5:
channels_irq = &gpio0_irq5;
break;
case 6:
channels_irq = &gpio0_irq6;
break;
case 7:
channels_irq = &gpio0_irq7;
break;
case 8:
channels_irq = &gpio0_irq8;
break;
case 9:
channels_irq = &gpio0_irq9;
break;
case 10:
channels_irq = &gpio0_irq10;
break;
case 11:
channels_irq = &gpio0_irq11;
break;
case 12:
channels_irq = &gpio0_irq12;
break;
case 13:
channels_irq = &gpio0_irq13;
break;
case 14:
channels_irq = &gpio0_irq14;
break;
case 15:
channels_irq = &gpio0_irq15;
break;
case 16:
channels_irq = &gpio1_irq0;
break;
case 17:
channels_irq = &gpio1_irq1;
break;
case 18:
channels_irq = &gpio1_irq2;
break;
case 19:
channels_irq = &gpio1_irq3;
break;
case 20:
channels_irq = &gpio1_irq4;
break;
case 21:
channels_irq = &gpio1_irq5;
break;
case 22:
channels_irq = &gpio1_irq6;
break;
case 23:
channels_irq = &gpio1_irq7;
break;
case 24:
channels_irq = &gpio1_irq8;
break;
case 25:
channels_irq = &gpio1_irq9;
break;
case 26:
channels_irq = &gpio1_irq10;
break;
case 27:
channels_irq = &gpio1_irq11;
break;
case 28:
channels_irq = &gpio1_irq12;
break;
case 29:
channels_irq = &gpio1_irq13;
break;
case 30:
channels_irq = &gpio1_irq14;
break;
case 31:
channels_irq = &gpio1_irq15;
break;
}
NVIC_SetVector((IRQn_Type)(PININT_IRQ + obj->ch),
(uint32_t)channels_irq);
NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ + obj->ch));
return 0;
}
}
void gpio_irq_free(gpio_irq_t *obj) {
}
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 (obj->ch <16) {
if (!(CMSDK_GPIO_0->INTTYPESET & ch_bit)) {
CMSDK_GPIO_0->INTCLEAR = ch_bit;
}
}
if (obj->ch >= 16) {
if (!(CMSDK_GPIO_1->INTTYPESET & ch_bit)) {
CMSDK_GPIO_1->INTCLEAR = ch_bit;
}
}
// Edge trigger
if (obj->ch <16) {
CMSDK_GPIO_0->INTTYPESET &= ch_bit;
if (event == IRQ_RISE) {
CMSDK_GPIO_0->INTPOLSET |= ch_bit;
if (enable) {
CMSDK_GPIO_0->INTENSET |= ch_bit;
} else {
CMSDK_GPIO_0->INTENCLR |= ch_bit;
}
} else {
CMSDK_GPIO_0->INTPOLCLR |= ch_bit;
if (enable) {
CMSDK_GPIO_0->INTENSET |= ch_bit;
} else {
CMSDK_GPIO_0->INTENCLR |= ch_bit;
}
}
}
if (obj->ch >= 16) {
CMSDK_GPIO_1->INTTYPESET &= ch_bit;
if (event == IRQ_RISE) {
CMSDK_GPIO_1->INTPOLSET |= ch_bit;
if (enable) {
CMSDK_GPIO_1->INTENSET |= ch_bit;
} else {
CMSDK_GPIO_1->INTENCLR |= ch_bit;
}
} else {
CMSDK_GPIO_1->INTPOLCLR |= ch_bit;
if (enable) {
CMSDK_GPIO_1->INTENSET |= ch_bit;
} else {
CMSDK_GPIO_1->INTENCLR |= ch_bit;
}
}
}
}
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));
}

View File

@ -0,0 +1,55 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_GPIO_OBJECT_H
#define MBED_GPIO_OBJECT_H
#include "cmsis.h"
#include "PortNames.h"
#include "PeripheralNames.h"
#include "PinNames.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
PinName pin;
uint32_t mask;
uint32_t pin_number;
__IO uint32_t *reg_dir;
__IO uint32_t *reg_dirclr;
__IO uint32_t *reg_data;
__I uint32_t *reg_in;
} gpio_t;
static inline void gpio_write(gpio_t *obj, int value) {
if (value == 1){
*obj->reg_data |= (obj->mask);
} else if (value == 0){
*obj->reg_data &= ~(obj->mask);
}
}
static inline int gpio_read(gpio_t *obj) {
return ((*obj->reg_in & obj->mask) ? 1 : 0);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,508 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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 "i2c_api.h"
#include "i2c_def.h"
#include "cmsis.h"
#include "pinmap.h"
#include "mbed_error.h"
#include "wait_api.h"
/* States of a possibly combined I2C transfer */
typedef enum i2c_transfer_state_t {
I2C_TRANSFER_SINGLE, /* Non combined transfer */
I2C_TRANSFER_COMBINED_FIRST_MESSAGE, /*
* First message of a
* combined transfer
*/
I2C_TRANSFER_COMBINED_INTERMEDIATE_MESSAGE, /*
* Message in the middle
* of a combined
* transfer
*/
I2C_TRANSFER_COMBINED_LAST_MESSAGE, /*
* Last message of a combined
* transfer
*/
} i2c_transfer_state_t;
/*
* Driver private data structure that should not be shared by multiple
* instances of the driver
* (same driver for multiple instances of the IP)
*/
typedef struct private_i2c_t {
/* State of a possibly combined ongoing i2c transfer */
i2c_transfer_state_t transfer_state;
}private_i2c_t;
/*
* Retrieve the private data of the instance related to a given IP
*/
static private_i2c_t* get_i2c_private(i2c_t *obj) {
static private_i2c_t data0, data1;
/*
* Select which instance to give using the base
* address of registers
*/
switch((intptr_t)obj->i2c) {
case I2C0_BASE:
return &data0;
case I2C1_BASE:
return &data1;
default:
error("i2c driver private data structure not found for this registers base address");
return (void*)0;
}
}
/*
* Infer the current state of a possibly combined transfer
* (repeated restart) from the current state and the "stop" parameter
* of read and write functions
* MUST be called ONCE AND ONLY ONCE at the beginning of i2c transfer
* functions (read and write)
*/
static i2c_transfer_state_t update_transfer_state(i2c_t *obj, int stop) {
private_i2c_t* private_data = get_i2c_private(obj);
i2c_transfer_state_t *state = &private_data->transfer_state;
/*
* Choose the current and next state depending on the current state
* This basically implements rising and falling edge detection on
* "stop" variable
*/
switch(*state) {
/* This is the default state for non restarted repeat transfer */
default:
case I2C_TRANSFER_SINGLE: /* Not a combined transfer */
if (stop) {
*state = I2C_TRANSFER_SINGLE;
} else {
*state = I2C_TRANSFER_COMBINED_FIRST_MESSAGE;
}
break;
/* First message of a combined transfer */
case I2C_TRANSFER_COMBINED_FIRST_MESSAGE:
/* Message in the middle of a combined transfer */
case I2C_TRANSFER_COMBINED_INTERMEDIATE_MESSAGE:
if (stop) {
*state = I2C_TRANSFER_COMBINED_LAST_MESSAGE;
} else {
*state = I2C_TRANSFER_COMBINED_INTERMEDIATE_MESSAGE;
}
break;
/* Last message of a combined transfer */
case I2C_TRANSFER_COMBINED_LAST_MESSAGE:
if (stop) {
*state = I2C_TRANSFER_SINGLE;
} else {
*state = I2C_TRANSFER_COMBINED_FIRST_MESSAGE;
}
break;
}
return *state;
}
static const PinMap PinMap_I2C_SDA[] = {
{SHIELD_SDA, I2C_0, 0},
{SENSOR_SDA, I2C_1, 0},
{NC, NC , 0}
};
static const PinMap PinMap_I2C_SCL[] = {
{SHIELD_SCL, I2C_0, 0},
{SENSOR_SCL, I2C_1, 0},
{NC, NC, 0}
};
static void clear_isr(i2c_t *obj) {
/*
* Writing to the IRQ status register clears set bits. Therefore, to
* clear indiscriminately, just read the register and write it back.
*/
uint32_t reg = obj->i2c->IRQ_STATUS;
obj->i2c->IRQ_STATUS = reg;
}
void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
/* Determine the I2C to use */
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
obj->i2c = (I2C_TypeDef *)pinmap_merge(i2c_sda, i2c_scl);
if ((int)obj->i2c == NC) {
error("I2C pin mapping failed");
}
pinmap_pinout(sda, PinMap_I2C_SDA);
pinmap_pinout(scl, PinMap_I2C_SCL);
/*
* Default configuration:
* - MS : Master mode
* - NEA : Normal (7-bit) addressing
* - ACKEN : Send ACKs when reading from slave
* - CLR_FIFO : Not a configuration bit => clears the FIFO
*/
uint32_t reg = I2C_CTRL_MS | \
I2C_CTRL_NEA | \
I2C_CTRL_ACKEN | \
I2C_CTRL_CLR_FIFO;
obj->i2c->CONTROL = reg;
get_i2c_private(obj)->transfer_state = I2C_TRANSFER_SINGLE;
i2c_frequency(obj, 100000); /* Default to 100kHz SCL frequency */
}
int i2c_start(i2c_t *obj) {
return 0;
}
int i2c_stop(i2c_t *obj) {
/* Clear the hardware FIFO */
obj->i2c->CONTROL |= I2C_CTRL_CLR_FIFO;
/* Clear the HOLD bit used for performing combined transfers */
obj->i2c->CONTROL &= ~I2C_CTRL_HOLD;
/* Reset the transfer size (read and write) */
obj->i2c->TRANSFER_SIZE = 0;
/* Clear interrupts */
clear_isr(obj);
return 0;
}
void i2c_frequency(i2c_t *obj, int hz) {
/*
* Divider is split in two halfs : A and B
* A is 2 bits wide and B is 6 bits wide
* The Fscl frequency (SCL clock) is calculated with the following
* equation:
* Fscl=SystemCoreClock/(22*(A+1)*(B+1))
* Here, we only calculate the B divisor which already enables a
* wide enough range of values
*/
uint32_t divisor_a = 0; /* Could be changed if a wider range of hz
is needed */
uint32_t divisor_b = (SystemCoreClock / (22.0 * hz)) - 1;
/* Clamp the divisors to their maximal value */
divisor_a = divisor_a > I2C_CTRL_DIVISOR_A_BIT_MASK ?
I2C_CTRL_DIVISOR_A_BIT_MASK : divisor_a;
divisor_b = divisor_b > I2C_CTRL_DIVISOR_B_BIT_MASK ?
I2C_CTRL_DIVISOR_B_BIT_MASK : divisor_b;
uint8_t divisor_combinded = (divisor_a & I2C_CTRL_DIVISOR_A_BIT_MASK)
| (divisor_b & I2C_CTRL_DIVISOR_B_BIT_MASK);
obj->i2c->CONTROL = (obj->i2c->CONTROL & ~I2C_CTRL_DIVISORS)
| (divisor_combinded << I2C_CTRL_DIVISOR_OFFSET);
}
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
int bytes_read = 0;
int length_backup = length;
char *data_backup = data;
obj->last_xfer_address = address;
i2c_transfer_state_t transfer_state = update_transfer_state(obj, stop);
/* Try to write until it finally succeed or times out */
int main_timeout = 10;
int retry = 0;
do {
main_timeout--;
retry = 0;
bytes_read = 0;
length = length_backup;
data = data_backup;
uint32_t reg = obj->i2c->CONTROL & 0xff7f;
reg |= I2C_CTRL_RW | \
I2C_CTRL_CLR_FIFO;
/*
* Only touch the HOLD bit at the beginning of
* (possibly combined) transactions
*/
if(transfer_state == I2C_TRANSFER_COMBINED_FIRST_MESSAGE
|| transfer_state == I2C_TRANSFER_SINGLE) {
reg |= I2C_CTRL_HOLD;
}
obj->i2c->CONTROL = reg;
/* Set the expected number of bytes to be received */
if (length > I2C_TRANSFER_SIZE) {
error("I2C transfer size too big for the FIFO");
}
obj->i2c->TRANSFER_SIZE = length & I2C_TRANSFER_SIZE;
clear_isr(obj);
/*
* Start the transaction by writing address.
* Discard the lower bit as it is automatically set
* by the controller based on I2C_CTRL_RW bit in CONTROL
* register
*/
obj->i2c->ADDRESS = (address & 0xFF) >> 1;
if(transfer_state == I2C_TRANSFER_COMBINED_LAST_MESSAGE
|| transfer_state == I2C_TRANSFER_SINGLE) {
/* Clear the hold bit before reading the DATA register */
obj->i2c->CONTROL &= ~I2C_CTRL_HOLD;
}
/* Wait for completion of the address transfer */
int completion_timeout = 1000;
while (completion_timeout) {
completion_timeout--;
uint32_t irq_status = obj->i2c->IRQ_STATUS;
if (irq_status & I2C_IRQ_NACK
|| irq_status & I2C_IRQ_ARB_LOST) {
retry = 1;
break;
}
if(irq_status & I2C_IRQ_COMP) {
break;
}
}
/* If retry, jump to the beginning and try again */
if (retry || !completion_timeout) {
retry = 1;
continue;
}
clear_isr(obj);
/* Read the data from the DATA register */
completion_timeout = 1000;
while (length && completion_timeout) {
completion_timeout--;
uint32_t irq_status = obj->i2c->IRQ_STATUS;
uint32_t status = obj->i2c->STATUS;
if(irq_status & I2C_IRQ_NACK ||
irq_status & I2C_IRQ_ARB_LOST) {
retry = 1;
break;
}
/*
* Just wait for RXDV because COMP is only risen at the end
* of the transfer
*/
if (status & I2C_STATUS_RXDV) {
*data++ = obj->i2c->DATA & 0xFF;
length--;
bytes_read++;
}
if (irq_status & I2C_IRQ_RX_UNF) {
error("Reading more bytes than the I2C transfer size");
retry = 1;
break;
}
}
/* If retry, jump to the beginning and try again */
if (retry || !completion_timeout) {
retry = 1;
continue;
}
} while(retry && main_timeout);
if (!main_timeout) {
bytes_read = 0;
data = data_backup;
}
obj->i2c->CONTROL |= I2C_CTRL_CLR_FIFO;
clear_isr(obj);
return bytes_read;
}
int i2c_write(i2c_t *obj, int address, const char *data, int length,
int stop) {
int bytes_written = 0;
int length_backup = length;
const char *data_backup = data;
obj->last_xfer_address = address;
i2c_transfer_state_t transfer_state = update_transfer_state(obj, stop);
/* Try to write until it finally succeed or times out */
int main_timeout = 10;
int retry = 0;
do {
main_timeout--;
retry = 0;
bytes_written = 0;
length = length_backup;
data = data_backup;
/* Read the defined bits in the control register */
uint32_t reg = obj->i2c->CONTROL & 0xff7f;
reg |= I2C_CTRL_CLR_FIFO;
reg &= ~I2C_CTRL_RW;
/*
* Only touch the HOLD bit at the beginning of
* (possibly combined) transactions
*/
if(transfer_state == I2C_TRANSFER_COMBINED_FIRST_MESSAGE
|| transfer_state == I2C_TRANSFER_SINGLE) {
reg |= I2C_CTRL_HOLD;
}
obj->i2c->CONTROL = reg;
clear_isr(obj);
/* Set the expected number of bytes to be transmitted */
if (length > I2C_TRANSFER_SIZE) {
error("I2C transfer size too big for the FIFO");
}
/* Set the expected number of bytes to be transmitted */
obj->i2c->TRANSFER_SIZE = length & I2C_TRANSFER_SIZE;
/*
* Write the address, triggering the start of the transfer
* Discard the lower bit as it is automatically set
* by the controller based on I2C_CTRL_RW bit in CONTROL
* register
*/
obj->i2c->ADDRESS = (address & 0xFF) >> 1;
/* Send the data bytes */
int write_timeout = 1000 + length;
while (length && write_timeout) {
write_timeout--;
uint32_t irq_status = obj->i2c->IRQ_STATUS;
/* If overflow, undo last step */
if (irq_status & I2C_IRQ_TX_OVF) {
*data--;
length++;
bytes_written--;
/* Clear the bit by writing 1 to it */
obj->i2c->IRQ_STATUS |= I2C_IRQ_TX_OVF;
}
if (irq_status & I2C_IRQ_NACK
|| irq_status & I2C_IRQ_ARB_LOST) {
retry = 1;
break;
}
obj->i2c->DATA = *data++;
length--;
bytes_written++;
}
/* If retry, jump to the beginning and try again */
if (retry || !write_timeout) {
retry = 1;
continue;
}
if(transfer_state == I2C_TRANSFER_COMBINED_LAST_MESSAGE
|| transfer_state == I2C_TRANSFER_SINGLE) {
/*
* Clear the hold bit to signify the end
* of the write sequence
*/
obj->i2c->CONTROL &= ~I2C_CTRL_HOLD;
}
/* Wait for transfer completion */
int completion_timeout = 1000;
while (completion_timeout) {
completion_timeout--;
uint32_t irq_status = obj->i2c->IRQ_STATUS;
if(irq_status & I2C_IRQ_NACK
|| irq_status & I2C_IRQ_ARB_LOST) {
retry = 1;
break;
}
if(irq_status & I2C_IRQ_COMP) {
break;
}
}
/* If retry, jump to the beginning and try again */
if (retry || !completion_timeout) {
continue;
}
obj->i2c->CONTROL |= I2C_CTRL_CLR_FIFO;
clear_isr(obj);
} while(retry && main_timeout);
return bytes_written;
}
void i2c_reset(i2c_t *obj) {
i2c_stop(obj);
}
int i2c_byte_read(i2c_t *obj, int last) {
char i2c_ret = 0;
i2c_read(obj, obj->last_xfer_address, &i2c_ret, 1, last);
return i2c_ret;
}
int i2c_byte_write(i2c_t *obj, int data) {
/* Store the number of written bytes */
uint32_t wb = i2c_write(obj, obj->last_xfer_address, (char*)&data, 1, 0);
if (wb == 1)
return 1;
else
return 0;
}
void i2c_slave_mode(i2c_t *obj, int enable_slave) {
}
int i2c_slave_receive(i2c_t *obj) {
return 0;
}
int i2c_slave_read(i2c_t *obj, char *data, int length) {
return 0;
}
int i2c_slave_write(i2c_t *obj, const char *data, int length) {
return 0;
}
void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
}

View File

@ -0,0 +1,101 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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.
*/
/*
* I2C interface Support
* =====================
*/
#ifndef MBED_I2C_DEF_H
#define MBED_I2C_DEF_H
#include <stdint.h> /* standard types definitions */
typedef struct beetle_i2c
{
__IO uint32_t CONTROL; /* RW Control register */
__I uint32_t STATUS; /* RO Status register */
__IO uint32_t ADDRESS; /* RW I2C address register */
__IO uint32_t DATA; /* RW I2C data register */
__IO uint32_t IRQ_STATUS; /* RO Interrupt status register ( read only but write to clear bits) */
__IO uint32_t TRANSFER_SIZE; /* RW Transfer size register */
__IO uint32_t SLAVE_MONITOR; /* RW Slave monitor pause register */
__IO uint32_t TIMEOUT; /* RW Time out register */
__I uint32_t IRQ_MASK; /* RO Interrupt mask register */
__O uint32_t IRQ_ENABLE; /* WO Interrupt enable register */
__O uint32_t IRQ_DISABLE; /* WO Interrupt disable register */
}I2C_TypeDef;
#define I2C0_BASE (0x40007000ul) /* Shield Header I2C Base Address */
#define I2C1_BASE (0x4000E000ul) /* Onboard I2C Base Address */
#define SHIELD_I2C ((I2C_TypeDef *) I2C0_BASE )
#define BOARD_I2C ((I2C_TypeDef *) I2C1_BASE )
/* Control Register Masks */
#define I2C_CTRL_RW 0x0001 /* Transfer direction */
#define I2C_CTRL_MS 0x0002 /* Mode (master / slave) */
#define I2C_CTRL_NEA 0x0004 /* Addressing mode */
#define I2C_CTRL_ACKEN 0x0008 /* ACK enable */
#define I2C_CTRL_HOLD 0x0010 /* Clock hold enable */
#define I2C_SLVMON 0x0020 /* Slave monitor mode */
#define I2C_CTRL_CLR_FIFO 0x0040 /* Force clear of FIFO */
#define I2C_CTRL_DIVISOR_B 0x3F00 /* Stage B clock divider */
#define I2C_CTRL_DIVISOR_A 0xA000 /* Stage A clock divider */
#define I2C_CTRL_DIVISORS 0xFF00 /* Combined A and B fields */
#define I2C_CTRL_DIVISOR_OFFSET 8 /* Offset of the clock divisor in
* the CONTROL register
*/
#define I2C_CTRL_DIVISOR_A_BIT_MASK 0x03
/*
* First part of the clock
* divisor in the CONTROL register
*/
#define I2C_CTRL_DIVISOR_B_BIT_MASK 0x3F
/*
* Second part of the clock
* divisor in the CONTROL register
*/
/* Status Register Masks */
#define I2C_STATUS_RXRW 0x0008 /* Mode of transmission from master */
#define I2C_STATUS_RXDV 0x0020 /* Valid data waiting to be read */
#define I2C_STATUS_TXDV 0x0040 /* Still a data byte to be sent */
#define I2C_STATUS_RXOVF 0x0080 /* Receiver overflow */
#define I2C_STATUS_BA 0x0100 /* Bus active */
/* Address Register Masks */
#define I2C_ADDRESS_7BIT 0x007F
/* Interrupt Status / Enable / Disable Register Masks */
#define I2C_IRQ_COMP 0x0001 /* Transfer complete */
#define I2C_IRQ_DATA 0x0002 /* More data */
#define I2C_IRQ_NACK 0x0004 /* Transfer not acknowledged */
#define I2C_IRQ_TO 0x0008 /* Transfer timed out */
#define I2C_IRQ_SLV_RDY 0x0010 /* Monitored slave ready */
#define I2C_IRQ_RX_OVF 0x0020 /* Receive overflow */
#define I2C_IRQ_TX_OVF 0x0040 /* Transmit overflow */
#define I2C_IRQ_RX_UNF 0x0080 /* Receive underflow */
#define I2C_IRQ_ARB_LOST 0x0200 /* Arbitration lost */
/* Transfer Size Register Masks */
#define I2C_TRANSFER_SIZE 0xFF
/* Error codes */
#define E_SUCCESS 0x0
#define E_INCOMPLETE_DATA 0x1
#endif

View File

@ -0,0 +1,135 @@
/*
* PackageLicenseDeclared: Apache-2.0
* Copyright (c) 2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cmsis.h"
#include "device.h"
#include "objects.h"
#include "lp_ticker_api.h"
/* Private lp_ticker data */
/* lp_ticker initialize */
static uint32_t lp_ticker_initialized = 0;
/* lp_ticker reload value */
static uint32_t lp_ticker_reload = 0x0; /* Max Value */
/* Store Overflow Count */
static uint32_t lp_ticker_overflows_count = 0;
#if DEVICE_LOWPOWERTIMER
/**
* Interrupt Handler
*/
void __lp_ticker_irq_handler(void)
{
if (DualTimer_GetIRQInfo(DUALTIMER0) == SINGLETIMER2) {
DualTimer_ClearInterrupt(DUALTIMER0);
lp_ticker_overflows_count++;
} else {
lp_ticker_irq_handler();
}
}
/**
* Initialize the low power ticker
*/
void lp_ticker_init(void)
{
uint32_t lp_ticker_irqn = 0;
/* Verify if lp_ticker has been already Initialized */
if (lp_ticker_initialized == 1)
{
return;
}
lp_ticker_initialized = 1;
/* Dualtimer Initialize */
DualTimer_Initialize(DUALTIMER0, lp_ticker_reload);
/* Dualtimer Enable */
DualTimer_Enable(DUALTIMER0, DUALTIMER_COUNT_32
//| DUALTIMER_PERIODIC
);
/* DualTimer get IRQn */
lp_ticker_irqn = DualTimer_GetIRQn(DUALTIMER0);
/* Enable lp_ticker IRQ */
NVIC_SetVector((IRQn_Type)lp_ticker_irqn,
(uint32_t)__lp_ticker_irq_handler);
NVIC_EnableIRQ((IRQn_Type)lp_ticker_irqn);
}
/**
* Read the current counter
* @return: The current timer's counter value in microseconds
*/
uint32_t lp_ticker_read(void)
{
uint32_t microseconds = 0;
/* Verify if lp_ticker has not been Initialized */
if (lp_ticker_initialized == 0)
lp_ticker_init();
/* Read Timer Value */
microseconds = DualTimer_Read_2(DUALTIMER0);
return microseconds;
}
/**
* Set interrupt for specified timestamp
* timestamp: The time in microseconds to be set
*/
void lp_ticker_set_interrupt(timestamp_t timestamp)
{
int32_t delta = 0;
/* Verify if lp_ticker has been not Initialized */
if (lp_ticker_initialized == 0)
lp_ticker_init();
/* Calculate the delta */
delta = (int32_t)(timestamp - lp_ticker_read());
/* Check if the event was in the past */
if (delta <= 0) {
/* This event was in the past */
DualTimer_SetInterrupt_1(DUALTIMER0, 0,
DUALTIMER_COUNT_32 | DUALTIMER_ONESHOT);
return;
}
/* Enable interrupt on SingleTimer1 */
DualTimer_SetInterrupt_1(DUALTIMER0, delta,
DUALTIMER_COUNT_32 | DUALTIMER_ONESHOT);
}
/**
* Disable low power ticker interrupt
*/
void lp_ticker_disable_interrupt(void)
{
/* Disable Interrupt */
DualTimer_DisableInterrupt(DUALTIMER0);
}
/**
* Clear the low power ticker interrupt
*/
void lp_ticker_clear_interrupt(void)
{
/* Clear Interrupt */
DualTimer_ClearInterrupt(DUALTIMER0);
}
#endif

View File

@ -0,0 +1,29 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cmsis.h"
void mbed_sdk_init(void) {
/* Beetle System Power Config */
SystemPowerConfig();
/* Config EFlash Controller Clock */
EFlash_Initialize();
/* Initialize Flash Cache */
FCache_Initialize();
FCache_Enable(1);
FCache_Invalidate();
}

View File

@ -0,0 +1,70 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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"
#include "i2c_def.h"
#include "spi_def.h"
#ifdef __cplusplus
extern "C" {
#endif
struct gpio_irq_s {
uint32_t ch;
};
struct port_s {
__IO uint32_t *reg_dir;
__IO uint32_t *reg_dirclr;
__IO uint32_t *reg_out;
__IO uint32_t *reg_in;
PortName port;
uint32_t mask;
};
struct serial_s {
CMSDK_UART_TypeDef *uart;
int index;
};
struct i2c_s {
I2C_TypeDef *i2c;
uint16_t last_xfer_address;
};
struct spi_s {
SPI_TypeDef *spi;
};
struct analogin_s {
ADCName adc;
PinName pin;
uint32_t pin_number;
__IO uint32_t address;
};
#include "gpio_object.h"
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,27 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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) {
MBED_ASSERT(pin != (PinName)NC);
}
void pin_mode(PinName pin, PinMode mode) {
MBED_ASSERT(pin != (PinName)NC);
}

View File

@ -0,0 +1,70 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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 "port_api.h"
#include "pinmap.h"
#include "gpio_api.h"
PinName port_pin(PortName port, int pin_n) {
return (PinName)((port << PORT_SHIFT) | pin_n);
}
void port_init(port_t *obj, PortName port, int mask, PinDirection dir) {
obj->port = port;
obj->mask = mask;
CMSDK_GPIO_TypeDef *port_reg =
(CMSDK_GPIO_TypeDef *)(CMSDK_GPIO0_BASE + ((int)port * 0x10));
obj->reg_in = &port_reg->DATAOUT;
obj->reg_dir = &port_reg->OUTENABLESET;
obj->reg_dirclr = &port_reg->OUTENABLECLR;
uint32_t i;
// The function is set per pin: reuse gpio logic
for (i=0; i<16; i++) {
if (obj->mask & (1<<i)) {
gpio_set(port_pin(obj->port, i));
}
}
port_dir(obj, dir);
}
void port_mode(port_t *obj, PinMode mode) {
uint32_t i;
// The mode is set per pin: reuse pinmap logic
for (i=0; i<32; i++) {
if (obj->mask & (1<<i)) {
pin_mode(port_pin(obj->port, i), mode);
}
}
}
void port_dir(port_t *obj, PinDirection dir) {
switch (dir) {
case PIN_INPUT : *obj->reg_dir &= ~obj->mask; break;
case PIN_OUTPUT: *obj->reg_dir |= obj->mask; break;
}
}
void port_write(port_t *obj, int value) {
*obj->reg_in = value;
}
int port_read(port_t *obj) {
return (*obj->reg_in);
}

View File

@ -0,0 +1,330 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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 <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "serial_api.h"
#include "cmsis.h"
#include "pinmap.h"
#include "PinNames.h"
#include "mbed_error.h"
#include "gpio_api.h"
/******************************************************************************
* INITIALIZATION
******************************************************************************/
static const PinMap PinMap_UART_TX[] = {
{UART_TX0, UART_0, 0},
{UART_TX1, UART_1, 0},
{NC, NC, 0}
};
static const PinMap PinMap_UART_RX[] = {
{UART_RX0, UART_0, 0},
{UART_RX1, UART_1, 0},
{NC, NC, 0}
};
#define UART_NUM 2
static uart_irq_handler irq_handler;
int stdio_uart_inited = 0;
serial_t stdio_uart;
struct serial_global_data_s {
uint32_t serial_irq_id;
gpio_t sw_rts, sw_cts;
uint8_t count, rx_irq_set_flow, rx_irq_set_api;
};
static struct serial_global_data_s uart_data[UART_NUM];
void serial_init(serial_t *obj, PinName tx, PinName rx) {
int is_stdio_uart = 0;
// determine the UART to use
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);
UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);
if ((int)uart == NC) {
error("Serial pinout mapping failed");
}
obj->uart = (CMSDK_UART_TypeDef *)uart;
//set baud rate and enable Uart in normarl mode (RX and TX enabled)
switch (uart) {
case UART_0:
{
CMSDK_UART0->CTRL = 0; // Disable UART when changing configuration
if ((int)tx != NC) {
CMSDK_UART0->CTRL = 0x1; // TX enable
}
if ((int)rx != NC) {
CMSDK_UART0->CTRL |= 0x2; // RX enable
}
}
break;
case UART_1:
{
CMSDK_UART1->CTRL = 0; // Disable UART when changing configuration
if((int)tx != NC) {
CMSDK_UART1->CTRL = 0x1; // TX enable
}
if((int)rx != NC) {
CMSDK_UART1->CTRL |= 0x2; // RX enable
}
}
break;
}
// set default baud rate and format
serial_baud(obj, 9600);
// pinout the chosen uart
pinmap_pinout(tx, PinMap_UART_TX);
pinmap_pinout(rx, PinMap_UART_RX);
switch (uart) {
case UART_0:
obj->index = 0;
break;
case UART_1:
obj->index = 1;
break;
}
uart_data[obj->index].sw_rts.pin = NC;
uart_data[obj->index].sw_cts.pin = NC;
serial_set_flow_control(obj, FlowControlNone, NC, NC);
is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
if (is_stdio_uart) {
stdio_uart_inited = 1;
memcpy(&stdio_uart, obj, sizeof(serial_t));
}
}
void serial_free(serial_t *obj) {
uart_data[obj->index].serial_irq_id = 0;
}
// serial_baud
// set the baud rate, taking in to account the current SystemFrequency
void serial_baud(serial_t *obj, int baudrate) {
// BEETLE has a simple divider to control the baud rate. The formula is:
//
// Baudrate = PCLK / BAUDDIV
//
// PCLK = SystemCoreClock
// so for a desired baud rate of 9600
// SystemCoreClock / 9600
//
//check to see if minimum baud value entered
int baudrate_div = 0;
baudrate_div = SystemCoreClock / baudrate;
if (baudrate >= 16) {
switch ((int)obj->uart) {
case UART_0:
CMSDK_UART0->BAUDDIV = baudrate_div;
break;
case UART_1:
CMSDK_UART1->BAUDDIV = baudrate_div;
break;
default:
error("serial_baud");
break;
}
} else {
error("serial_baud");
}
}
void serial_format(serial_t *obj, int data_bits,
SerialParity parity, int stop_bits) {
}
/******************************************************************************
* INTERRUPTS HANDLING
******************************************************************************/
static inline void uart_irq(uint32_t intstatus, uint32_t index,
CMSDK_UART_TypeDef *puart) {
SerialIrq irq_type;
switch (intstatus) {
case 1:
{
irq_type = TxIrq;
}
break;
case 2:
{
irq_type = RxIrq;
}
break;
default: return;
} /* End of Switch */
if ((irq_type == RxIrq) && (NC != uart_data[index].sw_rts.pin)) {
gpio_write(&uart_data[index].sw_rts, 1);
// Disable interrupt if it wasn't enabled by other part of the application
if (!uart_data[index].rx_irq_set_api) {
// puart->CTRL &= ~(1 << RxIrq);
/* Disable Rx interrupt */
puart->CTRL &= ~(CMSDK_UART_CTRL_RXIRQEN_Msk);
}
}
if (uart_data[index].serial_irq_id != 0) {
if ((irq_type != RxIrq) || (uart_data[index].rx_irq_set_api)) {
irq_handler(uart_data[index].serial_irq_id, irq_type);
}
}
if( irq_type == TxIrq ) {
/* Clear the TX interrupt Flag */
puart->INTCLEAR |= 0x01;
} else {
/* Clear the Rx interupt Flag */
puart->INTCLEAR |= 0x02;
}
}
void uart0_irq() {
uart_irq(CMSDK_UART0->INTSTATUS & 0x3, 0,
(CMSDK_UART_TypeDef*)CMSDK_UART0);
}
void uart1_irq() {
uart_irq(CMSDK_UART1->INTSTATUS & 0x3, 1,
(CMSDK_UART_TypeDef*)CMSDK_UART1);
}
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
irq_handler = handler;
uart_data[obj->index].serial_irq_id = id;
}
static void serial_irq_set_internal(serial_t *obj, SerialIrq irq, uint32_t enable) {
/* Declare a variable of type IRQn, initialise to 0 */
IRQn_Type irq_n = (IRQn_Type)0;
uint32_t vector = 0;
switch ((int)obj->uart) {
/*********************************************************************
* BEETLE SOC BOARD *
*********************************************************************/
case UART_0:
{
irq_n = UART0_IRQn;
vector = (uint32_t)&uart0_irq;
}
break;
case UART_1:
{
irq_n = UART1_IRQn;
vector = (uint32_t)&uart1_irq;
}
break;
}
if (enable) {
if(irq == TxIrq) {
/* Transmit IRQ, set appripriate enable */
/* set TX interrupt enable in CTRL REG */
obj->uart->CTRL |= CMSDK_UART_CTRL_TXIRQEN_Msk;
} else {
/* set Rx interrupt on in CTRL REG */
obj->uart->CTRL |= CMSDK_UART_CTRL_RXIRQEN_Msk;
}
NVIC_SetVector(irq_n, vector);
NVIC_EnableIRQ(irq_n);
} else if ((irq == TxIrq) || (uart_data[obj->index].rx_irq_set_api
+ uart_data[obj->index].rx_irq_set_flow == 0)) {
/* Disable IRQ */
int all_disabled = 0;
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
obj->uart->CTRL &= ~(1 << (irq + 2));
all_disabled = (obj->uart->CTRL & (1 << (other_irq + 2))) == 0;
if (all_disabled) {
NVIC_DisableIRQ(irq_n);
}
}
}
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
if (RxIrq == irq)
uart_data[obj->index].rx_irq_set_api = enable;
serial_irq_set_internal(obj, irq, enable);
}
/******************************************************************************
* READ/WRITE
******************************************************************************/
int serial_getc(serial_t *obj) {
while (serial_readable(obj) == 0);
int data = obj->uart->DATA;
return data;
}
void serial_putc(serial_t *obj, int c) {
#ifdef SERIAL_TEST
// Add CR to LF
if (c == 0x0A) {
while (serial_writable(obj));
obj->uart->DATA = 0x0D;
}
#endif
while (serial_writable(obj));
obj->uart->DATA = c;
}
int serial_readable(serial_t *obj) {
return obj->uart->STATE & 2;
}
int serial_writable(serial_t *obj) {
return obj->uart->STATE & 1;
}
void serial_clear(serial_t *obj) {
obj->uart->DATA = 0x00;
}
void serial_pinout_tx(PinName tx) {
pinmap_pinout(tx, PinMap_UART_TX);
}
void serial_break_set(serial_t *obj) {
}
void serial_break_clear(serial_t *obj) {
}
void serial_set_flow_control(serial_t *obj, FlowControl type,
PinName rxflow, PinName txflow) {
}

View File

@ -0,0 +1,271 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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 <math.h>
#include "spi_api.h"
#include "spi_def.h"
#include "cmsis.h"
#include "pinmap.h"
#include "mbed_error.h"
#include "wait_api.h"
/*
* Driver private data structure that should not be shared by multiple
* instances of the driver (same driver for multiple instances of the IP)
*/
typedef struct {
uint32_t size; /* size of an SPI frame in bits: can be 8 or 16 */
} private_spi_t;
static const PinMap PinMap_SPI_SCLK[] = {
{SHIELD_SPI_SCK , SPI_0, 0},
{ADC_SPI_SCK , SPI_1, 0},
{NC, NC, 0}
};
static const PinMap PinMap_SPI_MOSI[] = {
{SHIELD_SPI_MOSI, SPI_0, 0},
{ADC_SPI_MOSI, SPI_1, 0},
{NC, NC, 0}
};
static const PinMap PinMap_SPI_MISO[] = {
{SHIELD_SPI_MISO, SPI_0, 0},
{ADC_SPI_MISO, SPI_1, 0},
{NC, NC, 0}
};
static const PinMap PinMap_SPI_SSEL[] = {
{SHIELD_SPI_nCS, SPI_0, 0},
{ADC_SPI_nCS, SPI_1, 0},
{NC, NC, 0}
};
/*
* Retrieve the private data of the instance related to a given IP
*/
static private_spi_t* get_spi_private(spi_t *obj) {
static private_spi_t data0, data1;
/*
* Select which instance to give using the base
* address of registers
*/
switch ((intptr_t)obj->spi) {
case SPI0_BASE:
return &data0;
case SPI1_BASE:
return &data1;
default:
error("SPI driver private data structure not found for this registers base address");
return (void*)0;
}
}
void spi_init(spi_t *obj, PinName mosi,
PinName miso, PinName sclk, PinName ssel) {
// determine the SPI to use
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
obj->spi = (SPI_TypeDef*)pinmap_merge(spi_data, spi_cntl);
if ((int)obj->spi == NC) {
error("SPI pinout mapping failed");
}
/* Set default format and frequency */
if (ssel == NC) {
spi_format(obj, 8, 0, 0); // 8 bits, mode SPI_MSB, master
} else {
spi_format(obj, 8, 0, 1); // 8 bits, mode SPI_LSB, slave
}
spi_frequency(obj, 1562500);
/* Pin out the spi pins */
pinmap_pinout(mosi, PinMap_SPI_MOSI);
pinmap_pinout(miso, PinMap_SPI_MISO);
pinmap_pinout(sclk, PinMap_SPI_SCLK);
if (ssel != NC) {
pinmap_pinout(ssel, PinMap_SPI_SSEL);
}
/*
* Set desired enabled IRQs:
* MF: Mode Fail
* TF: TX FIFO Full
* TNF: TX FIFO Not Full
* RNE: RX FIFO Not Empty
*/
uint32_t irqs = (IRQ_ENABLE_MFE | IRQ_ENABLE_TFE
| IRQ_ENABLE_TNFE | IRQ_ENABLE_RNEE);
/*
* Enable:
* - Master mode
* - Manual start mode
* - Manual chip select
* - Peripheral select decode
*/
obj->spi->CONFIG |= (CONFIG_MSEL | CONFIG_MSE
/*| CONFIG_MCSE | CONFIG_PSD*/);
/* Set all peripheral select lines high - these should be unused */
obj->spi->CONFIG |= 0x00000; //CONFIG_PCSL;
obj->spi->IRQ_ENABLE = irqs;
obj->spi->IRQ_DISABLE = ~irqs;
obj->spi->SPI_ENABLE |= SPI_ENABLE_SPIE;
}
void spi_free(spi_t *obj) {
}
void spi_format(spi_t *obj, int bits, int mode, int slave) {
private_spi_t *private_spi = get_spi_private(obj);
obj->spi->SPI_ENABLE &= ~SPI_ENABLE_SPIE;
/*
* The mbed API specifies 'bits' as being 4-16 per frame. This
* controller supports only 8 or 16 bit frames. Therefore we will
* assume 8 bits and, if anything larger is specified, we will use
* 16 bits.
*/
obj->spi->CONFIG &= ~CONFIG_TWS; /* 00 = 8 bit frame */
private_spi->size = 8;
if (bits > 8) {
switch (bits) {
case 16:
private_spi->size = 16;
break;
default:
obj->spi->CONFIG |= CONFIG_TWS_1; /* 01 = 16 bit frame */
break;
}
}
switch (mode) {
default:
case 0:
obj->spi->CONFIG &= ~CONFIG_CPOL;
obj->spi->CONFIG &= ~CONFIG_CPHA;
break;
case 1:
obj->spi->CONFIG &= ~CONFIG_CPOL;
obj->spi->CONFIG |= CONFIG_CPHA;
break;
case 2:
obj->spi->CONFIG |= CONFIG_CPOL;
obj->spi->CONFIG &= ~CONFIG_CPHA;
break;
case 3:
obj->spi->CONFIG |= CONFIG_CPOL;
obj->spi->CONFIG |= CONFIG_CPHA;
break;
}
obj->spi->SPI_ENABLE |= SPI_ENABLE_SPIE;
}
void spi_frequency(spi_t *obj, int hz) {
/*
* Valid frequencies are derived from a 25MHz peripheral clock.
* Frequency | Divisor | MBRD Value | Hz
* 12.0 MHz 2 000 12000000
* 6.0 MHz 4 001 6000000
* 3.0 MHz 8 010 3000000
* 1.5 MHz 16 011 1500000
* 750.0 KHz 32 100 750000
* 375.0 KHz 64 101 375000
* 187.500 KHz 128 110 187500
* 93.750 KHz 256 111 93750
*/
int valid_frequencies[] = {12000000, 6000000, 3000000, 1500000,
750000, 375000, 187500, 93750};
uint16_t mbrd_value = 0;
uint32_t config = (obj->spi->CONFIG & ~CONFIG_MBRD);
/* Store the index of the minimum supported frequency */
uint32_t index = 7;
for (int i = 0; i < 8; i++) {
if (hz >= valid_frequencies[i]) {
/*
* Store the index of the closest lower or equal supported
* frequency.
*/
index = i;
break;
}
mbrd_value++;
}
/*
* Set the selected frequency. If the frequency is below the minimum
* supported the driver sets the minumum.
*/
config |= index << CONFIG_MBRD_SHIFT;
/*
* If the specified frequency didn't match any of the valid frequencies
* then leave CONFIG_MBRD to the closest lower frequency supported.
*/
obj->spi->CONFIG = config;
}
int spi_master_write(spi_t *obj, int value) {
private_spi_t *private_spi = get_spi_private(obj);
int data = 0;
if(private_spi->size == 16) {
obj->spi->TX_DATA = (uint8_t)((value >> 8) & TX_DATA_TDATA);
obj->spi->TX_DATA = (uint8_t)(value & TX_DATA_TDATA);
/* Manually trigger start */
obj->spi->CONFIG |= CONFIG_MSC;
while(!(obj->spi->IRQ_STATUS & IRQ_STATUS_TNF))
continue;
data = (obj->spi->RX_DATA & RX_DATA_RDATA) << 8;
data = data | (obj->spi->RX_DATA & RX_DATA_RDATA);
} else {
obj->spi->TX_DATA = (uint16_t)(value & TX_DATA_TDATA);
/* Manually trigger start */
obj->spi->CONFIG |= CONFIG_MSC;
while(!(obj->spi->IRQ_STATUS & IRQ_STATUS_TNF))
continue;
data = obj->spi->RX_DATA & RX_DATA_RDATA;
}
return data;
}
uint8_t spi_get_module(spi_t *obj) {
return obj->spi->MID;
}
int spi_busy(spi_t *obj) {
return 0;
}

View File

@ -0,0 +1,134 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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.
*/
/*
* SSP interface Support
* =====================
*/
#ifndef MBED_SPI_DEF_H
#define MBED_SPI_DEF_H
#include <stdint.h> /* standard types definitions */
#define Module_ID 0x00090108
typedef struct beetle_spi
{
__IO uint32_t CONFIG; /* 0x00 RW Configuration Register */
__I uint32_t IRQ_STATUS; /* 0x04 RO Interrupt Status Register*/
__O uint32_t IRQ_ENABLE; /* 0x08 WO Interrupt Enable Register*/
__O uint32_t IRQ_DISABLE; /* 0x0C WO Interrupt Disable Register */
__I uint32_t IRQ_MASK; /* 0x10 RO Interrupt Mask Register */
__IO uint32_t SPI_ENABLE; /* 0x14 RW SPI Enable Register */
__IO uint32_t DELAY; /* 0x18 RW Delay Register */
__O uint32_t TX_DATA; /* 0x1C WO Transmit Data Register */
__I uint32_t RX_DATA; /* 0x20 RO Receive Data Register */
__IO uint32_t SLAVE_IDLE_COUNT; /* 0x24 RW Slave Idle Count Register */
__IO uint32_t TX_THRESHOLD; /* 0x28 RW TX Threshold Register */
__IO uint32_t RX_THRESHOLD; /* 0x2C RW RX Threshold Register */
uint32_t reserved[208];
__I uint32_t MID; /* 0xFC RO Module ID Register */
}SPI_TypeDef;
#define SPI0_BASE (0x4000C000ul) /* Shield Header SPI Base Address */
#define SPI1_BASE (0x4000D000ul) /* ADC SPI Base Address */
#define SHIELD_SPI ((SPI_TypeDef *) SPI0_BASE )
#define ADC_SPI ((SPI_TypeDef *) SPI1_BASE )
/* Configuration Register Bit Masks */
#define CONFIG_MSEL 0x00001 // Bit [00] MSEL Mode Select
#define CONFIG_CPOL 0x00002 // Bit [01] CPOL External Clock Edge
#define CONFIG_CPHA 0x00004 // Bit [02] CPHA Clock Phase
#define CONFIG_MBRD 0x00038 // Bits [05:03] MBRD Master Baud Rate Divisor (2 to 256)
#define CONFIG_MBRD_0 0x00008
#define CONFIG_MBRD_1 0x00010
#define CONFIG_MBRD_2 0x00020
#define CONFIG_MBRD_SHIFT 3
#define CONFIG_TWS 0x000C0 // Bits [07:06] TWS Transfer Word Size
#define CONFIG_TWS_0 0x00000
#define CONFIG_TWS_1 0x00040
#define CONFIG_MRCS 0x00100 // Bit [08] MRCS Reference Clock Select
#define CONFIG_PSD 0x00200 // Bit [09] PSD Peripheral Select Decode
#define CONFIG_PCSL 0x03C00 // Bits [13:10] PCSL Peripheral Chip Select Lines (master mode only)
#define CONFIG_MCSE 0x04000 // Bit [14] MCSE Manual Chip Select Enable
#define CONFIG_MSE 0x08000 // Bit [15] MSE Manual Start Enable
#define CONFIG_MSC 0x10000 // Bit [16] MSC Manual Start Command
#define CONFIG_MFGE 0x20000 // Bit [17] MFGE Mode Fail Generation Enable
#define CONFIG_SPSE 0x40000 // Bit [18] SPSE Sample Point Shift Enable
/* Interrupt Status Register Bit Masks */
#define IRQ_STATUS_ROF 0x01 // Bit [00] ROF RX FIFO Overflow
#define IRQ_STATUS_MF 0x02 // Bit [01] MF Mode Fail
#define IRQ_STATUS_TNF 0x04 // Bit [02] TNF TX FIFO Not Full (current FIFO status)
#define IRQ_STATUS_TF 0x08 // Bit [03] TF TX FIFO Full (current FIFO status)
#define IRQ_STATUS_RNE 0x10 // Bit [04] RNE RX FIFO Not Empty (current FIFO status)
#define IRQ_STATUS_RF 0x20 // Bit [05] RF RX FIFO Full (current FIFO status)
#define IRQ_STATUS_TUF 0x40 // Bit [06] TUF TX FIFO Underflow
/* Interrupt Enable Register Bit Masks */
#define IRQ_ENABLE_ROFE 0x01 // Bit [00] ROFE RX FIFO Overflow Enable
#define IRQ_ENABLE_MFE 0x02 // Bit [01] MFE Mode Fail Enable
#define IRQ_ENABLE_TNFE 0x04 // Bit [02] TNFE TX FIFO Not Full Enable
#define IRQ_ENABLE_TFE 0x08 // Bit [03] TFE TX FIFO Full Enable
#define IRQ_ENABLE_RNEE 0x10 // Bit [04] RNEE RX FIFO Not Empty Enable
#define IRQ_ENABLE_RFE 0x20 // Bit [05] RFE RX FIFO Full Enable
#define IRQ_ENABLE_TUFE 0x40 // Bit [06] TUFE TX FIFO Underflow Enable
/* Interrupt Disable Register Bit Masks */
#define IRQ_DISABLE_ROFD 0x01 // Bit [00] ROFD RX FIFO Overflow Disable
#define IRQ_DISABLE_MFD 0x02 // Bit [01] MFD Mode Fail Disable
#define IRQ_DISABLE_TNFD 0x04 // Bit [02] TNFD TX FIFO Not Full Disable
#define IRQ_DISABLE_TFD 0x08 // Bit [03] TFD TX FIFO Full Disable
#define IRQ_DISABLE_RNED 0x10 // Bit [04] RNED RX FIFO Not Empty Disable
#define IRQ_DISABLE_RFD 0x20 // Bit [05] RFD RX FIFO Full Disable
#define IRQ_DISABLE_TUFD 0x40 // Bit [06] TUFD TX FIFO Underflow Disable
/* Interrupt Mask Register Bit Masks */
#define IRQ_MASK_ROFM 0x01 // Bit [00] ROFM RX FIFO Overflow Mask
#define IRQ_MASK_MFM 0x02 // Bit [01] MFM Mode Fail Mask
#define IRQ_MASK_TNFM 0x04 // Bit [02] TNFM TX FIFO Not Full Mask
#define IRQ_MASK_TFM 0x08 // Bit [03] TFM TX FIFO Full Mask
#define IRQ_MASK_RNEM 0x10 // Bit [04] RNEM RX FIFO Not Empty Mask
#define IRQ_MASK_RFM 0x20 // Bit [05] RFM RX FIFO Full Mask
#define IRQ_MASK_TUFM 0x40 // Bit [06] TUFM TX FIFO Underflow Mask
/* SPI Enable Register Bit Masks */
#define SPI_ENABLE_SPIE 0x01 // Bit [00] SPIE SPI Enable
/* Delay Register Bit Masks */
#define DELAY_D_INIT 0x000000FF // Bits [07:00] D_INIT Delay Init
#define DELAY_D_AFTER 0x0000FF00 // Bits [15:08] D_AFTER Delay After
#define DELAY_D_BTWN 0x00FF0000 // Bits [23:16] D_BTWN Delay Between
#define DELAY_D_NSS 0xFF000000 // Bits [31:24] D_NSS Delay NSS
/* Transmit Data Register Bit Masks */
#define TX_DATA_TDATA 0xFF
/* Receive Data Register Bit Masks */
#define RX_DATA_RDATA 0xFF
/* Slave Idle Count Register Bit Masks */
#define SLAVE_IDLE_COUNT_SICNT 0xFF // Bits [07:00] SICNT Slave Idle Count
/* TX Threshold Register Bit Masks */
#define TX_THRESHOLD_TTRSH 0x07 // Bits [N:00] TTRSH TX Threshold
/* RX Threshold Register Bit Masks */
#define RX_THRESHOLD_RTRSH 0x07 // Bits [N:00] RTRSH RX Threshold
#endif

View File

@ -0,0 +1,94 @@
/* mbed Microcontroller Library
* Copyright (c) 2015 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 "us_ticker_api.h"
#include "PeripheralNames.h"
/* Private data */
/* us_ticker reload value */
static uint32_t us_ticker_reload = 0x0; /* Max Value */
/* us ticker initialized */
static uint32_t us_ticker_inited = 0;
/* us ticker overflow */
static uint32_t us_ticker_overflow = 0;
void __us_ticker_irq_handler(void) {
Timer_ClearInterrupt(TIMER1);
us_ticker_overflow++;
}
void us_ticker_init(void) {
uint32_t us_ticker_irqn0 = 0;
uint32_t us_ticker_irqn1 = 0;
if (us_ticker_inited)
return;
us_ticker_inited = 1;
/* Initialize Timer 0 */
Timer_Initialize(TIMER0, us_ticker_reload);
/* Enable Timer 0 */
Timer_Enable(TIMER0);
/* Initialize Timer 1 */
Timer_Initialize(TIMER1, us_ticker_reload);
/* Enable Timer 1 */
Timer_Enable(TIMER1);
/* Timer 0 get IRQn */
us_ticker_irqn0 = Timer_GetIRQn(TIMER0);
NVIC_SetVector((IRQn_Type)us_ticker_irqn0, (uint32_t)us_ticker_irq_handler);
NVIC_EnableIRQ((IRQn_Type)us_ticker_irqn0);
/* Timer 1 get IRQn */
us_ticker_irqn1 = Timer_GetIRQn(TIMER1);
NVIC_SetVector((IRQn_Type)us_ticker_irqn1, (uint32_t)__us_ticker_irq_handler);
NVIC_EnableIRQ((IRQn_Type)us_ticker_irqn1);
}
uint32_t us_ticker_read() {
uint32_t return_value = 0;
if (!us_ticker_inited)
us_ticker_init();
return_value = Timer_Read(TIMER1);
return return_value;
}
void us_ticker_set_interrupt(timestamp_t timestamp) {
int32_t delta = 0;
if (!us_ticker_inited)
us_ticker_init();
delta = (int32_t)(timestamp - us_ticker_read());
/* Check if the event was in the past */
if (delta <= 0) {
/* This event was in the past */
Timer_SetInterrupt(TIMER0, 0);
return;
}
/* If the event was not in the past enable interrupt */
Timer_SetInterrupt(TIMER0, delta);
}
void us_ticker_disable_interrupt(void) {
Timer_DisableInterrupt(TIMER0);
}
void us_ticker_clear_interrupt(void) {
Timer_ClearInterrupt(TIMER0);
}