diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/Periph_Driver/inc/txz_i2c_api.h b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/Periph_Driver/inc/txz_i2c_api.h index 58325258ca..21b825cc5f 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/Periph_Driver/inc/txz_i2c_api.h +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/Periph_Driver/inc/txz_i2c_api.h @@ -280,6 +280,7 @@ uint8_t i2c_active_t(_i2c_t *p_obj); TXZ_Result i2c_transfer_asynch_t(_i2c_t *p_obj, uint8_t *p_tx, int32_t tx_length, uint8_t *p_rx, int32_t rx_length, int32_t address, int32_t stop); uint32_t i2c_irq_handler_asynch_t(_i2c_t *p_obj); void i2c_abort_asynch_t(_i2c_t *p_obj); +uint32_t set_i2c(uint8_t ch, uint32_t *p_irqn); /* For slave */ void i2c_slave_mode_t(_i2c_t *p_obj, int32_t enable_slave); diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/Periph_Driver/src/txz_i2c_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/Periph_Driver/src/txz_i2c_api.c index 658b0ffd46..c7f0302441 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/Periph_Driver/src/txz_i2c_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/Periph_Driver/src/txz_i2c_api.c @@ -237,7 +237,6 @@ __STATIC_INLINE void set_port_ch1(i2c_port_t sda, i2c_port_t scl); __STATIC_INLINE void set_port_ch2(i2c_port_t sda, i2c_port_t scl); __STATIC_INLINE void set_port_ch3(i2c_port_t sda, i2c_port_t scl); __STATIC_INLINE void set_port_ch4(i2c_port_t sda, i2c_port_t scl); -__STATIC_INLINE uint32_t set_i2c(uint8_t ch, uint32_t *p_irqn); __STATIC_INLINE void reset_asynch(_i2c_t *p_obj); __STATIC_INLINE int32_t wait_status(_i2c_t *p_obj); static void i2c_irq_handler(_i2c_t *p_obj); @@ -574,7 +573,7 @@ __STATIC_INLINE void set_port_ch4(i2c_port_t sda, i2c_port_t scl) * @note - */ /*--------------------------------------------------*/ -__STATIC_INLINE uint32_t set_i2c(uint8_t ch, uint32_t *p_irqn) +uint32_t set_i2c(uint8_t ch, uint32_t *p_irqn) { uint32_t instance = 0; @@ -725,7 +724,7 @@ static void i2c_irq_handler(_i2c_t *p_obj) } else { - if (p_obj->tx_buff.pos < p_obj->tx_buff.length) + if ((p_obj->tx_buff.pos < p_obj->tx_buff.length) || (p_obj->tx_buff.length == 0)) { if (p_obj->tx_buff.pos == 0) { @@ -740,16 +739,7 @@ static void i2c_irq_handler(_i2c_t *p_obj) } else if (p_obj->rx_buff.length != 0) { - if (p_obj->tx_buff.pos == 0) - { - p_obj->info.asynch.event = (I2C_EVENT_ERROR | I2C_EVENT_ERROR_NO_SLAVE); - p_obj->info.asynch.state = I2C_TRANSFER_STATE_IDLE; - } - else - { - p_obj->info.asynch.event = (I2C_EVENT_ERROR | I2C_EVENT_TRANSFER_EARLY_NACK); - p_obj->info.asynch.state = I2C_TRANSFER_STATE_IDLE; - } + I2C_start_condition(&p_obj->i2c, (p_obj->info.asynch.address | 1U)); } else { @@ -1470,35 +1460,32 @@ TXZ_Result i2c_transfer_asynch_t(_i2c_t *p_obj, uint8_t *p_tx, int32_t tx_length if (p_obj->info.asynch.state == I2C_TRANSFER_STATE_IDLE) { - if (((p_tx != I2C_NULL) && (tx_length > 0)) || ((p_rx != I2C_NULL) && (rx_length > 0))) + reset_asynch(p_obj); + I2C_clear_int_status(&p_obj->i2c); + clear_irq(p_obj->info.irqn); + p_obj->info.asynch.address = (uint32_t)address; + p_obj->info.asynch.event = 0; + p_obj->info.asynch.stop = (uint32_t)stop; + p_obj->tx_buff.p_buffer = p_tx; + p_obj->tx_buff.length = (uint32_t)tx_length; + p_obj->tx_buff.pos = 0; + p_obj->rx_buff.p_buffer = p_rx; + p_obj->rx_buff.length = (uint32_t)rx_length; + p_obj->rx_buff.pos = 0; + p_obj->info.asynch.state = I2C_TRANSFER_STATE_BUSY; + I2C_enable_interrupt(&p_obj->i2c); + if ((tx_length == 0) && (rx_length != 0)) { - reset_asynch(p_obj); - I2C_clear_int_status(&p_obj->i2c); - clear_irq(p_obj->info.irqn); - p_obj->info.asynch.address = (uint32_t)address; - p_obj->info.asynch.event = 0; - p_obj->info.asynch.stop = (uint32_t)stop; - p_obj->tx_buff.p_buffer = p_tx; - p_obj->tx_buff.length = (uint32_t)tx_length; - p_obj->tx_buff.pos = 0; - p_obj->rx_buff.p_buffer = p_rx; - p_obj->rx_buff.length = (uint32_t)rx_length; - p_obj->rx_buff.pos = 0; - p_obj->info.asynch.state = I2C_TRANSFER_STATE_BUSY; - I2C_enable_interrupt(&p_obj->i2c); - if ((tx_length == 0) && (rx_length != 0)) - { - I2C_start_condition(&p_obj->i2c, (uint32_t)((uint32_t)address | 1U)); - } - else - { - I2C_start_condition(&p_obj->i2c, (uint32_t)address); - } - p_obj->info.bus_free = 0; - p_obj->info.start = 0; - enable_irq(p_obj->info.irqn); - result = TXZ_SUCCESS; + I2C_start_condition(&p_obj->i2c, (uint32_t)((uint32_t)address | 1U)); } + else + { + I2C_start_condition(&p_obj->i2c, (uint32_t)address); + } + p_obj->info.bus_free = 0; + p_obj->info.start = 0; + enable_irq(p_obj->info.irqn); + result = TXZ_SUCCESS; } return (result); } diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/device.h b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/device.h index ed94b5f245..b481f45fb5 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/device.h +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/device.h @@ -16,6 +16,7 @@ #ifndef MBED_DEVICE_H #define MBED_DEVICE_H +#define TRANSACTION_QUEUE_SIZE_SPI 4 #define DEVICE_ID_LENGTH 32 #include diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/device/TOOLCHAIN_ARM_STD/tmpm4g9f15.sct b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/device/TOOLCHAIN_ARM_STD/tmpm4g9f15.sct index 74f7394e47..1459045bbd 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/device/TOOLCHAIN_ARM_STD/tmpm4g9f15.sct +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/device/TOOLCHAIN_ARM_STD/tmpm4g9f15.sct @@ -45,6 +45,6 @@ LR_IROM1 MBED_APP_START MBED_APP_SIZE ; load region size_region .ANY (+RW, +ZI) } - ARM_LIB_STACK (0x20000320+0x30000) EMPTY -Stack_Size { ; stack + ARM_LIB_STACK (0x20000000+0x30000) EMPTY -Stack_Size { ; stack } } diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/gpio_irq_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/gpio_irq_api.c index 1c250008be..f5699d03b0 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/gpio_irq_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/gpio_irq_api.c @@ -179,14 +179,14 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) // Get gpio interrupt event if (event == IRQ_RISE) { if ((obj->event == CG_INT_ACTIVE_STATE_FALLING) || - (obj->event == CG_INT_ACTIVE_STATE_BOTH_EDGES)) { + (obj->event == CG_INT_ACTIVE_STATE_BOTH_EDGES)) { obj->event = CG_INT_ACTIVE_STATE_BOTH_EDGES; } else { obj->event = CG_INT_ACTIVE_STATE_RISING; } } else if (event == IRQ_FALL) { if ((obj->event == CG_INT_ACTIVE_STATE_RISING) || - (obj->event == CG_INT_ACTIVE_STATE_BOTH_EDGES)) { + (obj->event == CG_INT_ACTIVE_STATE_BOTH_EDGES)) { obj->event = CG_INT_ACTIVE_STATE_BOTH_EDGES; } else { obj->event = CG_INT_ACTIVE_STATE_FALLING; @@ -198,14 +198,14 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) // Get gpio interrupt event if (event == IRQ_RISE) { if ((obj->event == CG_INT_ACTIVE_STATE_RISING) || - (obj->event == CG_INT_ACTIVE_STATE_INVALID)) { + (obj->event == CG_INT_ACTIVE_STATE_INVALID)) { obj->event = CG_INT_ACTIVE_STATE_BOTH_EDGES; } else { obj->event = CG_INT_ACTIVE_STATE_FALLING; } } else if (event == IRQ_FALL) { if ((obj->event == CG_INT_ACTIVE_STATE_FALLING) || - (obj->event == CG_INT_ACTIVE_STATE_INVALID)) { + (obj->event == CG_INT_ACTIVE_STATE_INVALID)) { obj->event = CG_INT_ACTIVE_STATE_BOTH_EDGES; } else { obj->event = CG_INT_ACTIVE_STATE_RISING; diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/i2c_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/i2c_api.c index 3bd9e7caf4..4770611af7 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/i2c_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/i2c_api.c @@ -25,6 +25,13 @@ #include "txz_i2c_api.h" #define MAX_I2C_FREQ 1000000 +#define I2C_TRANSFER_STATE_IDLE (0x0U) + +#if DEVICE_I2C_ASYNCH +#define I2C_S(obj) (struct i2c_s *) (&((obj)->i2c)) +#else +#define I2C_S(obj) (struct i2c_s *) (obj) +#endif static const PinMap PinMap_I2C_SDA[] = { {PG2, I2C_0, PIN_DATA(7, 2)}, @@ -47,44 +54,47 @@ static const PinMap PinMap_I2C_SCL[] = { // Initialize the I2C peripheral. It sets the default parameters for I2C void i2c_init(i2c_t *obj, PinName sda, PinName scl) { - MBED_ASSERT(obj != NULL); + struct i2c_s *obj_s = I2C_S(obj); + MBED_ASSERT(obj_s != NULL); I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA); I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL); I2CName i2c_name = (I2CName)pinmap_merge(i2c_sda, i2c_scl); MBED_ASSERT((int)i2c_name != NC); + obj_s->index = i2c_name; + obj_s->is_master = 1; switch (i2c_name) { case I2C_0: TSB_CG_FSYSMENA_IPMENA29 = TXZ_ENABLE; // Enable clock for I2C_0 TSB_CG_FSYSMENB_IPMENB08 = TXZ_ENABLE; // Enable clock for GPIO G - obj->my_i2c.i2c.p_instance = TSB_I2C0; - obj->my_i2c.info.irqn = INTI2C0_IRQn; + obj_s->my_i2c.i2c.p_instance = TSB_I2C0; + obj_s->irqn = INTI2C0_IRQn; break; case I2C_1: TSB_CG_FSYSMENA_IPMENA30 = TXZ_ENABLE; // Enable clock for I2C_1 TSB_CG_FSYSMENB_IPMENB07 = TXZ_ENABLE; // Enable clock for GPIO F - obj->my_i2c.i2c.p_instance = TSB_I2C1; - obj->my_i2c.info.irqn = INTI2C1_IRQn; + obj_s->my_i2c.i2c.p_instance = TSB_I2C1; + obj_s->irqn = INTI2C1_IRQn; break; case I2C_2: TSB_CG_FSYSMENA_IPMENA31 = TXZ_ENABLE; // Enable clock for I2C_2 TSB_CG_FSYSMENB_IPMENB08 = TXZ_ENABLE; // Enable clock for GPIO G - obj->my_i2c.i2c.p_instance = TSB_I2C2; - obj->my_i2c.info.irqn = INTI2C2_IRQn; + obj_s->my_i2c.i2c.p_instance = TSB_I2C2; + obj_s->irqn = INTI2C2_IRQn; break; case I2C_3: TSB_CG_FSYSMENB_IPMENB00 = TXZ_ENABLE; // Enable clock for I2C_3 TSB_CG_FSYSMENB_IPMENB10 = TXZ_ENABLE; // Enable clock for GPIO J - obj->my_i2c.i2c.p_instance = TSB_I2C3; - obj->my_i2c.info.irqn = INTI2C3_IRQn; + obj_s->my_i2c.i2c.p_instance = TSB_I2C3; + obj_s->irqn = INTI2C3_IRQn; break; case I2C_4: TSB_CG_FSYSMENB_IPMENB01 = TXZ_ENABLE; // Enable clock for I2C_4 TSB_CG_FSYSMENB_IPMENB10 = TXZ_ENABLE; // Enable clock for GPIO J - obj->my_i2c.i2c.p_instance = TSB_I2C4; - obj->my_i2c.info.irqn = INTI2C4_IRQn; + obj_s->my_i2c.i2c.p_instance = TSB_I2C4; + obj_s->irqn = INTI2C4_IRQn; break; default: error("I2C is not available"); @@ -101,42 +111,58 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) i2c_reset(obj); i2c_frequency(obj, 100000); - I2C_init(&obj->my_i2c.i2c); + I2C_init(&obj_s->my_i2c.i2c); } // Configure the I2C frequency void i2c_frequency(i2c_t *obj, int hz) { - if (hz <= MAX_I2C_FREQ) { - i2c_frequency_t(&obj->my_i2c, hz); - } else { + struct i2c_s *obj_s = I2C_S(obj); + + if (hz > MAX_I2C_FREQ) { error("Failed : Max I2C frequency is 1000000"); } + + i2c_frequency_t(&obj_s->my_i2c, hz); + + if(obj_s->is_master) { + I2C_init(&obj_s->my_i2c.i2c); + } else { + I2C_slave_init(&obj_s->my_i2c.i2c); + } } int i2c_start(i2c_t *obj) { - i2c_start_t(&obj->my_i2c); + struct i2c_s *obj_s = I2C_S(obj); + + i2c_start_t(&obj_s->my_i2c); + return TXZ_SUCCESS; } int i2c_stop(i2c_t *obj) { - i2c_stop_t(&obj->my_i2c); + struct i2c_s *obj_s = I2C_S(obj); + + i2c_stop_t(&obj_s->my_i2c); + return TXZ_SUCCESS; } void i2c_reset(i2c_t *obj) { + struct i2c_s *obj_s = I2C_S(obj); // Software reset - i2c_reset_t(&obj->my_i2c); + i2c_reset_t(&obj_s->my_i2c); } int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { int32_t count = 0; + struct i2c_s *obj_s = I2C_S(obj); - count = i2c_read_t(&obj->my_i2c, address, (uint8_t *)data, length, stop); + count = i2c_read_t(&obj_s->my_i2c, address, (uint8_t *)data, length, stop); return count; } @@ -144,8 +170,9 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { int32_t count = 0; + struct i2c_s *obj_s = I2C_S(obj); - count = i2c_write_t(&obj->my_i2c, address, (uint8_t *)data, length, stop); + count = i2c_write_t(&obj_s->my_i2c, address, (uint8_t *)data, length, stop); return count; } @@ -153,8 +180,9 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) int i2c_byte_read(i2c_t *obj, int last) { int32_t data = 0; + struct i2c_s *obj_s = I2C_S(obj); - data = i2c_byte_read_t(&obj->my_i2c, last); + data = i2c_byte_read_t(&obj_s->my_i2c, last); return data; } @@ -162,27 +190,34 @@ int i2c_byte_read(i2c_t *obj, int last) int i2c_byte_write(i2c_t *obj, int data) { int32_t result = 0; + struct i2c_s *obj_s = I2C_S(obj); - result = i2c_byte_write_t(&obj->my_i2c, data); + result = i2c_byte_write_t(&obj_s->my_i2c, data); return result; } void i2c_slave_mode(i2c_t *obj, int enable_slave) { - i2c_slave_mode_t(&obj->my_i2c, enable_slave); + struct i2c_s *obj_s = I2C_S(obj); + + obj_s->is_master = 0; + i2c_slave_mode_t(&obj_s->my_i2c, enable_slave); } void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) { - i2c_slave_address_t(&obj->my_i2c, address); + struct i2c_s *obj_s = I2C_S(obj); + + i2c_slave_address_t(&obj_s->my_i2c, address); } int i2c_slave_receive(i2c_t *obj) { int32_t result = 0; + struct i2c_s *obj_s = I2C_S(obj); - result = i2c_slave_receive_t(&obj->my_i2c); + result = i2c_slave_receive_t(&obj_s->my_i2c); return result; } @@ -190,8 +225,9 @@ int i2c_slave_receive(i2c_t *obj) int i2c_slave_read(i2c_t *obj, char *data, int length) { int32_t count = 0; + struct i2c_s *obj_s = I2C_S(obj); - count = i2c_slave_read_t(&obj->my_i2c, (uint8_t *)data, length); + count = i2c_slave_read_t(&obj_s->my_i2c, (uint8_t *)data, length); return count; } @@ -199,8 +235,9 @@ int i2c_slave_read(i2c_t *obj, char *data, int length) int i2c_slave_write(i2c_t *obj, const char *data, int length) { int32_t count = 0; + struct i2c_s *obj_s = I2C_S(obj); - count = i2c_slave_write_t(&obj->my_i2c, (uint8_t *)data, length); + count = i2c_slave_write_t(&obj_s->my_i2c, (uint8_t *)data, length); return count; } @@ -225,4 +262,46 @@ const PinMap *i2c_slave_scl_pinmap() return PinMap_I2C_SCL; } +#if DEVICE_I2C_ASYNCH + +void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address, + uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint) +{ + struct i2c_s *obj_s = I2C_S(obj); + + obj_s->event_mask = event; + //Set irqn table for future use + set_i2c(obj_s->index, &obj_s->my_i2c.info.irqn); + NVIC_SetVector(obj_s->irqn, handler); + i2c_transfer_asynch_t(&obj_s->my_i2c, (uint8_t *)tx, tx_length, (uint8_t *)rx, rx_length, address, stop); +} + +uint32_t i2c_irq_handler_asynch(i2c_t *obj) +{ + struct i2c_s *obj_s = I2C_S(obj); + uint32_t event = 0; + + event = i2c_irq_handler_asynch_t(&obj_s->my_i2c); + + return (event & obj_s->event_mask); +} + +uint8_t i2c_active(i2c_t *obj) +{ + struct i2c_s *obj_s = I2C_S(obj); + + uint8_t ret = (obj_s->my_i2c.info.asynch.state != I2C_TRANSFER_STATE_IDLE); + + return ret; +} + +void i2c_abort_asynch(i2c_t *obj) +{ + struct i2c_s *obj_s = I2C_S(obj); + + i2c_abort_asynch_t(&obj_s->my_i2c); +} + +#endif // #if DEVICE_I2C_ASYNCH + #endif // #if DEVICE_I2C diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/objects.h b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/objects.h index 48c68e90d1..2a6b40353d 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/objects.h +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/objects.h @@ -46,13 +46,23 @@ struct dac_s { TSB_DA_TypeDef *DACx; }; +typedef struct { + uint32_t BaudRate; + uint32_t DataBits; + uint32_t StopBits; + uint32_t Parity; + uint32_t Mode; + uint32_t FlowCtrl; +} FUART_InitTypeDef; + struct serial_s { uint32_t index; uint32_t mode; + uint8_t is_using_fuart; TSB_UART_TypeDef *UARTx; TSB_FURT_TypeDef *FUARTx; uart_boudrate_t boud_obj; - fuart_boudrate_t fboud_obj; + FUART_InitTypeDef fuart_config; }; struct pwmout_s { @@ -66,9 +76,17 @@ struct pwmout_s { }; struct spi_s { - uint8_t bits; - tspi_t p_obj; - SPIName module; + uint8_t bits; + tspi_t p_obj; + SPIName module; + PinName clk_pin; + IRQn_Type rxirqn; + IRQn_Type txirqn; + IRQn_Type errirqn; +#ifdef DEVICE_SPI_ASYNCH + uint32_t event_mask; + uint8_t state; +#endif }; struct gpio_irq_s { @@ -91,9 +109,13 @@ struct analogin_s { }; struct i2c_s { - int address; - uint32_t index; - _i2c_t my_i2c; + uint8_t is_master; + uint32_t index; + IRQn_Type irqn; + _i2c_t my_i2c; +#if DEVICE_I2C_ASYNCH + uint32_t event_mask; +#endif }; #include "gpio_object.h" diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/rtc_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/rtc_api.c new file mode 100644 index 0000000000..0028893659 --- /dev/null +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/rtc_api.c @@ -0,0 +1,233 @@ +/* mbed Microcontroller Library + * (C)Copyright TOSHIBA ELECTRONIC DEVICES & STORAGE CORPORATION 2019 All rights reserved + * + * 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" +#include "mbed_mktime.h" + +#define RTC_24_HOUR_MODE ((uint8_t)0x01) +#define PAGER_PAGE_ONE ((uint8_t)0x01) +#define PAGER_PAGE_ZERO ((uint8_t)0xEE) +#define RTC_CLK_ENABLE ((uint8_t)0x08) +#define RTC_CLK_DISABLE ((uint8_t)0xE7) +#define RTCRESTR_RSTTMR_MASK ((uint8_t)0x20) +#define RTCRESTR_RSTTMR_R_RUN ((uint8_t)0x20) +#define CGWUPLCR_WUPTL_HIGH_MASK ((uint32_t)0x07FFF000) +#define CGWUPLCR_WULEF_MASK ((uint32_t)0x00000002) +#define CGWUPLCR_WULEF_R_DONE ((uint32_t)0x00000000) +#define CGWUPLCR_WULON_W_ENABLE ((uint32_t)0x00000001) +#define RLMLOSCCR_XTEN_RW_ENABLE ((uint32_t)0x00000003) +#define ELOSC_CFG_WARM_UP_TIME ((uint64_t)(5000)) +#define ELOSC_CFG_CLOCK ((uint64_t)(32768)) +#define HEX2DEC(val) ((val >> 4U) * 10U + val % 16U) // Hex to Dec conversion macro +#define DEC2HEX(val) ((val / 10U) * 16U + val % 10U) // Dec to Hex conversion macro + +static int flag = 0; +static int diff_year = 100; //our RTC register only support 2000~2099 +static void external_losc_enable(void); + +void rtc_init(void) +{ + if (!flag) { + external_losc_enable(); // Enable low-speed oscillator + TSB_RTC->PAGER = 0x00; //disable clock and alarm + while ((TSB_RTC->RESTR & RTCRESTR_RSTTMR_MASK) == RTCRESTR_RSTTMR_R_RUN) { + // Reset RTC sec counter + } + + TSB_RTC->RESTR = 0xE7; + while ((TSB_RTC->RESTR & RTCRESTR_RSTTMR_MASK) == RTCRESTR_RSTTMR_R_RUN) { + // Reset RTC sec counter + } + + TSB_RTC->PAGER |= PAGER_PAGE_ONE; + TSB_RTC->YEARR = 0x03; // Set leap year state + TSB_RTC->MONTHR = RTC_24_HOUR_MODE; // Set hour mode + TSB_RTC->PAGER &= PAGER_PAGE_ZERO; // Set hour mode + TSB_RTC->YEARR = 0x01; // Set year value + TSB_RTC->MONTHR = (uint8_t)0x01; // Set month value + TSB_RTC->DATER = (uint8_t)0x01; // Set date value + TSB_RTC->DAYR = (uint8_t)0x0; // Set day value + TSB_RTC->HOURR = (uint8_t)0x01; // Set hour value + TSB_RTC->MINR = (uint8_t)0x02; // Set minute value + TSB_RTC->SECR = (uint8_t)0x22; // Set second value + TSB_RTC->PAGER |= RTC_CLK_ENABLE; // Enable Clock + flag = 1; // Enable internal flag + } +} + +void rtc_free(void) +{ + if (flag) { // Check status of RTC peripheral driver is ENABLE or DISABLE + flag = 0; // Set status of RTC peripheral driver is DISABLE + } +} + +int rtc_isenabled(void) +{ + return flag; // Return a flag that represents status of RTC peripheral driver +} + +time_t rtc_read(void) +{ + struct tm timeinfo; + uint8_t read_1 = 0U; + uint8_t read_2 = 0U; + + timeinfo.tm_isdst = 0; //no summer time + + TSB_RTC->PAGER &= PAGER_PAGE_ZERO; + + read_1 = TSB_RTC->SECR; // Get sec value + timeinfo.tm_sec = HEX2DEC(read_1); + + // Get minute value + do { + read_1 = TSB_RTC->MINR; + read_2 = TSB_RTC->MINR; + } while (read_1 != read_2); + timeinfo.tm_min = HEX2DEC(read_1); + + // Get hour value + do { + read_1 = TSB_RTC->HOURR; + read_2 = TSB_RTC->HOURR; + } while (read_1 != read_2); + timeinfo.tm_hour = HEX2DEC(read_1); + + // Get Month date value + do { + read_1 = TSB_RTC->DATER; + read_2 = TSB_RTC->DATER; + } while (read_1 != read_2); + timeinfo.tm_mday = HEX2DEC(read_1); + + // Get Month value + do { + read_1 = TSB_RTC->MONTHR; + read_2 = TSB_RTC->MONTHR; + } while (read_1 != read_2); + timeinfo.tm_mon = HEX2DEC(read_1)-1; + + // Get weekday value + do { + read_1 = TSB_RTC->DAYR; + read_2 = TSB_RTC->DAYR; + } while (read_1 != read_2); + timeinfo.tm_wday = HEX2DEC(read_1); + + // Get year value + do { + read_1 = TSB_RTC->YEARR; + read_2 = TSB_RTC->YEARR; + } while (read_1 != read_2); + timeinfo.tm_year = (HEX2DEC(read_1)+ diff_year); + + //time_t t = mktime(&timeinfo); // Convert to time stamp + time_t t; + + if (_rtc_maketime(&timeinfo, &t, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) { + return 0; + } + return t; +} + +void rtc_write(time_t t) +{ + struct tm timeinfo; + if (_rtc_localtime(t, &timeinfo, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) { + return; + } + + diff_year = timeinfo.tm_year - (timeinfo.tm_year % 100); + TSB_RTC->PAGER &= RTC_CLK_DISABLE; // Disable clock + + // Check current year is leap year or not + if (((timeinfo.tm_year % 4) == 0 && (timeinfo.tm_year % 100) != 0) || + (timeinfo.tm_year % 400) == 0) { + TSB_RTC->PAGER |= PAGER_PAGE_ONE; // Current year is a leap year + TSB_RTC->YEARR = 0x00; + } else if ((timeinfo.tm_year % 4) == 1) { + TSB_RTC->PAGER |= PAGER_PAGE_ONE; // Current year is the year following a leap year + TSB_RTC->YEARR = 0x01; + } else if ((timeinfo.tm_year % 4) == 2) { + TSB_RTC->PAGER |= PAGER_PAGE_ONE; // Current year is two years after a leap year + TSB_RTC->YEARR = 0x02; + } else { + TSB_RTC->PAGER |= PAGER_PAGE_ONE; // Current year is three years after a leap year + TSB_RTC->YEARR = 0x03; + } + + TSB_RTC->PAGER &= PAGER_PAGE_ZERO; // Select PAGE 0 + + TSB_RTC->YEARR = (uint8_t)DEC2HEX((timeinfo.tm_year - diff_year)); // Set year value + + // Set month value, tm_mon=0 means Jan while 1 is Jan + TSB_RTC->MONTHR = (uint8_t)DEC2HEX((timeinfo.tm_mon+1)); + TSB_RTC->DATER = (uint8_t)DEC2HEX(timeinfo.tm_mday); // Set date value + TSB_RTC->DAYR = (uint8_t)(timeinfo.tm_wday); // Set week day value + TSB_RTC->HOURR = (uint8_t)DEC2HEX(timeinfo.tm_hour); // Set hour value + TSB_RTC->MINR = (uint8_t)DEC2HEX(timeinfo.tm_min); // Set minute value + TSB_RTC->SECR = (uint8_t)DEC2HEX(timeinfo.tm_sec); // Set second value + + // Setting Wait + // When stop mode is selected, CaseA or CaseB is need. + // CaseA: Wait for RTC 1Hz interrupt. + // CaseB: Check the clock register setting. + { + uint8_t flag = 1; + time_t time_read = {0}; + while(flag) { + time_read = rtc_read(); + if( time_read == t) { // Wait for setting successfully + flag = 0; + } + } + } + TSB_RTC->PAGER |= RTC_CLK_ENABLE; // Enable Clock +} + +static void external_losc_enable(void) +{ + uint32_t work; + + // [CGWUPLCR] :Warm up time + //-------------------------------------- + // "1"counter (s) = 1 / ELOSC + // "1"counter (us) = (10^6) / ELOSC + // "x"counter (us) = time + //-------------------------------------- + // x : time = 1 : (10^6) / ELOSC + //-------------------------------------- + { + uint64_t x = (uint64_t)((uint64_t)(ELOSC_CFG_WARM_UP_TIME) * (uint64_t)(ELOSC_CFG_CLOCK)); + x = (uint64_t)(x / (uint64_t)(1000000)); + if (x > (uint64_t)(0x7FFFF)) { + /* invalid value */ + } + work = (uint32_t)x; + } + work &= (uint32_t)(0xFFFFFFF0); + work <<= 8; + TSB_CG->WUPLCR = work; + // [RLMLOSCCR] :LOSC Enable + TSB_RLM->LOSCCR = RLMLOSCCR_XTEN_RW_ENABLE; + // [CGWUPLCR] :Enable + work = (uint32_t)(TSB_CG->WUPLCR & CGWUPLCR_WUPTL_HIGH_MASK); + TSB_CG->WUPLCR = (uint32_t)(work | CGWUPLCR_WULON_W_ENABLE); + // [CGWUPLCR] :Read(wait for warm-up) + while ((TSB_CG->WUPLCR & CGWUPLCR_WULEF_MASK) != CGWUPLCR_WULEF_R_DONE) { + // no processing + } +} diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/serial_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/serial_api.c index eeccf5b0f1..ebc9e21715 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/serial_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/serial_api.c @@ -28,8 +28,13 @@ #define UARTxSWRST_SWRST_10 ((uint32_t)0x00000002) #define UARTxSWRST_SWRST_01 ((uint32_t)0x00000001) #define UART_RX_FIFO_FILL_LEVEL ((uint32_t)0x00000100) -#define FUART_ENABLE_RX ((uint32_t)0x00000200) -#define FUART_ENABLE_TX ((uint32_t)0x00000100) +#define LCR_H_WLEN_MASK ((uint32_t)0xFFFFFF9F) +#define LCR_H_STP2_MASK ((uint32_t)0xFFFFFFF7) +#define LCR_H_PARITY_MASK ((uint32_t)0xFFFFFF79) +#define CR_FLOW_CTRL_MASK ((uint32_t)0x00000F07) +#define CR_MODE_MASK ((uint32_t)0x0000CC07) +#define FUARTxCR_UARTEN_ENABLE_CLEAR ((uint32_t)0xFFFFFF7E) +#define FUART_CTS_RTS_DISABLE_MASK ((uint32_t)0XFFFF3FFF) #define BAUDRATE_DEFAULT (9600) #define CLR_REGISTER (0x00) @@ -40,6 +45,8 @@ static const PinMap PinMap_UART_TX[] = { {PU7, SERIAL_3, PIN_DATA(7, 1)}, {PU0, SERIAL_4, PIN_DATA(7, 1)}, {PJ1, SERIAL_5, PIN_DATA(3, 1)}, + {PG4, SERIAL_6, PIN_DATA(5, 1)}, + {PM7, SERIAL_7, PIN_DATA(7, 1)}, {NC, NC, 0} }; @@ -50,9 +57,35 @@ static const PinMap PinMap_UART_RX[] = { {PU6, SERIAL_3, PIN_DATA(7, 0)}, {PU1, SERIAL_4, PIN_DATA(7, 0)}, {PJ0, SERIAL_5, PIN_DATA(3, 0)}, + {PG5, SERIAL_6, PIN_DATA(5, 0)}, + {PM6, SERIAL_7, PIN_DATA(7, 0)}, {NC, NC, 0} }; +static const PinMap PinMap_UART_RTS[] = { + {PE0, SERIAL_0, PIN_DATA(7, 1)}, + {PH2, SERIAL_1, PIN_DATA(3, 1)}, + {PG2, SERIAL_2, PIN_DATA(3, 1)}, + {PU4, SERIAL_3, PIN_DATA(7, 1)}, + {PU3, SERIAL_4, PIN_DATA(5, 1)}, + {PJ2, SERIAL_5, PIN_DATA(3, 1)}, + {PG6, SERIAL_6, PIN_DATA(5, 1)}, + {PM5, SERIAL_7, PIN_DATA(7, 1)}, + {NC, NC, 0} +}; + +static const PinMap PinMap_UART_CTS[] = { + {PE1, SERIAL_0, PIN_DATA(7, 0)}, + {PH3, SERIAL_1, PIN_DATA(3, 0)}, + {PG3, SERIAL_2, PIN_DATA(3, 0)}, + {PU5, SERIAL_3, PIN_DATA(7, 0)}, + {PU2, SERIAL_4, PIN_DATA(5, 0)}, + {PJ3, SERIAL_5, PIN_DATA(3, 0)}, + {PG7, SERIAL_6, PIN_DATA(5, 0)}, + {PM4, SERIAL_7, PIN_DATA(7, 0)}, + {NC, NC, 0} +}; + static int serial_irq_ids[UART_NUM] = {0}; static uart_irq_handler irq_handler; @@ -60,6 +93,8 @@ int stdio_uart_inited = 0; serial_t stdio_uart; static void uart_swreset(TSB_UART_TypeDef *UARTx); +static void fuart_init_config(TSB_FURT_TypeDef * FUARTx, FUART_InitTypeDef * InitStruct); + void serial_init(serial_t *obj, PinName tx, PinName rx) { int is_stdio_uart = 0; @@ -74,6 +109,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) MBED_ASSERT((int)uart_name != NC); + obj->is_using_fuart = 0; obj->index = uart_name; // Initialize UART instance switch (uart_name) { @@ -113,6 +149,20 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) TSB_CG_FSYSMENA_IPMENA28 = TXZ_ENABLE; TSB_CG_FSYSMENB_IPMENB10 = TXZ_ENABLE; break; + case SERIAL_6: + obj->FUARTx = TSB_FURT0; + //Enable clock for UART6 and Port G + TSB_CG_FSYSMENA_IPMENA01 = TXZ_ENABLE; + TSB_CG_FSYSMENB_IPMENB08 = TXZ_ENABLE; + obj->is_using_fuart = 1; + break; + case SERIAL_7: + obj->FUARTx = TSB_FURT1; + //Enable clock for UART7 and Port M + TSB_CG_FSYSMENA_IPMENA02 = TXZ_ENABLE; + TSB_CG_FSYSMENB_IPMENB13 = TXZ_ENABLE; + obj->is_using_fuart = 1; + break; default: break; } @@ -121,31 +171,48 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) pinmap_pinout(tx, PinMap_UART_TX); pinmap_pinout(rx, PinMap_UART_RX); - if (tx != NC && rx != NC) { - obj->mode = UART_ENABLE_RX | UART_ENABLE_TX; - } else { - if (tx != NC) { - obj->mode = UART_ENABLE_TX; + if(!(obj->is_using_fuart)) { + if (tx != NC && rx != NC) { + obj->mode = UART_ENABLE_RX | UART_ENABLE_TX; } else { - if (rx != NC) { - obj->mode = UART_ENABLE_RX; + if (tx != NC) { + obj->mode = UART_ENABLE_TX; + } else { + if (rx != NC) { + obj->mode = UART_ENABLE_RX; + } } } + //software reset + uart_swreset(obj->UARTx); + //mbed default configurations + obj->UARTx->CR0 |= (1U); // data lengh 8 bit No parity one stop bit + prescal.prsel = UART_PLESCALER_1; + uart_get_boudrate_setting(cg_get_mphyt0(¶mCG), &prescal, BAUDRATE_DEFAULT, &obj->boud_obj); + obj->UARTx->BRD |=((obj->boud_obj.ken) | (obj->boud_obj.brk << 16) | (obj->boud_obj.brn)); + obj->UARTx->FIFOCLR = (UARTxFIFOCLR_TFCLR_CLEAR | UARTxFIFOCLR_RFCLR_CLEAR); // Clear FIFO + obj->UARTx->TRANS |= obj->mode; // Enable TX RX block. + obj->UARTx->CR1 = (UART_RX_FIFO_FILL_LEVEL | UART_TX_INT_ENABLE | UART_RX_INT_ENABLE); + } else { + if (tx != NC && rx != NC) { + obj->fuart_config.Mode = FUARTxCR_TXE_ENABLE | FUARTxCR_RXE_ENABLE; + } else if (tx != NC) { + obj->fuart_config.Mode = FUARTxCR_TXE_ENABLE; + } else if (rx != NC) { + obj->fuart_config.Mode = FUARTxCR_RXE_ENABLE; + } + + obj->fuart_config.BaudRate = BAUDRATE_DEFAULT; + obj->fuart_config.DataBits = FUART_DATA_LENGTH_8; + obj->fuart_config.StopBits = FUART_STOP_BIT_1; + obj->fuart_config.Parity = FUART_PARITY_DISABLE; + obj->fuart_config.FlowCtrl = FUART_CTS_DISABLE | FUART_RTS_DISABLE; + + fuart_init_config(obj->FUARTx, &obj->fuart_config); + //Enable FUART + obj->FUARTx->CR |= FUARTxCR_UARTEN_ENABLE; } - // Software reset - uart_swreset(obj->UARTx); - - // Mbed default configurations - obj->UARTx->CR0 |= (1U); // Data lengh 8 bit No parity one stop bit - prescal.prsel = UART_PLESCALER_1; - uart_get_boudrate_setting(cg_get_mphyt0(¶mCG), &prescal, BAUDRATE_DEFAULT, &obj->boud_obj); - - obj->UARTx->BRD |= ((obj->boud_obj.ken) | (obj->boud_obj.brk << 16) | (obj->boud_obj.brn)); - obj->UARTx->FIFOCLR = (UARTxFIFOCLR_TFCLR_CLEAR | UARTxFIFOCLR_RFCLR_CLEAR); // Clear FIFO - obj->UARTx->TRANS |= obj->mode; // Enable TX RX block. - obj->UARTx->CR1 = (UART_RX_FIFO_FILL_LEVEL | UART_TX_INT_ENABLE | UART_RX_INT_ENABLE); - is_stdio_uart = (uart_name == STDIO_UART) ? (1) : (0); if (is_stdio_uart) { stdio_uart_inited = 1; @@ -155,12 +222,20 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) void serial_free(serial_t *obj) { - obj->UARTx->TRANS = CLR_REGISTER; - obj->UARTx->CR0 = CLR_REGISTER; - obj->UARTx->CR1 = CLR_REGISTER; - obj->UARTx = CLR_REGISTER; - uart_swreset(obj->UARTx); - obj->index = (uint32_t)NC; + if(!(obj->is_using_fuart)) { + obj->UARTx->TRANS = CLR_REGISTER; + obj->UARTx->CR0 = CLR_REGISTER; + obj->UARTx->CR1 = CLR_REGISTER; + obj->UARTx = CLR_REGISTER; + uart_swreset(obj->UARTx); + } else { + obj->FUARTx->CR = CLR_REGISTER; + obj->FUARTx->IMSC = CLR_REGISTER; + obj->FUARTx->ICR = CLR_REGISTER; + obj->FUARTx->LCR_H = CLR_REGISTER; + obj->FUARTx = CLR_REGISTER; + } + obj->index = (uint32_t)NC; } void serial_baud(serial_t *obj, int baudrate) @@ -168,10 +243,17 @@ void serial_baud(serial_t *obj, int baudrate) cg_t paramCG; paramCG.p_instance = TSB_CG; uart_clock_t prescal; - prescal.prsel = UART_PLESCALER_1; - uart_get_boudrate_setting(cg_get_mphyt0(¶mCG), &prescal, baudrate, &obj->boud_obj); - obj->UARTx->BRD = CLR_REGISTER; // Clear BRD register - obj->UARTx->BRD |= ((obj->boud_obj.ken) | (obj->boud_obj.brk << 16) | (obj->boud_obj.brn)); + if(!(obj->is_using_fuart)) { + prescal.prsel = UART_PLESCALER_1; + uart_get_boudrate_setting(cg_get_mphyt0(¶mCG), &prescal, baudrate, &obj->boud_obj); + obj->UARTx->BRD = CLR_REGISTER; //clear BRD register + obj->UARTx->BRD |=((obj->boud_obj.ken) | (obj->boud_obj.brk << 16) | (obj->boud_obj.brn)); + } else { + obj->FUARTx->CR &= FUARTxCR_UARTEN_ENABLE_CLEAR; + obj->fuart_config.BaudRate = baudrate * 2; + fuart_init_config(obj->FUARTx, &obj->fuart_config); + obj->FUARTx->CR |= FUARTxCR_UARTEN_ENABLE; + } } void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) @@ -183,13 +265,33 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b MBED_ASSERT((stop_bits == 1) || (stop_bits == 2)); MBED_ASSERT((parity == ParityNone) || (parity == ParityOdd) || (parity == ParityEven)); - MBED_ASSERT((data_bits > 6) && (data_bits < 10)); // 0: 7 data bits ... 2: 9 data bits - parity_check = ((parity == ParityOdd) ? 1 :((parity == ParityEven) ? 3 : 0)); - data_length = (data_bits == 8 ? 1 :((data_bits == 7) ? 0 : 2)); - sblen = (stop_bits == 1) ? 0 : 1; // 0: 1 stop bits, 1: 2 stop bits - tmp = ((sblen << 4) |(parity_check << 2) | data_length); - obj->UARTx->CR0 = tmp; + if(!(obj->is_using_fuart)) { + MBED_ASSERT((data_bits > 6) && (data_bits < 10)); // 0: 7 data bits ... 2: 9 data bits + parity_check = ((parity == ParityOdd) ? 1 :((parity == ParityEven) ? 3 : 0)); + data_length = (data_bits == 8 ? 1 :((data_bits == 7) ? 0 : 2)); + sblen = (stop_bits == 1) ? 0 : 1; // 0: 1 stop bits, 1: 2 stop bits + tmp = ((sblen << 4) |(parity_check << 2) | data_length); + obj->UARTx->CR0 = tmp; + } else { + MBED_ASSERT((data_bits > 6) && (data_bits < 9)); // 0: 5 data bits ... 2: 8 data bits + obj->FUARTx->CR &= FUARTxCR_UARTEN_ENABLE_CLEAR; + // Parity bit update + if(parity == ParityOdd) { + obj->fuart_config.Parity = FUART_PARITY_BIT_ODD | FUART_PARITY_ENABLE; + } else if(parity == ParityEven) { + obj->fuart_config.Parity = FUART_PARITY_BIT_EVEN | FUART_PARITY_ENABLE; + } else { + obj->fuart_config.Parity = FUART_PARITY_DISABLE; + } + // Stop bit update + obj->fuart_config.StopBits = (stop_bits == 1) ? FUART_STOP_BIT_1 : FUART_STOP_BIT_2; + // Data length update + obj->fuart_config.DataBits = (data_bits == 7) ? FUART_DATA_LENGTH_7 : FUART_DATA_LENGTH_8; + + fuart_init_config(obj->FUARTx, &obj->fuart_config); + obj->FUARTx->CR |= FUARTxCR_UARTEN_ENABLE; + } } // INTERRUPT HANDLING @@ -253,6 +355,34 @@ void INTUART5TX_IRQHandler(void) irq_handler(serial_irq_ids[SERIAL_5], TxIrq); } +void INTFUART0_IRQHandler(void) +{ + uint32_t int_status; + + int_status = TSB_FURT0->MIS; + if (int_status & (1 << 4U)) { + irq_handler(serial_irq_ids[SERIAL_6], RxIrq); + } else if (int_status & (1 << 5U)) { + irq_handler(serial_irq_ids[SERIAL_6], TxIrq); + } else { + return; + } +} + +void INTFUART1_IRQHandler(void) +{ + uint32_t int_status; + + int_status = TSB_FURT1->MIS; + if (int_status & (1 << 4U)) { + irq_handler(serial_irq_ids[SERIAL_7], RxIrq); + } else if (int_status & (1 << 5U)) { + irq_handler(serial_irq_ids[SERIAL_7], TxIrq); + } else { + return; + } +} + void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { irq_handler = handler; @@ -306,10 +436,24 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) irq_n = INTUART5TX_IRQn; } break; + case SERIAL_6: + irq_n = INTFUART0_IRQn; + break; + case SERIAL_7: + irq_n = INTFUART1_IRQn; + break; default: break; } + if(obj->is_using_fuart) { + // Set interrupt mask + if (irq == RxIrq) { + obj->FUARTx->IMSC = (1 << 4U); + } else { + obj->FUARTx->IMSC = (1 << 5U); + } + } NVIC_ClearPendingIRQ(irq_n); if (enable) { @@ -327,9 +471,13 @@ int serial_getc(serial_t *obj) // Do nothing } - // Read Data Register - data = (obj->UARTx->DR & 0xFFU); - obj->UARTx->SR |= (1U << 6); // Clear RXEND flag + if(!(obj->is_using_fuart)) { + //Read Data Register + data = (obj->UARTx->DR & 0xFFU); + obj->UARTx->SR |= (1U << 6); // clear RXEND flag + } else { + data = (obj->FUARTx->DR & 0xFFU); + } return data; } @@ -341,21 +489,30 @@ void serial_putc(serial_t *obj, int c) } // Write Data Register - obj->UARTx->DR = (c & 0xFF); + if(!(obj->is_using_fuart)) { + obj->UARTx->DR = (c & 0xFF); - while ((obj->UARTx->SR & (1U << 14)) == 0) { - // Do nothing + while((obj->UARTx->SR & (1U << 14)) == 0) { + } + + obj->UARTx->SR |= (1U << 14); // clear TXEND flag + } else { + obj->FUARTx->DR = (c & 0xFF); } - - obj->UARTx->SR |= (1U << 14); // Clear TXEND flag } int serial_readable(serial_t *obj) { int ret = 0; - if ((obj->UARTx->SR & 0x000F) != 0) { - ret = 1; + if(!(obj->is_using_fuart)) { + if ((obj->UARTx->SR & 0x000F) != 0) { + ret = 1; + } + } else { + if(obj->FUARTx->FR & (1 << 6U)) { + ret = 1; + } } return ret; @@ -365,23 +522,110 @@ int serial_writable(serial_t *obj) { int ret = 0; - if ((obj->UARTx->SR & 0x8000) == 0) { - ret = 1; + if(!(obj->is_using_fuart)) { + if ((obj->UARTx->SR & 0x8000) == 0) { + ret = 1; + } + } else { + if(obj->FUARTx->FR & (1 << 7U)) { + ret = 1; + } } return ret; } +void serial_clear(serial_t *obj) +{ + uint32_t dummy; + if(!(obj->is_using_fuart)) { + obj->UARTx->FIFOCLR = 0x03; + } else { + { + dummy = obj->FUARTx->DR; //dummy read + } + } +} + +void serial_pinout_tx(PinName tx) +{ + pinmap_pinout(tx, PinMap_UART_TX); +} + +// Set flow control +void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) +{ + UARTName uart_cts = (UARTName)pinmap_peripheral(txflow, PinMap_UART_CTS); + UARTName uart_rts = (UARTName)pinmap_peripheral(rxflow, PinMap_UART_RTS); + UARTName uart_name = (UARTName)pinmap_merge(uart_cts, uart_rts); + + if (!(obj->is_using_fuart)) { + if (type == FlowControlCTS) { + MBED_ASSERT(uart_cts != (UARTName) NC); + pinmap_pinout(txflow, PinMap_UART_CTS); // Enable the pin for CTS function + pin_mode(txflow, PullUp); // initial state of CTS preferably high + obj->UARTx->CR0 |= (1 << 10); // Enable CTS hardware control + + } else if (type == FlowControlRTS) { + MBED_ASSERT(uart_rts != (UARTName) NC); + pinmap_pinout(rxflow, PinMap_UART_RTS); // Enable the pin for RTS function + obj->UARTx->CR0 |= (1 << 9); // Enable RTS hardware control + + } else if (type == FlowControlRTSCTS) { + MBED_ASSERT(uart_name != (UARTName) NC); + obj->UARTx->CR0 |= (3 << 9); // Enable CTS and RTS hardware flow control + + pinmap_pinout(txflow, PinMap_UART_CTS); // Enable the pin for CTS function + pinmap_pinout(rxflow, PinMap_UART_RTS); // Enable the pin for RTS function + pin_mode(txflow, PullUp); + } else { + obj->UARTx->CR0 &= (~(3 << 9)); // Disable CTS and RTS hardware flow control + } + } else { + obj->FUARTx->CR &= FUARTxCR_UARTEN_ENABLE_CLEAR; // Disable FUART + if (type == FlowControlCTS) { + MBED_ASSERT(uart_cts != (UARTName) NC); + obj->FUARTx->CR |= FUART_CTS_ENABLE; // Enable CTS hardware flow control + pinmap_pinout(txflow, PinMap_UART_CTS); // Enable the pin for CTS and RTS function + pin_mode(txflow, PullUp); + + } else if (type == FlowControlRTS) { + MBED_ASSERT(uart_rts != (UARTName) NC); + obj->FUARTx->CR |= FUART_RTS_ENABLE; // Enable RTS hardware flow control + pinmap_pinout(rxflow, PinMap_UART_RTS); // Enable the pin for RTS function + + } else if (type == FlowControlRTSCTS) { + MBED_ASSERT(uart_name != (UARTName) NC); + obj->FUARTx->CR |= (FUART_CTS_ENABLE | FUART_RTS_ENABLE); // Enable CTS and RTS hardware flow control + pinmap_pinout(txflow, PinMap_UART_CTS); // Enable the pin for CTS function + pinmap_pinout(rxflow, PinMap_UART_RTS); // Enable the pin for RTS function + pin_mode(txflow, PullUp); + + } else { + obj->FUARTx->CR &= FUART_CTS_RTS_DISABLE_MASK; // Disable CTS and RTS hardware flow control + } + obj->FUARTx->CR |= FUARTxCR_UARTEN_ENABLE; + } +} + // Pause transmission void serial_break_set(serial_t *obj) { - obj->UARTx->TRANS |= 0x08; + if (!(obj->is_using_fuart)) { + obj->UARTx->TRANS |= 0x08; + } else { + obj->FUARTx->LCR_H |= FUARTxLCR_H_BRK_SEND; + } } // Switch to normal transmission void serial_break_clear(serial_t *obj) { - obj->UARTx->TRANS &= ~(0x08); + if (!(obj->is_using_fuart)) { + obj->UARTx->TRANS &= ~(0x08); + } else { + obj->FUARTx->LCR_H &= ~(FUARTxLCR_H_BRK_SEND); + } } static void uart_swreset(TSB_UART_TypeDef *UARTx) @@ -398,6 +642,52 @@ static void uart_swreset(TSB_UART_TypeDef *UARTx) } } +static void fuart_init_config(TSB_FURT_TypeDef * FUARTx, FUART_InitTypeDef * InitStruct) +{ + uint32_t tmp = 0U; + uint32_t fuartclk = 0U; + uint32_t ibd = 0U; + uint32_t fbd = 0U; + uint32_t br = InitStruct->BaudRate; + + SystemCoreClockUpdate(); + fuartclk = SystemCoreClock; + + ibd = fuartclk / (16U * br); + fbd = (8U * fuartclk + br - 128U * ibd * br) / (2U * br); + + if (fbd == 0U) { + fbd = 1U; //Fractional part of baud rate divisor can not be 0x00 + } else { + + } + + FUARTx->BRD = ibd; // Set integer part of baud rate divisor + FUARTx->FBRD = fbd; // Set fractional part of baud rate divisor + + tmp = FUARTx->LCR_H; + + tmp &= LCR_H_WLEN_MASK; + tmp |= InitStruct->DataBits; + + tmp &= LCR_H_STP2_MASK; + tmp |= InitStruct->StopBits; + + tmp &= LCR_H_PARITY_MASK; + tmp |= InitStruct->Parity; + + FUARTx->LCR_H = tmp; //Set DataBits, StopBits, Parity + + tmp = FUARTx->CR; + tmp &= CR_FLOW_CTRL_MASK; + tmp |= InitStruct->FlowCtrl; + + tmp &= CR_MODE_MASK; + tmp |= InitStruct->Mode; + + FUARTx->CR = tmp; +} + const PinMap *serial_tx_pinmap() { return PinMap_UART_TX; @@ -410,22 +700,10 @@ const PinMap *serial_rx_pinmap() const PinMap *serial_cts_pinmap() { -#if !DEVICE_SERIAL_FC - static const PinMap PinMap_UART_CTS[] = { - {NC, NC, 0} - }; -#endif - return PinMap_UART_CTS; } const PinMap *serial_rts_pinmap() { -#if !DEVICE_SERIAL_FC - static const PinMap PinMap_UART_RTS[] = { - {NC, NC, 0} - }; -#endif - return PinMap_UART_RTS; } diff --git a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/spi_api.c b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/spi_api.c index ae2e3f638a..1068bf240c 100644 --- a/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/spi_api.c +++ b/targets/TARGET_TOSHIBA/TARGET_TMPM4G9/spi_api.c @@ -21,6 +21,18 @@ #define TIMEOUT (5000) #define BAUDRATE_1MHZ_BRS (0x0A) #define BAUDRATE_1MHZ_BRCK (0x30) +#define SPI_TRANSFER_STATE_IDLE (0U) +#define SPI_TRANSFER_STATE_BUSY (1U) + +#if DEVICE_SPI_ASYNCH +#define SPI_S(obj) (( struct spi_s *)(&(obj->spi))) +#else +#define SPI_S(obj) (( struct spi_s *)(obj)) +#endif + +#if DEVICE_SPI_ASYNCH +static inline void state_idle(struct spi_s *obj_s); +#endif static const PinMap PinMap_SPI_SCLK[] = { {PA1, SPI_0, PIN_DATA(7, 1)}, @@ -35,6 +47,19 @@ static const PinMap PinMap_SPI_SCLK[] = { {NC, NC, 0} }; +static const PinMap PinMap_SPI_SLAVE_SCLK[] = { + {PA1, SPI_0, PIN_DATA(7, 0)}, + {PL1, SPI_1, PIN_DATA(7, 0)}, + {PA6, SPI_2, PIN_DATA(7, 0)}, + {PK6, SPI_3, PIN_DATA(4, 0)}, + {PD1, SPI_4, PIN_DATA(4, 0)}, + {PV6, SPI_5, PIN_DATA(4, 0)}, + {PM2, SPI_6, PIN_DATA(6, 0)}, + {PM5, SPI_7, PIN_DATA(6, 0)}, + {PW1, SPI_8, PIN_DATA(4, 0)}, + {NC, NC, 0} +}; + static const PinMap PinMap_SPI_MOSI[] = { {PA3, SPI_0, PIN_DATA(7, 1)}, {PL3, SPI_1, PIN_DATA(7, 1)}, @@ -62,19 +87,21 @@ static const PinMap PinMap_SPI_MISO[] = { }; static const PinMap PinMap_SPI_SSEL[] = { - {PA0, SPI_0, PIN_DATA(7, 1)}, - {PL0, SPI_1, PIN_DATA(7, 1)}, - {PA7, SPI_2, PIN_DATA(7, 1)}, - {PK7, SPI_3, PIN_DATA(4, 1)}, - {PD0, SPI_4, PIN_DATA(4, 1)}, - {PV7, SPI_5, PIN_DATA(4, 1)}, - {PM3, SPI_6, PIN_DATA(6, 1)}, - {PM4, SPI_7, PIN_DATA(6, 1)}, - {PW0, SPI_8, PIN_DATA(4, 1)}, + {PA0, SPI_0, PIN_DATA(7, 2)}, + {PL0, SPI_1, PIN_DATA(7, 2)}, + {PA7, SPI_2, PIN_DATA(7, 2)}, + {PK7, SPI_3, PIN_DATA(4, 2)}, + {PD0, SPI_4, PIN_DATA(4, 2)}, + {PV7, SPI_5, PIN_DATA(4, 2)}, + {PM3, SPI_6, PIN_DATA(6, 2)}, + {PM4, SPI_7, PIN_DATA(6, 2)}, + {PW0, SPI_8, PIN_DATA(4, 2)}, {NC, NC, 0} }; + void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { + struct spi_s *obj_s = SPI_S(obj); // Check pin parameters SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); @@ -83,69 +110,100 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); - obj->module = (SPIName)pinmap_merge(spi_data, spi_sclk); - obj->module = (SPIName)pinmap_merge(spi_data, spi_cntl); - MBED_ASSERT((int)obj->module!= NC); + obj_s->module = (SPIName)pinmap_merge(spi_data, spi_sclk); + obj_s->module = (SPIName)pinmap_merge(spi_data, spi_cntl); + MBED_ASSERT((int)obj_s->module!= NC); + obj_s->clk_pin = sclk; +#if DEVICE_SPI_ASYNCH + obj_s->state = SPI_TRANSFER_STATE_IDLE; +#endif // Identify SPI module to use - switch ((int)obj->module) { + switch ((int)obj_s->module) { case SPI_0: - obj->p_obj.p_instance = TSB_TSPI0; + obj_s->p_obj.p_instance = TSB_TSPI0; + obj_s->rxirqn = INTT0RX_IRQn; + obj_s->txirqn = INTT0TX_IRQn; + obj_s->errirqn = INTT0ERR_IRQn; // Enable clock for particular Port and SPI TSB_CG_FSYSENA_IPENA04 = TXZ_ENABLE; TSB_CG_FSYSMENB_IPMENB02 = TXZ_ENABLE; break; case SPI_1: - obj->p_obj.p_instance = TSB_TSPI1; + obj_s->p_obj.p_instance = TSB_TSPI1; + obj_s->rxirqn = INTT1RX_IRQn; + obj_s->txirqn = INTT1TX_IRQn; + obj_s->errirqn = INTT1ERR_IRQn; // Enable clock for particular Port and SPI TSB_CG_FSYSENA_IPENA05 = TXZ_ENABLE; TSB_CG_FSYSMENB_IPMENB12 = TXZ_ENABLE; break; case SPI_2: - obj->p_obj.p_instance = TSB_TSPI2; + obj_s->p_obj.p_instance = TSB_TSPI2; + obj_s->rxirqn = INTT2RX_IRQn; + obj_s->txirqn = INTT2TX_IRQn; + obj_s->errirqn = INTT2ERR_IRQn; // Enable clock for particular Port and SPI TSB_CG_FSYSENA_IPENA06 = TXZ_ENABLE; TSB_CG_FSYSMENB_IPMENB02 = TXZ_ENABLE; break; case SPI_3: - obj->p_obj.p_instance = TSB_TSPI3; + obj_s->p_obj.p_instance = TSB_TSPI3; + obj_s->rxirqn = INTT3RX_IRQn; + obj_s->txirqn = INTT3TX_IRQn; + obj_s->errirqn = INTT3ERR_IRQn; // Enable clock for particular Port and SPI TSB_CG_FSYSENA_IPENA07 = TXZ_ENABLE; TSB_CG_FSYSMENB_IPMENB11 = TXZ_ENABLE; break; case SPI_4: - obj->p_obj.p_instance = TSB_TSPI4; + obj_s->p_obj.p_instance = TSB_TSPI4; + obj_s->rxirqn = INTT4RX_IRQn; + obj_s->txirqn = INTT4TX_IRQn; + obj_s->errirqn = INTT4ERR_IRQn; // Enable clock for particular Port and SPI TSB_CG_FSYSENA_IPENA08 = TXZ_ENABLE; TSB_CG_FSYSMENB_IPMENB05 = TXZ_ENABLE; break; case SPI_5: - obj->p_obj.p_instance = TSB_TSPI5; + obj_s->p_obj.p_instance = TSB_TSPI5; + obj_s->rxirqn = INTT5RX_IRQn; + obj_s->txirqn = INTT5TX_IRQn; + obj_s->errirqn = INTT5ERR_IRQn; // Enable clock for particular Port and SPI TSB_CG_FSYSENA_IPENA09 = TXZ_ENABLE; TSB_CG_FSYSMENB_IPMENB19 = TXZ_ENABLE; break; case SPI_6: - obj->p_obj.p_instance = TSB_TSPI6; + obj_s->p_obj.p_instance = TSB_TSPI6; + obj_s->rxirqn = INTT6RX_IRQn; + obj_s->txirqn = INTT6TX_IRQn; + obj_s->errirqn = INTT6ERR_IRQn; // Enable clock for particular Port and SPI TSB_CG_FSYSMENA_IPMENA20 = TXZ_ENABLE; TSB_CG_FSYSMENB_IPMENB13 = TXZ_ENABLE; break; case SPI_7: - obj->p_obj.p_instance = TSB_TSPI7; + obj_s->p_obj.p_instance = TSB_TSPI7; + obj_s->rxirqn = INTT7RX_IRQn; + obj_s->txirqn = INTT7TX_IRQn; + obj_s->errirqn = INTT7ERR_IRQn; // Enable clock for particular Port and SPI TSB_CG_FSYSMENA_IPMENA21 = TXZ_ENABLE; TSB_CG_FSYSMENB_IPMENB13 = TXZ_ENABLE; break; case SPI_8: - obj->p_obj.p_instance = TSB_TSPI8; + obj_s->p_obj.p_instance = TSB_TSPI8; + obj_s->rxirqn = INTT8RX_IRQn; + obj_s->txirqn = INTT8TX_IRQn; + obj_s->errirqn = INTT8ERR_IRQn; // Enable clock for particular Port and SPI TSB_CG_FSYSMENA_IPMENA22 = TXZ_ENABLE; TSB_CG_FSYSMENB_IPMENB20 = TXZ_ENABLE; break; default: - obj->p_obj.p_instance = NULL; - obj->module = (SPIName)NC; + obj_s->p_obj.p_instance = NULL; + obj_s->module = (SPIName)NC; error("Cannot found SPI module corresponding with input pins."); break; } @@ -161,96 +219,108 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel // Default configurations 8 bit, 1Mhz frequency // Control 1 configurations - obj->p_obj.init.id = (uint32_t)obj->module; - obj->p_obj.init.cnt1.trgen = TSPI_TRGEN_DISABLE; // Trigger disabled - obj->p_obj.init.cnt1.trxe = TSPI_DISABLE; // Enable Communication - obj->p_obj.init.cnt1.tspims = TSPI_SPI_MODE; // SPI mode - obj->p_obj.init.cnt1.mstr = TSPI_MASTER_OPEARTION; // Master mode operation - obj->p_obj.init.cnt1.tmmd = TSPI_TWO_WAY; // Full-duplex mode (Transmit/receive) - obj->p_obj.init.cnt1.cssel = TSPI_TSPIxCS0_ENABLE; // Chip select of pin CS0 is valid - obj->p_obj.init.cnt1.fc = TSPI_TRANS_RANGE_SINGLE; // Transfer single frame at a time contineously + obj_s->p_obj.init.id = (uint32_t)obj_s->module; + obj_s->p_obj.init.cnt1.trgen = TSPI_TRGEN_DISABLE; // Trigger disabled + obj_s->p_obj.init.cnt1.trxe = TSPI_DISABLE; // Enable Communication + obj_s->p_obj.init.cnt1.tspims = TSPI_SPI_MODE; // SPI mode + obj_s->p_obj.init.cnt1.mstr = TSPI_MASTER_OPEARTION; // master mode operation + obj_s->p_obj.init.cnt1.tmmd = TSPI_TWO_WAY; // Full-duplex mode (Transmit/receive) + obj_s->p_obj.init.cnt1.cssel = TSPI_TSPIxCS0_ENABLE; // Chip select of pin CS0 is valid + obj_s->p_obj.init.cnt1.fc = TSPI_TRANS_RANGE_SINGLE; // transfer single frame at a time contineously - // Control 2 configurations - obj->p_obj.init.cnt2.tidle = TSPI_TIDLE_HI; - obj->p_obj.init.cnt2.txdemp = TSPI_TXDEMP_HI; // When slave underruns TxD fixed to low - obj->p_obj.init.cnt2.rxdly = TSPI_RXDLY_SET; - obj->p_obj.init.cnt2.til = TSPI_TX_FILL_LEVEL_0; // Transmit FIFO Level - obj->p_obj.init.cnt2.ril = TSPI_RX_FILL_LEVEL_1; // Receive FIFO Level - obj->p_obj.init.cnt2.inttxwe = TSPI_TX_INT_DISABLE; - obj->p_obj.init.cnt2.intrxwe = TSPI_RX_INT_DISABLE; - obj->p_obj.init.cnt2.inttxfe = TSPI_TX_FIFO_INT_DISABLE; - obj->p_obj.init.cnt2.intrxfe = TSPI_RX_FIFO_INT_DISABLE; - obj->p_obj.init.cnt2.interr = TSPI_ERR_INT_DISABLE; - obj->p_obj.init.cnt2.dmate = TSPI_TX_DMA_INT_DISABLE; - obj->p_obj.init.cnt2.dmare = TSPI_RX_DMA_INT_DISABLE; + //Control 2 configurations + obj_s->p_obj.init.cnt2.tidle = TSPI_TIDLE_HI; + obj_s->p_obj.init.cnt2.txdemp = TSPI_TXDEMP_HI; // when slave underruns TxD fixed to low + obj_s->p_obj.init.cnt2.rxdly = TSPI_RXDLY_SET; + obj_s->p_obj.init.cnt2.til = TSPI_TX_FILL_LEVEL_0; // transmit FIFO Level + obj_s->p_obj.init.cnt2.ril = TSPI_RX_FILL_LEVEL_1; // receive FIFO Level + obj_s->p_obj.init.cnt2.inttxwe = TSPI_TX_INT_ENABLE; + obj_s->p_obj.init.cnt2.intrxwe = TSPI_RX_INT_ENABLE; + obj_s->p_obj.init.cnt2.inttxfe = TSPI_TX_FIFO_INT_DISABLE; + obj_s->p_obj.init.cnt2.intrxfe = TSPI_RX_FIFO_INT_DISABLE; + obj_s->p_obj.init.cnt2.interr = TSPI_ERR_INT_DISABLE; + obj_s->p_obj.init.cnt2.dmate = TSPI_TX_DMA_INT_DISABLE; + obj_s->p_obj.init.cnt2.dmare = TSPI_RX_DMA_INT_DISABLE; - // Control 3 configurations - obj->p_obj.init.cnt3.tfempclr = TSPI_TX_BUFF_CLR_DONE; // Transmit buffer clear - obj->p_obj.init.cnt3.rffllclr = TSPI_RX_BUFF_CLR_DONE; // Receive buffer clear + //Control 3 configurations + obj_s->p_obj.init.cnt3.tfempclr = TSPI_TX_BUFF_CLR_DONE; // transmit buffer clear + obj_s->p_obj.init.cnt3.rffllclr = TSPI_RX_BUFF_CLR_DONE; // receive buffer clear - // Baudrate settings - 1 Mhz default - obj->p_obj.init.brd.brck = BAUDRATE_1MHZ_BRCK; - obj->p_obj.init.brd.brs = BAUDRATE_1MHZ_BRS; + //baudrate settings - 1Mhz default + obj_s->p_obj.init.brd.brck = BAUDRATE_1MHZ_BRCK; + obj_s->p_obj.init.brd.brs = BAUDRATE_1MHZ_BRS; - // Format Control 0 settings - obj->p_obj.init.fmr0.dir = TSPI_DATA_DIRECTION_MSB; // MSB bit first - obj->p_obj.init.fmr0.fl = TSPI_DATA_LENGTH_8; - obj->p_obj.init.fmr0.fint = TSPI_INTERVAL_TIME_0; + //Format Control 0 settings + obj_s->p_obj.init.fmr0.dir = TSPI_DATA_DIRECTION_MSB; // MSB bit first + obj_s->p_obj.init.fmr0.fl = TSPI_DATA_LENGTH_8; + obj_s->p_obj.init.fmr0.fint = TSPI_INTERVAL_TIME_0; - // Special control on polarity of signal and generation timing - obj->p_obj.init.fmr0.cs3pol = TSPI_TSPIxCS3_NEGATIVE; - obj->p_obj.init.fmr0.cs2pol = TSPI_TSPIxCS2_NEGATIVE; - obj->p_obj.init.fmr0.cs1pol = TSPI_TSPIxCS1_NEGATIVE; - obj->p_obj.init.fmr0.cs0pol = TSPI_TSPIxCS0_NEGATIVE; - obj->p_obj.init.fmr0.ckpha = TSPI_SERIAL_CK_1ST_EDGE; - obj->p_obj.init.fmr0.ckpol = TSPI_SERIAL_CK_IDLE_LOW; - obj->p_obj.init.fmr0.csint = TSPI_MIN_IDLE_TIME_1; + //Special control on polarity of signal and generation timing + obj_s->p_obj.init.fmr0.cs3pol = TSPI_TSPIxCS3_NEGATIVE; + obj_s->p_obj.init.fmr0.cs2pol = TSPI_TSPIxCS2_NEGATIVE; + obj_s->p_obj.init.fmr0.cs1pol = TSPI_TSPIxCS1_NEGATIVE; + obj_s->p_obj.init.fmr0.cs0pol = TSPI_TSPIxCS0_NEGATIVE; - obj->p_obj.init.fmr0.cssckdl = TSPI_SERIAL_CK_DELAY_1; - obj->p_obj.init.fmr0.sckcsdl = TSPI_NEGATE_1; + obj_s->p_obj.init.fmr0.ckpha = TSPI_SERIAL_CK_1ST_EDGE; + obj_s->p_obj.init.fmr0.ckpol = TSPI_SERIAL_CK_IDLE_LOW; + obj_s->p_obj.init.fmr0.csint = TSPI_MIN_IDLE_TIME_1; + obj_s->p_obj.init.fmr0.cssckdl = TSPI_SERIAL_CK_DELAY_1; + obj_s->p_obj.init.fmr0.sckcsdl = TSPI_NEGATE_1; - // Format Control 1 settings tspi_fmtr1_t - obj->p_obj.init.fmr1.vpe = TSPI_PARITY_DISABLE; - obj->p_obj.init.fmr1.vpm = TSPI_PARITY_BIT_ODD; + //Format Control 1 settings tspi_fmtr1_t + obj_s->p_obj.init.fmr1.vpe = TSPI_PARITY_DISABLE; + obj_s->p_obj.init.fmr1.vpm = TSPI_PARITY_BIT_ODD; - obj->bits = (uint8_t)TSPI_DATA_LENGTH_8; + obj_s->bits = (uint8_t)TSPI_DATA_LENGTH_8; - // Initialize SPI - tspi_init(&obj->p_obj); + //initialize SPI + tspi_init(&obj_s->p_obj); } void spi_free(spi_t *obj) { - tspi_deinit(&obj->p_obj); - obj->module = (SPIName)NC; + struct spi_s *obj_s = SPI_S(obj); + + tspi_deinit(&obj_s->p_obj); + obj_s->module = (SPIName)NC; } void spi_format(spi_t *obj, int bits, int mode, int slave) { - MBED_ASSERT((slave == 0U)); // 0: master mode, 1: slave mode + struct spi_s *obj_s = SPI_S(obj); + + MBED_ASSERT((slave == 0U) || (slave == 1U)); // 0: master mode, 1: slave mode MBED_ASSERT((bits >= 8) && (bits <= 32)); - obj->bits = bits; - obj->p_obj.init.fmr0.fl = (bits << 24); + obj_s->bits = bits; + obj_s->p_obj.init.fmr0.fl = (bits << 24); - if ((mode >> 1) & 0x1) { - obj->p_obj.init.fmr0.ckpol = TSPI_SERIAL_CK_IDLE_HI; - } else { - obj->p_obj.init.fmr0.ckpol = TSPI_SERIAL_CK_IDLE_LOW; + if(slave) { + pinmap_pinout(obj_s->clk_pin, PinMap_SPI_SLAVE_SCLK); + obj_s->p_obj.init.cnt1.mstr = TSPI_SLAVE_OPERATION; // slave mode operation } - if (mode & 0x1) { - obj->p_obj.init.fmr0.ckpha = TSPI_SERIAL_CK_2ND_EDGE; + if((mode >> 1) & 0x1) { + obj_s->p_obj.init.fmr0.ckpol = TSPI_SERIAL_CK_IDLE_HI; } else { - obj->p_obj.init.fmr0.ckpha = TSPI_SERIAL_CK_1ST_EDGE; + obj_s->p_obj.init.fmr0.ckpol = TSPI_SERIAL_CK_IDLE_LOW; } - tspi_init(&obj->p_obj); + if(mode & 0x1) { + obj_s->p_obj.init.fmr0.ckpha = TSPI_SERIAL_CK_2ND_EDGE; + } else { + obj_s->p_obj.init.fmr0.ckpha = TSPI_SERIAL_CK_1ST_EDGE; + } + + tspi_init(&obj_s->p_obj); } void spi_frequency(spi_t *obj, int hz) { + struct spi_s *obj_s = SPI_S(obj); + SystemCoreClockUpdate(); + uint8_t brs = 0; uint8_t brck = 0; uint16_t prsck = 1; @@ -265,23 +335,24 @@ void spi_frequency(spi_t *obj, int hz) fscl = fx /brs; if ((fscl <= (uint64_t)hz) && (fscl > tmp_fscl)) { tmp_fscl = fscl; - obj->p_obj.init.brd.brck = (brck << 4); - if (brs == 16) { - obj->p_obj.init.brd.brs = 0; + obj_s->p_obj.init.brd.brck = (brck << 4); + if(brs == 16) { + obj_s->p_obj.init.brd.brs = 0; } else { - obj->p_obj.init.brd.brs = brs; + obj_s->p_obj.init.brd.brs = brs; } } } brck ++; } - tspi_init(&obj->p_obj); + tspi_init(&obj_s->p_obj); } int spi_master_write(spi_t *obj, int value) { - uint8_t ret_value = 0; + struct spi_s *obj_s = SPI_S(obj); + uint8_t ret_value = 0; tspi_transmit_t send_obj; tspi_receive_t rec_obj; @@ -289,12 +360,12 @@ int spi_master_write(spi_t *obj, int value) // Transmit data send_obj.tx8.p_data = (uint8_t *)&value; send_obj.tx8.num = 1; - tspi_master_write(&obj->p_obj, &send_obj, TIMEOUT); + tspi_master_write(&obj_s->p_obj, &send_obj, TIMEOUT); // Read received data rec_obj.rx8.p_data = &ret_value; rec_obj.rx8.num = 1; - tspi_master_read(&obj->p_obj, &rec_obj, TIMEOUT); + tspi_master_read(&obj_s->p_obj, &rec_obj, TIMEOUT); return ret_value; } @@ -315,12 +386,45 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, return total; } +int spi_slave_receive(spi_t *obj) +{ + struct spi_s *obj_s = SPI_S(obj); + if((obj_s->p_obj.p_instance->SR & 0x0F) != 0) { + return 1; + } + + return 0; +} + +int spi_slave_read(spi_t *obj) +{ + struct spi_s *obj_s = SPI_S(obj); + uint8_t ret_value = 0; + + ret_value = obj_s->p_obj.p_instance->DR & 0xFF; + obj_s->p_obj.p_instance->CR1 &= TSPI_TRXE_DISABLE_MASK; + + return ret_value; +} + +void spi_slave_write(spi_t *obj, int value) +{ + struct spi_s *obj_s = SPI_S(obj); + if((obj_s->p_obj.p_instance->CR1 & TSPI_TX_ONLY) != TSPI_TX_ONLY) { //Enable TX if not Enabled + obj_s->p_obj.p_instance->CR1 |= TSPI_TX_ONLY; + } + + obj_s->p_obj.p_instance->CR1 |= TSPI_TRXE_ENABLE; + obj_s->p_obj.p_instance->DR = (uint8_t)(value & 0xFF); +} + int spi_busy(spi_t *obj) { + struct spi_s *obj_s = SPI_S(obj); int ret = 1; uint32_t status = 0; - tspi_get_status(&obj->p_obj, &status); + tspi_get_status(&obj_s->p_obj, &status); if ((status & (TSPI_TX_FLAG_ACTIVE | TSPI_RX_FLAG_ACTIVE)) == 0) { ret = 0; @@ -331,7 +435,8 @@ int spi_busy(spi_t *obj) uint8_t spi_get_module(spi_t *obj) { - return (uint8_t)(obj->module); + struct spi_s *obj_s = SPI_S(obj); + return (uint8_t)(obj_s->module); } const PinMap *spi_master_mosi_pinmap() @@ -366,10 +471,153 @@ const PinMap *spi_slave_miso_pinmap() const PinMap *spi_slave_clk_pinmap() { - return PinMap_SPI_SCLK; + return PinMap_SPI_SLAVE_SCLK; } const PinMap *spi_slave_cs_pinmap() { return PinMap_SPI_SSEL; } + +#ifdef DEVICE_SPI_ASYNCH + +void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint) +{ + struct spi_s *obj_s = SPI_S(obj); + tspi_t *p_obj = &(obj_s->p_obj); + + obj_s->event_mask = event | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE; + + // check which use-case we have + bool use_tx = (tx != NULL && tx_length > 0); + bool use_rx = (rx != NULL && rx_length > 0); + + // don't do anything, if the buffers aren't valid + if (!use_tx && !use_rx) { + return; + } + + // copy the buffers to the SPI object + obj->tx_buff.buffer = (void *) tx; + obj->tx_buff.length = tx ? tx_length : 0; + obj->tx_buff.pos = 0; + + obj->rx_buff.buffer = rx; + obj->rx_buff.length = rx ? rx_length : 0; + obj->rx_buff.pos = 0; + + + NVIC_SetVector(obj_s->rxirqn, (uint32_t)handler); //receive interrupt + NVIC_SetVector(obj_s->txirqn, (uint32_t)handler); //transmit interrupt + NVIC_SetVector(obj_s->errirqn, (uint32_t)handler); //error interrupt + NVIC_ClearPendingIRQ(obj_s->rxirqn); + NVIC_ClearPendingIRQ(obj_s->txirqn); + NVIC_ClearPendingIRQ(obj_s->errirqn); + + obj_s->state = SPI_TRANSFER_STATE_BUSY; + obj_s->p_obj.p_instance->CR1 |= TSPI_TRXE_ENABLE; + + // Enable Interrupt bit in SPI peripheral - Enabled in init() + if(use_tx) { + // Transmit first byte to enter into handler + p_obj->p_instance->DR = *(uint8_t *)(tx); + obj->tx_buff.pos++; + NVIC_EnableIRQ(obj_s->txirqn); + } + if (use_rx) { + if(!use_tx) { + //if RX only then transmit one dummy byte to enter into handler + p_obj->p_instance->DR = 0xFF; + } + NVIC_EnableIRQ(obj_s->rxirqn); + } + NVIC_EnableIRQ(obj_s->errirqn); +} + +uint32_t spi_irq_handler_asynch(spi_t *obj) +{ + struct spi_s *obj_s = SPI_S(obj); + tspi_t *p_obj = &(obj_s->p_obj); + int event = 0; + uint32_t err = 0; + + if (obj_s->state != SPI_TRANSFER_STATE_BUSY) { + event = SPI_EVENT_ERROR | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE; + state_idle(obj_s); + return (event & obj_s->event_mask); + } + + if((p_obj->p_instance->SR & TSPI_RX_DONE_FLAG) == TSPI_RX_DONE) { + + if(obj->rx_buff.pos < obj->rx_buff.length) { + *((uint8_t *)obj->rx_buff.buffer + obj->rx_buff.pos) = (p_obj->p_instance->DR & 0xFF); + obj->rx_buff.pos++; + + if((obj->tx_buff.pos == obj->tx_buff.length) && (obj->rx_buff.pos < obj->rx_buff.length)) { + // transmit complete but receive pending - dummy write + p_obj->p_instance->DR = 0xFF; + } + + } else { + //Receive complete - dummy read + uint8_t dummy = p_obj->p_instance->DR; + } + } + if((p_obj->p_instance->SR & TSPI_TX_DONE_FLAG) == TSPI_TX_DONE) { + + p_obj->p_instance->SR |= TSPI_TX_DONE_CLR; + + if(obj->tx_buff.pos < obj->tx_buff.length) { + p_obj->p_instance->DR = *((uint8_t *)obj->tx_buff.buffer + obj->tx_buff.pos) & 0xFF; + obj->tx_buff.pos++; + + } else if (obj->rx_buff.pos == obj->rx_buff.length) { + // Tx and Rx complete + event = SPI_EVENT_COMPLETE | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE; + state_idle(obj_s); + } + } + + err = p_obj->p_instance->ERR; + if(err != 0) { + p_obj->p_instance->ERR = (TSPI_TRGERR_ERR | TSPI_UNDERRUN_ERR |TSPI_OVERRUN_ERR | TSPI_PARITY_ERR ); + event = SPI_EVENT_ERROR | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE; + state_idle(obj_s); + } + + return (event & obj_s->event_mask); +} + +uint8_t spi_active(spi_t *obj) +{ + struct spi_s *obj_s = SPI_S(obj); + + return (obj_s->state != SPI_TRANSFER_STATE_IDLE); +} + +void spi_abort_asynch(spi_t *obj) +{ + struct spi_s *obj_s = SPI_S(obj); + + state_idle(obj_s); + tspi_init(&obj_s->p_obj); //Reinitialising with software reset +} + +static inline void state_idle(struct spi_s *obj_s) +{ + NVIC_DisableIRQ(obj_s->rxirqn); + NVIC_DisableIRQ(obj_s->txirqn); + NVIC_DisableIRQ(obj_s->errirqn); + NVIC_ClearPendingIRQ(obj_s->rxirqn); + NVIC_ClearPendingIRQ(obj_s->txirqn); + NVIC_ClearPendingIRQ(obj_s->errirqn); + obj_s->state = SPI_TRANSFER_STATE_IDLE; + + //clean-up + obj_s->p_obj.p_instance->CR1 &= TSPI_TRXE_DISABLE_MASK; + obj_s->p_obj.p_instance->SR = (TSPI_TX_DONE_CLR | TSPI_RX_DONE_CLR); + obj_s->p_obj.p_instance->CR3 = (TSPI_TX_BUFF_CLR_DONE | TSPI_RX_BUFF_CLR_DONE); + obj_s->p_obj.p_instance->ERR = (TSPI_TRGERR_ERR | TSPI_UNDERRUN_ERR |TSPI_OVERRUN_ERR | TSPI_PARITY_ERR ); +} + +#endif //DEVICE_SPI_ASYNCH diff --git a/targets/targets.json b/targets/targets.json index f624ca73db..8cca0eeb4f 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -8285,7 +8285,7 @@ "is_disk_virtual": true, "extra_labels": ["TOSHIBA"], "macros": ["__TMPM4G9__"], - "supported_toolchains": ["GCC_ARM", "ARM", "IAR"], + "supported_toolchains": ["GCC_ARM", "ARMC5", "IAR"], "device_has": [ "ANALOGIN", "ANALOGOUT", @@ -8296,9 +8296,14 @@ "PWMOUT", "RESET_REASON", "SERIAL", + "SERIAL_FC", "SPI", + "SPISLAVE", + "SPI_ASYNCH", "I2C", "I2CSLAVE", + "I2C_ASYNCH", + "RTC", "STDIO_MESSAGES", "FLASH", "SLEEP",