From 9ddce12aa647b683446a26e538e85e929ea860fe Mon Sep 17 00:00:00 2001 From: Takayuki Kurosawa Date: Fri, 24 Oct 2014 11:05:17 +0900 Subject: [PATCH] [RZ/A1H] commit for HAL changes - adds GPIO driver - adds I2C driver - adds SPI driver - adds PWM driver - adds serial driver (irq not supported) - adds ticker driver - add analogin driver --- .../TARGET_RZ_A1H/PeripheralNames.h | 128 +++++++ .../TARGET_RENESAS/TARGET_RZ_A1H/PinNames.h | 119 ++++++ .../TARGET_RENESAS/TARGET_RZ_A1H/PortNames.h | 34 ++ .../TARGET_MBED_MBRZA1H/reserved_pins.h | 6 + .../TARGET_RZ_A1H/analogin_api.c | 117 ++++++ .../hal/TARGET_RENESAS/TARGET_RZ_A1H/device.h | 60 +++ .../TARGET_RZ_A1H/gpio_addrdefine.h | 22 ++ .../TARGET_RENESAS/TARGET_RZ_A1H/gpio_api.c | 53 +++ .../TARGET_RZ_A1H/gpio_object.h | 48 +++ .../TARGET_RENESAS/TARGET_RZ_A1H/i2c_api.c | 357 ++++++++++++++++++ .../TARGET_RENESAS/TARGET_RZ_A1H/objects.h | 73 ++++ .../hal/TARGET_RENESAS/TARGET_RZ_A1H/pinmap.c | 47 +++ .../TARGET_RENESAS/TARGET_RZ_A1H/port_api.c | 65 ++++ .../TARGET_RENESAS/TARGET_RZ_A1H/pwmout_api.c | 174 +++++++++ .../TARGET_RENESAS/TARGET_RZ_A1H/serial_api.c | 357 ++++++++++++++++++ .../TARGET_RENESAS/TARGET_RZ_A1H/spi_api.c | 234 ++++++++++++ .../TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c | 96 +++++ 17 files changed, 1990 insertions(+) create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PeripheralNames.h create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PinNames.h create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PortNames.h create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/TARGET_MBED_MBRZA1H/reserved_pins.h create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/analogin_api.c create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/device.h create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/gpio_addrdefine.h create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/gpio_api.c create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/gpio_object.h create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/i2c_api.c create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/objects.h create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/pinmap.c create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/port_api.c create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/pwmout_api.c create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/serial_api.c create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/spi_api.c create mode 100644 libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PeripheralNames.h b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PeripheralNames.h new file mode 100644 index 0000000000..a2aed587d6 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PeripheralNames.h @@ -0,0 +1,128 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_PERIPHERALNAMES_H +#define MBED_PERIPHERALNAMES_H + +#include "cmsis.h" +#include "PinNames.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + UART0, + UART1, + UART2, + UART3, +} UARTName; + +// PWMType & 1 == 1 then have to use PWDTR[12] == 1 +typedef enum { + PWM1A = 0, + PWM1B, + PWM1C, + PWM1D, + PWM1E, + PWM1F, + PWM1G, + PWM1H, + PWM2A = 0x10, + PWM2B, + PWM2C, + PWM2D, + PWM2E, + PWM2F, + PWM2G, + PWM2H, +} PWMType; + +#define PTM_SHIFT 8 +typedef enum { + PWM0_PIN = (1 << PTM_SHIFT) | PWM2E, // LED_R (through MTU2) TIOC4A [T.B.D] + PWM1_PIN = (0 << PTM_SHIFT) | PWM2F, // LED_G + PWM2_PIN = (0 << PTM_SHIFT) | PWM2G, // LED_B + PWM3_PIN = (0 << PTM_SHIFT) | PWM2H, // LED_USER (not explicitly supported) + PWM4_PIN = (0 << PTM_SHIFT) | PWM1G, // D9 + PWM5_PIN = (0 << PTM_SHIFT) | PWM1H, // D8 not explicitly supported + PWM6_PIN = (0 << PTM_SHIFT) | PWM1F, // D7 not explicitly supported + PWM7_PIN = (0 << PTM_SHIFT) | PWM1D, // D6 +} PWMName; + +typedef enum { + AN0= 0, + AN1= 1, + AN2= 2, + AN3= 3, + AN4= 4, + AN5= 5, + AN6= 6, + AN7= 7, +} ADCName; + +typedef enum { + SPI_0 = 0, + SPI_1, +} SPIName; + +typedef enum { + I2C_0 = 0, + I2C_1, + I2C_2, + I2C_3 +} I2CName; + + +#define STDIO_UART_TX USBTX +#define STDIO_UART_RX USBRX +#define STDIO_UART P_SCIF2 + +// Default peripherals +#define MBED_SPI0 p5, p6, p7, p8 +#define MBED_SPI1 p11, p12, p13, p14 + +#define MBED_UART0 p9, p10 +#define MBED_UART1 p13, p14 +#define MBED_UART2 p28, p27 +#define MBED_UARTUSB USBTX, USBRX + +#define MBED_I2C0 p28, p27 +#define MBED_I2C1 p9, p10 + +#define MBED_CAN0 p30, p29 + +#define MBED_ANALOGOUT0 p18 + +#define MBED_ANALOGIN0 p15 +#define MBED_ANALOGIN1 p16 +#define MBED_ANALOGIN2 p17 +#define MBED_ANALOGIN3 p18 +#define MBED_ANALOGIN4 p19 +#define MBED_ANALOGIN5 p20 + +#define MBED_PWMOUT0 p26 +#define MBED_PWMOUT1 p25 +#define MBED_PWMOUT2 p24 +#define MBED_PWMOUT3 p23 +#define MBED_PWMOUT4 p22 +#define MBED_PWMOUT5 p21 + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PinNames.h b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PinNames.h new file mode 100644 index 0000000000..85ad4da8bb --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PinNames.h @@ -0,0 +1,119 @@ +/* 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_PINNAMES_H +#define MBED_PINNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PIN_INPUT, + PIN_OUTPUT +} PinDirection; + +#define PORT_SHIFT 4 + +typedef enum { + P0_0 = 0, + P0_1, P0_2, P0_3, P0_4, P0_5,_P0_6,_P0_7,_P0_8,_P0_9,_P0_10,_P0_11,_P0_12,_P0_13,_P0_14,_P0_15, + P1_0, P1_1, P1_2, P1_3, P1_4, P1_5, P1_6, P1_7, P1_8, P1_9, P1_10, P1_11, P1_12, P1_13, P1_14, P1_15, + P2_0, P2_1, P2_2, P2_3, P2_4, P2_5, P2_6, P2_7, P2_8, P2_9, P2_10, P2_11, P2_12, P2_13, P2_14, P2_15, + P3_0, P3_1, P3_2, P3_3, P3_4, P3_5, P3_6, P3_7, P3_8, P3_9, P3_10, P3_11, P3_12, P3_13, P3_14, P3_15, + P4_0, P4_1, P4_2, P4_3, P4_4, P4_5, P4_6, P4_7, P4_8, P4_9, P4_10, P4_11, P4_12, P4_13, P4_14, P4_15, + P5_0, P5_1, P5_2, P5_3, P5_4, P5_5, P5_6, P5_7, P5_8, P5_9, P5_10, P5_11, P5_12, P5_13, P5_14, P5_15, + P6_0, P6_1, P6_2, P6_3, P6_4, P6_5, P6_6, P6_7, P6_8, P6_9, P6_10, P6_11, P6_12, P6_13, P6_14, P6_15, + P7_0, P7_1, P7_2, P7_3, P7_4, P7_5, P7_6, P7_7, P7_8, P7_9, P7_10, P7_11, P7_12, P7_13, P7_14, P7_15, + P8_0, P8_1, P8_2, P8_3, P8_4, P8_5, P8_6, P8_7, P8_8, P8_9, P8_10, P8_11, P8_12, P8_13, P8_14, P8_15, + P9_0, P9_1, P9_2, P9_3, P9_4, P9_5, P9_6, P9_7, P9_8, P9_9, P9_10, P9_11, P9_12, P9_13, P9_14, P9_15, + P10_0,P10_1,P10_2,P10_3,P10_4,P10_5,P10_6,P10_7,P10_8,P10_9,P10_10,P10_11,P10_12,P10_13,P10_14,P10_15, + P11_0,P11_1,P11_2,P11_3,P11_4,P11_5,P11_6,P11_7,P11_8,P11_9,P11_10,P11_11,P11_12,P11_13,P11_14,P11_15, + + // mbed DIP Pin Names + p10 = P0_1, + p21 = P2_5, + p22 = P2_4, + p23 = P2_3, + p24 = P2_2, + p25 = P2_1, + p26 = P2_0, + p29 = P0_5, + p30 = P0_4, + + // Other mbed Pin Names + LED1 = P4_4, + LED2 = P4_5, + LED3 = P4_6, + LED4 = P4_7, + + LED_RED = LED1, + LED_GREEN= LED2, + LED_BLUE = LED3, + LED_USER = LED4, + + USBTX = P6_3, + USBRX = P6_2, + + // Arduiono Pin Names + D0 = P2_15, + D1 = P2_14, + D2 = P11_15, + D3 = P11_14, + D4 = P11_13, + D5 = P11_12, + D6 = P8_11, + D7 = P8_13, + D8 = P8_15, + D9 = P8_14, + D10 = P10_13, + D11 = P10_14, + D12 = P10_15, + D13 = P10_12, + D14 = P1_3, + D15 = P1_2, + + A0 = P1_8, + A1 = P1_9, + A2 = P1_10, + A3 = P1_11, + A4 = P1_13, + A5 = P1_15, + + I2C_SCL = D15, + I2C_SDA = D14, + + // Not connected + NC = (int)0xFFFFFFFF +} PinName; + +typedef enum { + PullUp = 0, + PullDown = 3, + PullNone = 2, + OpenDrain = 4, + PullDefault = PullDown +} PinMode; + +#define PINGROUP(pin) (((pin)>>PORT_SHIFT)&0x0f) +#define PINNO(pin) ((pin)&0x0f) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PortNames.h b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PortNames.h new file mode 100644 index 0000000000..270cdeecb0 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PortNames.h @@ -0,0 +1,34 @@ +/* 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 { + Port0 = 0, + Port1 = 1, + Port2 = 2, + Port3 = 3, + Port4 = 4 +} PortName; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/TARGET_MBED_MBRZA1H/reserved_pins.h b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/TARGET_MBED_MBRZA1H/reserved_pins.h new file mode 100644 index 0000000000..10d094ce32 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/TARGET_MBED_MBRZA1H/reserved_pins.h @@ -0,0 +1,6 @@ +#ifndef RESERVED_PINS_H +#define RESERVED_PINS_H + +#define TARGET_RESERVED_PINS {} + +#endif diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/analogin_api.c b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/analogin_api.c new file mode 100644 index 0000000000..8307996f9f --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/analogin_api.c @@ -0,0 +1,117 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include "analogin_api.h" + +#include "cmsis.h" +#include "pinmap.h" + +#include "adc_iodefine.h" +#include "cpg_iodefine.h" + +#define ANALOGIN_MEDIAN_FILTER 1 + +#define ADC_12BIT_RANGE 0xFFF + +static const PinMap PinMap_ADC[] = { + {P1_8, AN0, 1}, + {P1_9, AN1, 1}, + {P1_10, AN2, 1}, + {P1_11, AN3, 1}, + {P1_13, AN5, 1}, + {P1_15, AN7, 1}, + {NC, NC, 0} +}; + +static volatile uint16_t *ADCDR[] = { + &ADCADDRA, + &ADCADDRB, + &ADCADDRC, + &ADCADDRD, + &ADCADDRE, + &ADCADDRF, + &ADCADDRG, + &ADCADDRH, +}; + +#define ADC_RANGE ADC_12BIT_RANGE + +void analogin_init(analogin_t *obj, PinName pin) { + obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC); + MBED_ASSERT(obj->adc != (ADCName)NC); + + CPGSTBCR3 &= ~(1 << 1); + CPGSTBCR6 &= ~(1 << 7); + + // 000_0 000_1 11_00 0_xxx + // 15: ADFlag 14: IntEn 13: start, [12:9] Triger..0 + // [8:6] CLK 100 :: 12-bit 1054tclk + // [5:3] scanmode 000 :: single mode + // [2:0] channel select + ADCADCSR = 0x0100 | (obj->adc&0xf); + + pinmap_pinout(pin, PinMap_ADC); +} + +static inline uint32_t adc_read(analogin_t *obj) { + // Select the appropriate channel and start conversion + ADCADCSR |= (1 << 13 | (obj->adc&0xf)); + + // Repeatedly get the sample data until DONE bit +#define nothing + while ((ADCADCSR & (1 << 15)) == 0 || (ADCADCSR & (1<<13)) != 0) nothing; + + // clear flag + ADCADCSR &= ~(1 << 15); + + return ((*(ADCDR[obj->adc]))>>4) & ADC_RANGE; // 12 bit +} + +static inline void order(uint32_t *a, uint32_t *b) { + if (*a > *b) { + uint32_t t = *a; + *a = *b; + *b = t; + } +} + +static inline uint32_t adc_read_u32(analogin_t *obj) { + uint32_t value; +#if ANALOGIN_MEDIAN_FILTER + uint32_t v1 = adc_read(obj); + uint32_t v2 = adc_read(obj); + uint32_t v3 = adc_read(obj); + order(&v1, &v2); + order(&v2, &v3); + order(&v1, &v2); + value = v2; +#else + value = adc_read(obj); +#endif + return value; +} + +uint16_t analogin_read_u16(analogin_t *obj) { + uint32_t value = adc_read_u32(obj); + + return value; + //(value << 4) | ((value >> 8) & 0x000F); // 12 bit +} + +float analogin_read(analogin_t *obj) { + uint32_t value = adc_read_u32(obj); + return (float)value * (1.0f / (float)ADC_RANGE); +} diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/device.h b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/device.h new file mode 100644 index 0000000000..23089470a2 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/device.h @@ -0,0 +1,60 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_DEVICE_H +#define MBED_DEVICE_H + +#define DEVICE_PORTIN 1 +#define DEVICE_PORTOUT 1 +#define DEVICE_PORTINOUT 1 + +#define DEVICE_INTERRUPTIN 1 + +#define DEVICE_ANALOGIN 1 +#define DEVICE_ANALOGOUT 0 + +#define DEVICE_SERIAL 1 +#define DEVICE_SERIAL_FC 1 + +#define DEVICE_I2C 1 +#define DEVICE_I2CSLAVE 1 + +#define DEVICE_SPI 1 +#define DEVICE_SPISLAVE 1 + +#define DEVICE_CAN 0 + +#define DEVICE_RTC 0 + +#define DEVICE_ETHERNET 0 + +#define DEVICE_PWMOUT 1 + +#define DEVICE_SEMIHOST 0 +#define DEVICE_LOCALFILESYSTEM 0 +#define DEVICE_ID_LENGTH 32 +#define DEVICE_MAC_OFFSET 20 + +#define DEVICE_SLEEP 0 + +#define DEVICE_DEBUG_AWARENESS 0 + +#define DEVICE_STDIO_MESSAGES 0 + +#define DEVICE_ERROR_PATTERN 0 + +#include "objects.h" + +#endif diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/gpio_addrdefine.h b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/gpio_addrdefine.h new file mode 100644 index 0000000000..3865c03ec2 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/gpio_addrdefine.h @@ -0,0 +1,22 @@ +#ifndef __GPIO_ADDRDEFINE__ +#define __GPIO_ADDRDEFINE__ + +#define GPIO_BASE ((long)0xFCFE3000uL) /* GPIO */ + +#define PORT(n) (volatile unsigned short *)(GPIO_BASE + 0x000 + ((n)*4)) +#define PSR(n) (volatile unsigned long *)(GPIO_BASE + 0x100 + ((n)*4)) +#define PPR(n) (volatile unsigned short *)(GPIO_BASE + 0x200 + ((n)*4)) +#define PM(n) (volatile unsigned short *)(GPIO_BASE + 0x300 + ((n)*4)) +#define PMC(n) (volatile unsigned short *)(GPIO_BASE + 0x400 + ((n)*4)) +#define PFC(n) (volatile unsigned short *)(GPIO_BASE + 0x500 + ((n)*4)) +#define PFCE(n) (volatile unsigned short *)(GPIO_BASE + 0x600 + ((n)*4)) +#define PNOT(n) (volatile unsigned short *)(GPIO_BASE + 0x700 + ((n)*4)) +#define PMSR(n) (volatile unsigned long *)(GPIO_BASE + 0x800 + ((n)*4)) +#define PMCSR(n) (volatile unsigned long *)(GPIO_BASE + 0x900 + ((n)*4)) +#define PFCAE(n) (volatile unsigned short *)(GPIO_BASE + 0xa00 + ((n)*4)) +#define PIBC(n) (volatile unsigned short *)(GPIO_BASE + 0x4000 +((n)*4)) +#define PBDC(n) (volatile unsigned short *)(GPIO_BASE + 0x4100 +((n)*4)) +#define PIPC(n) (volatile unsigned short *)(GPIO_BASE + 0x4200 +((n)*4)) + +#endif/*__GPIO_ADDRDEFINE__*/ + diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/gpio_api.c b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/gpio_api.c new file mode 100644 index 0000000000..14831bd688 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/gpio_api.c @@ -0,0 +1,53 @@ +/* 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" +#include "gpio_addrdefine.h" + + +uint32_t gpio_set(PinName pin) { + pin_function(pin, 0); + return (1 << PINNO(pin)); +} + +void gpio_init(gpio_t *obj, PinName pin) { + int group ; + if(pin == NC) return; + + obj->pin = pin; + obj->mask = gpio_set(pin); + + group = PINGROUP(pin); + if (group > 11) return; + + obj->reg_set = (volatile uint32_t *)PORT(group); + obj->reg_in = (volatile uint32_t *) PPR(group); + obj->reg_dir = (volatile uint32_t *) PM(group); + obj->reg_buf = (volatile uint32_t *)PIBC(group); +} + +void gpio_mode(gpio_t *obj, PinMode mode) { +// pullup, pulldown, open...etc +} + +void gpio_dir(gpio_t *obj, PinDirection direction) { + switch (direction) { + case PIN_INPUT : *obj->reg_dir |= obj->mask; + *obj->reg_buf |= obj->mask; break; + case PIN_OUTPUT: *obj->reg_dir &= ~obj->mask; + *obj->reg_buf &= ~obj->mask; break; + } +} diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/gpio_object.h b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/gpio_object.h new file mode 100644 index 0000000000..6eb8d80402 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/gpio_object.h @@ -0,0 +1,48 @@ +/* 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; + __I uint32_t *reg_in; + __IO uint32_t *reg_buf; +} gpio_t; + +static inline void gpio_write(gpio_t *obj, int value) { + if (value) + *obj->reg_set |= obj->mask; + else + *obj->reg_set &= ~obj->mask; +} + +static inline int gpio_read(gpio_t *obj) { + return ((*obj->reg_in & obj->mask) ? 1 : 0); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/i2c_api.c b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/i2c_api.c new file mode 100644 index 0000000000..0ec6bc68e2 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/i2c_api.c @@ -0,0 +1,357 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include "i2c_api.h" +#include "cmsis.h" +#include "pinmap.h" + + +#include "riic_iodefine.h" + +volatile struct st_riic *RIIC[] = RIIC_ADDRESS_LIST; + +#define REG(N) \ + RIIC[obj->i2c]->RIICn##N + +#define NACKF (1 << 4) + +static const PinMap PinMap_I2C_SDA[] = { + {P1_1 , I2C_0, 1}, + {P1_3 , I2C_1, 1}, + {P1_7 , I2C_3, 1}, + {NC , NC , 0} +}; + +static const PinMap PinMap_I2C_SCL[] = { + {P1_0 , I2C_0, 1}, + {P1_2 , I2C_1, 1}, + {P1_6 , I2C_3, 1}, + {NC , NC, 0} +}; + +// Clear the Transmit data Empty TDRE +static inline int i2c_addressed(i2c_t *obj) { + volatile int sar0 = (REG(SR1.UINT8[0])&1), + trs = (REG(CR2.UINT8[0])&0x20) >> 5; + return sar0 | (trs <<1); +} + +static inline int i2c_status(i2c_t *obj) { + return REG(SR2.UINT8[0]); +} + +static inline void i2c_clear_TDRE(i2c_t *obj) { + REG(SR2.UINT32) &= ~(1 << 7); +} + +static inline void i2c_wait_RDRF(i2c_t *obj) { + while (!(i2c_status(obj) & (1 << 5))) ; +} + +// Wait until the Trans Data Empty (TDRE) is set +static int i2c_wait_TDRE(i2c_t *obj) { + int timeout = 0; + + while (!(i2c_status(obj) & (1 << 7))) { + if (timeout > 100000) return -1; + } + + return 0; +} + +static inline void i2c_power_enable(i2c_t *obj) { + volatile uint8_t dummy; + switch ((int)obj->i2c) { + case I2C_0: CPGSTBCR9 &= ~(0x80); break; + case I2C_1: CPGSTBCR9 &= ~(0x40); break; + case I2C_2: CPGSTBCR9 &= ~(0x20); break; + case I2C_3: CPGSTBCR9 &= ~(0x10); break; + } + dummy = CPGSTBCR9; +} + +void i2c_init(i2c_t *obj, PinName sda, PinName scl) { + // determine the SPI to use + I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA); + I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL); + obj->i2c = pinmap_merge(i2c_sda, i2c_scl); + obj->dummy = 1; + MBED_ASSERT((int)obj->i2c != NC); + + // enable power + i2c_power_enable(obj); + + // full reset + REG(CR1.UINT8[0]) &= ~(1 << 7); // CR1.ICE off + REG(CR1.UINT8[0]) |= (1 << 6); // CR1.IICRST on + REG(CR1.UINT8[0]) |= (1 << 7); // CR1.ICE on + + REG(MR1.UINT8[0]) = 0x08; // P_phi /8 9bit (including Ack) + REG(SER.UINT8[0]) = 0x00; // no slave addr enabled + + // set default frequency at 100k + i2c_frequency(obj, 100000); + + REG(MR2.UINT8[0]) = 0x07; + REG(MR3.UINT8[0]) = 0x00; + + REG(FER.UINT8[0]) = 0x72; // SCLE, NFE enabled, TMOT + REG(IER.UINT8[0]) = 0x00; // no interrupt + + REG(CR1.UINT32) &= ~(1 << 6); // CR1.IICRST negate reset + + pinmap_pinout(sda, PinMap_I2C_SDA); + pinmap_pinout(scl, PinMap_I2C_SCL); +} + +inline int i2c_start(i2c_t *obj) { + if (REG(CR2.UINT32) & (1 << 7)) { // BBSY check + return 0xff; + } + REG(CR2.UINT8[0]) |= 0x62; // start + + return 0x10; +} + +inline int i2c_stop(i2c_t *obj) { + int timeout = 0; + + // write the stop bit + REG(CR2.UINT32) |= (1 << 3); + + // wait for SP bit to reset + while(REG(CR2.UINT32) & (1 << 3)) { + timeout ++; + if (timeout > 100000) return 1; + } + + obj->dummy = 1; + REG(CR2.UINT32) &= ~ (1 << 3); + return 0; +} + +static inline int i2c_do_write(i2c_t *obj, int value) { + // write the data + if (!(i2c_status(obj) & NACKF)) { // NACF=0 + i2c_wait_TDRE(obj); + REG(DRT.UINT32) = value; + } else { + return 0xff; + } + return i2c_status(obj); +} + +static inline int i2c_do_read(i2c_t *obj, int last) { + if (obj->dummy) { + volatile int dummy = REG(DRR.UINT32); + obj->dummy = 0; + } + if (last) { + // send a NOT ACK + REG(MR2.UINT32) |= (1 <<6); + } else { + // send a ACK + REG(MR2.UINT32) &= ~(1 <<6); + } + // wait for it to arrive + i2c_wait_RDRF(obj); + + // return the data + return (REG(DRR.UINT32) & 0xFF); +} + +void i2c_frequency(i2c_t *obj, int hz) { + uint32_t PCLK = 6666666; + + uint32_t pulse = PCLK / (hz * 2); + + // I2C Rate + REG(BRL.UINT32) = pulse; + REG(BRH.UINT32) = pulse; +} + +int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { + int count, status; + + status = i2c_start(obj); + + if (status == 0xff) { + i2c_stop(obj); + return I2C_ERROR_BUS_BUSY; + } + + status = i2c_do_write(obj, (address | 0x01)); + if (status & 0x01) { + i2c_stop(obj); + return I2C_ERROR_NO_SLAVE; + } + + // Read in all except last byte + for (count = 0; count < (length - 1); count++) { + int value = i2c_do_read(obj, 0); + status = i2c_status(obj); + if (status & 0x10) { + i2c_stop(obj); + return count; + } + data[count] = (char) value; + } + + // read in last byte + int value = i2c_do_read(obj, 1); + status = i2c_status(obj); + if (status & 0x10) { + i2c_stop(obj); + return length - 1; + } + + data[count] = (char) value; + + // If not repeated start, send stop. + if (stop) { + i2c_stop(obj); + } + + return length; +} + +int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { + int i, status; + + status = i2c_start(obj); + + if ((status == 0xff)) { + i2c_stop(obj); + return I2C_ERROR_BUS_BUSY; + } + + status = i2c_do_write(obj, address); + if (status & 0x10) { + i2c_stop(obj); + return I2C_ERROR_NO_SLAVE; + } + + for (i=0; idummy) { + volatile int dummy = REG(DRR.UINT32) ; + obj->dummy = 0; + } + + do { + i2c_wait_RDRF(obj); + status = i2c_status(obj); + if(!(status & 0x10)) { + data[count] = REG(DRR.UINT32) & 0xFF; + } + count++; + } while ( !(status & 0x10) && (count < length) ); + + if(status & 0x10) { + i2c_stop(obj); + } + + //i2c_clear_TDRE(obj); + + return count; +} + +int i2c_slave_write(i2c_t *obj, const char *data, int length) { + int count = 0; + int status; + + if(length <= 0) { + return(0); + } + + do { + status = i2c_do_write(obj, data[count]); + count++; + } while ((count < length) && !(status & 0x10)); + + if (!(status & 0x10)) { + i2c_stop(obj); + } + + i2c_clear_TDRE(obj); + + return(count); +} + +void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) { + REG(SAR0.UINT32) = address & 0xfe; +} diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/objects.h b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/objects.h new file mode 100644 index 0000000000..db8ed0d8d3 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/objects.h @@ -0,0 +1,73 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_OBJECTS_H +#define MBED_OBJECTS_H + +#include +#include "cmsis.h" +#include "PortNames.h" +#include "PeripheralNames.h" +#include "PinNames.h" +#include "gpio_object.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct i2c_s { + uint32_t i2c; + uint32_t dummy; +}; + +struct spi_s { + uint32_t spi; +}; + +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 serial_s { + struct st_scif *uart; + int index; +}; + +struct pwmout_s { + __IO uint16_t *MR; + __IO uint16_t *CY; + uint16_t flag; + PWMName pwm; +}; + +struct analogin_s { + ADCName adc; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/pinmap.c b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/pinmap.c new file mode 100644 index 0000000000..4480b83a73 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/pinmap.c @@ -0,0 +1,47 @@ +/* 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 "mbed_error.h" +#include "gpio_addrdefine.h" + +void pin_function(PinName pin, int function) { + if (pin == (PinName)NC) return; + + int n = pin >> 4; + int bitmask = 1<<(pin & 0xf); + + if (function == 0) { + // means GPIO mode + *PMC(n) &= ~bitmask; + } else { + // alt-function mode + *PMC(n) |= bitmask; + --function; + + if (function & (1 << 2)) { *PFCAE(n) |= bitmask;}else { *PFCAE(n) &= ~bitmask;} + if (function & (1 << 1)) { *PFCE(n) |= bitmask;}else { *PFCE(n) &= ~bitmask;} + if (function & (1 << 0)) { *PFC(n) |= bitmask;}else { *PFC(n) &= ~bitmask;} + *PIPC(n) |= bitmask; + + if (P1_0 <= pin && pin <= P1_7 && function == 0) { + *PBDC(n) |= bitmask; + } + } +} + +void pin_mode(PinName pin, PinMode mode) { +// if (pin == (PinName)NC) { return; } +} diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/port_api.c b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/port_api.c new file mode 100644 index 0000000000..5f9f16e4d5 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/port_api.c @@ -0,0 +1,65 @@ +/* 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)(0); +} + +void port_init(port_t *obj, PortName port, int mask, PinDirection dir) { + obj->port = port; + obj->mask = mask; + + // Do not use masking, because it prevents the use of the unmasked pins + // port_reg->FIOMASK = ~mask; + + uint32_t i; + // The function is set per pin: reuse gpio logic + for (i=0; i<32; i++) { + if (obj->mask & (1<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<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); +} diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/pwmout_api.c b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/pwmout_api.c new file mode 100644 index 0000000000..e1fe139962 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/pwmout_api.c @@ -0,0 +1,174 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include "pwmout_api.h" +#include "cmsis.h" +#include "pinmap.h" + +#include "cpg_iodefine.h" +#include "pwm_iodefine.h" + +#define TCR_CNT_EN 0x00000001 +#define TCR_RESET 0x00000002 + +// PORT ID, PWM ID, Pin function +static const PinMap PinMap_PWM[] = { + {LED_RED , 0, 4}, + {LED_GREEN, 1, 4}, + {LED_BLUE , 2, 4}, + {P4_7 , 3, 4}, + {P8_14 , 4, 6}, + {P8_15 , 5, 6}, + {P8_13 , 6, 6}, + {P8_11 , 7, 6}, + {NC, NC, 0} +}; + +static __IO uint16_t PORT[] = { + PWM2E, + PWM2F, + PWM2G, + PWM2H, + PWM1G, + PWM1H, + PWM1F, + PWM1D, +}; +static __IO uint16_t *PWM_MATCH[] = { + &PWMPWBFR_2E, + &PWMPWBFR_2E, + &PWMPWBFR_2G, + &PWMPWBFR_2G, + &PWMPWBFR_1G, + &PWMPWBFR_1G, + &PWMPWBFR_1E, + &PWMPWBFR_1C, +}; + +#define TCR_PWM_EN 0x00000008 + +static unsigned int pwm_clock_mhz; + +void pwmout_init(pwmout_t* obj, PinName pin) { + // determine the channel + PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM); + MBED_ASSERT(pwm != (PWMName)NC); + + obj->pwm = pwm; + obj->MR = PWM_MATCH[pwm]; + obj->flag = (PORT[pwm]&1)<<12; + + // power on + CPGSTBCR3 &= ~(1<<0); + + // clk mode settings PWM mode + PWMPWCR_1_BYTE_L = 0xc4; + PWMPWCR_2_BYTE_L = 0xc4; + + // output settings + PWMPWPR_1_BYTE_L = 0x00; + PWMPWPR_2_BYTE_L = 0x00; + + // cycle reg. + PWMPWCYR_1 = 0x3ff; + PWMPWCYR_2 = 0x3ff; + + //pwm_clock_mhz = SystemCoreClock / 4000000; + + PWMPWCR_1_BYTE_L = 0xcc; + PWMPWCR_2_BYTE_L = 0xcc; + // 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) { + // [TODO] +} + +void pwmout_write(pwmout_t* obj, float value) { + if (value < 0.0f) { + value = 0.0; + } else if (value > 1.0f) { + value = 1.0; + } + + // set channel match to percentage + uint16_t v = (uint32_t)((float)0x3ff* value); + + v |= (obj->flag); + + // workaround for PWM1[1] - Never make it equal MR0, else we get 1 cycle dropout + *obj->MR = v; + + // accept on next period start + //LPC_PWM1->LER |= 1 << obj->pwm; +} + +float pwmout_read(pwmout_t* obj) { + float v = (float)((*obj->MR&0x3ff)) / 0x3ff; + return (v > 1.0f) ? (1.0f) : (v); +} + +void pwmout_period(pwmout_t* obj, float seconds) { + pwmout_period_us(obj, seconds * 1000000.0f); +} + +void pwmout_period_ms(pwmout_t* obj, int ms) { + pwmout_period_us(obj, ms * 1000); +} + +// Set the PWM period, keeping the duty cycle the same. +void pwmout_period_us(pwmout_t* obj, int us) { + // calculate number of ticks + uint16_t ticks = 0x3ff * us; + + // stop timer + *obj->MR = ticks; + + // Scale the pulse width to preserve the duty ratio + + // set the channel latch to update value at next period start +// LPC_PWM1->LER |= 1 << 0; + + // enable counter and pwm, clear reset + // LPC_PWM1->TCR = TCR_CNT_EN | TCR_PWM_EN; +} + +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) { + // calculate number of ticks + uint32_t v = pwm_clock_mhz * us; + + // workaround for PWM1[1] - Never make it equal MR0, else we get 1 cycle dropout + + // set the match register value + *obj->MR = v; + + // set the channel latch to update value at next period start + //LPC_PWM1->LER |= 1 << obj->pwm; +} diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/serial_api.c b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/serial_api.c new file mode 100644 index 0000000000..d738af2c41 --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/serial_api.c @@ -0,0 +1,357 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// math.h required for floating point operations for baud rate calculation +#include "mbed_assert.h" +#include +#include +#include + +#include "serial_api.h" +#include "cmsis.h" +#include "pinmap.h" +#include "gpio_api.h" + +#include "scif_iodefine.h" +typedef struct st_scif SCIF_TypeDef; +#include "cpg_iodefine.h" + +/****************************************************************************** + * INITIALIZATION + ******************************************************************************/ +#define UART_NUM 6 + +static const PinMap PinMap_UART_TX[] = { + {P6_3 , P_SCIF2, 7}, + {P2_14, P_SCIF0, 6}, + {P5_0 , P_SCIF4, 5}, + {P5_3 , P_SCIF3, 5}, + {P5_6 , P_SCIF6, 5}, + {P2_5 , P_SCIF1, 6}, + {P8_14, P_SCIF4, 7}, + {P8_13, P_SCIF5, 5}, + {P7_5 , P_SCIF7, 4}, + {NC , NC , 0} +}; + +static const PinMap PinMap_UART_RX[] = { + {P6_2 , P_SCIF2, 7}, + {P2_15, P_SCIF0, 6}, + {P5_1 , P_SCIF4, 5}, + {P5_4 , P_SCIF3, 5}, + {P5_7 , P_SCIF6, 5}, + {P2_6 , P_SCIF1, 6}, + {P8_15, P_SCIF4, 7}, + {P8_11, P_SCIF5, 5}, + {P7_4 , P_SCIF7, 4}, + {NC , NC , 0} +}; + +/* [TODO] impliment hardware Flow Control, interrupt +static const PinMap PinMap_UART_RTS[] = { + {P7_7, (int)P_SCIF7, 4}, + {P2_7 , (int)P_SCIF1, 6}, + {NC, NC, 0} +}; + +static const PinMap PinMap_UART_CTS[] = { + {P7_6, (int)P_SCIF7, 4}, + {P2_3, (int)P_SCIF1, 6}, + {NC, NC, 0} +};*/ + +static uart_irq_handler irq_handler; + +int stdio_uart_inited = 0; +serial_t stdio_uart; + +struct serial_global_data_s { + uint32_t serial_irq_id; + gpio_t sw_rts, sw_cts; + uint8_t count, rx_irq_set_flow, rx_irq_set_api; +}; + +static struct serial_global_data_s uart_data[UART_NUM]; + +void serial_init(serial_t *obj, PinName tx, PinName rx) { + int is_stdio_uart = 0; + + // determine the UART to use + uint32_t uart_tx = pinmap_peripheral(tx, PinMap_UART_TX); + uint32_t uart_rx = pinmap_peripheral(rx, PinMap_UART_RX); + uint32_t uart = pinmap_merge(uart_tx, uart_rx); + MBED_ASSERT((int)uart != NC); + + obj->uart = (SCIF_TypeDef *)uart; + // enable power + switch (uart) { + case P_SCIF0: CPG.STBCR4 &= ~(1 << 7); break; + case P_SCIF1: CPG.STBCR4 &= ~(1 << 6); break; + case P_SCIF2: CPG.STBCR4 &= ~(1 << 5); break; + case P_SCIF3: CPG.STBCR4 &= ~(1 << 4); break; + case P_SCIF4: CPG.STBCR4 &= ~(1 << 3); break; + case P_SCIF5: CPG.STBCR4 &= ~(1 << 2); break; + case P_SCIF6: CPG.STBCR4 &= ~(1 << 1); break; + case P_SCIF7: CPG.STBCR4 &= ~(1 << 0); break; + } + volatile uint8_t dummy ; + dummy = CPG.STBCR4; + + /* ==== SCIF initial setting ==== */ + /* ---- Serial control register (SCSCR) setting ---- */ + /* B'00 : Internal CLK */ + obj->uart->SCSCR = 0x0000u; /* SCIF transmitting and receiving operations stop */ + + /* ---- FIFO control register (SCFCR) setting ---- */ + /* Transmit FIFO reset & Receive FIFO data register reset */ + obj->uart->SCFCR = 0x0006; + + /* ---- Serial status register (SCFSR) setting ---- */ + obj->uart->SCFSR &= 0xFF6Cu; /* ER,BRK,DR bit clear */ + + /* ---- Line status register (SCLSR) setting ---- */ + /* ORER bit clear */ + obj->uart->SCLSR = 0; + + /* ---- Serial extension mode register (SCEMR) setting ---- + b7 BGDM - Baud rate generator double-speed mode : Normal mode + b0 ABCS - Base clock select in asynchronous mode : Base clock is 16 times the bit rate */ + obj->uart->SCEMR = 0x0000u; + + /* ---- Bit rate register (SCBRR) setting ---- */ + serial_baud (obj, 9600); + serial_format(obj, 8, ParityNone, 1); + + /* ---- FIFO control register (SCFCR) setting ---- */ + obj->uart->SCFCR = 0x0030u; + + /* ---- Serial port register (SCSPTR) setting ---- + b1 SPB2IO - Serial port break output : disabled + b0 SPB2DT - Serial port break data : High-level */ + //obj->uart->SCSPTR |= 0x0000u; + + obj->uart->SCSCR = 0x0030; + + // pinout the chosen uart + pinmap_pinout(tx, PinMap_UART_TX); + pinmap_pinout(rx, PinMap_UART_RX); + + switch (uart) { + case P_SCIF0: obj->index = 0; break; + case P_SCIF1: obj->index = 1; break; + case P_SCIF2: obj->index = 2; break; + case P_SCIF3: obj->index = 3; break; + case P_SCIF4: obj->index = 4; break; + case P_SCIF5: obj->index = 5; break; + case P_SCIF6: obj->index = 6; break; + } + uart_data[obj->index].sw_rts.pin = NC; + uart_data[obj->index].sw_cts.pin = NC; + serial_set_flow_control(obj, FlowControlNone, NC, NC); + + is_stdio_uart = (uart == STDIO_UART) ? (1) : (0); + + if (is_stdio_uart) { + stdio_uart_inited = 1; + memcpy(&stdio_uart, obj, sizeof(serial_t)); + } +} + +void serial_free(serial_t *obj) { + uart_data[obj->index].serial_irq_id = 0; +} + +// serial_baud +// set the baud rate, taking in to account the current SystemFrequency +void serial_baud(serial_t *obj, int baudrate) { + + uint32_t PCLK = 66666666; + + uint16_t DL = (PCLK / (32 * baudrate)) -1; + + // set LCR[DLAB] to enable writing to divider registers + obj->uart->SCBRR = DL; +} + +void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) { + MBED_ASSERT((stop_bits == 1) || (stop_bits == 2)); // 0: 1 stop bits, 1: 2 stop bits + MBED_ASSERT((data_bits > 6) && (data_bits < 9)); // 0: 5 data bits ... 3: 8 data bits + MBED_ASSERT((parity == ParityNone) || (parity == ParityOdd) || (parity == ParityEven) || + (parity == ParityForced1) || (parity == ParityForced0)); + + stop_bits = (stop_bits == 1)? 0: + (stop_bits == 2)? 1: + 0; // must not to be + + data_bits = (data_bits == 8)? 0: + (data_bits == 7)? 1: + 0; // must not to be + + int parity_enable, parity_select; + switch (parity) { + case ParityNone: parity_enable = 0; parity_select = 0; break; + case ParityOdd : parity_enable = 1; parity_select = 0; break; + case ParityEven: parity_enable = 1; parity_select = 1; break; + default: + parity_enable = 0, parity_select = 0; + break; + } + + obj->uart->SCSMR = data_bits << 6 + | parity_enable << 5 + | parity_select << 4 + | stop_bits << 3; +} + +/****************************************************************************** + * INTERRUPTS HANDLING + ******************************************************************************/ + +void uart0_irq() {irq_handler(0, RxIrq);//dummy call + } +void uart1_irq() {/*uart_irq((LPC_UART1->IIR >> 1) & 0x7, 1, (LPC_UART_TypeDef*)LPC_UART1);*/} +void uart2_irq() {/*uart_irq((LPC_UART2->IIR >> 1) & 0x7, 2, (LPC_UART_TypeDef*)LPC_UART2);*/} +void uart3_irq() {/*uart_irq((LPC_UART3->IIR >> 1) & 0x7, 3, (LPC_UART_TypeDef*)LPC_UART3);*/} + +void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { + irq_handler = handler; + uart_data[obj->index].serial_irq_id = id; +} + +static void serial_irq_set_internal(serial_t *obj, SerialIrq irq, uint32_t enable) { +/* IRQn_Type irq_n = (IRQn_Type)0; + uint32_t vector = 0; + switch ((int)obj->uart) { + case UART_0: irq_n=UART0_IRQn; vector = (uint32_t)&uart0_irq; break; + case UART_1: irq_n=UART1_IRQn; vector = (uint32_t)&uart1_irq; break; + case UART_2: irq_n=UART2_IRQn; vector = (uint32_t)&uart2_irq; break; + case UART_3: irq_n=UART3_IRQn; vector = (uint32_t)&uart3_irq; break; + } + + if (enable) { + obj->uart->IER |= 1 << irq; + //NVIC_SetVector(irq_n, vector); + //NVIC_EnableIRQ(irq_n); + } else if ((TxIrq == irq) || (uart_data[obj->index].rx_irq_set_api + uart_data[obj->index].rx_irq_set_flow == 0)) { // disable + int all_disabled = 0; + SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq); + obj->uart->IER &= ~(1 << irq); + all_disabled = (obj->uart->IER & (1 << other_irq)) == 0; + if (all_disabled) ; + //NVIC_DisableIRQ(irq_n); + }*/ +} + +void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) { + if (RxIrq == irq) + uart_data[obj->index].rx_irq_set_api = enable; + serial_irq_set_internal(obj, irq, enable); +} + +static void serial_flow_irq_set(serial_t *obj, uint32_t enable) { + uart_data[obj->index].rx_irq_set_flow = enable; + serial_irq_set_internal(obj, RxIrq, enable); +} + +/****************************************************************************** + * READ/WRITE + ******************************************************************************/ +int serial_getc(serial_t *obj) { + if (obj->uart->SCFSR & 0x93) { obj->uart->SCFSR = ~0x93;} + while (!serial_readable(obj)); + int data = obj->uart->SCFRDR & 0xff; + /* Clear DR,RDF */ + obj->uart->SCFSR &= 0xfffc; + return data; +} + +void serial_putc(serial_t *obj, int c) { + while (!serial_writable(obj)); + obj->uart->SCFTDR = c; + obj->uart->SCFSR &= 0xff9f; // Clear TEND/TDFE + uart_data[obj->index].count++; +} + +int serial_readable(serial_t *obj) { + return obj->uart->SCFSR & 0x02; // RDF +} + +int serial_writable(serial_t *obj) { + return obj->uart->SCFSR & 0x20; // TDFE +} + +void serial_clear(serial_t *obj) { + obj->uart->SCFCR = 0x06; + obj->uart->SCFCR = 0x06; +} + +void serial_pinout_tx(PinName tx) { + pinmap_pinout(tx, PinMap_UART_TX); +} + +void serial_break_set(serial_t *obj) { + //obj->uart->LCR |= (1 << 6); +} + +void serial_break_clear(serial_t *obj) { + //obj->uart->LCR &= ~(1 << 6); +} + +void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) { + serial_flow_irq_set(obj, 0); + // Only UART1 has hardware flow control on LPC176x + /*LPC_UART1_TypeDef *uart1 = (uint32_t)obj->uart == (uint32_t)LPC_UART1 ? LPC_UART1 : NULL; + int index = obj->index; + + // First, disable flow control completely + if (uart1) + uart1->MCR = uart1->MCR & ~UART_MCR_FLOWCTRL_MASK; + uart_data[index].sw_rts.pin = uart_data[index].sw_cts.pin = NC; + serial_flow_irq_set(obj, 0); + if (FlowControlNone == type) + return; + // Check type(s) of flow control to use + UARTName uart_rts = (UARTName)pinmap_find_peripheral(rxflow, PinMap_UART_RTS); + UARTName uart_cts = (UARTName)pinmap_find_peripheral(txflow, PinMap_UART_CTS); + if (((FlowControlCTS == type) || (FlowControlRTSCTS == type)) && (NC != txflow)) { + // Can this be enabled in hardware? + if ((UART_1 == uart_cts) && (NULL != uart1)) { + // Enable auto-CTS mode + uart1->MCR |= UART_MCR_CTSEN_MASK; + pinmap_pinout(txflow, PinMap_UART_CTS); + } else { + // Can't enable in hardware, use software emulation + gpio_init_in(&uart_data[index].sw_cts, txflow); + } + } + if (((FlowControlRTS == type) || (FlowControlRTSCTS == type)) && (NC != rxflow)) { + // Enable FIFOs, trigger level of 1 char on RX FIFO + obj->uart->FCR = 1 << 0 // FIFO Enable - 0 = Disables, 1 = Enabled + | 1 << 1 // Rx Fifo Reset + | 1 << 2 // Tx Fifo Reset + | 0 << 6; // Rx irq trigger level - 0 = 1 char, 1 = 4 chars, 2 = 8 chars, 3 = 14 chars + // Can this be enabled in hardware? + if ((UART_1 == uart_rts) && (NULL != uart1)) { + // Enable auto-RTS mode + uart1->MCR |= UART_MCR_RTSEN_MASK; + pinmap_pinout(rxflow, PinMap_UART_RTS); + } else { // can't enable in hardware, use software emulation + gpio_init_out_ex(&uart_data[index].sw_rts, rxflow, 0); + // Enable RX interrupt + serial_flow_irq_set(obj, 1); + } + }*/ +} + diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/spi_api.c b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/spi_api.c new file mode 100644 index 0000000000..4aaafc1b7f --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/spi_api.c @@ -0,0 +1,234 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include + +#include "spi_api.h" +#include "cmsis.h" +#include "pinmap.h" +#include "mbed_error.h" + + +#include "rspi_iodefine.h" + +static const PinMap PinMap_SPI_SCLK[] = { + {P10_12, SPI_0, 4}, + {P11_12, SPI_1, 2}, + {NC , NC , 0} +}; + +static const PinMap PinMap_SPI_SSEL[] = { + {P10_13, SPI_0, 4}, + {P11_13, SPI_1, 2}, + {NC , NC , 0} +}; + +static const PinMap PinMap_SPI_MOSI[] = { + {P10_14, SPI_0, 4}, + {P11_14, SPI_1, 2}, + {NC , NC , 0} +}; + +static const PinMap PinMap_SPI_MISO[] = { + {P10_15, SPI_0, 4}, + {P11_15, SPI_1, 2}, + {NC , NC , 0} +}; + +struct st_rspi *RSPI[] = RSPI_ADDRESS_LIST; + +static inline void spi_disable(spi_t *obj); +static inline void spi_enable(spi_t *obj); +static inline int spi_readable(spi_t *obj); +static inline void spi_write(spi_t *obj, int value); +static inline int spi_writable(spi_t *obj); +static inline int spi_read(spi_t *obj); + +void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { + // determine the SPI to use + SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); + SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); + SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); + SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); + //SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); + //SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); + obj->spi = spi_mosi; //pinmap_merge(spi_data, spi_cntl); + MBED_ASSERT((int)obj->spi != NC); + + // enable power and clocking + volatile uint8_t dummy; + switch ((int)obj->spi) { + case SPI_0: CPGSTBCR10 &= ~(0x80); break; + case SPI_1: CPGSTBCR10 &= ~(0x40); break; + } + dummy = CPGSTBCR10; + + RSPI[obj->spi]->SPCR = 0x00; // CTRL to 0 + RSPI[obj->spi]->SPSCR = 0x00; // no sequential operation + RSPI[obj->spi]->SSLP = 0x00; // SSL 'L' active + RSPI[obj->spi]->SPDCR = 0x20; // byte access + RSPI[obj->spi]->SPCKD = 0x00; // SSL -> enable CLK delay : 1RSPCK + RSPI[obj->spi]->SSLND = 0x00; // CLK end -> SSL neg delay : 1RSPCK + RSPI[obj->spi]->SPND = 0x00; // delay between CMD : 1RSPCK + 2P1CLK + RSPI[obj->spi]->SPPCR = 0x20; // + + RSPI[obj->spi]->SPBFCR= 0xf0; // and set trigger count: read 1, write 1 + RSPI[obj->spi]->SPBFCR= 0x30; // and reset buffer + + // set default format and frequency + if (ssel == NC) { + spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master + } else { + spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave + } + spi_frequency(obj, 1000000); + + // enable the ssp channel + spi_enable(obj); + + // pin out the spi pins + pinmap_pinout(mosi, PinMap_SPI_MOSI); + pinmap_pinout(miso, PinMap_SPI_MISO); + pinmap_pinout(sclk, PinMap_SPI_SCLK); + if (ssel != NC) { + pinmap_pinout(ssel, PinMap_SPI_SSEL); + } +} + +void spi_free(spi_t *obj) {} + +void spi_format(spi_t *obj, int bits, int mode, int slave) { + spi_disable(obj); + MBED_ASSERT(((bits >= 4) && (bits <= 16)) && (mode >= 0 && mode <= 3)); + + int polarity = (mode & 0x2) ? 1 : 0; + int phase = (mode & 0x1) ? 1 : 0; + uint16_t tmp = 0, mask = 0xf03; + + tmp |= phase; + tmp |= polarity << 1; + + int DSS; // DSS (data select size) + switch (bits) { + case 8: + DSS = 0x7; break; + case 16: + DSS = 0xf; break; + case 32: + DSS = 0x2; break; + default: + error("SPI module don't support other than 8/16/32bits"); + return ; + } + tmp |= (DSS << 8); + + // set it up + RSPI[obj->spi]->SPCMD0 &= ~mask; + RSPI[obj->spi]->SPCMD0 |= (mask & tmp); + + if (slave) { + RSPI[obj->spi]->SPCR &=~(1 << 3); + } else { + RSPI[obj->spi]->SPCR |= (1 << 3); + } + + spi_enable(obj); +} + +void spi_frequency(spi_t *obj, int hz) { + spi_disable(obj); + const int P1CLK = 66666666; // 66.6666MHz + uint8_t div, brdv; + uint16_t mask = 0x000c0; + + if (hz <= P1CLK/2 && hz >= P1CLK/255) { + div = (P1CLK / hz / 2) -1; + brdv = 0x0 << 2; + } else if (hz >= P1CLK/255/2) { + div = (P1CLK / hz / 2 /2) -1; + brdv = 0x1 << 2; + } else if (hz >= P1CLK/255/4) { + div = (P1CLK / hz / 2 /4) -1; + brdv = 0x2 << 2; + } else if (hz >= P1CLK/255/8) { + div = (P1CLK / hz / 2 /8) -1; + brdv = 0x3 << 2; + } else { + error("Couldn't setup requested SPI frequency"); + return; + } + + RSPI[obj->spi]->SPBR = div; + + RSPI[obj->spi]->SPCMD0 &= ~mask; + RSPI[obj->spi]->SPCMD0 |= (mask & brdv); + + + spi_enable(obj); +} + +static inline void spi_disable(spi_t *obj) { + RSPI[obj->spi]->SPCR &= ~(1 << 6); // SPE to 0 +} + +static inline void spi_enable(spi_t *obj) { + RSPI[obj->spi]->SPCR |= (1 << 6); // SPE to 1 +} + +static inline int spi_readable(spi_t *obj) { + return RSPI[obj->spi]->SPSR & (1 << 7); +} + +static inline int spi_tend(spi_t *obj) { + return RSPI[obj->spi]->SPSR & (1 << 6); +} + +static inline int spi_writable(spi_t *obj) { + return RSPI[obj->spi]->SPSR & (1 << 5); +} + +static inline void spi_write(spi_t *obj, int value) { + while (!spi_writable(obj)); + RSPI[obj->spi]->SPDR.UINT8[0] = value; +} + +static inline int spi_read(spi_t *obj) { + //while (!spi_readable(obj)); + return RSPI[obj->spi]->SPDR.UINT8[0]; +} + +int spi_master_write(spi_t *obj, int value) { + spi_write(obj, value); + while(!spi_tend(obj)); + return spi_read(obj); +} + +int spi_slave_receive(spi_t *obj) { + return (spi_readable(obj) && !spi_busy(obj)) ? (1) : (0); +} + +int spi_slave_read(spi_t *obj) { + return RSPI[obj->spi]->SPDR.UINT8[0]; +} + +void spi_slave_write(spi_t *obj, int value) { + while (spi_writable(obj) == 0) ; + RSPI[obj->spi]->SPDR.UINT8[0] = value; +} + +int spi_busy(spi_t *obj) { + return (RSPI[obj->spi]->SPSR & (1 << 6)) ? (0) : (1); +} diff --git a/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c new file mode 100644 index 0000000000..9d432530df --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/us_ticker.c @@ -0,0 +1,96 @@ +/* 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 +#include "us_ticker_api.h" +#include "PeripheralNames.h" +#include "mtu2_iodefine.h" + +#define US_TICKER_TIMER (OSTM0.OSTMnCMP) +#define US_TICKER_TIMER_IRQn TIMER3_IRQn + +int us_ticker_inited = 0; + +void us_ticker_interrupt(void) { + us_ticker_irq_handler(); + GIC_EndInterrupt(TGI2A_IRQn); +} + +void us_ticker_init(void) { + if (us_ticker_inited) return; + us_ticker_inited = 1; + + /* Power Control for Peripherals */ + CPGSTBCR3 &= ~ 0x8; // turn on MTU2 + + // timer settings + MTU2.TSYR = 0x6; // cascading T_1-T_2 + + MTU2.TCR_2 = 0x03; // divider 1/64 + MTU2.TCR_1 = 0x07; // count-up from T_2 pulse(cascade) + + MTU2.TCNT_1 = 0x00; // counter value set to 0 + MTU2.TCNT_2 = 0x00; // + + MTU2.TSTR |= 0x06; // + MTU2.TSR_2 = 0xc0; // timer start + + // INTC settings + InterruptHandlerRegister(TGI2A_IRQn, (void (*)(uint32_t))us_ticker_interrupt); + GIC_SetPriority(TGI2A_IRQn, 5); + GIC_EnableIRQ(TGI2A_IRQn); + __enable_irq(); +} + +//static const float PCLK =33.33, // dummy + //PRESCALE =64.0; // dummy +static const float FACTOR_C2U = 1.9201920192019204, //(PRESCALE/PCLK) + FACTOR_U2C = 0.52078125; //(PCLK/PRESCALE) + +#define F_CLK2us(val) ((uint32_t)((val)*FACTOR_C2U)) +#define F_us2CLK(val) ((uint32_t)((val)*FACTOR_U2C)) + + +uint32_t us_ticker_read() { + static uint32_t max_val = 0x8551eb85; //*F_us2CLK(0xffffffff)+1; + uint32_t val; + if (!us_ticker_inited) + us_ticker_init(); + + val = MTU2.TCNT_1<<16 | MTU2.TCNT_2; // concat cascaded Counters + if (val > max_val) { // if overflow (in us-timer) + val -= max_val; // correct value + MTU2.TCNT_1 = 0; // reset counter + MTU2.TCNT_2 = val; + } + val = F_CLK2us(val); + return val; +} + +void us_ticker_set_interrupt(timestamp_t timestamp) { + // set match value + timestamp = F_us2CLK(timestamp); + MTU2.TGRA_2 = timestamp & 0xffff; + // enable match interrupt + MTU2.TIER_2 = 0x01; +} + +void us_ticker_disable_interrupt(void) { + MTU2.TIER_2 &= ~(0xc0); +} + +void us_ticker_clear_interrupt(void) { + MTU2.TSR_2 &= 0xc0; +}