mirror of https://github.com/ARMmbed/mbed-os.git
Merge branch 'master' of git://github.com/Sissors/mbed into Sissors-master
Conflicts: libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KL05Z/analogin_api.c libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KL05Z/analogout_api.c libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KL05Z/gpio_api.c libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KL05Z/i2c_api.c libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KL05Z/pinmap.c libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KL05Z/pwmout_api.cpull/159/merge
commit
f2e1518220
|
@ -1,31 +0,0 @@
|
||||||
/* 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_PORTNAMES_H
|
|
||||||
#define MBED_PORTNAMES_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PortA = 0,
|
|
||||||
PortB = 1
|
|
||||||
} PortName;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
|
@ -1,89 +0,0 @@
|
||||||
/* 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 "analogin_api.h"
|
|
||||||
|
|
||||||
#include "cmsis.h"
|
|
||||||
#include "pinmap.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
static const PinMap PinMap_ADC[] = {
|
|
||||||
/* A0-A5 pins */
|
|
||||||
{PTA0, ADC0_SE12, 0},
|
|
||||||
{PTA8, ADC0_SE3, 0},
|
|
||||||
{PTA9, ADC0_SE2, 0},
|
|
||||||
{PTB8, ADC0_SE11, 0},
|
|
||||||
{PTB9, ADC0_SE10, 0},
|
|
||||||
{PTB13, ADC0_SE13, 0},
|
|
||||||
/* Rest of pins ADC Mux */
|
|
||||||
{PTB2, ADC0_SE4, 0},
|
|
||||||
{PTB1, ADC0_SE5, 0},
|
|
||||||
{PTB5, ADC0_SE1, 0},
|
|
||||||
{PTA12, ADC0_SE0, 0},
|
|
||||||
{PTB10, ADC0_SE9, 0},
|
|
||||||
{PTB11, ADC0_SE8, 0},
|
|
||||||
{PTB7, ADC0_SE7, 0},
|
|
||||||
{PTB0, ADC0_SE6, 0},
|
|
||||||
{NC, NC, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
void analogin_init(analogin_t *obj, PinName pin) {
|
|
||||||
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
|
|
||||||
if (obj->adc == (ADCName)NC) {
|
|
||||||
error("ADC pin mapping failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK;
|
|
||||||
|
|
||||||
uint32_t port = (uint32_t)pin >> PORT_SHIFT;
|
|
||||||
SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port);
|
|
||||||
|
|
||||||
ADC0->SC1[1] = ADC_SC1_ADCH(obj->adc);
|
|
||||||
|
|
||||||
ADC0->CFG1 = ADC_CFG1_ADLPC_MASK // Low-Power Configuration
|
|
||||||
| ADC_CFG1_ADIV(3) // Clock Divide Select: (Input Clock)/8
|
|
||||||
| ADC_CFG1_ADLSMP_MASK // Long Sample Time
|
|
||||||
| ADC_CFG1_MODE(1) // (12)bits Resolution
|
|
||||||
| ADC_CFG1_ADICLK(1); // Input Clock: (Bus Clock)/2
|
|
||||||
|
|
||||||
ADC0->CFG2 = ADC_CFG2_MUXSEL_MASK // ADxxb channels are selected
|
|
||||||
| ADC_CFG2_ADACKEN_MASK // Asynchronous Clock Output Enable
|
|
||||||
| ADC_CFG2_ADHSC_MASK // High-Speed Configuration
|
|
||||||
| ADC_CFG2_ADLSTS(0); // Long Sample Time Select
|
|
||||||
|
|
||||||
ADC0->SC2 = ADC_SC2_REFSEL(0); // Default Voltage Reference
|
|
||||||
|
|
||||||
ADC0->SC3 = ADC_SC3_AVGE_MASK // Hardware Average Enable
|
|
||||||
| ADC_SC3_AVGS(0); // 4 Samples Averaged
|
|
||||||
|
|
||||||
pinmap_pinout(pin, PinMap_ADC);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t analogin_read_u16(analogin_t *obj) {
|
|
||||||
// start conversion
|
|
||||||
ADC0->SC1[0] = ADC_SC1_ADCH(obj->adc);
|
|
||||||
|
|
||||||
// Wait Conversion Complete
|
|
||||||
while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK);
|
|
||||||
|
|
||||||
// Return value (12bit)
|
|
||||||
return (uint16_t)ADC0->R[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
float analogin_read(analogin_t *obj) {
|
|
||||||
uint16_t value = analogin_read_u16(obj);
|
|
||||||
return (float)value * (1.0f / (float)0xFFFF);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
/* 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 "analogout_api.h"
|
|
||||||
|
|
||||||
#include "cmsis.h"
|
|
||||||
#include "pinmap.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
#define RANGE_12BIT 0xFFF
|
|
||||||
|
|
||||||
static const PinMap PinMap_DAC[] = {
|
|
||||||
{PTB1, DAC_0, 0},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
void analogout_init(dac_t *obj, PinName pin) {
|
|
||||||
obj->dac = (DACName)pinmap_peripheral(pin, PinMap_DAC);
|
|
||||||
if (obj->dac == (DACName)NC) {
|
|
||||||
error("DAC pin mapping failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
SIM->SCGC6 |= SIM_SCGC6_DAC0_MASK;
|
|
||||||
|
|
||||||
uint32_t port = (uint32_t)pin >> PORT_SHIFT;
|
|
||||||
SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port);
|
|
||||||
|
|
||||||
DAC0->DAT[obj->dac].DATH = 0;
|
|
||||||
DAC0->DAT[obj->dac].DATL = 0;
|
|
||||||
|
|
||||||
DAC0->C1 = DAC_C1_DACBFMD_MASK; // One-Time Scan Mode
|
|
||||||
|
|
||||||
DAC0->C0 = DAC_C0_DACEN_MASK // Enable
|
|
||||||
| DAC_C0_DACSWTRG_MASK; // Software Trigger
|
|
||||||
|
|
||||||
pinmap_pinout(pin, PinMap_DAC);
|
|
||||||
|
|
||||||
analogout_write_u16(obj, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void analogout_free(dac_t *obj) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dac_write(dac_t *obj, int value) {
|
|
||||||
DAC0->DAT[obj->dac].DATL = (uint8_t)( value & 0xFF);
|
|
||||||
DAC0->DAT[obj->dac].DATH = (uint8_t)((value >> 8) & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int dac_read(dac_t *obj) {
|
|
||||||
return ((DAC0->DAT[obj->dac].DATH << 8) | DAC0->DAT[obj->dac].DATL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void analogout_write(dac_t *obj, float value) {
|
|
||||||
if (value < 0.0) {
|
|
||||||
dac_write(obj, 0);
|
|
||||||
} else if (value > 1.0) {
|
|
||||||
dac_write(obj, RANGE_12BIT);
|
|
||||||
} else {
|
|
||||||
dac_write(obj, value * (float)RANGE_12BIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void analogout_write_u16(dac_t *obj, uint16_t value) {
|
|
||||||
dac_write(obj, value >> 4); // 12-bit
|
|
||||||
}
|
|
||||||
|
|
||||||
float analogout_read(dac_t *obj) {
|
|
||||||
uint32_t value = dac_read(obj);
|
|
||||||
return (float)value * (1.0f / (float)RANGE_12BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t analogout_read_u16(dac_t *obj) {
|
|
||||||
uint32_t value = dac_read(obj); // 12-bit
|
|
||||||
return (value << 4) | ((value >> 8) & 0x003F);
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
/* 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 "gpio_api.h"
|
|
||||||
#include "pinmap.h"
|
|
||||||
|
|
||||||
uint32_t gpio_set(PinName pin) {
|
|
||||||
pin_function(pin, 1);
|
|
||||||
return 1 << ((pin & 0x7F) >> 2); // 1 << pin number
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_init(gpio_t *obj, PinName pin, PinDirection direction) {
|
|
||||||
if (pin == (PinName)NC) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->pin = pin;
|
|
||||||
obj->mask = gpio_set(pin);
|
|
||||||
|
|
||||||
uint32_t port = (uint32_t)pin >> PORT_SHIFT;
|
|
||||||
|
|
||||||
FGPIO_Type *reg = (FGPIO_Type *)(FPTA_BASE + port * 0x40);
|
|
||||||
obj->reg_set = ®->PSOR;
|
|
||||||
obj->reg_clr = ®->PCOR;
|
|
||||||
obj->reg_in = ®->PDIR;
|
|
||||||
obj->reg_dir = ®->PDDR;
|
|
||||||
|
|
||||||
gpio_dir(obj, direction);
|
|
||||||
switch (direction) {
|
|
||||||
case PIN_OUTPUT:
|
|
||||||
pin_mode(pin, PullNone);
|
|
||||||
break;
|
|
||||||
case PIN_INPUT :
|
|
||||||
pin_mode(pin, PullUp); //down not avail
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_mode(gpio_t *obj, PinMode mode) {
|
|
||||||
pin_mode(obj->pin, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_dir(gpio_t *obj, PinDirection direction) {
|
|
||||||
switch (direction) {
|
|
||||||
case PIN_INPUT :
|
|
||||||
*obj->reg_dir &= ~obj->mask;
|
|
||||||
break;
|
|
||||||
case PIN_OUTPUT:
|
|
||||||
*obj->reg_dir |= obj->mask;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
/* 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
|
|
||||||
|
|
||||||
#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) {
|
|
||||||
if (value) {
|
|
||||||
*obj->reg_set = obj->mask;
|
|
||||||
} else {
|
|
||||||
*obj->reg_clr = obj->mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int gpio_read(gpio_t *obj) {
|
|
||||||
return ((*obj->reg_in & obj->mask) ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,402 +0,0 @@
|
||||||
/* 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 "i2c_api.h"
|
|
||||||
|
|
||||||
#include "cmsis.h"
|
|
||||||
#include "pinmap.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
static const PinMap PinMap_I2C_SDA[] = {
|
|
||||||
{PTB4, I2C_0, 2},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PinMap PinMap_I2C_SCL[] = {
|
|
||||||
{PTB3, I2C_0, 2},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint16_t ICR[0x40] = {
|
|
||||||
20, 22, 24, 26, 28,
|
|
||||||
30, 34, 40, 28, 32,
|
|
||||||
36, 40, 44, 48, 56,
|
|
||||||
68, 48, 56, 64, 72,
|
|
||||||
80, 88, 104, 128, 80,
|
|
||||||
96, 112, 128, 144, 160,
|
|
||||||
192, 240, 160, 192, 224,
|
|
||||||
256, 288, 320, 384, 480,
|
|
||||||
320, 384, 448, 512, 576,
|
|
||||||
640, 768, 960, 640, 768,
|
|
||||||
896, 1024, 1152, 1280, 1536,
|
|
||||||
1920, 1280, 1536, 1792, 2048,
|
|
||||||
2304, 2560, 3072, 3840
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint8_t first_read;
|
|
||||||
|
|
||||||
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_Type*)pinmap_merge(i2c_sda, i2c_scl);
|
|
||||||
if ((int)obj->i2c == NC) {
|
|
||||||
error("I2C pin mapping failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// enable clocks
|
|
||||||
switch ((int)obj->i2c) {
|
|
||||||
case I2C_0:
|
|
||||||
SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK;
|
|
||||||
SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set default frequency at 100k
|
|
||||||
i2c_frequency(obj, 100000);
|
|
||||||
|
|
||||||
// enable I2C interface
|
|
||||||
obj->i2c->C1 |= 0x80;
|
|
||||||
|
|
||||||
pinmap_pinout(sda, PinMap_I2C_SDA);
|
|
||||||
pinmap_pinout(scl, PinMap_I2C_SCL);
|
|
||||||
|
|
||||||
first_read = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_start(i2c_t *obj) {
|
|
||||||
// if we are in the middle of a transaction
|
|
||||||
// activate the repeat_start flag
|
|
||||||
if (obj->i2c->S & I2C_S_BUSY_MASK) {
|
|
||||||
obj->i2c->C1 |= 0x04;
|
|
||||||
} else {
|
|
||||||
obj->i2c->C1 |= I2C_C1_MST_MASK;
|
|
||||||
obj->i2c->C1 |= I2C_C1_TX_MASK;
|
|
||||||
}
|
|
||||||
first_read = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_stop(i2c_t *obj) {
|
|
||||||
volatile uint32_t n = 0;
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_MST_MASK;
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
// It seems that there are timing problems
|
|
||||||
// when there is no waiting time after a STOP.
|
|
||||||
// This wait is also included on the samples
|
|
||||||
// code provided with the freedom board
|
|
||||||
for (n = 0; n < 100; n++) __NOP();
|
|
||||||
first_read = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int timeout_status_poll(i2c_t *obj, uint32_t mask) {
|
|
||||||
uint32_t i, timeout = 1000;
|
|
||||||
|
|
||||||
for (i = 0; i < timeout; i++) {
|
|
||||||
if (obj->i2c->S & mask) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this function waits the end of a tx transfer and return the status of the transaction:
|
|
||||||
// 0: OK ack received
|
|
||||||
// 1: OK ack not received
|
|
||||||
// 2: failure
|
|
||||||
static int i2c_wait_end_tx_transfer(i2c_t *obj) {
|
|
||||||
|
|
||||||
// wait for the interrupt flag
|
|
||||||
if (timeout_status_poll(obj, I2C_S_IICIF_MASK)) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->i2c->S |= I2C_S_IICIF_MASK;
|
|
||||||
|
|
||||||
// wait transfer complete
|
|
||||||
if (timeout_status_poll(obj, I2C_S_TCF_MASK)) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we received the ACK or not
|
|
||||||
return obj->i2c->S & I2C_S_RXAK_MASK ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this function waits the end of a rx transfer and return the status of the transaction:
|
|
||||||
// 0: OK
|
|
||||||
// 1: failure
|
|
||||||
static int i2c_wait_end_rx_transfer(i2c_t *obj) {
|
|
||||||
// wait for the end of the rx transfer
|
|
||||||
if (timeout_status_poll(obj, I2C_S_IICIF_MASK)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->i2c->S |= I2C_S_IICIF_MASK;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_send_nack(i2c_t *obj) {
|
|
||||||
obj->i2c->C1 |= I2C_C1_TXAK_MASK; // NACK
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_send_ack(i2c_t *obj) {
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_TXAK_MASK; // ACK
|
|
||||||
}
|
|
||||||
|
|
||||||
static int i2c_do_write(i2c_t *obj, int value) {
|
|
||||||
// write the data
|
|
||||||
obj->i2c->D = value;
|
|
||||||
|
|
||||||
// init and wait the end of the transfer
|
|
||||||
return i2c_wait_end_tx_transfer(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int i2c_do_read(i2c_t *obj, char * data, int last) {
|
|
||||||
if (last) {
|
|
||||||
i2c_send_nack(obj);
|
|
||||||
} else {
|
|
||||||
i2c_send_ack(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
*data = (obj->i2c->D & 0xFF);
|
|
||||||
|
|
||||||
// start rx transfer and wait the end of the transfer
|
|
||||||
return i2c_wait_end_rx_transfer(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2c_frequency(i2c_t *obj, int hz) {
|
|
||||||
uint8_t icr = 0;
|
|
||||||
uint8_t mult = 0;
|
|
||||||
uint32_t error = 0;
|
|
||||||
uint32_t p_error = 0xffffffff;
|
|
||||||
uint32_t ref = 0;
|
|
||||||
uint8_t i, j;
|
|
||||||
// bus clk
|
|
||||||
uint32_t PCLK = 23986176u;
|
|
||||||
uint32_t pulse;
|
|
||||||
|
|
||||||
// we look for the values that minimize the error
|
|
||||||
|
|
||||||
// test all the MULT values
|
|
||||||
for (i = 1; i < 5; i*=2) {
|
|
||||||
for (j = 0; j < 0x40; j++) {
|
|
||||||
ref = PCLK / (i*ICR[j]);
|
|
||||||
if (ref > (uint32_t)hz)
|
|
||||||
continue;
|
|
||||||
error = hz - ref;
|
|
||||||
if (error < p_error) {
|
|
||||||
icr = j;
|
|
||||||
mult = i/2;
|
|
||||||
p_error = error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pulse = icr | (mult << 6);
|
|
||||||
|
|
||||||
// I2C Rate
|
|
||||||
obj->i2c->F = pulse;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
|
|
||||||
uint8_t count;
|
|
||||||
char dummy_read, *ptr;
|
|
||||||
|
|
||||||
if (i2c_start(obj)) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i2c_do_write(obj, (address | 0x01))) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set rx mode
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
// Read in bytes
|
|
||||||
for (count = 0; count < (length); count++) {
|
|
||||||
ptr = (count == 0) ? &dummy_read : &data[count - 1];
|
|
||||||
uint8_t stop_ = (count == (length - 1)) ? 1 : 0;
|
|
||||||
if (i2c_do_read(obj, ptr, stop_)) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not repeated start, send stop.
|
|
||||||
if (stop) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
// last read
|
|
||||||
data[count-1] = obj->i2c->D;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (i2c_start(obj)) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i2c_do_write(obj, (address & 0xFE))) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
if(i2c_do_write(obj, data[i])) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stop) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2c_reset(i2c_t *obj) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_byte_read(i2c_t *obj, int last) {
|
|
||||||
char data;
|
|
||||||
|
|
||||||
// set rx mode
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
if(first_read) {
|
|
||||||
// first dummy read
|
|
||||||
i2c_do_read(obj, &data, 0);
|
|
||||||
first_read = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last) {
|
|
||||||
// set tx mode
|
|
||||||
obj->i2c->C1 |= I2C_C1_TX_MASK;
|
|
||||||
return obj->i2c->D;
|
|
||||||
}
|
|
||||||
|
|
||||||
i2c_do_read(obj, &data, last);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_byte_write(i2c_t *obj, int data) {
|
|
||||||
first_read = 1;
|
|
||||||
|
|
||||||
// set tx mode
|
|
||||||
obj->i2c->C1 |= I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
return !i2c_do_write(obj, (data & 0xFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void i2c_slave_mode(i2c_t *obj, int enable_slave) {
|
|
||||||
if (enable_slave) {
|
|
||||||
// set slave mode
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_MST_MASK;
|
|
||||||
obj->i2c->C1 |= I2C_C1_IICIE_MASK;
|
|
||||||
} else {
|
|
||||||
// set master mode
|
|
||||||
obj->i2c->C1 |= I2C_C1_MST_MASK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_slave_receive(i2c_t *obj) {
|
|
||||||
switch(obj->i2c->S) {
|
|
||||||
// read addressed
|
|
||||||
case 0xE6:
|
|
||||||
return 1;
|
|
||||||
// write addressed
|
|
||||||
case 0xE2:
|
|
||||||
return 3;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_slave_read(i2c_t *obj, char *data, int length) {
|
|
||||||
uint8_t dummy_read, count;
|
|
||||||
uint8_t *ptr;
|
|
||||||
|
|
||||||
// set rx mode
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
// first dummy read
|
|
||||||
dummy_read = obj->i2c->D;
|
|
||||||
if(i2c_wait_end_rx_transfer(obj)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read address
|
|
||||||
dummy_read = obj->i2c->D;
|
|
||||||
if(i2c_wait_end_rx_transfer(obj)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read (length - 1) bytes
|
|
||||||
for (count = 0; count < (length - 1); count++) {
|
|
||||||
data[count] = obj->i2c->D;
|
|
||||||
if(i2c_wait_end_rx_transfer(obj)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// read last byte
|
|
||||||
ptr = (length == 0) ? &dummy_read : (uint8_t *)&data[count];
|
|
||||||
*ptr = obj->i2c->D;
|
|
||||||
|
|
||||||
return (length) ? (count + 1) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_slave_write(i2c_t *obj, const char *data, int length) {
|
|
||||||
int32_t i, count = 0;
|
|
||||||
|
|
||||||
// set tx mode
|
|
||||||
obj->i2c->C1 |= I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
if(i2c_do_write(obj, data[count++]) == 2) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set rx mode
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
// dummy rx transfer needed
|
|
||||||
// otherwise the master cannot generate a stop bit
|
|
||||||
obj->i2c->D;
|
|
||||||
if(i2c_wait_end_rx_transfer(obj) == 2) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
|
|
||||||
obj->i2c->A1 = address & 0xfe;
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
/* 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 port;
|
|
||||||
uint32_t pin;
|
|
||||||
uint32_t ch;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct port_s {
|
|
||||||
__IO uint32_t *reg_dir;
|
|
||||||
__IO uint32_t *reg_out;
|
|
||||||
__I uint32_t *reg_in;
|
|
||||||
PortName port;
|
|
||||||
uint32_t mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pwmout_s {
|
|
||||||
__IO uint32_t *MOD;
|
|
||||||
__IO uint32_t *CNT;
|
|
||||||
__IO uint32_t *CnV;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct serial_s {
|
|
||||||
UARTLP_Type *uart;
|
|
||||||
int index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct analogin_s {
|
|
||||||
ADCName adc;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct dac_s {
|
|
||||||
DACName dac;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct i2c_s {
|
|
||||||
I2C_Type *i2c;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct spi_s {
|
|
||||||
SPI_Type *spi;
|
|
||||||
};
|
|
||||||
|
|
||||||
#include "gpio_object.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,43 +0,0 @@
|
||||||
/* 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 "pinmap.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
void pin_function(PinName pin, int function) {
|
|
||||||
if (pin == (PinName)NC) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t port_n = (uint32_t)pin >> PORT_SHIFT;
|
|
||||||
uint32_t pin_n = (uint32_t)(pin & 0x7C) >> 2;
|
|
||||||
|
|
||||||
SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port_n);
|
|
||||||
__IO uint32_t* pin_pcr = &(((PORT_Type *)(PORTA_BASE + (1 << PORT_SHIFT) * port_n)))->PCR[pin_n];
|
|
||||||
|
|
||||||
// pin mux bits: [10:8] -> 11100000000 = (0x700)
|
|
||||||
*pin_pcr = (*pin_pcr & ~0x700) | (function << 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pin_mode(PinName pin, PinMode mode) {
|
|
||||||
if (pin == (PinName)NC) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
__IO uint32_t* pin_pcr = (__IO uint32_t*)(PORTA_BASE + pin);
|
|
||||||
|
|
||||||
// pin pullup bits: [1:0] -> 11 = (0x3)
|
|
||||||
*pin_pcr = (*pin_pcr & ~0x3) | mode;
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/* 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 "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 << 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
void port_init(port_t *obj, PortName port, int mask, PinDirection dir) {
|
|
||||||
obj->port = port;
|
|
||||||
obj->mask = mask;
|
|
||||||
|
|
||||||
FGPIO_Type *reg = (FGPIO_Type *)(FPTA_BASE + port * 0x40);
|
|
||||||
|
|
||||||
obj->reg_out = ®->PDOR;
|
|
||||||
obj->reg_in = ®->PDIR;
|
|
||||||
obj->reg_dir = ®->PDDR;
|
|
||||||
|
|
||||||
uint32_t i;
|
|
||||||
// The function is set per pin: reuse gpio logic
|
|
||||||
for (i=0; i<32; 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_out = (*obj->reg_in & ~obj->mask) | (value & obj->mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
int port_read(port_t *obj) {
|
|
||||||
return (*obj->reg_in & obj->mask);
|
|
||||||
}
|
|
|
@ -1,118 +0,0 @@
|
||||||
/* 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 "pwmout_api.h"
|
|
||||||
|
|
||||||
#include "cmsis.h"
|
|
||||||
#include "pinmap.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
static const PinMap PinMap_PWM[] = {
|
|
||||||
// LEDs
|
|
||||||
{LED_RED , PWM_4 , 2}, // PTB8 , TPM0 CH3
|
|
||||||
{LED_GREEN, PWM_3, 2}, // PTB9 , TPM0 CH2
|
|
||||||
{LED_BLUE , PWM_2 , 2}, // PTB10, TPM0 CH1
|
|
||||||
|
|
||||||
// Arduino digital pinout
|
|
||||||
{D3, PWM_8 , 2}, // PTB5 , TPM1 CH1
|
|
||||||
{D5, PWM_7 , 2}, // PTA12, TPM1 CH0
|
|
||||||
{D6, PWM_4 , 2}, // PTB6 , TPM0 CH3
|
|
||||||
{D7, PWM_3 , 2}, // PTB7 , TPM0 CH2
|
|
||||||
{D8, PWM_2 , 2}, // PTB10, TPM0 CH1
|
|
||||||
{D9, PWM_1 , 2}, // PTB11, TPM0 CH0
|
|
||||||
{D10, PWM_6 , 2}, // PTA5 , TPM0 CH5
|
|
||||||
{D12, PWM_5 , 2}, // PTA6 , TPM0 CH4
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PWM_CLOCK_MHZ (0.75) // (48)MHz / 64 = (0.75)MHz
|
|
||||||
|
|
||||||
void pwmout_init(pwmout_t* obj, PinName pin) {
|
|
||||||
// determine the channel
|
|
||||||
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
|
|
||||||
if (pwm == (PWMName)NC) {
|
|
||||||
error("PwmOut pin mapping failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int port = (unsigned int)pin >> PORT_SHIFT;
|
|
||||||
unsigned int tpm_n = (pwm >> TPM_SHIFT);
|
|
||||||
unsigned int ch_n = (pwm & 0xFF);
|
|
||||||
|
|
||||||
SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port);
|
|
||||||
SIM->SCGC6 |= 1 << (SIM_SCGC6_TPM0_SHIFT + tpm_n);
|
|
||||||
SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); // Clock source: MCGFLLCLK or MCGPLLCLK
|
|
||||||
|
|
||||||
TPM_Type *tpm = (TPM_Type *)(TPM0_BASE + 0x1000 * tpm_n);
|
|
||||||
tpm->SC = TPM_SC_CMOD(1) | TPM_SC_PS(6); // (48)MHz / 64 = (0.75)MHz
|
|
||||||
tpm->CONTROLS[ch_n].CnSC = (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK); // No Interrupts; High True pulses on Edge Aligned PWM
|
|
||||||
|
|
||||||
obj->CnV = &tpm->CONTROLS[ch_n].CnV;
|
|
||||||
obj->MOD = &tpm->MOD;
|
|
||||||
obj->CNT = &tpm->CNT;
|
|
||||||
|
|
||||||
// default to 20ms: standard for servos, and fine for e.g. brightness control
|
|
||||||
pwmout_period_ms(obj, 20);
|
|
||||||
pwmout_write(obj, 0);
|
|
||||||
|
|
||||||
// Wire pinout
|
|
||||||
pinmap_pinout(pin, PinMap_PWM);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pwmout_free(pwmout_t* obj) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void pwmout_write(pwmout_t* obj, float value) {
|
|
||||||
if (value < 0.0) {
|
|
||||||
value = 0.0;
|
|
||||||
} else if (value > 1.0) {
|
|
||||||
value = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*obj->CnV = (uint32_t)((float)(*obj->MOD) * value);
|
|
||||||
*obj->CNT = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float pwmout_read(pwmout_t* obj) {
|
|
||||||
float v = (float)(*obj->CnV) / (float)(*obj->MOD);
|
|
||||||
return (v > 1.0) ? (1.0) : (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) {
|
|
||||||
float dc = pwmout_read(obj);
|
|
||||||
*obj->MOD = PWM_CLOCK_MHZ * us;
|
|
||||||
pwmout_write(obj, dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
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->CnV = PWM_CLOCK_MHZ * us;
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
/* 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"
|
|
||||||
|
|
||||||
static void init(void) {
|
|
||||||
// enable RTC clock
|
|
||||||
SIM->SCGC6 |= SIM_SCGC6_RTC_MASK;
|
|
||||||
|
|
||||||
// select OSC32 as RTC clock source
|
|
||||||
SIM->SOPT1 &= ~SIM_SOPT1_OSC32KSEL_MASK;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void rtc_init(void) {
|
|
||||||
uint32_t i;
|
|
||||||
init();
|
|
||||||
|
|
||||||
//Configure the TSR. default value: 1
|
|
||||||
RTC->TSR = 1;
|
|
||||||
|
|
||||||
RTC->CR |= RTC_CR_OSCE_MASK;
|
|
||||||
|
|
||||||
//delay for OSCE stabilization
|
|
||||||
for(i=0; i<0x1000; i++) __NOP();
|
|
||||||
|
|
||||||
// enable counter
|
|
||||||
RTC->SR |= RTC_SR_TCE_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rtc_free(void) {
|
|
||||||
// [TODO]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int rtc_isenabled(void) {
|
|
||||||
// even if the RTC module is enabled,
|
|
||||||
// as we use RTC_CLKIN and an external clock,
|
|
||||||
// we need to reconfigure the pins. That is why we
|
|
||||||
// call init() if the rtc is enabled
|
|
||||||
|
|
||||||
// if RTC not enabled return 0
|
|
||||||
SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
|
|
||||||
SIM->SCGC6 |= SIM_SCGC6_RTC_MASK;
|
|
||||||
if ((RTC->SR & RTC_SR_TCE_MASK) == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
init();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t rtc_read(void) {
|
|
||||||
return RTC->TSR;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rtc_write(time_t t) {
|
|
||||||
// disable counter
|
|
||||||
RTC->SR &= ~RTC_SR_TCE_MASK;
|
|
||||||
|
|
||||||
// we do not write 0 into TSR
|
|
||||||
// to avoid invalid time
|
|
||||||
if (t == 0) {
|
|
||||||
t = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write seconds
|
|
||||||
RTC->TSR = t;
|
|
||||||
|
|
||||||
// re-enable counter
|
|
||||||
RTC->SR |= RTC_SR_TCE_MASK;
|
|
||||||
}
|
|
|
@ -1,288 +0,0 @@
|
||||||
/* 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 "serial_api.h"
|
|
||||||
|
|
||||||
// math.h required for floating point operations for baud rate calculation
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "cmsis.h"
|
|
||||||
#include "pinmap.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
#define UART_CLOCK_HZ 47972352u
|
|
||||||
#define UART_NUM 1
|
|
||||||
|
|
||||||
static const PinMap PinMap_UART_TX[] = {
|
|
||||||
{PTB1, UART_0, 2},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PinMap PinMap_UART_RX[] = {
|
|
||||||
{PTB2, UART_0, 2},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint32_t serial_irq_ids[UART_NUM] = {0};
|
|
||||||
static uart_irq_handler irq_handler;
|
|
||||||
|
|
||||||
int stdio_uart_inited = 0;
|
|
||||||
serial_t stdio_uart;
|
|
||||||
|
|
||||||
void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
|
||||||
// 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 = (UARTLP_Type *)uart;
|
|
||||||
// enable clk
|
|
||||||
switch (uart) {
|
|
||||||
case UART_0:
|
|
||||||
SIM->SOPT2 |= 1 << SIM_SOPT2_UART0SRC_SHIFT;
|
|
||||||
SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK;
|
|
||||||
SIM->SCGC4 |= SIM_SCGC4_UART0_MASK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Disable UART before changing registers
|
|
||||||
obj->uart->C2 &= ~(UART0_C2_RE_MASK | UART0_C2_TE_MASK);
|
|
||||||
|
|
||||||
switch (uart) {
|
|
||||||
case UART_0:
|
|
||||||
obj->index = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set default baud rate and format
|
|
||||||
serial_baud (obj, 9600);
|
|
||||||
serial_format(obj, 8, ParityNone, 1);
|
|
||||||
|
|
||||||
// pinout the chosen uart
|
|
||||||
pinmap_pinout(tx, PinMap_UART_TX);
|
|
||||||
pinmap_pinout(rx, PinMap_UART_RX);
|
|
||||||
|
|
||||||
// set rx/tx pins in PullUp mode
|
|
||||||
pin_mode(tx, PullUp);
|
|
||||||
pin_mode(rx, PullUp);
|
|
||||||
|
|
||||||
obj->uart->C2 |= (UART0_C2_RE_MASK | UART0_C2_TE_MASK);
|
|
||||||
|
|
||||||
if (uart == STDIO_UART) {
|
|
||||||
stdio_uart_inited = 1;
|
|
||||||
memcpy(&stdio_uart, obj, sizeof(serial_t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_free(serial_t *obj) {
|
|
||||||
serial_irq_ids[obj->index] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_baud(serial_t *obj, int baudrate) {
|
|
||||||
// save C2 state
|
|
||||||
uint8_t c2_state = (obj->uart->C2 & (UART0_C2_RE_MASK | UART0_C2_TE_MASK));
|
|
||||||
|
|
||||||
// Disable UART before changing registers
|
|
||||||
obj->uart->C2 &= ~(UART0_C2_RE_MASK | UART0_C2_TE_MASK);
|
|
||||||
|
|
||||||
// First we check to see if the basic divide with no DivAddVal/MulVal
|
|
||||||
// ratio gives us an integer result. If it does, we set DivAddVal = 0,
|
|
||||||
// MulVal = 1. Otherwise, we search the valid ratio value range to find
|
|
||||||
// the closest match. This could be more elegant, using search methods
|
|
||||||
// and/or lookup tables, but the brute force method is not that much
|
|
||||||
// slower, and is more maintainable.
|
|
||||||
uint16_t DL = UART_CLOCK_HZ / (16 * baudrate);
|
|
||||||
|
|
||||||
// set BDH and BDL
|
|
||||||
obj->uart->BDH = (obj->uart->BDH & ~(0x1f)) | ((DL >> 8) & 0x1f);
|
|
||||||
obj->uart->BDL = (obj->uart->BDL & ~(0xff)) | ((DL >> 0) & 0xff);
|
|
||||||
|
|
||||||
// restore C2 state
|
|
||||||
obj->uart->C2 |= c2_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
|
|
||||||
uint8_t m10 = 0;
|
|
||||||
|
|
||||||
// save C2 state
|
|
||||||
uint8_t c2_state = (obj->uart->C2 & (UART0_C2_RE_MASK | UART0_C2_TE_MASK));
|
|
||||||
|
|
||||||
// Disable UART before changing registers
|
|
||||||
obj->uart->C2 &= ~(UART0_C2_RE_MASK | UART0_C2_TE_MASK);
|
|
||||||
|
|
||||||
// 8 data bits = 0 ... 9 data bits = 1
|
|
||||||
if ((data_bits < 8) || (data_bits > 9)) {
|
|
||||||
error("Invalid number of bits (%d) in serial format, should be 8..9\r\n", data_bits);
|
|
||||||
}
|
|
||||||
data_bits -= 8;
|
|
||||||
|
|
||||||
uint8_t parity_enable, parity_select;
|
|
||||||
switch (parity) {
|
|
||||||
case ParityNone: parity_enable = 0; parity_select = 0; break;
|
|
||||||
case ParityOdd : parity_enable = 1; parity_select = 1; data_bits++; break;
|
|
||||||
case ParityEven: parity_enable = 1; parity_select = 0; data_bits++; break;
|
|
||||||
default:
|
|
||||||
error("Invalid serial parity setting\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1 stop bits = 0, 2 stop bits = 1
|
|
||||||
if ((stop_bits != 1) && (stop_bits != 2)) {
|
|
||||||
error("Invalid stop bits specified\r\n");
|
|
||||||
}
|
|
||||||
stop_bits -= 1;
|
|
||||||
|
|
||||||
// 9 data bits + parity
|
|
||||||
if (data_bits == 2) {
|
|
||||||
// only uart0 supports 10 bit communication
|
|
||||||
if (obj->index != 0) {
|
|
||||||
error("Invalid number of bits (9) to be used with parity\r\n");
|
|
||||||
}
|
|
||||||
data_bits = 0;
|
|
||||||
m10 = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// data bits, parity and parity mode
|
|
||||||
obj->uart->C1 = ((data_bits << 4)
|
|
||||||
| (parity_enable << 1)
|
|
||||||
| (parity_select << 0));
|
|
||||||
|
|
||||||
// enable 10bit mode if needed
|
|
||||||
if (obj->index == 0) {
|
|
||||||
obj->uart->C4 &= ~UARTLP_C4_M10_MASK;
|
|
||||||
obj->uart->C4 |= (m10 << UARTLP_C4_M10_SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop bits
|
|
||||||
obj->uart->BDH &= ~UART0_BDH_SBNS_MASK;
|
|
||||||
obj->uart->BDH |= (stop_bits << UART0_BDH_SBNS_SHIFT);
|
|
||||||
|
|
||||||
// restore C2 state
|
|
||||||
obj->uart->C2 |= c2_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void uart_irq(uint8_t status, uint32_t index) {
|
|
||||||
if (serial_irq_ids[index] != 0) {
|
|
||||||
if (status & UART0_S1_TDRE_MASK)
|
|
||||||
irq_handler(serial_irq_ids[index], TxIrq);
|
|
||||||
|
|
||||||
if (status & UART0_S1_RDRF_MASK)
|
|
||||||
irq_handler(serial_irq_ids[index], RxIrq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void uart0_irq() {
|
|
||||||
uart_irq(UART0->S1, 0);
|
|
||||||
if (UART0->S1 & UART0_S1_OR_MASK)
|
|
||||||
UART0->S1 |= UART0_S1_OR_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 UART_0:
|
|
||||||
irq_n=UART0_IRQn;
|
|
||||||
vector = (uint32_t)&uart0_irq;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable) {
|
|
||||||
switch (irq) {
|
|
||||||
case RxIrq:
|
|
||||||
obj->uart->C2 |= (UART0_C2_RIE_MASK);
|
|
||||||
break;
|
|
||||||
case TxIrq:
|
|
||||||
obj->uart->C2 |= (UART0_C2_TIE_MASK);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
NVIC_SetVector(irq_n, vector);
|
|
||||||
NVIC_EnableIRQ(irq_n);
|
|
||||||
|
|
||||||
} else { // disable
|
|
||||||
int all_disabled = 0;
|
|
||||||
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
|
|
||||||
switch (irq) {
|
|
||||||
case RxIrq:
|
|
||||||
obj->uart->C2 &= ~(UART0_C2_RIE_MASK);
|
|
||||||
break;
|
|
||||||
case TxIrq:
|
|
||||||
obj->uart->C2 &= ~(UART0_C2_TIE_MASK);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
switch (other_irq) {
|
|
||||||
case RxIrq:
|
|
||||||
all_disabled = (obj->uart->C2 & (UART0_C2_RIE_MASK)) == 0;
|
|
||||||
break;
|
|
||||||
case TxIrq:
|
|
||||||
all_disabled = (obj->uart->C2 & (UART0_C2_TIE_MASK)) == 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (all_disabled)
|
|
||||||
NVIC_DisableIRQ(irq_n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int serial_getc(serial_t *obj) {
|
|
||||||
while (!serial_readable(obj));
|
|
||||||
return obj->uart->D;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_putc(serial_t *obj, int c) {
|
|
||||||
while (!serial_writable(obj));
|
|
||||||
obj->uart->D = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
int serial_readable(serial_t *obj) {
|
|
||||||
// check overrun
|
|
||||||
if (obj->uart->S1 & UART0_S1_OR_MASK) {
|
|
||||||
obj->uart->S1 |= UART0_S1_OR_MASK;
|
|
||||||
}
|
|
||||||
return (obj->uart->S1 & UART0_S1_RDRF_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
int serial_writable(serial_t *obj) {
|
|
||||||
// check overrun
|
|
||||||
if (obj->uart->S1 & UART0_S1_OR_MASK) {
|
|
||||||
obj->uart->S1 |= UART0_S1_OR_MASK;
|
|
||||||
}
|
|
||||||
return (obj->uart->S1 & UART0_S1_TDRE_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_clear(serial_t *obj) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_pinout_tx(PinName tx) {
|
|
||||||
pinmap_pinout(tx, PinMap_UART_TX);
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_break_set(serial_t *obj) {
|
|
||||||
obj->uart->C2 |= UART0_C2_SBK_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_break_clear(serial_t *obj) {
|
|
||||||
obj->uart->C2 &= ~UART0_C2_SBK_MASK;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
/* 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"
|
|
||||||
|
|
||||||
/* Prototypes */
|
|
||||||
static void pit_init(void);
|
|
||||||
static void lptmr_init(void);
|
|
||||||
static void lptmr_isr(void);
|
|
||||||
|
|
||||||
/* Global variables */
|
|
||||||
static uint32_t us_ticker_inited = 0;
|
|
||||||
static uint32_t us_ticker_int_counter = 0;
|
|
||||||
static uint16_t us_ticker_int_remainder = 0;
|
|
||||||
|
|
||||||
|
|
||||||
void us_ticker_init(void) {
|
|
||||||
if (us_ticker_inited) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
us_ticker_inited = 1;
|
|
||||||
|
|
||||||
pit_init();
|
|
||||||
lptmr_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pit_init(void) {
|
|
||||||
SIM->SCGC6 |= SIM_SCGC6_PIT_MASK; // Clock PIT
|
|
||||||
PIT->MCR = 0; // Enable PIT
|
|
||||||
|
|
||||||
// Channel 1
|
|
||||||
PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;
|
|
||||||
PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK; // Chain to timer 0, disable Interrupts
|
|
||||||
PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK; // Start timer 1
|
|
||||||
|
|
||||||
// Use channel 0 as a prescaler for channel 1
|
|
||||||
PIT->CHANNEL[0].LDVAL = 23;
|
|
||||||
PIT->CHANNEL[0].TCTRL = PIT_TCTRL_TEN_MASK; // Start timer 0, disable interrupts
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t us_ticker_read() {
|
|
||||||
if (!us_ticker_inited) {
|
|
||||||
us_ticker_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
// The PIT is a countdown timer
|
|
||||||
return ~(PIT->CHANNEL[1].CVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lptmr_init(void) {
|
|
||||||
SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK;
|
|
||||||
|
|
||||||
LPTMR0->CSR = 0;
|
|
||||||
|
|
||||||
NVIC_SetVector(LPTimer_IRQn, (uint32_t)lptmr_isr);
|
|
||||||
NVIC_EnableIRQ(LPTimer_IRQn);
|
|
||||||
|
|
||||||
// Clock at (1)MHz -> (1)tick/us
|
|
||||||
LPTMR0->PSR = LPTMR_PSR_PCS(0); // MCGIRCLK -> 2MHz / presc 2 = 1MHz
|
|
||||||
}
|
|
||||||
|
|
||||||
void us_ticker_disable_interrupt(void) {
|
|
||||||
LPTMR0->CSR &= ~LPTMR_CSR_TIE_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void us_ticker_clear_interrupt(void) {
|
|
||||||
// we've already cleared interrupt in lptmr_isr
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lptmr_set(unsigned short count) {
|
|
||||||
// Reset
|
|
||||||
LPTMR0->CSR = 0;
|
|
||||||
|
|
||||||
// Set the compare register
|
|
||||||
LPTMR0->CMR = count;
|
|
||||||
|
|
||||||
// Enable interrupt
|
|
||||||
LPTMR0->CSR |= LPTMR_CSR_TIE_MASK;
|
|
||||||
|
|
||||||
// Start the timer
|
|
||||||
LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lptmr_isr(void) {
|
|
||||||
// write 1 to TCF to clear the LPT timer compare flag
|
|
||||||
LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;
|
|
||||||
|
|
||||||
if (us_ticker_int_counter > 0) {
|
|
||||||
lptmr_set(0xFFFF);
|
|
||||||
us_ticker_int_counter--;
|
|
||||||
} else {
|
|
||||||
if (us_ticker_int_remainder > 0) {
|
|
||||||
lptmr_set(us_ticker_int_remainder);
|
|
||||||
us_ticker_int_remainder = 0;
|
|
||||||
} else {
|
|
||||||
// This function is going to disable the interrupts if there are
|
|
||||||
// no other events in the queue
|
|
||||||
us_ticker_irq_handler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void us_ticker_set_interrupt(unsigned int timestamp) {
|
|
||||||
int32_t delta = (int32_t)(timestamp - us_ticker_read());
|
|
||||||
if (delta <= 0) {
|
|
||||||
// This event was in the past:
|
|
||||||
us_ticker_irq_handler();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
us_ticker_int_counter = (uint32_t)(delta >> 16);
|
|
||||||
us_ticker_int_remainder = (uint16_t)(0xFFFF & delta);
|
|
||||||
if (us_ticker_int_counter > 0) {
|
|
||||||
lptmr_set(0xFFFF);
|
|
||||||
us_ticker_int_counter--;
|
|
||||||
} else {
|
|
||||||
lptmr_set(us_ticker_int_remainder);
|
|
||||||
us_ticker_int_remainder = 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,86 +0,0 @@
|
||||||
/* 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 "analogout_api.h"
|
|
||||||
|
|
||||||
#include "cmsis.h"
|
|
||||||
#include "pinmap.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
#define RANGE_12BIT 0xFFF
|
|
||||||
|
|
||||||
static const PinMap PinMap_DAC[] = {
|
|
||||||
{PTE30, DAC_0, 0},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
void analogout_init(dac_t *obj, PinName pin) {
|
|
||||||
obj->dac = (DACName)pinmap_peripheral(pin, PinMap_DAC);
|
|
||||||
if (obj->dac == (DACName)NC) {
|
|
||||||
error("DAC pin mapping failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
SIM->SCGC6 |= SIM_SCGC6_DAC0_MASK;
|
|
||||||
|
|
||||||
uint32_t port = (uint32_t)pin >> PORT_SHIFT;
|
|
||||||
SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port);
|
|
||||||
|
|
||||||
DAC0->DAT[obj->dac].DATH = 0;
|
|
||||||
DAC0->DAT[obj->dac].DATL = 0;
|
|
||||||
|
|
||||||
DAC0->C1 = DAC_C1_DACBFMD_MASK; // One-Time Scan Mode
|
|
||||||
|
|
||||||
DAC0->C0 = DAC_C0_DACEN_MASK // Enable
|
|
||||||
| DAC_C0_DACSWTRG_MASK; // Software Trigger
|
|
||||||
|
|
||||||
pinmap_pinout(pin, PinMap_DAC);
|
|
||||||
|
|
||||||
analogout_write_u16(obj, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void analogout_free(dac_t *obj) {}
|
|
||||||
|
|
||||||
static inline void dac_write(dac_t *obj, int value) {
|
|
||||||
DAC0->DAT[obj->dac].DATL = (uint8_t)( value & 0xFF);
|
|
||||||
DAC0->DAT[obj->dac].DATH = (uint8_t)((value >> 8) & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int dac_read(dac_t *obj) {
|
|
||||||
return ((DAC0->DAT[obj->dac].DATH << 8) | DAC0->DAT[obj->dac].DATL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void analogout_write(dac_t *obj, float value) {
|
|
||||||
if (value < 0.0) {
|
|
||||||
dac_write(obj, 0);
|
|
||||||
} else if (value > 1.0) {
|
|
||||||
dac_write(obj, RANGE_12BIT);
|
|
||||||
} else {
|
|
||||||
dac_write(obj, value * (float)RANGE_12BIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void analogout_write_u16(dac_t *obj, uint16_t value) {
|
|
||||||
dac_write(obj, value >> 4); // 12-bit
|
|
||||||
}
|
|
||||||
|
|
||||||
float analogout_read(dac_t *obj) {
|
|
||||||
uint32_t value = dac_read(obj);
|
|
||||||
return (float)value * (1.0f / (float)RANGE_12BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t analogout_read_u16(dac_t *obj) {
|
|
||||||
uint32_t value = dac_read(obj); // 12-bit
|
|
||||||
return (value << 4) | ((value >> 8) & 0x003F);
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
/* 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"
|
|
||||||
|
|
||||||
static void init(void) {
|
|
||||||
// enable PORTC clock
|
|
||||||
SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
|
|
||||||
|
|
||||||
// enable RTC clock
|
|
||||||
SIM->SCGC6 |= SIM_SCGC6_RTC_MASK;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* configure PTC1 with alternate function 1: RTC_CLKIN
|
|
||||||
* As the kl25z board does not have a 32kHz osc,
|
|
||||||
* we use an external clock generated by the
|
|
||||||
* interface chip
|
|
||||||
*/
|
|
||||||
PORTC->PCR[1] &= ~PORT_PCR_MUX_MASK;
|
|
||||||
PORTC->PCR[1] = PORT_PCR_MUX(1);
|
|
||||||
|
|
||||||
// select RTC_CLKIN as RTC clock source
|
|
||||||
SIM->SOPT1 &= ~SIM_SOPT1_OSC32KSEL_MASK;
|
|
||||||
SIM->SOPT1 |= SIM_SOPT1_OSC32KSEL(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rtc_init(void) {
|
|
||||||
init();
|
|
||||||
|
|
||||||
//Configure the TSR. default value: 1
|
|
||||||
RTC->TSR = 1;
|
|
||||||
|
|
||||||
// enable counter
|
|
||||||
RTC->SR |= RTC_SR_TCE_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rtc_free(void) {
|
|
||||||
// [TODO]
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Little check routine to see if the RTC has been enabled
|
|
||||||
* 0 = Disabled, 1 = Enabled
|
|
||||||
*/
|
|
||||||
int rtc_isenabled(void) {
|
|
||||||
// even if the RTC module is enabled,
|
|
||||||
// as we use RTC_CLKIN and an external clock,
|
|
||||||
// we need to reconfigure the pins. That is why we
|
|
||||||
// call init() if the rtc is enabled
|
|
||||||
|
|
||||||
// if RTC not enabled return 0
|
|
||||||
SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
|
|
||||||
SIM->SCGC6 |= SIM_SCGC6_RTC_MASK;
|
|
||||||
if ((RTC->SR & RTC_SR_TCE_MASK) == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
init();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t rtc_read(void) {
|
|
||||||
return RTC->TSR;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rtc_write(time_t t) {
|
|
||||||
// disable counter
|
|
||||||
RTC->SR &= ~RTC_SR_TCE_MASK;
|
|
||||||
|
|
||||||
// we do not write 0 into TSR
|
|
||||||
// to avoid invalid time
|
|
||||||
if (t == 0)
|
|
||||||
t = 1;
|
|
||||||
|
|
||||||
// write seconds
|
|
||||||
RTC->TSR = t;
|
|
||||||
|
|
||||||
// re-enable counter
|
|
||||||
RTC->SR |= RTC_SR_TCE_MASK;
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
/* 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_PORTNAMES_H
|
|
||||||
#define MBED_PORTNAMES_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PortA = 0,
|
|
||||||
PortB = 1,
|
|
||||||
PortC = 2,
|
|
||||||
PortD = 3,
|
|
||||||
PortE = 4
|
|
||||||
} PortName;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
|
@ -1,94 +0,0 @@
|
||||||
/* 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 "analogin_api.h"
|
|
||||||
|
|
||||||
#include "cmsis.h"
|
|
||||||
#include "pinmap.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
static const PinMap PinMap_ADC[] = {
|
|
||||||
{PTE20, ADC0_SE0, 0},
|
|
||||||
{PTE22, ADC0_SE3, 0},
|
|
||||||
{PTE21, ADC0_SE4a, 0},
|
|
||||||
{PTE29, ADC0_SE4b, 0},
|
|
||||||
{PTE30, ADC0_SE23, 0},
|
|
||||||
{PTE23, ADC0_SE7a, 0},
|
|
||||||
{PTB0, ADC0_SE8, 0},
|
|
||||||
{PTB1, ADC0_SE9, 0},
|
|
||||||
{PTB2, ADC0_SE12, 0},
|
|
||||||
{PTB3, ADC0_SE13, 0},
|
|
||||||
{PTC0, ADC0_SE14, 0},
|
|
||||||
{PTC1, ADC0_SE15, 0},
|
|
||||||
{PTC2, ADC0_SE11, 0},
|
|
||||||
{PTD1, ADC0_SE5b, 0},
|
|
||||||
{PTD5, ADC0_SE6b, 0},
|
|
||||||
{PTD6, ADC0_SE7b, 0},
|
|
||||||
{NC, NC, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
void analogin_init(analogin_t *obj, PinName pin) {
|
|
||||||
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
|
|
||||||
if (obj->adc == (ADCName)NC) {
|
|
||||||
error("ADC pin mapping failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK;
|
|
||||||
|
|
||||||
uint32_t port = (uint32_t)pin >> PORT_SHIFT;
|
|
||||||
SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port);
|
|
||||||
|
|
||||||
uint32_t cfg2_muxsel = ADC_CFG2_MUXSEL_MASK;
|
|
||||||
if (obj->adc & (1 << CHANNELS_A_SHIFT)) {
|
|
||||||
cfg2_muxsel = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ADC0->SC1[1] = ADC_SC1_ADCH(obj->adc & ~(1 << CHANNELS_A_SHIFT));
|
|
||||||
|
|
||||||
ADC0->CFG1 = ADC_CFG1_ADLPC_MASK // Low-Power Configuration
|
|
||||||
| ADC_CFG1_ADIV(3) // Clock Divide Select: (Input Clock)/8
|
|
||||||
| ADC_CFG1_ADLSMP_MASK // Long Sample Time
|
|
||||||
| ADC_CFG1_MODE(3) // (16)bits Resolution
|
|
||||||
| ADC_CFG1_ADICLK(1); // Input Clock: (Bus Clock)/2
|
|
||||||
|
|
||||||
ADC0->CFG2 = cfg2_muxsel // ADxxb or ADxxa channels
|
|
||||||
| ADC_CFG2_ADACKEN_MASK // Asynchronous Clock Output Enable
|
|
||||||
| ADC_CFG2_ADHSC_MASK // High-Speed Configuration
|
|
||||||
| ADC_CFG2_ADLSTS(0); // Long Sample Time Select
|
|
||||||
|
|
||||||
ADC0->SC2 = ADC_SC2_REFSEL(0); // Default Voltage Reference
|
|
||||||
|
|
||||||
ADC0->SC3 = ADC_SC3_AVGE_MASK // Hardware Average Enable
|
|
||||||
| ADC_SC3_AVGS(0); // 4 Samples Averaged
|
|
||||||
|
|
||||||
pinmap_pinout(pin, PinMap_ADC);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t analogin_read_u16(analogin_t *obj) {
|
|
||||||
// start conversion
|
|
||||||
ADC0->SC1[0] = ADC_SC1_ADCH(obj->adc & ~(1 << CHANNELS_A_SHIFT));
|
|
||||||
|
|
||||||
// Wait Conversion Complete
|
|
||||||
while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK);
|
|
||||||
|
|
||||||
// Return value
|
|
||||||
return (uint16_t)ADC0->R[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
float analogin_read(analogin_t *obj) {
|
|
||||||
uint16_t value = analogin_read_u16(obj);
|
|
||||||
return (float)value * (1.0f / (float)0xFFFF);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
/* 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 "gpio_api.h"
|
|
||||||
#include "pinmap.h"
|
|
||||||
|
|
||||||
uint32_t gpio_set(PinName pin) {
|
|
||||||
pin_function(pin, 1);
|
|
||||||
return 1 << ((pin & 0x7F) >> 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_init(gpio_t *obj, PinName pin, PinDirection direction) {
|
|
||||||
if(pin == NC) return;
|
|
||||||
|
|
||||||
obj->pin = pin;
|
|
||||||
obj->mask = gpio_set(pin);
|
|
||||||
|
|
||||||
unsigned int port = (unsigned int)pin >> PORT_SHIFT;
|
|
||||||
|
|
||||||
FGPIO_Type *reg = (FGPIO_Type *)(FPTA_BASE + port * 0x40);
|
|
||||||
obj->reg_set = ®->PSOR;
|
|
||||||
obj->reg_clr = ®->PCOR;
|
|
||||||
obj->reg_in = ®->PDIR;
|
|
||||||
obj->reg_dir = ®->PDDR;
|
|
||||||
|
|
||||||
gpio_dir(obj, direction);
|
|
||||||
switch (direction) {
|
|
||||||
case PIN_OUTPUT: pin_mode(pin, PullNone); break;
|
|
||||||
case PIN_INPUT : pin_mode(pin, PullUp); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_mode(gpio_t *obj, PinMode mode) {
|
|
||||||
pin_mode(obj->pin, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_dir(gpio_t *obj, PinDirection direction) {
|
|
||||||
switch (direction) {
|
|
||||||
case PIN_INPUT : *obj->reg_dir &= ~obj->mask; break;
|
|
||||||
case PIN_OUTPUT: *obj->reg_dir |= obj->mask; break;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
/* 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
|
|
||||||
|
|
||||||
#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) {
|
|
||||||
if (value)
|
|
||||||
*obj->reg_set = obj->mask;
|
|
||||||
else
|
|
||||||
*obj->reg_clr = obj->mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int gpio_read(gpio_t *obj) {
|
|
||||||
return ((*obj->reg_in & obj->mask) ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,423 +0,0 @@
|
||||||
/* 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 "i2c_api.h"
|
|
||||||
|
|
||||||
#include "cmsis.h"
|
|
||||||
#include "pinmap.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
static const PinMap PinMap_I2C_SDA[] = {
|
|
||||||
{PTE25, I2C_0, 5},
|
|
||||||
{PTC9, I2C_0, 2},
|
|
||||||
{PTE0, I2C_1, 6},
|
|
||||||
{PTB1, I2C_0, 2},
|
|
||||||
{PTB3, I2C_0, 2},
|
|
||||||
{PTC11, I2C_1, 2},
|
|
||||||
{PTC2, I2C_1, 2},
|
|
||||||
{PTA4, I2C_1, 2},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PinMap PinMap_I2C_SCL[] = {
|
|
||||||
{PTE24, I2C_0, 5},
|
|
||||||
{PTC8, I2C_0, 2},
|
|
||||||
{PTE1, I2C_1, 6},
|
|
||||||
{PTB0, I2C_0, 2},
|
|
||||||
{PTB2, I2C_0, 2},
|
|
||||||
{PTC10, I2C_1, 2},
|
|
||||||
{PTC1, I2C_1, 2},
|
|
||||||
{NC , NC, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint16_t ICR[0x40] = {
|
|
||||||
20, 22, 24, 26, 28,
|
|
||||||
30, 34, 40, 28, 32,
|
|
||||||
36, 40, 44, 48, 56,
|
|
||||||
68, 48, 56, 64, 72,
|
|
||||||
80, 88, 104, 128, 80,
|
|
||||||
96, 112, 128, 144, 160,
|
|
||||||
192, 240, 160, 192, 224,
|
|
||||||
256, 288, 320, 384, 480,
|
|
||||||
320, 384, 448, 512, 576,
|
|
||||||
640, 768, 960, 640, 768,
|
|
||||||
896, 1024, 1152, 1280, 1536,
|
|
||||||
1920, 1280, 1536, 1792, 2048,
|
|
||||||
2304, 2560, 3072, 3840
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint8_t first_read;
|
|
||||||
|
|
||||||
|
|
||||||
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_Type*)pinmap_merge(i2c_sda, i2c_scl);
|
|
||||||
if ((int)obj->i2c == NC) {
|
|
||||||
error("I2C pin mapping failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// enable power
|
|
||||||
switch ((int)obj->i2c) {
|
|
||||||
case I2C_0: SIM->SCGC5 |= 1 << 13; SIM->SCGC4 |= 1 << 6; break;
|
|
||||||
case I2C_1: SIM->SCGC5 |= 1 << 11; SIM->SCGC4 |= 1 << 7; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set default frequency at 100k
|
|
||||||
i2c_frequency(obj, 100000);
|
|
||||||
|
|
||||||
// enable I2C interface
|
|
||||||
obj->i2c->C1 |= 0x80;
|
|
||||||
|
|
||||||
pinmap_pinout(sda, PinMap_I2C_SDA);
|
|
||||||
pinmap_pinout(scl, PinMap_I2C_SCL);
|
|
||||||
|
|
||||||
first_read = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_start(i2c_t *obj) {
|
|
||||||
uint8_t temp;
|
|
||||||
volatile int i;
|
|
||||||
// if we are in the middle of a transaction
|
|
||||||
// activate the repeat_start flag
|
|
||||||
if (obj->i2c->S & I2C_S_BUSY_MASK) {
|
|
||||||
// KL25Z errata sheet: repeat start cannot be generated if the
|
|
||||||
// I2Cx_F[MULT] field is set to a non-zero value
|
|
||||||
temp = obj->i2c->F >> 6;
|
|
||||||
obj->i2c->F &= 0x3F;
|
|
||||||
obj->i2c->C1 |= 0x04;
|
|
||||||
for (i = 0; i < 100; i ++) __NOP();
|
|
||||||
obj->i2c->F |= temp << 6;
|
|
||||||
} else {
|
|
||||||
obj->i2c->C1 |= I2C_C1_MST_MASK;
|
|
||||||
obj->i2c->C1 |= I2C_C1_TX_MASK;
|
|
||||||
}
|
|
||||||
first_read = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_stop(i2c_t *obj) {
|
|
||||||
volatile uint32_t n = 0;
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_MST_MASK;
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
// It seems that there are timing problems
|
|
||||||
// when there is no waiting time after a STOP.
|
|
||||||
// This wait is also included on the samples
|
|
||||||
// code provided with the freedom board
|
|
||||||
for (n = 0; n < 100; n++) __NOP();
|
|
||||||
first_read = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int timeout_status_poll(i2c_t *obj, uint32_t mask) {
|
|
||||||
uint32_t i, timeout = 1000;
|
|
||||||
|
|
||||||
for (i = 0; i < timeout; i++) {
|
|
||||||
if (obj->i2c->S & mask)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this function waits the end of a tx transfer and return the status of the transaction:
|
|
||||||
// 0: OK ack received
|
|
||||||
// 1: OK ack not received
|
|
||||||
// 2: failure
|
|
||||||
static int i2c_wait_end_tx_transfer(i2c_t *obj) {
|
|
||||||
|
|
||||||
// wait for the interrupt flag
|
|
||||||
if (timeout_status_poll(obj, I2C_S_IICIF_MASK)) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->i2c->S |= I2C_S_IICIF_MASK;
|
|
||||||
|
|
||||||
// wait transfer complete
|
|
||||||
if (timeout_status_poll(obj, I2C_S_TCF_MASK)) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we received the ACK or not
|
|
||||||
return obj->i2c->S & I2C_S_RXAK_MASK ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this function waits the end of a rx transfer and return the status of the transaction:
|
|
||||||
// 0: OK
|
|
||||||
// 1: failure
|
|
||||||
static int i2c_wait_end_rx_transfer(i2c_t *obj) {
|
|
||||||
// wait for the end of the rx transfer
|
|
||||||
if (timeout_status_poll(obj, I2C_S_IICIF_MASK)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->i2c->S |= I2C_S_IICIF_MASK;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_send_nack(i2c_t *obj) {
|
|
||||||
obj->i2c->C1 |= I2C_C1_TXAK_MASK; // NACK
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2c_send_ack(i2c_t *obj) {
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_TXAK_MASK; // ACK
|
|
||||||
}
|
|
||||||
|
|
||||||
static int i2c_do_write(i2c_t *obj, int value) {
|
|
||||||
// write the data
|
|
||||||
obj->i2c->D = value;
|
|
||||||
|
|
||||||
// init and wait the end of the transfer
|
|
||||||
return i2c_wait_end_tx_transfer(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int i2c_do_read(i2c_t *obj, char * data, int last) {
|
|
||||||
if (last)
|
|
||||||
i2c_send_nack(obj);
|
|
||||||
else
|
|
||||||
i2c_send_ack(obj);
|
|
||||||
|
|
||||||
*data = (obj->i2c->D & 0xFF);
|
|
||||||
|
|
||||||
// start rx transfer and wait the end of the transfer
|
|
||||||
return i2c_wait_end_rx_transfer(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2c_frequency(i2c_t *obj, int hz) {
|
|
||||||
uint8_t icr = 0;
|
|
||||||
uint8_t mult = 0;
|
|
||||||
uint32_t error = 0;
|
|
||||||
uint32_t p_error = 0xffffffff;
|
|
||||||
uint32_t ref = 0;
|
|
||||||
uint8_t i, j;
|
|
||||||
// bus clk
|
|
||||||
uint32_t PCLK = 24000000u;
|
|
||||||
uint32_t pulse = PCLK / (hz * 2);
|
|
||||||
|
|
||||||
// we look for the values that minimize the error
|
|
||||||
|
|
||||||
// test all the MULT values
|
|
||||||
for (i = 1; i < 5; i*=2) {
|
|
||||||
for (j = 0; j < 0x40; j++) {
|
|
||||||
ref = PCLK / (i*ICR[j]);
|
|
||||||
if (ref > (uint32_t)hz)
|
|
||||||
continue;
|
|
||||||
error = hz - ref;
|
|
||||||
if (error < p_error) {
|
|
||||||
icr = j;
|
|
||||||
mult = i/2;
|
|
||||||
p_error = error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pulse = icr | (mult << 6);
|
|
||||||
|
|
||||||
// I2C Rate
|
|
||||||
obj->i2c->F = pulse;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
|
|
||||||
int count;
|
|
||||||
char dummy_read, *ptr;
|
|
||||||
|
|
||||||
if (i2c_start(obj)) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
return I2C_ERROR_BUS_BUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i2c_do_write(obj, (address | 0x01))) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
return I2C_ERROR_NO_SLAVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set rx mode
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
// Read in bytes
|
|
||||||
for (count = 0; count < (length); count++) {
|
|
||||||
ptr = (count == 0) ? &dummy_read : &data[count - 1];
|
|
||||||
uint8_t stop_ = (count == (length - 1)) ? 1 : 0;
|
|
||||||
if (i2c_do_read(obj, ptr, stop_)) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not repeated start, send stop.
|
|
||||||
if (stop) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
// last read
|
|
||||||
data[count-1] = obj->i2c->D;
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (i2c_start(obj)) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
return I2C_ERROR_BUS_BUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i2c_do_write(obj, (address & 0xFE))) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
return I2C_ERROR_NO_SLAVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
if(i2c_do_write(obj, data[i])) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stop) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2c_reset(i2c_t *obj) {
|
|
||||||
i2c_stop(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_byte_read(i2c_t *obj, int last) {
|
|
||||||
char data;
|
|
||||||
|
|
||||||
// set rx mode
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
if(first_read) {
|
|
||||||
// first dummy read
|
|
||||||
i2c_do_read(obj, &data, 0);
|
|
||||||
first_read = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last) {
|
|
||||||
// set tx mode
|
|
||||||
obj->i2c->C1 |= I2C_C1_TX_MASK;
|
|
||||||
return obj->i2c->D;
|
|
||||||
}
|
|
||||||
|
|
||||||
i2c_do_read(obj, &data, last);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_byte_write(i2c_t *obj, int data) {
|
|
||||||
first_read = 1;
|
|
||||||
|
|
||||||
// set tx mode
|
|
||||||
obj->i2c->C1 |= I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
return !i2c_do_write(obj, (data & 0xFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if DEVICE_I2CSLAVE
|
|
||||||
void i2c_slave_mode(i2c_t *obj, int enable_slave) {
|
|
||||||
if (enable_slave) {
|
|
||||||
// set slave mode
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_MST_MASK;
|
|
||||||
obj->i2c->C1 |= I2C_C1_IICIE_MASK;
|
|
||||||
} else {
|
|
||||||
// set master mode
|
|
||||||
obj->i2c->C1 |= I2C_C1_MST_MASK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_slave_receive(i2c_t *obj) {
|
|
||||||
switch(obj->i2c->S) {
|
|
||||||
// read addressed
|
|
||||||
case 0xE6: return 1;
|
|
||||||
|
|
||||||
// write addressed
|
|
||||||
case 0xE2: return 3;
|
|
||||||
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_slave_read(i2c_t *obj, char *data, int length) {
|
|
||||||
uint8_t dummy_read;
|
|
||||||
uint8_t * ptr;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
// set rx mode
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
// first dummy read
|
|
||||||
dummy_read = obj->i2c->D;
|
|
||||||
if(i2c_wait_end_rx_transfer(obj)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read address
|
|
||||||
dummy_read = obj->i2c->D;
|
|
||||||
if(i2c_wait_end_rx_transfer(obj)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read (length - 1) bytes
|
|
||||||
for (count = 0; count < (length - 1); count++) {
|
|
||||||
data[count] = obj->i2c->D;
|
|
||||||
if(i2c_wait_end_rx_transfer(obj)) {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// read last byte
|
|
||||||
ptr = (length == 0) ? &dummy_read : (uint8_t *)&data[count];
|
|
||||||
*ptr = obj->i2c->D;
|
|
||||||
|
|
||||||
return (length) ? (count + 1) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i2c_slave_write(i2c_t *obj, const char *data, int length) {
|
|
||||||
int i, count = 0;
|
|
||||||
|
|
||||||
// set tx mode
|
|
||||||
obj->i2c->C1 |= I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
if(i2c_do_write(obj, data[count++]) == 2) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set rx mode
|
|
||||||
obj->i2c->C1 &= ~I2C_C1_TX_MASK;
|
|
||||||
|
|
||||||
// dummy rx transfer needed
|
|
||||||
// otherwise the master cannot generate a stop bit
|
|
||||||
obj->i2c->D;
|
|
||||||
if(i2c_wait_end_rx_transfer(obj) == 2) {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
|
|
||||||
obj->i2c->A1 = address & 0xfe;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
/* 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 port;
|
|
||||||
uint32_t pin;
|
|
||||||
uint32_t ch;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct port_s {
|
|
||||||
__IO uint32_t *reg_dir;
|
|
||||||
__IO uint32_t *reg_out;
|
|
||||||
__I uint32_t *reg_in;
|
|
||||||
PortName port;
|
|
||||||
uint32_t mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pwmout_s {
|
|
||||||
__IO uint32_t *MOD;
|
|
||||||
__IO uint32_t *CNT;
|
|
||||||
__IO uint32_t *CnV;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct serial_s {
|
|
||||||
UART0_Type *uart;
|
|
||||||
int index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct analogin_s {
|
|
||||||
ADCName adc;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct dac_s {
|
|
||||||
DACName dac;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct i2c_s {
|
|
||||||
I2C_Type *i2c;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct spi_s {
|
|
||||||
SPI_Type *spi;
|
|
||||||
};
|
|
||||||
|
|
||||||
#include "gpio_object.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,39 +0,0 @@
|
||||||
/* 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 "pinmap.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
void pin_function(PinName pin, int function) {
|
|
||||||
if (pin == (PinName)NC) return;
|
|
||||||
|
|
||||||
uint32_t port_n = (uint32_t)pin >> PORT_SHIFT;
|
|
||||||
uint32_t pin_n = (uint32_t)(pin & 0x7C) >> 2;
|
|
||||||
|
|
||||||
SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port_n);
|
|
||||||
__IO uint32_t* pin_pcr = &(((PORT_Type *)(PORTA_BASE + 0x1000 * port_n)))->PCR[pin_n];
|
|
||||||
|
|
||||||
// pin mux bits: [10:8] -> 11100000000 = (0x700)
|
|
||||||
*pin_pcr = (*pin_pcr & ~0x700) | (function << 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pin_mode(PinName pin, PinMode mode) {
|
|
||||||
if (pin == (PinName)NC) { return; }
|
|
||||||
|
|
||||||
__IO uint32_t* pin_pcr = (__IO uint32_t*)(PORTA_BASE + pin);
|
|
||||||
|
|
||||||
// pin pullup bits: [1:0] -> 11 = (0x3)
|
|
||||||
*pin_pcr = (*pin_pcr & ~0x3) | mode;
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
/* 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 "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 << 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
void port_init(port_t *obj, PortName port, int mask, PinDirection dir) {
|
|
||||||
obj->port = port;
|
|
||||||
obj->mask = mask;
|
|
||||||
|
|
||||||
FGPIO_Type *reg = (FGPIO_Type *)(FPTA_BASE + port * 0x40);
|
|
||||||
|
|
||||||
obj->reg_out = ®->PDOR;
|
|
||||||
obj->reg_in = ®->PDIR;
|
|
||||||
obj->reg_dir = ®->PDDR;
|
|
||||||
|
|
||||||
uint32_t i;
|
|
||||||
// The function is set per pin: reuse gpio logic
|
|
||||||
for (i=0; i<32; 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_out = (*obj->reg_in & ~obj->mask) | (value & obj->mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
int port_read(port_t *obj) {
|
|
||||||
return (*obj->reg_in & obj->mask);
|
|
||||||
}
|
|
|
@ -1,143 +0,0 @@
|
||||||
/* 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 "pwmout_api.h"
|
|
||||||
|
|
||||||
#include "cmsis.h"
|
|
||||||
#include "pinmap.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
static const PinMap PinMap_PWM[] = {
|
|
||||||
// LEDs - only RED pin is PWM capable
|
|
||||||
{LED_RED, PWM_3, 3}, // PTE29, TPM0 CH2
|
|
||||||
|
|
||||||
// Arduino digital pinout
|
|
||||||
{D0, PWM_9 , 3}, // PTA1 , TPM2 CH0
|
|
||||||
{D1, PWM_10, 3}, // PTA2 , TPM2 CH1
|
|
||||||
{D2, PWM_4 , 4}, // PTD3 , TPM0 CH3
|
|
||||||
{D3, PWM_7 , 3}, // PTA12, TPM1 CH0
|
|
||||||
{D4, PWM_2 , 3}, // PTA4 , TPM0 CH1
|
|
||||||
{D5, PWM_3 , 3}, // PTA5 , TPM0 CH2
|
|
||||||
{D6, PWM_5 , 3}, // PTC8 , TPM0 CH4
|
|
||||||
{D7, PWM_6 , 3}, // PTC9 , TPM0 CH5
|
|
||||||
{D8, PWM_8 , 3}, // PTA13, TPM1 CH1
|
|
||||||
{D9, PWM_3 , 4}, // PTD2 , TPM0 CH2
|
|
||||||
{D10, PWM_5 , 4}, // PTD4 , TPM0 CH4
|
|
||||||
//PWM on D11 not available
|
|
||||||
//PWM on D12 not available
|
|
||||||
{D13, PWM_2 , 4}, // PTD5 , TPM0 CH1,
|
|
||||||
|
|
||||||
{PTA0, PWM_6, 3},
|
|
||||||
{PTA3, PWM_1, 3},
|
|
||||||
{PTA6, PWM_4, 3},
|
|
||||||
{PTA7, PWM_5, 3},
|
|
||||||
{PTB0, PWM_7, 3},
|
|
||||||
{PTB1, PWM_8, 3},
|
|
||||||
{PTB2, PWM_9, 3},
|
|
||||||
{PTB3, PWM_10, 3},
|
|
||||||
{PTC1, PWM_1, 4},
|
|
||||||
{PTC2, PWM_2, 4},
|
|
||||||
{PTC3, PWM_3, 4},
|
|
||||||
{PTC4, PWM_4, 4},
|
|
||||||
{PTE20, PWM_7, 3},
|
|
||||||
{PTE21, PWM_8, 3},
|
|
||||||
{PTE22, PWM_9, 3},
|
|
||||||
{PTE23, PWM_10, 3},
|
|
||||||
{PTE24, PWM_1, 3},
|
|
||||||
{PTE25, PWM_2, 3},
|
|
||||||
{PTE26, PWM_6, 3},
|
|
||||||
{PTE29, PWM_3, 3},
|
|
||||||
{PTE30, PWM_4, 3},
|
|
||||||
{PTE31, PWM_5, 3},
|
|
||||||
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PWM_CLOCK_MHZ (0.75) // (48)MHz / 64 = (0.75)MHz
|
|
||||||
|
|
||||||
void pwmout_init(pwmout_t* obj, PinName pin) {
|
|
||||||
// determine the channel
|
|
||||||
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
|
|
||||||
if (pwm == (PWMName)NC)
|
|
||||||
error("PwmOut pin mapping failed");
|
|
||||||
|
|
||||||
unsigned int port = (unsigned int)pin >> PORT_SHIFT;
|
|
||||||
unsigned int tpm_n = (pwm >> TPM_SHIFT);
|
|
||||||
unsigned int ch_n = (pwm & 0xFF);
|
|
||||||
|
|
||||||
SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port);
|
|
||||||
SIM->SCGC6 |= 1 << (SIM_SCGC6_TPM0_SHIFT + tpm_n);
|
|
||||||
SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); // Clock source: MCGFLLCLK or MCGPLLCLK
|
|
||||||
|
|
||||||
TPM_Type *tpm = (TPM_Type *)(TPM0_BASE + 0x1000 * tpm_n);
|
|
||||||
tpm->SC = TPM_SC_CMOD(1) | TPM_SC_PS(6); // (48)MHz / 64 = (0.75)MHz
|
|
||||||
tpm->CONTROLS[ch_n].CnSC = (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK); /* No Interrupts; High True pulses on Edge Aligned PWM */
|
|
||||||
|
|
||||||
obj->CnV = &tpm->CONTROLS[ch_n].CnV;
|
|
||||||
obj->MOD = &tpm->MOD;
|
|
||||||
obj->CNT = &tpm->CNT;
|
|
||||||
|
|
||||||
// default to 20ms: standard for servos, and fine for e.g. brightness control
|
|
||||||
pwmout_period_ms(obj, 20);
|
|
||||||
pwmout_write (obj, 0);
|
|
||||||
|
|
||||||
// Wire pinout
|
|
||||||
pinmap_pinout(pin, PinMap_PWM);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pwmout_free(pwmout_t* obj) {}
|
|
||||||
|
|
||||||
void pwmout_write(pwmout_t* obj, float value) {
|
|
||||||
if (value < 0.0) {
|
|
||||||
value = 0.0;
|
|
||||||
} else if (value > 1.0) {
|
|
||||||
value = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*obj->CnV = (uint32_t)((float)(*obj->MOD) * value);
|
|
||||||
*obj->CNT = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float pwmout_read(pwmout_t* obj) {
|
|
||||||
float v = (float)(*obj->CnV) / (float)(*obj->MOD);
|
|
||||||
return (v > 1.0) ? (1.0) : (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) {
|
|
||||||
float dc = pwmout_read(obj);
|
|
||||||
*obj->MOD = PWM_CLOCK_MHZ * us;
|
|
||||||
pwmout_write(obj, dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
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->CnV = PWM_CLOCK_MHZ * us;
|
|
||||||
}
|
|
|
@ -1,317 +0,0 @@
|
||||||
/* 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 "serial_api.h"
|
|
||||||
|
|
||||||
// math.h required for floating point operations for baud rate calculation
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "cmsis.h"
|
|
||||||
#include "pinmap.h"
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* INITIALIZATION
|
|
||||||
******************************************************************************/
|
|
||||||
static const PinMap PinMap_UART_TX[] = {
|
|
||||||
{PTA2, UART_0, 2},
|
|
||||||
{PTA14, UART_0, 3},
|
|
||||||
{PTC4, UART_1, 3},
|
|
||||||
{PTD3, UART_2, 3},
|
|
||||||
{PTD5, UART_2, 3},
|
|
||||||
{PTD7, UART_0, 3},
|
|
||||||
{PTE0, UART_1, 3},
|
|
||||||
{PTE16, UART_2, 3},
|
|
||||||
{PTE20, UART_0, 4},
|
|
||||||
{PTE22, UART_2, 4},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PinMap PinMap_UART_RX[] = {
|
|
||||||
{PTA1, UART_0, 2},
|
|
||||||
{PTA15, UART_0, 3},
|
|
||||||
{PTC3, UART_1, 3},
|
|
||||||
{PTD2, UART_2, 3},
|
|
||||||
{PTD4, UART_2, 3},
|
|
||||||
{PTD6, UART_0, 3},
|
|
||||||
{PTE1, UART_1, 3},
|
|
||||||
{PTE17, UART_2, 3},
|
|
||||||
{PTE21, UART_0, 4},
|
|
||||||
{PTE23, UART_2, 4},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define UART_NUM 3
|
|
||||||
static uint32_t serial_irq_ids[UART_NUM] = {0};
|
|
||||||
static uart_irq_handler irq_handler;
|
|
||||||
|
|
||||||
int stdio_uart_inited = 0;
|
|
||||||
serial_t stdio_uart;
|
|
||||||
|
|
||||||
void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
|
||||||
// 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 = (UART0_Type *)uart;
|
|
||||||
// enable clk
|
|
||||||
switch (uart) {
|
|
||||||
case UART_0: SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK | (1<<SIM_SOPT2_UART0SRC_SHIFT);
|
|
||||||
SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK; SIM->SCGC4 |= SIM_SCGC4_UART0_MASK; break;
|
|
||||||
case UART_1: SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK; SIM->SCGC4 |= SIM_SCGC4_UART1_MASK; break;
|
|
||||||
case UART_2: SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK; SIM->SCGC4 |= SIM_SCGC4_UART2_MASK; break;
|
|
||||||
}
|
|
||||||
// Disable UART before changing registers
|
|
||||||
obj->uart->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
|
|
||||||
|
|
||||||
switch (uart) {
|
|
||||||
case UART_0: obj->index = 0; break;
|
|
||||||
case UART_1: obj->index = 1; break;
|
|
||||||
case UART_2: obj->index = 2; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set default baud rate and format
|
|
||||||
serial_baud (obj, 9600);
|
|
||||||
serial_format(obj, 8, ParityNone, 1);
|
|
||||||
|
|
||||||
// pinout the chosen uart
|
|
||||||
pinmap_pinout(tx, PinMap_UART_TX);
|
|
||||||
pinmap_pinout(rx, PinMap_UART_RX);
|
|
||||||
|
|
||||||
// set rx/tx pins in PullUp mode
|
|
||||||
pin_mode(tx, PullUp);
|
|
||||||
pin_mode(rx, PullUp);
|
|
||||||
|
|
||||||
obj->uart->C2 |= (UART_C2_RE_MASK | UART_C2_TE_MASK);
|
|
||||||
|
|
||||||
if (uart == STDIO_UART) {
|
|
||||||
stdio_uart_inited = 1;
|
|
||||||
memcpy(&stdio_uart, obj, sizeof(serial_t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_free(serial_t *obj) {
|
|
||||||
serial_irq_ids[obj->index] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// serial_baud
|
|
||||||
//
|
|
||||||
// set the baud rate, taking in to account the current SystemFrequency
|
|
||||||
//
|
|
||||||
// The LPC2300 and LPC1700 have a divider and a fractional divider to control the
|
|
||||||
// baud rate. The formula is:
|
|
||||||
//
|
|
||||||
// Baudrate = (1 / PCLK) * 16 * DL * (1 + DivAddVal / MulVal)
|
|
||||||
// where:
|
|
||||||
// 1 < MulVal <= 15
|
|
||||||
// 0 <= DivAddVal < 14
|
|
||||||
// DivAddVal < MulVal
|
|
||||||
//
|
|
||||||
void serial_baud(serial_t *obj, int baudrate) {
|
|
||||||
|
|
||||||
// save C2 state
|
|
||||||
uint8_t c2_state = (obj->uart->C2 & (UART_C2_RE_MASK | UART_C2_TE_MASK));
|
|
||||||
|
|
||||||
// Disable UART before changing registers
|
|
||||||
obj->uart->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
|
|
||||||
|
|
||||||
// [TODO] not hardcode this value
|
|
||||||
uint32_t PCLK = (obj->uart == UART0) ? 48000000u : 24000000u;
|
|
||||||
|
|
||||||
// First we check to see if the basic divide with no DivAddVal/MulVal
|
|
||||||
// ratio gives us an integer result. If it does, we set DivAddVal = 0,
|
|
||||||
// MulVal = 1. Otherwise, we search the valid ratio value range to find
|
|
||||||
// the closest match. This could be more elegant, using search methods
|
|
||||||
// and/or lookup tables, but the brute force method is not that much
|
|
||||||
// slower, and is more maintainable.
|
|
||||||
uint16_t DL = PCLK / (16 * baudrate);
|
|
||||||
|
|
||||||
// set BDH and BDL
|
|
||||||
obj->uart->BDH = (obj->uart->BDH & ~(0x1f)) | ((DL >> 8) & 0x1f);
|
|
||||||
obj->uart->BDL = (obj->uart->BDL & ~(0xff)) | ((DL >> 0) & 0xff);
|
|
||||||
|
|
||||||
// restore C2 state
|
|
||||||
obj->uart->C2 |= c2_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
|
|
||||||
uint8_t m10 = 0;
|
|
||||||
|
|
||||||
// save C2 state
|
|
||||||
uint8_t c2_state = (obj->uart->C2 & (UART_C2_RE_MASK | UART_C2_TE_MASK));
|
|
||||||
|
|
||||||
// Disable UART before changing registers
|
|
||||||
obj->uart->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
|
|
||||||
|
|
||||||
// 8 data bits = 0 ... 9 data bits = 1
|
|
||||||
if ((data_bits < 8) || (data_bits > 9)) {
|
|
||||||
error("Invalid number of bits (%d) in serial format, should be 8..9\r\n", data_bits);
|
|
||||||
}
|
|
||||||
data_bits -= 8;
|
|
||||||
|
|
||||||
uint8_t parity_enable, parity_select;
|
|
||||||
switch (parity) {
|
|
||||||
case ParityNone: parity_enable = 0; parity_select = 0; break;
|
|
||||||
case ParityOdd : parity_enable = 1; parity_select = 1; data_bits++; break;
|
|
||||||
case ParityEven: parity_enable = 1; parity_select = 0; data_bits++; break;
|
|
||||||
default:
|
|
||||||
error("Invalid serial parity setting\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1 stop bits = 0, 2 stop bits = 1
|
|
||||||
if ((stop_bits != 1) && (stop_bits != 2)) {
|
|
||||||
error("Invalid stop bits specified\r\n");
|
|
||||||
}
|
|
||||||
stop_bits -= 1;
|
|
||||||
|
|
||||||
// 9 data bits + parity
|
|
||||||
if (data_bits == 2) {
|
|
||||||
// only uart0 supports 10 bit communication
|
|
||||||
if (obj->index != 0) {
|
|
||||||
error("Invalid number of bits (9) to be used with parity\r\n");
|
|
||||||
}
|
|
||||||
data_bits = 0;
|
|
||||||
m10 = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// data bits, parity and parity mode
|
|
||||||
obj->uart->C1 = ((data_bits << 4)
|
|
||||||
| (parity_enable << 1)
|
|
||||||
| (parity_select << 0));
|
|
||||||
|
|
||||||
// enable 10bit mode if needed
|
|
||||||
if (obj->index == 0) {
|
|
||||||
obj->uart->C4 &= ~UART0_C4_M10_MASK;
|
|
||||||
obj->uart->C4 |= (m10 << UART0_C4_M10_SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop bits
|
|
||||||
obj->uart->BDH &= ~UART_BDH_SBNS_MASK;
|
|
||||||
obj->uart->BDH |= (stop_bits << UART_BDH_SBNS_SHIFT);
|
|
||||||
|
|
||||||
// restore C2 state
|
|
||||||
obj->uart->C2 |= c2_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* INTERRUPTS HANDLING
|
|
||||||
******************************************************************************/
|
|
||||||
static inline void uart_irq(uint8_t status, uint32_t index) {
|
|
||||||
if (serial_irq_ids[index] != 0) {
|
|
||||||
if (status & UART_S1_TDRE_MASK)
|
|
||||||
irq_handler(serial_irq_ids[index], TxIrq);
|
|
||||||
|
|
||||||
if (status & UART_S1_RDRF_MASK)
|
|
||||||
irq_handler(serial_irq_ids[index], RxIrq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void uart0_irq() {
|
|
||||||
uart_irq(UART0->S1, 0);
|
|
||||||
if (UART0->S1 & UART_S1_OR_MASK)
|
|
||||||
UART0->S1 |= UART_S1_OR_MASK;
|
|
||||||
}
|
|
||||||
void uart1_irq() {uart_irq(UART1->S1, 1);}
|
|
||||||
void uart2_irq() {uart_irq(UART2->S1, 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 UART_0: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break;
|
|
||||||
case UART_1: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break;
|
|
||||||
case UART_2: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable) {
|
|
||||||
switch (irq) {
|
|
||||||
case RxIrq: obj->uart->C2 |= (UART_C2_RIE_MASK); break;
|
|
||||||
case TxIrq: obj->uart->C2 |= (UART_C2_TIE_MASK); break;
|
|
||||||
}
|
|
||||||
NVIC_SetVector(irq_n, vector);
|
|
||||||
NVIC_EnableIRQ(irq_n);
|
|
||||||
|
|
||||||
} else { // disable
|
|
||||||
int all_disabled = 0;
|
|
||||||
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
|
|
||||||
switch (irq) {
|
|
||||||
case RxIrq: obj->uart->C2 &= ~(UART_C2_RIE_MASK); break;
|
|
||||||
case TxIrq: obj->uart->C2 &= ~(UART_C2_TIE_MASK); break;
|
|
||||||
}
|
|
||||||
switch (other_irq) {
|
|
||||||
case RxIrq: all_disabled = (obj->uart->C2 & (UART_C2_RIE_MASK)) == 0; break;
|
|
||||||
case TxIrq: all_disabled = (obj->uart->C2 & (UART_C2_TIE_MASK)) == 0; break;
|
|
||||||
}
|
|
||||||
if (all_disabled)
|
|
||||||
NVIC_DisableIRQ(irq_n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* READ/WRITE
|
|
||||||
******************************************************************************/
|
|
||||||
int serial_getc(serial_t *obj) {
|
|
||||||
while (!serial_readable(obj));
|
|
||||||
return obj->uart->D;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_putc(serial_t *obj, int c) {
|
|
||||||
while (!serial_writable(obj));
|
|
||||||
obj->uart->D = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
int serial_readable(serial_t *obj) {
|
|
||||||
// check overrun
|
|
||||||
if (obj->uart->S1 & UART_S1_OR_MASK) {
|
|
||||||
obj->uart->S1 |= UART_S1_OR_MASK;
|
|
||||||
}
|
|
||||||
return (obj->uart->S1 & UART_S1_RDRF_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
int serial_writable(serial_t *obj) {
|
|
||||||
// check overrun
|
|
||||||
if (obj->uart->S1 & UART_S1_OR_MASK) {
|
|
||||||
obj->uart->S1 |= UART_S1_OR_MASK;
|
|
||||||
}
|
|
||||||
return (obj->uart->S1 & UART_S1_TDRE_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_clear(serial_t *obj) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_pinout_tx(PinName tx) {
|
|
||||||
pinmap_pinout(tx, PinMap_UART_TX);
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_break_set(serial_t *obj) {
|
|
||||||
obj->uart->C2 |= UART_C2_SBK_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_break_clear(serial_t *obj) {
|
|
||||||
obj->uart->C2 &= ~UART_C2_SBK_MASK;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
/* 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 "sleep_api.h"
|
|
||||||
#include "cmsis.h"
|
|
||||||
|
|
||||||
//Normal wait mode
|
|
||||||
void sleep(void)
|
|
||||||
{
|
|
||||||
SMC->PMPROT = SMC_PMPROT_AVLLS_MASK | SMC_PMPROT_ALLS_MASK | SMC_PMPROT_AVLP_MASK;
|
|
||||||
|
|
||||||
//Normal sleep mode for ARM core:
|
|
||||||
SCB->SCR = 0;
|
|
||||||
__WFI();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Very low-power stop mode
|
|
||||||
void deepsleep(void)
|
|
||||||
{
|
|
||||||
//Check if PLL/FLL is enabled:
|
|
||||||
uint32_t PLL_FLL_en = (MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(0);
|
|
||||||
|
|
||||||
SMC->PMPROT = SMC_PMPROT_AVLLS_MASK | SMC_PMPROT_ALLS_MASK | SMC_PMPROT_AVLP_MASK;
|
|
||||||
SMC->PMCTRL = SMC_PMCTRL_STOPM(2);
|
|
||||||
|
|
||||||
//Deep sleep for ARM core:
|
|
||||||
SCB->SCR = 1<<SCB_SCR_SLEEPDEEP_Pos;
|
|
||||||
|
|
||||||
__WFI();
|
|
||||||
|
|
||||||
//Switch back to PLL as clock source if needed
|
|
||||||
//The interrupt that woke up the device will run at reduced speed
|
|
||||||
if (PLL_FLL_en) {
|
|
||||||
if (MCG->C6 & (1<<MCG_C6_PLLS_SHIFT) != 0) /* If PLL */
|
|
||||||
while((MCG->S & MCG_S_LOCK0_MASK) == 0x00U); /* Wait until locked */
|
|
||||||
MCG->C1 &= ~MCG_C1_CLKS_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,146 +0,0 @@
|
||||||
/* 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"
|
|
||||||
|
|
||||||
static void pit_init(void);
|
|
||||||
static void lptmr_init(void);
|
|
||||||
|
|
||||||
static int us_ticker_inited = 0;
|
|
||||||
|
|
||||||
void us_ticker_init(void) {
|
|
||||||
if (us_ticker_inited) return;
|
|
||||||
us_ticker_inited = 1;
|
|
||||||
|
|
||||||
pit_init();
|
|
||||||
lptmr_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Timer for us timing.
|
|
||||||
******************************************************************************/
|
|
||||||
static void pit_init(void) {
|
|
||||||
SIM->SCGC6 |= SIM_SCGC6_PIT_MASK; // Clock PIT
|
|
||||||
PIT->MCR = 0; // Enable PIT
|
|
||||||
|
|
||||||
// Channel 1
|
|
||||||
PIT->CHANNEL[1].LDVAL = 0xFFFFFFFF;
|
|
||||||
PIT->CHANNEL[1].TCTRL = PIT_TCTRL_CHN_MASK; // Chain to timer 0, disable Interrupts
|
|
||||||
PIT->CHANNEL[1].TCTRL |= PIT_TCTRL_TEN_MASK; // Start timer 1
|
|
||||||
|
|
||||||
// Use channel 0 as a prescaler for channel 1
|
|
||||||
PIT->CHANNEL[0].LDVAL = 23;
|
|
||||||
PIT->CHANNEL[0].TCTRL = PIT_TCTRL_TEN_MASK; // Start timer 0, disable interrupts
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t us_ticker_read() {
|
|
||||||
if (!us_ticker_inited)
|
|
||||||
us_ticker_init();
|
|
||||||
|
|
||||||
// The PIT is a countdown timer
|
|
||||||
return ~(PIT->CHANNEL[1].CVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Timer Event
|
|
||||||
*
|
|
||||||
* It schedules interrupts at given (32bit)us interval of time.
|
|
||||||
* It is implemented used the 16bit Low Power Timer that remains powered in all
|
|
||||||
* power modes.
|
|
||||||
******************************************************************************/
|
|
||||||
static void lptmr_isr(void);
|
|
||||||
|
|
||||||
static void lptmr_init(void) {
|
|
||||||
/* Clock the timer */
|
|
||||||
SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK;
|
|
||||||
|
|
||||||
/* Reset */
|
|
||||||
LPTMR0->CSR = 0;
|
|
||||||
|
|
||||||
/* Set interrupt handler */
|
|
||||||
NVIC_SetVector(LPTimer_IRQn, (uint32_t)lptmr_isr);
|
|
||||||
NVIC_EnableIRQ(LPTimer_IRQn);
|
|
||||||
|
|
||||||
/* Clock at (1)MHz -> (1)tick/us */
|
|
||||||
LPTMR0->PSR = LPTMR_PSR_PCS(3); // OSCERCLK -> 8MHz
|
|
||||||
LPTMR0->PSR |= LPTMR_PSR_PRESCALE(2); // divide by 8
|
|
||||||
}
|
|
||||||
|
|
||||||
void us_ticker_disable_interrupt(void) {
|
|
||||||
LPTMR0->CSR &= ~LPTMR_CSR_TIE_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void us_ticker_clear_interrupt(void) {
|
|
||||||
// we already clear interrupt in lptmr_isr
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t us_ticker_int_counter = 0;
|
|
||||||
static uint16_t us_ticker_int_remainder = 0;
|
|
||||||
|
|
||||||
static void lptmr_set(unsigned short count) {
|
|
||||||
/* Reset */
|
|
||||||
LPTMR0->CSR = 0;
|
|
||||||
|
|
||||||
/* Set the compare register */
|
|
||||||
LPTMR0->CMR = count;
|
|
||||||
|
|
||||||
/* Enable interrupt */
|
|
||||||
LPTMR0->CSR |= LPTMR_CSR_TIE_MASK;
|
|
||||||
|
|
||||||
/* Start the timer */
|
|
||||||
LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lptmr_isr(void) {
|
|
||||||
// write 1 to TCF to clear the LPT timer compare flag
|
|
||||||
LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;
|
|
||||||
|
|
||||||
if (us_ticker_int_counter > 0) {
|
|
||||||
lptmr_set(0xFFFF);
|
|
||||||
us_ticker_int_counter--;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (us_ticker_int_remainder > 0) {
|
|
||||||
lptmr_set(us_ticker_int_remainder);
|
|
||||||
us_ticker_int_remainder = 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// This function is going to disable the interrupts if there are
|
|
||||||
// no other events in the queue
|
|
||||||
us_ticker_irq_handler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void us_ticker_set_interrupt(unsigned int timestamp) {
|
|
||||||
int delta = (int)(timestamp - us_ticker_read());
|
|
||||||
if (delta <= 0) {
|
|
||||||
// This event was in the past:
|
|
||||||
us_ticker_irq_handler();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
us_ticker_int_counter = (uint32_t)(delta >> 16);
|
|
||||||
us_ticker_int_remainder = (uint16_t)(0xFFFF & delta);
|
|
||||||
if (us_ticker_int_counter > 0) {
|
|
||||||
lptmr_set(0xFFFF);
|
|
||||||
us_ticker_int_counter--;
|
|
||||||
} else {
|
|
||||||
lptmr_set(us_ticker_int_remainder);
|
|
||||||
us_ticker_int_remainder = 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/* 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_PERIPHERALPINS_H
|
||||||
|
#define MBED_PERIPHERALPINS_H
|
||||||
|
|
||||||
|
#include "pinmap.h"
|
||||||
|
#include "PeripheralNames.h"
|
||||||
|
|
||||||
|
/************RTC***************/
|
||||||
|
extern const PinMap PinMap_RTC[];
|
||||||
|
|
||||||
|
/************ADC***************/
|
||||||
|
extern const PinMap PinMap_ADC[];
|
||||||
|
|
||||||
|
/************DAC***************/
|
||||||
|
extern const PinMap PinMap_DAC[];
|
||||||
|
|
||||||
|
/************I2C***************/
|
||||||
|
extern const PinMap PinMap_I2C_SDA[];
|
||||||
|
extern const PinMap PinMap_I2C_SCL[];
|
||||||
|
|
||||||
|
/************UART***************/
|
||||||
|
extern const PinMap PinMap_UART_TX[];
|
||||||
|
extern const PinMap PinMap_UART_RX[];
|
||||||
|
|
||||||
|
/************SPI***************/
|
||||||
|
extern const PinMap PinMap_SPI_SCLK[];
|
||||||
|
extern const PinMap PinMap_SPI_MOSI[];
|
||||||
|
extern const PinMap PinMap_SPI_MISO[];
|
||||||
|
extern const PinMap PinMap_SPI_SSEL[];
|
||||||
|
|
||||||
|
/************PWM***************/
|
||||||
|
extern const PinMap PinMap_PWM[];
|
||||||
|
|
||||||
|
#endif
|
|
@ -22,6 +22,11 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
OSC32KCLK = 0,
|
||||||
|
RTC_CLKIN = 2
|
||||||
|
} RTCName;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UART_0 = (int)UART0_BASE
|
UART_0 = (int)UART0_BASE
|
||||||
} UARTName;
|
} UARTName;
|
||||||
|
@ -31,7 +36,8 @@ typedef enum {
|
||||||
#define STDIO_UART UART_0
|
#define STDIO_UART UART_0
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
I2C_0 = (int)I2C0_BASE
|
I2C_0 = (int)I2C0_BASE,
|
||||||
|
I2C_1 = -1
|
||||||
} I2CName;
|
} I2CName;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
|
@ -0,0 +1,111 @@
|
||||||
|
/* 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 "PeripheralPins.h"
|
||||||
|
|
||||||
|
/************RTC***************/
|
||||||
|
const PinMap PinMap_RTC[] = {
|
||||||
|
{NC, OSC32KCLK, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
/************ADC***************/
|
||||||
|
const PinMap PinMap_ADC[] = {
|
||||||
|
/* A0-A5 pins */
|
||||||
|
{PTA0, ADC0_SE12, 0},
|
||||||
|
{PTA8, ADC0_SE3, 0},
|
||||||
|
{PTA9, ADC0_SE2, 0},
|
||||||
|
{PTB8, ADC0_SE11, 0},
|
||||||
|
{PTB9, ADC0_SE10, 0},
|
||||||
|
{PTB13, ADC0_SE13, 0},
|
||||||
|
/* Rest of pins ADC Mux */
|
||||||
|
{PTB2, ADC0_SE4, 0},
|
||||||
|
{PTB1, ADC0_SE5, 0},
|
||||||
|
{PTB5, ADC0_SE1, 0},
|
||||||
|
{PTA12, ADC0_SE0, 0},
|
||||||
|
{PTB10, ADC0_SE9, 0},
|
||||||
|
{PTB11, ADC0_SE8, 0},
|
||||||
|
{PTB7, ADC0_SE7, 0},
|
||||||
|
{PTB0, ADC0_SE6, 0},
|
||||||
|
{NC, NC, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************DAC***************/
|
||||||
|
const PinMap PinMap_DAC[] = {
|
||||||
|
{PTB1, DAC_0, 0},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************I2C***************/
|
||||||
|
const PinMap PinMap_I2C_SDA[] = {
|
||||||
|
{PTB4, I2C_0, 2},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_I2C_SCL[] = {
|
||||||
|
{PTB3, I2C_0, 2},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
/************UART***************/
|
||||||
|
const PinMap PinMap_UART_TX[] = {
|
||||||
|
{PTB1, UART_0, 2},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_UART_RX[] = {
|
||||||
|
{PTB2, UART_0, 2},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************SPI***************/
|
||||||
|
const PinMap PinMap_SPI_SCLK[] = {
|
||||||
|
{PTB0, SPI_0, 3},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_SPI_MOSI[] = {
|
||||||
|
{PTA7, SPI_0, 3},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_SPI_MISO[] = {
|
||||||
|
{PTA6, SPI_0, 3},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_SPI_SSEL[] = {
|
||||||
|
{PTA5, SPI_0, 3},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************PWM***************/
|
||||||
|
const PinMap PinMap_PWM[] = {
|
||||||
|
// LEDs
|
||||||
|
{LED_RED , PWM_4 , 2}, // PTB8 , TPM0 CH3
|
||||||
|
{LED_GREEN, PWM_3, 2}, // PTB9 , TPM0 CH2
|
||||||
|
{LED_BLUE , PWM_2 , 2}, // PTB10, TPM0 CH1
|
||||||
|
|
||||||
|
// Arduino digital pinout
|
||||||
|
{D3, PWM_8 , 2}, // PTB5 , TPM1 CH1
|
||||||
|
{D5, PWM_7 , 2}, // PTA12, TPM1 CH0
|
||||||
|
{D6, PWM_4 , 2}, // PTB6 , TPM0 CH3
|
||||||
|
{D7, PWM_3 , 2}, // PTB7 , TPM0 CH2
|
||||||
|
{D8, PWM_2 , 2}, // PTB10, TPM0 CH1
|
||||||
|
{D9, PWM_1 , 2}, // PTB11, TPM0 CH0
|
||||||
|
{D10, PWM_6 , 2}, // PTA5 , TPM0 CH5
|
||||||
|
{D12, PWM_5 , 2}, // PTA6 , TPM0 CH4
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
OSC32KCLK = 0,
|
||||||
|
RTC_CLKIN = 2
|
||||||
|
} RTCName;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UART_0 = (int)UART0_BASE,
|
UART_0 = (int)UART0_BASE,
|
||||||
UART_1 = (int)UART1_BASE,
|
UART_1 = (int)UART1_BASE,
|
||||||
|
@ -52,7 +57,7 @@ typedef enum {
|
||||||
PWM_10 = (2 << TPM_SHIFT) | (1) // TPM2 CH1
|
PWM_10 = (2 << TPM_SHIFT) | (1) // TPM2 CH1
|
||||||
} PWMName;
|
} PWMName;
|
||||||
|
|
||||||
#define CHANNELS_A_SHIFT 5
|
#define CHANNELS_A_SHIFT 5
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ADC0_SE0 = 0,
|
ADC0_SE0 = 0,
|
||||||
ADC0_SE3 = 3,
|
ADC0_SE3 = 3,
|
|
@ -0,0 +1,198 @@
|
||||||
|
|
||||||
|
/* 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 "PeripheralPins.h"
|
||||||
|
|
||||||
|
/************RTC***************/
|
||||||
|
const PinMap PinMap_RTC[] = {
|
||||||
|
{PTC1, RTC_CLKIN, 2},
|
||||||
|
};
|
||||||
|
|
||||||
|
/************ADC***************/
|
||||||
|
const PinMap PinMap_ADC[] = {
|
||||||
|
{PTE20, ADC0_SE0, 0},
|
||||||
|
{PTE22, ADC0_SE3, 0},
|
||||||
|
{PTE21, ADC0_SE4a, 0},
|
||||||
|
{PTE29, ADC0_SE4b, 0},
|
||||||
|
{PTE30, ADC0_SE23, 0},
|
||||||
|
{PTE23, ADC0_SE7a, 0},
|
||||||
|
{PTB0, ADC0_SE8, 0},
|
||||||
|
{PTB1, ADC0_SE9, 0},
|
||||||
|
{PTB2, ADC0_SE12, 0},
|
||||||
|
{PTB3, ADC0_SE13, 0},
|
||||||
|
{PTC0, ADC0_SE14, 0},
|
||||||
|
{PTC1, ADC0_SE15, 0},
|
||||||
|
{PTC2, ADC0_SE11, 0},
|
||||||
|
{PTD1, ADC0_SE5b, 0},
|
||||||
|
{PTD5, ADC0_SE6b, 0},
|
||||||
|
{PTD6, ADC0_SE7b, 0},
|
||||||
|
{NC, NC, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************DAC***************/
|
||||||
|
const PinMap PinMap_DAC[] = {
|
||||||
|
{PTE30, DAC_0, 0},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************I2C***************/
|
||||||
|
const PinMap PinMap_I2C_SDA[] = {
|
||||||
|
{PTE25, I2C_0, 5},
|
||||||
|
{PTC9, I2C_0, 2},
|
||||||
|
{PTE0, I2C_1, 6},
|
||||||
|
{PTB1, I2C_0, 2},
|
||||||
|
{PTB3, I2C_0, 2},
|
||||||
|
{PTC11, I2C_1, 2},
|
||||||
|
{PTC2, I2C_1, 2},
|
||||||
|
{PTA4, I2C_1, 2},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_I2C_SCL[] = {
|
||||||
|
{PTE24, I2C_0, 5},
|
||||||
|
{PTC8, I2C_0, 2},
|
||||||
|
{PTE1, I2C_1, 6},
|
||||||
|
{PTB0, I2C_0, 2},
|
||||||
|
{PTB2, I2C_0, 2},
|
||||||
|
{PTC10, I2C_1, 2},
|
||||||
|
{PTC1, I2C_1, 2},
|
||||||
|
{NC , NC, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************UART***************/
|
||||||
|
const PinMap PinMap_UART_TX[] = {
|
||||||
|
{PTC4, UART_1, 3},
|
||||||
|
{PTA2, UART_0, 2},
|
||||||
|
{PTD5, UART_2, 3},
|
||||||
|
{PTD3, UART_2, 3},
|
||||||
|
{PTD7, UART_0, 3},
|
||||||
|
{PTE20, UART_0, 4},
|
||||||
|
{PTE22, UART_2, 4},
|
||||||
|
{PTE0, UART_1, 3},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_UART_RX[] = {
|
||||||
|
{PTC3, UART_1, 3},
|
||||||
|
{PTA1, UART_0, 2},
|
||||||
|
{PTD4, UART_2, 3},
|
||||||
|
{PTD2, UART_2, 3},
|
||||||
|
{PTD6, UART_0, 3},
|
||||||
|
{PTE23, UART_2, 4},
|
||||||
|
{PTE21, UART_0, 4},
|
||||||
|
{PTE1, UART_1, 3},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************SPI***************/
|
||||||
|
const PinMap PinMap_SPI_SCLK[] = {
|
||||||
|
{PTA15, SPI_0, 2},
|
||||||
|
{PTB11, SPI_1, 2},
|
||||||
|
{PTC5, SPI_0, 2},
|
||||||
|
{PTD1, SPI_0, 2},
|
||||||
|
{PTD5, SPI_1, 2},
|
||||||
|
{PTE2, SPI_1, 2},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_SPI_MOSI[] = {
|
||||||
|
{PTA16, SPI_0, 2},
|
||||||
|
{PTA17, SPI_0, 5},
|
||||||
|
{PTB16, SPI_1, 2},
|
||||||
|
{PTB17, SPI_1, 5},
|
||||||
|
{PTC6, SPI_0, 2},
|
||||||
|
{PTC7, SPI_0, 5},
|
||||||
|
{PTD2, SPI_0, 2},
|
||||||
|
{PTD3, SPI_0, 5},
|
||||||
|
{PTD6, SPI_1, 2},
|
||||||
|
{PTD7, SPI_1, 5},
|
||||||
|
{PTE1, SPI_1, 2},
|
||||||
|
{PTE3, SPI_1, 5},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_SPI_MISO[] = {
|
||||||
|
{PTA16, SPI_0, 5},
|
||||||
|
{PTA17, SPI_0, 2},
|
||||||
|
{PTB16, SPI_1, 5},
|
||||||
|
{PTB17, SPI_1, 2},
|
||||||
|
{PTC6, SPI_0, 5},
|
||||||
|
{PTC7, SPI_0, 2},
|
||||||
|
{PTD2, SPI_0, 5},
|
||||||
|
{PTD3, SPI_0, 2},
|
||||||
|
{PTD6, SPI_1, 5},
|
||||||
|
{PTD7, SPI_1, 2},
|
||||||
|
{PTE1, SPI_1, 5},
|
||||||
|
{PTE3, SPI_1, 2},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_SPI_SSEL[] = {
|
||||||
|
{PTA14, SPI_0, 2},
|
||||||
|
{PTB10, SPI_1, 2},
|
||||||
|
{PTC4, SPI_0, 2},
|
||||||
|
{PTD0, SPI_0, 2},
|
||||||
|
{PTD4, SPI_1, 2},
|
||||||
|
{PTE4, SPI_1, 2},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************PWM***************/
|
||||||
|
const PinMap PinMap_PWM[] = {
|
||||||
|
// LEDs
|
||||||
|
{LED_RED , PWM_9 , 3}, // PTB18, TPM2 CH0
|
||||||
|
{LED_GREEN, PWM_10, 3}, // PTB19, TPM2 CH1
|
||||||
|
{LED_BLUE , PWM_2 , 4}, // PTD1 , TPM0 CH1
|
||||||
|
|
||||||
|
// Arduino digital pinout
|
||||||
|
{D0, PWM_9 , 3}, // PTA1 , TPM2 CH0
|
||||||
|
{D1, PWM_10, 3}, // PTA2 , TPM2 CH1
|
||||||
|
{D2, PWM_5 , 4}, // PTD4 , TPM0 CH4
|
||||||
|
{D3, PWM_7 , 3}, // PTA12, TPM1 CH0
|
||||||
|
{D4, PWM_2 , 3}, // PTA4 , TPM0 CH1
|
||||||
|
{D5, PWM_3 , 3}, // PTA5 , TPM0 CH2
|
||||||
|
{D6, PWM_5 , 3}, // PTC8 , TPM0 CH4
|
||||||
|
{D7, PWM_6 , 3}, // PTC9 , TPM0 CH5
|
||||||
|
{D8, PWM_8 , 3}, // PTA13, TPM1 CH1
|
||||||
|
{D9, PWM_6 , 4}, // PTD5 , TPM0 CH5
|
||||||
|
{D10, PWM_1 , 4}, // PTD0 , TPM0 CH0
|
||||||
|
{D11, PWM_3 , 4}, // PTD2 , TPM0 CH2
|
||||||
|
{D12, PWM_4 , 4}, // PTD3 , TPM0 CH3
|
||||||
|
{D13, PWM_2 , 4}, // PTD1 , TPM0 CH1,
|
||||||
|
|
||||||
|
{PTA0, PWM_6, 3},
|
||||||
|
{PTA3, PWM_1, 3},
|
||||||
|
{PTB0, PWM_7, 3},
|
||||||
|
{PTB1, PWM_8, 3},
|
||||||
|
{PTB2, PWM_9, 3},
|
||||||
|
{PTB3, PWM_10, 3},
|
||||||
|
{PTC1, PWM_1, 4},
|
||||||
|
{PTC2, PWM_2, 4},
|
||||||
|
{PTC3, PWM_3, 4},
|
||||||
|
{PTC4, PWM_4, 4},
|
||||||
|
{PTE20, PWM_7, 3},
|
||||||
|
{PTE21, PWM_8, 3},
|
||||||
|
{PTE22, PWM_9, 3},
|
||||||
|
{PTE23, PWM_10, 3},
|
||||||
|
{PTE24, PWM_1, 3},
|
||||||
|
{PTE25, PWM_2, 3},
|
||||||
|
{PTE29, PWM_3, 3},
|
||||||
|
{PTE30, PWM_4, 3},
|
||||||
|
{PTE31, PWM_5, 3},
|
||||||
|
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
|
@ -21,58 +21,7 @@
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "clk_freqs.h"
|
#include "clk_freqs.h"
|
||||||
|
#include "PeripheralPins.h"
|
||||||
static const PinMap PinMap_SPI_SCLK[] = {
|
|
||||||
{PTA15, SPI_0, 2},
|
|
||||||
{PTB11, SPI_1, 2},
|
|
||||||
{PTC5, SPI_0, 2},
|
|
||||||
{PTD1, SPI_0, 2},
|
|
||||||
{PTD5, SPI_1, 2},
|
|
||||||
{PTE2, SPI_1, 2},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PinMap PinMap_SPI_MOSI[] = {
|
|
||||||
{PTA16, SPI_0, 2},
|
|
||||||
{PTA17, SPI_0, 5},
|
|
||||||
{PTB16, SPI_1, 2},
|
|
||||||
{PTB17, SPI_1, 5},
|
|
||||||
{PTC6, SPI_0, 2},
|
|
||||||
{PTC7, SPI_0, 5},
|
|
||||||
{PTD2, SPI_0, 2},
|
|
||||||
{PTD3, SPI_0, 5},
|
|
||||||
{PTD6, SPI_1, 2},
|
|
||||||
{PTD7, SPI_1, 5},
|
|
||||||
{PTE1, SPI_1, 2},
|
|
||||||
{PTE3, SPI_1, 5},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PinMap PinMap_SPI_MISO[] = {
|
|
||||||
{PTA16, SPI_0, 5},
|
|
||||||
{PTA17, SPI_0, 2},
|
|
||||||
{PTB16, SPI_1, 5},
|
|
||||||
{PTB17, SPI_1, 2},
|
|
||||||
{PTC6, SPI_0, 5},
|
|
||||||
{PTC7, SPI_0, 2},
|
|
||||||
{PTD2, SPI_0, 5},
|
|
||||||
{PTD3, SPI_0, 2},
|
|
||||||
{PTD6, SPI_1, 5},
|
|
||||||
{PTD7, SPI_1, 2},
|
|
||||||
{PTE1, SPI_1, 5},
|
|
||||||
{PTE3, SPI_1, 2},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PinMap PinMap_SPI_SSEL[] = {
|
|
||||||
{PTA14, SPI_0, 2},
|
|
||||||
{PTB10, SPI_1, 2},
|
|
||||||
{PTC4, SPI_0, 2},
|
|
||||||
{PTD0, SPI_0, 2},
|
|
||||||
{PTD4, SPI_1, 2},
|
|
||||||
{PTE4, SPI_1, 2},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
|
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
|
||||||
// determine the SPI to use
|
// determine the SPI to use
|
|
@ -22,6 +22,11 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
OSC32KCLK = 0,
|
||||||
|
RTC_CLKIN = 2
|
||||||
|
} RTCName;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UART_0 = (int)UART0_BASE,
|
UART_0 = (int)UART0_BASE,
|
||||||
UART_1 = (int)UART1_BASE,
|
UART_1 = (int)UART1_BASE,
|
||||||
|
@ -52,7 +57,7 @@ typedef enum {
|
||||||
PWM_10 = (2 << TPM_SHIFT) | (1) // TPM2 CH1
|
PWM_10 = (2 << TPM_SHIFT) | (1) // TPM2 CH1
|
||||||
} PWMName;
|
} PWMName;
|
||||||
|
|
||||||
#define CHANNELS_A_SHIFT 5
|
#define CHANNELS_A_SHIFT 5
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ADC0_SE0 = 0,
|
ADC0_SE0 = 0,
|
||||||
ADC0_SE3 = 3,
|
ADC0_SE3 = 3,
|
|
@ -0,0 +1,209 @@
|
||||||
|
/* 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 "PeripheralPins.h"
|
||||||
|
|
||||||
|
/************RTC***************/
|
||||||
|
const PinMap PinMap_RTC[] = {
|
||||||
|
{PTC1, RTC_CLKIN, 2},
|
||||||
|
};
|
||||||
|
|
||||||
|
/************ADC***************/
|
||||||
|
const PinMap PinMap_ADC[] = {
|
||||||
|
{PTE20, ADC0_SE0, 0},
|
||||||
|
{PTE22, ADC0_SE3, 0},
|
||||||
|
{PTE21, ADC0_SE4a, 0},
|
||||||
|
{PTE29, ADC0_SE4b, 0},
|
||||||
|
{PTE30, ADC0_SE23, 0},
|
||||||
|
{PTE23, ADC0_SE7a, 0},
|
||||||
|
{PTB0, ADC0_SE8, 0},
|
||||||
|
{PTB1, ADC0_SE9, 0},
|
||||||
|
{PTB2, ADC0_SE12, 0},
|
||||||
|
{PTB3, ADC0_SE13, 0},
|
||||||
|
{PTC0, ADC0_SE14, 0},
|
||||||
|
{PTC1, ADC0_SE15, 0},
|
||||||
|
{PTC2, ADC0_SE11, 0},
|
||||||
|
{PTD1, ADC0_SE5b, 0},
|
||||||
|
{PTD5, ADC0_SE6b, 0},
|
||||||
|
{PTD6, ADC0_SE7b, 0},
|
||||||
|
{NC, NC, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************DAC***************/
|
||||||
|
const PinMap PinMap_DAC[] = {
|
||||||
|
{PTE30, DAC_0, 0},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************I2C***************/
|
||||||
|
const PinMap PinMap_I2C_SDA[] = {
|
||||||
|
{PTE25, I2C_0, 5},
|
||||||
|
{PTC9, I2C_0, 2},
|
||||||
|
{PTE0, I2C_1, 6},
|
||||||
|
{PTB1, I2C_0, 2},
|
||||||
|
{PTB3, I2C_0, 2},
|
||||||
|
{PTC11, I2C_1, 2},
|
||||||
|
{PTC2, I2C_1, 2},
|
||||||
|
{PTA4, I2C_1, 2},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_I2C_SCL[] = {
|
||||||
|
{PTE24, I2C_0, 5},
|
||||||
|
{PTC8, I2C_0, 2},
|
||||||
|
{PTE1, I2C_1, 6},
|
||||||
|
{PTB0, I2C_0, 2},
|
||||||
|
{PTB2, I2C_0, 2},
|
||||||
|
{PTC10, I2C_1, 2},
|
||||||
|
{PTC1, I2C_1, 2},
|
||||||
|
{NC , NC, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************UART***************/
|
||||||
|
const PinMap PinMap_UART_TX[] = {
|
||||||
|
{PTA2, UART_0, 2},
|
||||||
|
{PTA14, UART_0, 3},
|
||||||
|
{PTC4, UART_1, 3},
|
||||||
|
{PTD3, UART_2, 3},
|
||||||
|
{PTD5, UART_2, 3},
|
||||||
|
{PTD7, UART_0, 3},
|
||||||
|
{PTE0, UART_1, 3},
|
||||||
|
{PTE16, UART_2, 3},
|
||||||
|
{PTE20, UART_0, 4},
|
||||||
|
{PTE22, UART_2, 4},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_UART_RX[] = {
|
||||||
|
{PTA1, UART_0, 2},
|
||||||
|
{PTA15, UART_0, 3},
|
||||||
|
{PTC3, UART_1, 3},
|
||||||
|
{PTD2, UART_2, 3},
|
||||||
|
{PTD4, UART_2, 3},
|
||||||
|
{PTD6, UART_0, 3},
|
||||||
|
{PTE1, UART_1, 3},
|
||||||
|
{PTE17, UART_2, 3},
|
||||||
|
{PTE21, UART_0, 4},
|
||||||
|
{PTE23, UART_2, 4},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************SPI***************/
|
||||||
|
const PinMap PinMap_SPI_SCLK[] = {
|
||||||
|
{PTA15, SPI_0, 2},
|
||||||
|
{PTB9, SPI_1, 2},
|
||||||
|
{PTB11, SPI_1, 2},
|
||||||
|
{PTC5, SPI_0, 2},
|
||||||
|
{PTD1, SPI_0, 2},
|
||||||
|
{PTD5, SPI_1, 2},
|
||||||
|
{PTE2, SPI_1, 2},
|
||||||
|
{PTE17, SPI_0, 2},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_SPI_MOSI[] = {
|
||||||
|
{PTA16, SPI_0, 2},
|
||||||
|
{PTA17, SPI_0, 5},
|
||||||
|
{PTB16, SPI_1, 2},
|
||||||
|
{PTB17, SPI_1, 5},
|
||||||
|
{PTC6, SPI_0, 2},
|
||||||
|
{PTC7, SPI_0, 5},
|
||||||
|
{PTD2, SPI_0, 2},
|
||||||
|
{PTD3, SPI_0, 5},
|
||||||
|
{PTD6, SPI_1, 2},
|
||||||
|
{PTD7, SPI_1, 5},
|
||||||
|
{PTE1, SPI_1, 2},
|
||||||
|
{PTE3, SPI_1, 5},
|
||||||
|
{PTE18, SPI_0, 2},
|
||||||
|
{PTE19, SPI_0, 5},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_SPI_MISO[] = {
|
||||||
|
{PTA16, SPI_0, 5},
|
||||||
|
{PTA17, SPI_0, 2},
|
||||||
|
{PTB16, SPI_1, 5},
|
||||||
|
{PTB17, SPI_1, 2},
|
||||||
|
{PTC6, SPI_0, 5},
|
||||||
|
{PTC7, SPI_0, 2},
|
||||||
|
{PTD2, SPI_0, 5},
|
||||||
|
{PTD3, SPI_0, 2},
|
||||||
|
{PTD6, SPI_1, 5},
|
||||||
|
{PTD7, SPI_1, 2},
|
||||||
|
{PTE1, SPI_1, 5},
|
||||||
|
{PTE3, SPI_1, 2},
|
||||||
|
{PTE18, SPI_0, 5},
|
||||||
|
{PTE19, SPI_0, 2},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinMap PinMap_SPI_SSEL[] = {
|
||||||
|
{PTA14, SPI_0, 2},
|
||||||
|
{PTB10, SPI_1, 2},
|
||||||
|
{PTC4, SPI_0, 2},
|
||||||
|
{PTD0, SPI_0, 2},
|
||||||
|
{PTD4, SPI_1, 2},
|
||||||
|
{PTE4, SPI_1, 2},
|
||||||
|
{PTE16, SPI_0, 2},
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/************PWM***************/
|
||||||
|
const PinMap PinMap_PWM[] = {
|
||||||
|
// LEDs - only RED pin is PWM capable
|
||||||
|
{LED_RED, PWM_3, 3}, // PTE29, TPM0 CH2
|
||||||
|
|
||||||
|
// Arduino digital pinout
|
||||||
|
{D0, PWM_9 , 3}, // PTA1 , TPM2 CH0
|
||||||
|
{D1, PWM_10, 3}, // PTA2 , TPM2 CH1
|
||||||
|
{D2, PWM_4 , 4}, // PTD3 , TPM0 CH3
|
||||||
|
{D3, PWM_7 , 3}, // PTA12, TPM1 CH0
|
||||||
|
{D4, PWM_2 , 3}, // PTA4 , TPM0 CH1
|
||||||
|
{D5, PWM_3 , 3}, // PTA5 , TPM0 CH2
|
||||||
|
{D6, PWM_5 , 3}, // PTC8 , TPM0 CH4
|
||||||
|
{D7, PWM_6 , 3}, // PTC9 , TPM0 CH5
|
||||||
|
{D8, PWM_8 , 3}, // PTA13, TPM1 CH1
|
||||||
|
{D9, PWM_3 , 4}, // PTD2 , TPM0 CH2
|
||||||
|
{D10, PWM_5 , 4}, // PTD4 , TPM0 CH4
|
||||||
|
//PWM on D11 not available
|
||||||
|
//PWM on D12 not available
|
||||||
|
{D13, PWM_2 , 4}, // PTD5 , TPM0 CH1,
|
||||||
|
|
||||||
|
{PTA0, PWM_6, 3},
|
||||||
|
{PTA3, PWM_1, 3},
|
||||||
|
{PTA6, PWM_4, 3},
|
||||||
|
{PTA7, PWM_5, 3},
|
||||||
|
{PTB0, PWM_7, 3},
|
||||||
|
{PTB1, PWM_8, 3},
|
||||||
|
{PTB2, PWM_9, 3},
|
||||||
|
{PTB3, PWM_10, 3},
|
||||||
|
{PTC1, PWM_1, 4},
|
||||||
|
{PTC2, PWM_2, 4},
|
||||||
|
{PTC3, PWM_3, 4},
|
||||||
|
{PTC4, PWM_4, 4},
|
||||||
|
{PTE20, PWM_7, 3},
|
||||||
|
{PTE21, PWM_8, 3},
|
||||||
|
{PTE22, PWM_9, 3},
|
||||||
|
{PTE23, PWM_10, 3},
|
||||||
|
{PTE24, PWM_1, 3},
|
||||||
|
{PTE25, PWM_2, 3},
|
||||||
|
{PTE26, PWM_6, 3},
|
||||||
|
{PTE29, PWM_3, 3},
|
||||||
|
{PTE30, PWM_4, 3},
|
||||||
|
{PTE31, PWM_5, 3},
|
||||||
|
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
|
@ -197,13 +197,13 @@ typedef enum {
|
||||||
// mbed original LED naming
|
// mbed original LED naming
|
||||||
LED1 = LED_GREEN,
|
LED1 = LED_GREEN,
|
||||||
LED2 = LED_RED,
|
LED2 = LED_RED,
|
||||||
LED3 = LED_GREEN,
|
LED3 = LED_GREEN,
|
||||||
LED4 = LED_RED,
|
LED4 = LED_RED,
|
||||||
|
|
||||||
//Push buttons
|
//Push buttons
|
||||||
SW1 = PTC3,
|
SW1 = PTC3,
|
||||||
SW3 = PTC12,
|
SW3 = PTC12,
|
||||||
|
|
||||||
// USB Pins
|
// USB Pins
|
||||||
USBTX = PTA2,
|
USBTX = PTA2,
|
||||||
USBRX = PTA1,
|
USBRX = PTA1,
|
|
@ -19,28 +19,11 @@
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "clk_freqs.h"
|
#include "clk_freqs.h"
|
||||||
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
#define MAX_FADC 6000000
|
#define MAX_FADC 6000000
|
||||||
|
#define CHANNELS_A_SHIFT 5
|
||||||
|
|
||||||
static const PinMap PinMap_ADC[] = {
|
|
||||||
{PTE20, ADC0_SE0, 0},
|
|
||||||
{PTE22, ADC0_SE3, 0},
|
|
||||||
{PTE21, ADC0_SE4a, 0},
|
|
||||||
{PTE29, ADC0_SE4b, 0},
|
|
||||||
{PTE30, ADC0_SE23, 0},
|
|
||||||
{PTE23, ADC0_SE7a, 0},
|
|
||||||
{PTB0, ADC0_SE8, 0},
|
|
||||||
{PTB1, ADC0_SE9, 0},
|
|
||||||
{PTB2, ADC0_SE12, 0},
|
|
||||||
{PTB3, ADC0_SE13, 0},
|
|
||||||
{PTC0, ADC0_SE14, 0},
|
|
||||||
{PTC1, ADC0_SE15, 0},
|
|
||||||
{PTC2, ADC0_SE11, 0},
|
|
||||||
{PTD1, ADC0_SE5b, 0},
|
|
||||||
{PTD5, ADC0_SE6b, 0},
|
|
||||||
{PTD6, ADC0_SE7b, 0},
|
|
||||||
{NC, NC, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
void analogin_init(analogin_t *obj, PinName pin) {
|
void analogin_init(analogin_t *obj, PinName pin) {
|
||||||
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
|
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
|
|
@ -18,13 +18,10 @@
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
#define RANGE_12BIT 0xFFF
|
#define RANGE_12BIT 0xFFF
|
||||||
|
|
||||||
static const PinMap PinMap_DAC[] = {
|
|
||||||
{PTE30, DAC_0, 0},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
void analogout_init(dac_t *obj, PinName pin) {
|
void analogout_init(dac_t *obj, PinName pin) {
|
||||||
obj->dac = (DACName)pinmap_peripheral(pin, PinMap_DAC);
|
obj->dac = (DACName)pinmap_peripheral(pin, PinMap_DAC);
|
|
@ -20,6 +20,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
//Get the peripheral bus clock frequency
|
//Get the peripheral bus clock frequency
|
||||||
static inline uint32_t bus_frequency(void) {
|
static inline uint32_t bus_frequency(void) {
|
||||||
return SystemCoreClock / (((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) + 1);
|
return SystemCoreClock / (((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) + 1);
|
||||||
|
@ -32,9 +34,11 @@ static uint32_t extosc_frequency(void) {
|
||||||
if ((MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(2)) //MCG clock = external reference clock
|
if ((MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(2)) //MCG clock = external reference clock
|
||||||
return MCGClock;
|
return MCGClock;
|
||||||
|
|
||||||
|
uint32_t divider, multiplier;
|
||||||
|
#ifdef MCG_C5_PLLCLKEN0_MASK //PLL available
|
||||||
if ((MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(0)) { //PLL/FLL is selected
|
if ((MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(0)) { //PLL/FLL is selected
|
||||||
uint32_t divider, multiplier;
|
|
||||||
if ((MCG->C6 & MCG_C6_PLLS_MASK) == 0x0u) { //FLL is selected
|
if ((MCG->C6 & MCG_C6_PLLS_MASK) == 0x0u) { //FLL is selected
|
||||||
|
#endif
|
||||||
if ((MCG->S & MCG_S_IREFST_MASK) == 0x0u) { //FLL uses external reference
|
if ((MCG->S & MCG_S_IREFST_MASK) == 0x0u) { //FLL uses external reference
|
||||||
divider = (uint8_t)(1u << ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT));
|
divider = (uint8_t)(1u << ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT));
|
||||||
if ((MCG->C2 & MCG_C2_RANGE0_MASK) != 0x0u)
|
if ((MCG->C2 & MCG_C2_RANGE0_MASK) != 0x0u)
|
||||||
|
@ -70,12 +74,14 @@ static uint32_t extosc_frequency(void) {
|
||||||
|
|
||||||
return MCGClock * divider / multiplier;
|
return MCGClock * divider / multiplier;
|
||||||
}
|
}
|
||||||
|
#ifdef MCG_C5_PLLCLKEN0_MASK
|
||||||
} else { //PLL is selected
|
} else { //PLL is selected
|
||||||
divider = (1u + (MCG->C5 & MCG_C5_PRDIV0_MASK));
|
divider = (1u + (MCG->C5 & MCG_C5_PRDIV0_MASK));
|
||||||
multiplier = ((MCG->C6 & MCG_C6_VDIV0_MASK) + 24u);
|
multiplier = ((MCG->C6 & MCG_C6_VDIV0_MASK) + 24u);
|
||||||
return MCGClock * divider / multiplier;
|
return MCGClock * divider / multiplier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//In all other cases either there is no crystal or we cannot determine it
|
//In all other cases either there is no crystal or we cannot determine it
|
||||||
//For example when the FLL is running on the internal reference, and there is also an
|
//For example when the FLL is running on the internal reference, and there is also an
|
||||||
|
@ -89,13 +95,17 @@ static uint32_t mcgpllfll_frequency(void) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint32_t MCGClock = SystemCoreClock * (1u + ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT));
|
uint32_t MCGClock = SystemCoreClock * (1u + ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT));
|
||||||
|
#ifdef MCG_C5_PLLCLKEN0_MASK
|
||||||
if ((MCG->C6 & MCG_C6_PLLS_MASK) == 0x0u) { //FLL is selected
|
if ((MCG->C6 & MCG_C6_PLLS_MASK) == 0x0u) { //FLL is selected
|
||||||
SIM->SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK; //MCG peripheral clock is FLL output
|
SIM->SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK; //MCG peripheral clock is FLL output
|
||||||
|
#endif
|
||||||
return MCGClock;
|
return MCGClock;
|
||||||
|
#ifdef MCG_C5_PLLCLKEN0_MASK
|
||||||
} else { //PLL is selected
|
} else { //PLL is selected
|
||||||
SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK; //MCG peripheral clock is PLL output
|
SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK; //MCG peripheral clock is PLL output
|
||||||
return (MCGClock >> 1);
|
return (MCGClock >> 1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//It is possible the SystemCoreClock isn't running on the PLL, and the PLL is still active
|
//It is possible the SystemCoreClock isn't running on the PLL, and the PLL is still active
|
||||||
//for the peripherals, this is however an unlikely setup
|
//for the peripherals, this is however an unlikely setup
|
|
@ -19,29 +19,7 @@
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "clk_freqs.h"
|
#include "clk_freqs.h"
|
||||||
|
#include "PeripheralPins.h"
|
||||||
static const PinMap PinMap_I2C_SDA[] = {
|
|
||||||
{PTE25, I2C_0, 5},
|
|
||||||
{PTC9, I2C_0, 2},
|
|
||||||
{PTE0, I2C_1, 6},
|
|
||||||
{PTB1, I2C_0, 2},
|
|
||||||
{PTB3, I2C_0, 2},
|
|
||||||
{PTC11, I2C_1, 2},
|
|
||||||
{PTC2, I2C_1, 2},
|
|
||||||
{PTA4, I2C_1, 2},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PinMap PinMap_I2C_SCL[] = {
|
|
||||||
{PTE24, I2C_0, 5},
|
|
||||||
{PTC8, I2C_0, 2},
|
|
||||||
{PTE1, I2C_1, 6},
|
|
||||||
{PTB0, I2C_0, 2},
|
|
||||||
{PTB2, I2C_0, 2},
|
|
||||||
{PTC10, I2C_1, 2},
|
|
||||||
{PTC1, I2C_1, 2},
|
|
||||||
{NC , NC, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint16_t ICR[0x40] = {
|
static const uint16_t ICR[0x40] = {
|
||||||
20, 22, 24, 26, 28,
|
20, 22, 24, 26, 28,
|
|
@ -25,6 +25,10 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TARGET_KL46Z
|
||||||
|
#define UARTLP_Type UART0_Type
|
||||||
|
#endif
|
||||||
|
|
||||||
struct gpio_irq_s {
|
struct gpio_irq_s {
|
||||||
uint32_t port;
|
uint32_t port;
|
||||||
uint32_t pin;
|
uint32_t pin;
|
|
@ -19,51 +19,7 @@
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "clk_freqs.h"
|
#include "clk_freqs.h"
|
||||||
|
#include "PeripheralPins.h"
|
||||||
static const PinMap PinMap_PWM[] = {
|
|
||||||
// LEDs
|
|
||||||
{LED_RED , PWM_9 , 3}, // PTB18, TPM2 CH0
|
|
||||||
{LED_GREEN, PWM_10, 3}, // PTB19, TPM2 CH1
|
|
||||||
{LED_BLUE , PWM_2 , 4}, // PTD1 , TPM0 CH1
|
|
||||||
|
|
||||||
// Arduino digital pinout
|
|
||||||
{D0, PWM_9 , 3}, // PTA1 , TPM2 CH0
|
|
||||||
{D1, PWM_10, 3}, // PTA2 , TPM2 CH1
|
|
||||||
{D2, PWM_5 , 4}, // PTD4 , TPM0 CH4
|
|
||||||
{D3, PWM_7 , 3}, // PTA12, TPM1 CH0
|
|
||||||
{D4, PWM_2 , 3}, // PTA4 , TPM0 CH1
|
|
||||||
{D5, PWM_3 , 3}, // PTA5 , TPM0 CH2
|
|
||||||
{D6, PWM_5 , 3}, // PTC8 , TPM0 CH4
|
|
||||||
{D7, PWM_6 , 3}, // PTC9 , TPM0 CH5
|
|
||||||
{D8, PWM_8 , 3}, // PTA13, TPM1 CH1
|
|
||||||
{D9, PWM_6 , 4}, // PTD5 , TPM0 CH5
|
|
||||||
{D10, PWM_1 , 4}, // PTD0 , TPM0 CH0
|
|
||||||
{D11, PWM_3 , 4}, // PTD2 , TPM0 CH2
|
|
||||||
{D12, PWM_4 , 4}, // PTD3 , TPM0 CH3
|
|
||||||
{D13, PWM_2 , 4}, // PTD1 , TPM0 CH1,
|
|
||||||
|
|
||||||
{PTA0, PWM_6, 3},
|
|
||||||
{PTA3, PWM_1, 3},
|
|
||||||
{PTB0, PWM_7, 3},
|
|
||||||
{PTB1, PWM_8, 3},
|
|
||||||
{PTB2, PWM_9, 3},
|
|
||||||
{PTB3, PWM_10, 3},
|
|
||||||
{PTC1, PWM_1, 4},
|
|
||||||
{PTC2, PWM_2, 4},
|
|
||||||
{PTC3, PWM_3, 4},
|
|
||||||
{PTC4, PWM_4, 4},
|
|
||||||
{PTE20, PWM_7, 3},
|
|
||||||
{PTE21, PWM_8, 3},
|
|
||||||
{PTE22, PWM_9, 3},
|
|
||||||
{PTE23, PWM_10, 3},
|
|
||||||
{PTE24, PWM_1, 3},
|
|
||||||
{PTE25, PWM_2, 3},
|
|
||||||
{PTE29, PWM_3, 3},
|
|
||||||
{PTE30, PWM_4, 3},
|
|
||||||
{PTE31, PWM_5, 3},
|
|
||||||
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static float pwm_clock;
|
static float pwm_clock;
|
||||||
|
|
|
@ -14,26 +14,17 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#include "rtc_api.h"
|
#include "rtc_api.h"
|
||||||
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
static void init(void) {
|
static void init(void) {
|
||||||
// enable PORTC clock
|
|
||||||
SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
|
|
||||||
|
|
||||||
// enable RTC clock
|
// enable RTC clock
|
||||||
SIM->SCGC6 |= SIM_SCGC6_RTC_MASK;
|
SIM->SCGC6 |= SIM_SCGC6_RTC_MASK;
|
||||||
|
|
||||||
/*
|
pinmap_pinout(PinMap_RTC[0].pin, PinMap_RTC); //Map RTC clk input (if not NC)
|
||||||
* configure PTC1 with alternate function 1: RTC_CLKIN
|
|
||||||
* As the KL46Z board does not have a 32kHz osc,
|
|
||||||
* we use an external clock generated by the
|
|
||||||
* interface chip
|
|
||||||
*/
|
|
||||||
PORTC->PCR[1] &= ~PORT_PCR_MUX_MASK;
|
|
||||||
PORTC->PCR[1] = PORT_PCR_MUX(1);
|
|
||||||
|
|
||||||
// select RTC_CLKIN as RTC clock source
|
// select RTC clock source
|
||||||
SIM->SOPT1 &= ~SIM_SOPT1_OSC32KSEL_MASK;
|
SIM->SOPT1 &= ~SIM_SOPT1_OSC32KSEL_MASK;
|
||||||
SIM->SOPT1 |= SIM_SOPT1_OSC32KSEL(2);
|
SIM->SOPT1 |= SIM_SOPT1_OSC32KSEL(PinMap_RTC[0].peripheral);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rtc_init(void) {
|
void rtc_init(void) {
|
||||||
|
@ -41,6 +32,12 @@ void rtc_init(void) {
|
||||||
|
|
||||||
//Configure the TSR. default value: 1
|
//Configure the TSR. default value: 1
|
||||||
RTC->TSR = 1;
|
RTC->TSR = 1;
|
||||||
|
|
||||||
|
if (PinMap_RTC[0].pin == NC) { //Use OSC32K
|
||||||
|
RTC->CR |= RTC_CR_OSCE_MASK;
|
||||||
|
//delay for OSCE stabilization
|
||||||
|
for(int i=0; i<0x1000; i++) __NOP();
|
||||||
|
}
|
||||||
|
|
||||||
// enable counter
|
// enable counter
|
||||||
RTC->SR |= RTC_SR_TCE_MASK;
|
RTC->SR |= RTC_SR_TCE_MASK;
|
||||||
|
@ -61,7 +58,7 @@ int rtc_isenabled(void) {
|
||||||
// call init() if the rtc is enabled
|
// call init() if the rtc is enabled
|
||||||
|
|
||||||
// if RTC not enabled return 0
|
// if RTC not enabled return 0
|
||||||
SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK;
|
SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
|
||||||
SIM->SCGC6 |= SIM_SCGC6_RTC_MASK;
|
SIM->SCGC6 |= SIM_SCGC6_RTC_MASK;
|
||||||
if ((RTC->SR & RTC_SR_TCE_MASK) == 0)
|
if ((RTC->SR & RTC_SR_TCE_MASK) == 0)
|
||||||
return 0;
|
return 0;
|
|
@ -24,35 +24,32 @@
|
||||||
#include "pinmap.h"
|
#include "pinmap.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "clk_freqs.h"
|
#include "clk_freqs.h"
|
||||||
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
|
//Devices either user UART0 or UARTLP
|
||||||
|
#ifndef UARTLP_BASES
|
||||||
|
#define UARTLP_C2_RE_MASK UART0_C2_RE_MASK
|
||||||
|
#define UARTLP_C2_TE_MASK UART0_C2_TE_MASK
|
||||||
|
#define UARTLP_BDH_SBNS_MASK UART0_BDH_SBNS_MASK
|
||||||
|
#define UARTLP_BDH_SBNS_SHIFT UART0_BDH_SBNS_SHIFT
|
||||||
|
#define UARTLP_S1_TDRE_MASK UART0_S1_TDRE_MASK
|
||||||
|
#define UARTLP_S1_OR_MASK UART0_S1_OR_MASK
|
||||||
|
#define UARTLP_C2_RIE_MASK UART0_C2_RIE_MASK
|
||||||
|
#define UARTLP_C2_TIE_MASK UART0_C2_TIE_MASK
|
||||||
|
#define UARTLP_C2_SBK_MASK UART0_C2_SBK_MASK
|
||||||
|
#define UARTLP_S1_RDRF_MASK UART0_S1_RDRF_MASK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UART2
|
||||||
|
#define UART_NUM 3
|
||||||
|
#else
|
||||||
|
#define UART_NUM 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* INITIALIZATION
|
* INITIALIZATION
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
static const PinMap PinMap_UART_TX[] = {
|
|
||||||
{PTC4, UART_1, 3},
|
|
||||||
{PTA2, UART_0, 2},
|
|
||||||
{PTD5, UART_2, 3},
|
|
||||||
{PTD3, UART_2, 3},
|
|
||||||
{PTD7, UART_0, 3},
|
|
||||||
{PTE20, UART_0, 4},
|
|
||||||
{PTE22, UART_2, 4},
|
|
||||||
{PTE0, UART_1, 3},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const PinMap PinMap_UART_RX[] = {
|
|
||||||
{PTC3, UART_1, 3},
|
|
||||||
{PTA1, UART_0, 2},
|
|
||||||
{PTD4, UART_2, 3},
|
|
||||||
{PTD2, UART_2, 3},
|
|
||||||
{PTD6, UART_0, 3},
|
|
||||||
{PTE23, UART_2, 4},
|
|
||||||
{PTE21, UART_0, 4},
|
|
||||||
{PTE1, UART_1, 3},
|
|
||||||
{NC , NC , 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define UART_NUM 3
|
|
||||||
static uint32_t serial_irq_ids[UART_NUM] = {0};
|
static uint32_t serial_irq_ids[UART_NUM] = {0};
|
||||||
static uart_irq_handler irq_handler;
|
static uart_irq_handler irq_handler;
|
||||||
|
|
||||||
|
@ -75,17 +72,21 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
||||||
SIM->SOPT2 |= (1<<SIM_SOPT2_UART0SRC_SHIFT);
|
SIM->SOPT2 |= (1<<SIM_SOPT2_UART0SRC_SHIFT);
|
||||||
else
|
else
|
||||||
SIM->SOPT2 |= (2<<SIM_SOPT2_UART0SRC_SHIFT);
|
SIM->SOPT2 |= (2<<SIM_SOPT2_UART0SRC_SHIFT);
|
||||||
SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK; SIM->SCGC4 |= SIM_SCGC4_UART0_MASK; break;
|
SIM->SCGC4 |= SIM_SCGC4_UART0_MASK; break;
|
||||||
case UART_1: SIM->SCGC5 |= SIM_SCGC5_PORTC_MASK; SIM->SCGC4 |= SIM_SCGC4_UART1_MASK; break;
|
#if UART_NUM > 1
|
||||||
case UART_2: SIM->SCGC5 |= SIM_SCGC5_PORTD_MASK; SIM->SCGC4 |= SIM_SCGC4_UART2_MASK; break;
|
case UART_1: SIM->SCGC4 |= SIM_SCGC4_UART1_MASK; break;
|
||||||
|
case UART_2: SIM->SCGC4 |= SIM_SCGC4_UART2_MASK; break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
// Disable UART before changing registers
|
// Disable UART before changing registers
|
||||||
obj->uart->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
|
obj->uart->C2 &= ~(UARTLP_C2_RE_MASK | UARTLP_C2_TE_MASK);
|
||||||
|
|
||||||
switch (uart) {
|
switch (uart) {
|
||||||
case UART_0: obj->index = 0; break;
|
case UART_0: obj->index = 0; break;
|
||||||
|
#if UART_NUM > 1
|
||||||
case UART_1: obj->index = 1; break;
|
case UART_1: obj->index = 1; break;
|
||||||
case UART_2: obj->index = 2; break;
|
case UART_2: obj->index = 2; break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// set default baud rate and format
|
// set default baud rate and format
|
||||||
|
@ -100,7 +101,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
||||||
pin_mode(tx, PullUp);
|
pin_mode(tx, PullUp);
|
||||||
pin_mode(rx, PullUp);
|
pin_mode(rx, PullUp);
|
||||||
|
|
||||||
obj->uart->C2 |= (UART_C2_RE_MASK | UART_C2_TE_MASK);
|
obj->uart->C2 |= (UARTLP_C2_RE_MASK | UARTLP_C2_TE_MASK);
|
||||||
|
|
||||||
if (uart == STDIO_UART) {
|
if (uart == STDIO_UART) {
|
||||||
stdio_uart_inited = 1;
|
stdio_uart_inited = 1;
|
||||||
|
@ -118,10 +119,10 @@ void serial_free(serial_t *obj) {
|
||||||
void serial_baud(serial_t *obj, int baudrate) {
|
void serial_baud(serial_t *obj, int baudrate) {
|
||||||
|
|
||||||
// save C2 state
|
// save C2 state
|
||||||
uint8_t c2_state = (obj->uart->C2 & (UART_C2_RE_MASK | UART_C2_TE_MASK));
|
uint8_t c2_state = (obj->uart->C2 & (UARTLP_C2_RE_MASK | UARTLP_C2_TE_MASK));
|
||||||
|
|
||||||
// Disable UART before changing registers
|
// Disable UART before changing registers
|
||||||
obj->uart->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
|
obj->uart->C2 &= ~(UARTLP_C2_RE_MASK | UARTLP_C2_TE_MASK);
|
||||||
|
|
||||||
uint32_t PCLK;
|
uint32_t PCLK;
|
||||||
if (obj->uart == UART0) {
|
if (obj->uart == UART0) {
|
||||||
|
@ -149,19 +150,17 @@ void serial_baud(serial_t *obj, int baudrate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
|
void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) {
|
||||||
uint8_t m10 = 0;
|
|
||||||
|
|
||||||
// save C2 state
|
// save C2 state
|
||||||
uint8_t c2_state = (obj->uart->C2 & (UART_C2_RE_MASK | UART_C2_TE_MASK));
|
uint8_t c2_state = (obj->uart->C2 & (UARTLP_C2_RE_MASK | UARTLP_C2_TE_MASK));
|
||||||
|
|
||||||
// Disable UART before changing registers
|
// Disable UART before changing registers
|
||||||
obj->uart->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
|
obj->uart->C2 &= ~(UARTLP_C2_RE_MASK | UARTLP_C2_TE_MASK);
|
||||||
|
|
||||||
// 8 data bits = 0 ... 9 data bits = 1
|
// TODO: Support other number of data bits (also in the write method!)
|
||||||
if ((data_bits < 8) || (data_bits > 9)) {
|
if ((data_bits < 8) || (data_bits > 8)) {
|
||||||
error("Invalid number of bits (%d) in serial format, should be 8..9\r\n", data_bits);
|
error("Invalid number of bits (%d) in serial format, should be 8\r\n", data_bits);
|
||||||
}
|
}
|
||||||
data_bits -= 8;
|
|
||||||
|
|
||||||
uint8_t parity_enable, parity_select;
|
uint8_t parity_enable, parity_select;
|
||||||
switch (parity) {
|
switch (parity) {
|
||||||
|
@ -178,31 +177,14 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
|
||||||
error("Invalid stop bits specified\r\n");
|
error("Invalid stop bits specified\r\n");
|
||||||
}
|
}
|
||||||
stop_bits -= 1;
|
stop_bits -= 1;
|
||||||
|
|
||||||
// 9 data bits + parity
|
|
||||||
if (data_bits == 2) {
|
|
||||||
// only uart0 supports 10 bit communication
|
|
||||||
if (obj->index != 0) {
|
|
||||||
error("Invalid number of bits (9) to be used with parity\r\n");
|
|
||||||
}
|
|
||||||
data_bits = 0;
|
|
||||||
m10 = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// data bits, parity and parity mode
|
// data bits, parity and parity mode
|
||||||
obj->uart->C1 = ((data_bits << 4)
|
obj->uart->C1 = ((parity_enable << 1)
|
||||||
| (parity_enable << 1)
|
|
||||||
| (parity_select << 0));
|
| (parity_select << 0));
|
||||||
|
|
||||||
// enable 10bit mode if needed
|
|
||||||
if (obj->index == 0) {
|
|
||||||
obj->uart->C4 &= ~UARTLP_C4_M10_MASK;
|
|
||||||
obj->uart->C4 |= (m10 << UARTLP_C4_M10_SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop bits
|
// stop bits
|
||||||
obj->uart->BDH &= ~UART_BDH_SBNS_MASK;
|
obj->uart->BDH &= ~UARTLP_BDH_SBNS_MASK;
|
||||||
obj->uart->BDH |= (stop_bits << UART_BDH_SBNS_SHIFT);
|
obj->uart->BDH |= (stop_bits << UARTLP_BDH_SBNS_SHIFT);
|
||||||
|
|
||||||
// restore C2 state
|
// restore C2 state
|
||||||
obj->uart->C2 |= c2_state;
|
obj->uart->C2 |= c2_state;
|
||||||
|
@ -213,21 +195,23 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
static inline void uart_irq(uint8_t status, uint32_t index) {
|
static inline void uart_irq(uint8_t status, uint32_t index) {
|
||||||
if (serial_irq_ids[index] != 0) {
|
if (serial_irq_ids[index] != 0) {
|
||||||
if (status & UART_S1_TDRE_MASK)
|
if (status & UARTLP_S1_TDRE_MASK)
|
||||||
irq_handler(serial_irq_ids[index], TxIrq);
|
irq_handler(serial_irq_ids[index], TxIrq);
|
||||||
|
|
||||||
if (status & UART_S1_RDRF_MASK)
|
if (status & UARTLP_S1_RDRF_MASK)
|
||||||
irq_handler(serial_irq_ids[index], RxIrq);
|
irq_handler(serial_irq_ids[index], RxIrq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart0_irq() {
|
void uart0_irq() {
|
||||||
uart_irq(UART0->S1, 0);
|
uart_irq(UART0->S1, 0);
|
||||||
if (UART0->S1 & UART_S1_OR_MASK)
|
if (UART0->S1 & UARTLP_S1_OR_MASK)
|
||||||
UART0->S1 |= UART_S1_OR_MASK;
|
UART0->S1 |= UARTLP_S1_OR_MASK;
|
||||||
}
|
}
|
||||||
|
#if UART_NUM > 1
|
||||||
void uart1_irq() {uart_irq(UART1->S1, 1);}
|
void uart1_irq() {uart_irq(UART1->S1, 1);}
|
||||||
void uart2_irq() {uart_irq(UART2->S1, 2);}
|
void uart2_irq() {uart_irq(UART2->S1, 2);}
|
||||||
|
#endif
|
||||||
|
|
||||||
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
|
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
|
||||||
irq_handler = handler;
|
irq_handler = handler;
|
||||||
|
@ -239,14 +223,16 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
|
||||||
uint32_t vector = 0;
|
uint32_t vector = 0;
|
||||||
switch ((int)obj->uart) {
|
switch ((int)obj->uart) {
|
||||||
case UART_0: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break;
|
case UART_0: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break;
|
||||||
|
#if UART_NUM > 1
|
||||||
case UART_1: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break;
|
case UART_1: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break;
|
||||||
case UART_2: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break;
|
case UART_2: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
switch (irq) {
|
switch (irq) {
|
||||||
case RxIrq: obj->uart->C2 |= (UART_C2_RIE_MASK); break;
|
case RxIrq: obj->uart->C2 |= (UARTLP_C2_RIE_MASK); break;
|
||||||
case TxIrq: obj->uart->C2 |= (UART_C2_TIE_MASK); break;
|
case TxIrq: obj->uart->C2 |= (UARTLP_C2_TIE_MASK); break;
|
||||||
}
|
}
|
||||||
NVIC_SetVector(irq_n, vector);
|
NVIC_SetVector(irq_n, vector);
|
||||||
NVIC_EnableIRQ(irq_n);
|
NVIC_EnableIRQ(irq_n);
|
||||||
|
@ -255,12 +241,12 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
|
||||||
int all_disabled = 0;
|
int all_disabled = 0;
|
||||||
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
|
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
|
||||||
switch (irq) {
|
switch (irq) {
|
||||||
case RxIrq: obj->uart->C2 &= ~(UART_C2_RIE_MASK); break;
|
case RxIrq: obj->uart->C2 &= ~(UARTLP_C2_RIE_MASK); break;
|
||||||
case TxIrq: obj->uart->C2 &= ~(UART_C2_TIE_MASK); break;
|
case TxIrq: obj->uart->C2 &= ~(UARTLP_C2_TIE_MASK); break;
|
||||||
}
|
}
|
||||||
switch (other_irq) {
|
switch (other_irq) {
|
||||||
case RxIrq: all_disabled = (obj->uart->C2 & (UART_C2_RIE_MASK)) == 0; break;
|
case RxIrq: all_disabled = (obj->uart->C2 & (UARTLP_C2_RIE_MASK)) == 0; break;
|
||||||
case TxIrq: all_disabled = (obj->uart->C2 & (UART_C2_TIE_MASK)) == 0; break;
|
case TxIrq: all_disabled = (obj->uart->C2 & (UARTLP_C2_TIE_MASK)) == 0; break;
|
||||||
}
|
}
|
||||||
if (all_disabled)
|
if (all_disabled)
|
||||||
NVIC_DisableIRQ(irq_n);
|
NVIC_DisableIRQ(irq_n);
|
||||||
|
@ -282,18 +268,18 @@ void serial_putc(serial_t *obj, int c) {
|
||||||
|
|
||||||
int serial_readable(serial_t *obj) {
|
int serial_readable(serial_t *obj) {
|
||||||
// check overrun
|
// check overrun
|
||||||
if (obj->uart->S1 & UART_S1_OR_MASK) {
|
if (obj->uart->S1 & UARTLP_S1_OR_MASK) {
|
||||||
obj->uart->S1 |= UART_S1_OR_MASK;
|
obj->uart->S1 |= UARTLP_S1_OR_MASK;
|
||||||
}
|
}
|
||||||
return (obj->uart->S1 & UART_S1_RDRF_MASK);
|
return (obj->uart->S1 & UARTLP_S1_RDRF_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
int serial_writable(serial_t *obj) {
|
int serial_writable(serial_t *obj) {
|
||||||
// check overrun
|
// check overrun
|
||||||
if (obj->uart->S1 & UART_S1_OR_MASK) {
|
if (obj->uart->S1 & UARTLP_S1_OR_MASK) {
|
||||||
obj->uart->S1 |= UART_S1_OR_MASK;
|
obj->uart->S1 |= UARTLP_S1_OR_MASK;
|
||||||
}
|
}
|
||||||
return (obj->uart->S1 & UART_S1_TDRE_MASK);
|
return (obj->uart->S1 & UARTLP_S1_TDRE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_clear(serial_t *obj) {
|
void serial_clear(serial_t *obj) {
|
||||||
|
@ -304,10 +290,10 @@ void serial_pinout_tx(PinName tx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_break_set(serial_t *obj) {
|
void serial_break_set(serial_t *obj) {
|
||||||
obj->uart->C2 |= UART_C2_SBK_MASK;
|
obj->uart->C2 |= UARTLP_C2_SBK_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_break_clear(serial_t *obj) {
|
void serial_break_clear(serial_t *obj) {
|
||||||
obj->uart->C2 &= ~UART_C2_SBK_MASK;
|
obj->uart->C2 &= ~UARTLP_C2_SBK_MASK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
#include "sleep_api.h"
|
#include "sleep_api.h"
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
//Normal wait mode
|
//Normal wait mode
|
||||||
void sleep(void)
|
void sleep(void)
|
||||||
|
@ -43,8 +44,10 @@ void deepsleep(void)
|
||||||
//Switch back to PLL as clock source if needed
|
//Switch back to PLL as clock source if needed
|
||||||
//The interrupt that woke up the device will run at reduced speed
|
//The interrupt that woke up the device will run at reduced speed
|
||||||
if (PLL_FLL_en) {
|
if (PLL_FLL_en) {
|
||||||
|
#ifdef MCG_C5_PLLCLKEN0_MASK //PLL available
|
||||||
if (MCG->C6 & (1<<MCG_C6_PLLS_SHIFT) != 0) /* If PLL */
|
if (MCG->C6 & (1<<MCG_C6_PLLS_SHIFT) != 0) /* If PLL */
|
||||||
while((MCG->S & MCG_S_LOCK0_MASK) == 0x00U); /* Wait until locked */
|
while((MCG->S & MCG_S_LOCK0_MASK) == 0x00U); /* Wait until locked */
|
||||||
|
#endif
|
||||||
MCG->C1 &= ~MCG_C1_CLKS_MASK;
|
MCG->C1 &= ~MCG_C1_CLKS_MASK;
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue