Merge pull request #1626 from mtkrtk/rz_a1h_async_patch

[Renesas RZ/A1H] Enable asynchronous communications
pull/1697/head
Martin Kojtal 2016-04-28 19:07:37 -05:00
commit fe9720f24b
11 changed files with 1230 additions and 223 deletions

View File

@ -24,7 +24,7 @@
#define CTHUNK_ADDRESS 1
#if defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__thumb2__)
#if (defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__thumb2__)) && ! defined(__CORTEX_A9)
#define CTHUNK_VARIABLES volatile uint32_t code[1]
/**
* CTHUNK disassembly for Cortex-M3/M4 (thumb2):
@ -38,7 +38,7 @@
*/
#define CTHUNK_ASSIGMENT m_thunk.code[0] = 0x8007E89F
#elif defined(__CORTEX_M0PLUS) || defined(__CORTEX_M0)
#elif defined(__CORTEX_M0PLUS) || defined(__CORTEX_M0) || defined(__CORTEX_A9)
/*
* CTHUNK disassembly for Cortex M0 (thumb):
* * push {r0,r1,r2,r3,r4,lr} save touched registers and return address
@ -194,6 +194,24 @@ class CThunk
m_thunk.callback = (uint32_t)&m_callback;
m_thunk.trampoline = (uint32_t)&trampoline;
#if defined(__CORTEX_A9)
/* Data cache clean */
/* Cache control */
{
uint32_t start_addr = (uint32_t)&m_thunk & 0xFFFFFFE0;
uint32_t end_addr = (uint32_t)&m_thunk + sizeof(m_thunk);
uint32_t addr;
/* Data cache clean and invalid */
for (addr = start_addr; addr < end_addr; addr += 0x20) {
__v7_clean_inv_dcache_mva((void *)addr);
}
/* Instruction cache invalid */
__v7_inv_icache_all();
__ca9u_inv_tlb_all();
__v7_inv_btac();
}
#endif
__ISB();
__DSB();
}

View File

@ -124,7 +124,12 @@ int SPI::queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, i
if (_transaction_buffer.full()) {
return -1; // the buffer is full
} else {
__disable_irq();
_transaction_buffer.push(transaction);
if (!spi_active(&_spi)) {
dequeue_transaction();
}
__enable_irq();
return 0;
}
#else

View File

@ -754,11 +754,12 @@ typedef enum IRQn
region.outer_norm_t = WB_WA; \
region.mem_t = NORMAL; \
region.sec_t = NON_SECURE; \
region.xn_t = NON_EXECUTE; \
region.xn_t = EXECUTE; \
region.priv_t = RW; \
region.user_t = RW; \
region.sh_t = NON_SHARED; \
__get_section_descriptor(&descriptor_l1, region);
//Sect_SO. Strongly-ordered (therefore shareable), not executable, rw, domain 0, base addr 0
#define section_so(descriptor_l1, region) region.rg_t = SECTION; \
region.domain = 0x0; \
@ -788,7 +789,7 @@ typedef enum IRQn
region.user_t = READ; \
region.sh_t = NON_SHARED; \
__get_section_descriptor(&descriptor_l1, region);
//Sect_Device_RW. Sect_Device_RO, but writeable
#define section_device_rw(descriptor_l1, region) region.rg_t = SECTION; \
region.domain = 0x0; \
@ -832,6 +833,7 @@ typedef enum IRQn
region.user_t = RW; \
region.sh_t = NON_SHARED; \
__get_page_descriptor(&descriptor_l1, &descriptor_l2, region);
/*@}*/ /* end of group Renesas_RZ_A1_MemoryMap */

View File

@ -24,45 +24,50 @@
#endif
/* <-Take measures about optimization problems of web compiler */
#define DEVICE_PORTIN 1
#define DEVICE_PORTOUT 1
#define DEVICE_PORTINOUT 1
#define DEVICE_PORTIN 1
#define DEVICE_PORTOUT 1
#define DEVICE_PORTINOUT 1
#define DEVICE_INTERRUPTIN 1
#define DEVICE_INTERRUPTIN 1
#define DEVICE_ANALOGIN 1
#define DEVICE_ANALOGOUT 0
#define DEVICE_ANALOGIN 1
#define DEVICE_ANALOGOUT 0
#define DEVICE_SERIAL 1
#define DEVICE_SERIAL_FC 1
#define DEVICE_SERIAL 1
#define DEVICE_SERIAL_FC 1
#define DEVICE_SERIAL_ASYNCH 1
#define DEVICE_I2C 1
#define DEVICE_I2CSLAVE 1
#define DEVICE_I2C 1
#define DEVICE_I2CSLAVE 1
#define DEVICE_I2C_ASYNCH 1
#define DEVICE_SPI 1
#define DEVICE_SPISLAVE 1
#define DEVICE_SPI 1
#define DEVICE_SPISLAVE 1
#define DEVICE_SPI_ASYNCH 1
#define TRANSACTION_QUEUE_SIZE_SPI 16
#define DEVICE_CAN 1
#define DEVICE_CAN 1
#define DEVICE_RTC 1
#define DEVICE_RTC 1
#define DEVICE_ETHERNET 1
#define DEVICE_ETHERNET 1
#define DEVICE_PWMOUT 1
#define DEVICE_PWMOUT 1
#define DEVICE_SEMIHOST 0
#define DEVICE_LOCALFILESYSTEM 0
#define DEVICE_ID_LENGTH 32
#define DEVICE_MAC_OFFSET 20
#define DEVICE_SEMIHOST 0
#define DEVICE_LOCALFILESYSTEM 0
#define DEVICE_ID_LENGTH 32
#define DEVICE_MAC_OFFSET 20
#define DEVICE_SLEEP 0
#define DEVICE_SLEEP 0
#define DEVICE_DEBUG_AWARENESS 0
#define DEVICE_DEBUG_AWARENESS 0
#define DEVICE_STDIO_MESSAGES 1
#define DEVICE_STDIO_MESSAGES 1
#define DEVICE_ERROR_PATTERN 1
#define DEVICE_ERROR_PATTERN 1
#include "objects.h"
#include "dma_api.h"
#endif

View File

@ -14,6 +14,7 @@
* limitations under the License.
*/
#include "mbed_assert.h"
#include "dma_api.h"
#include "i2c_api.h"
#include "cmsis.h"
#include "pinmap.h"
@ -26,7 +27,7 @@
volatile struct st_riic *RIIC[] = RIIC_ADDRESS_LIST;
#define REG(N) \
RIIC[obj->i2c]->RIICn##N
RIIC[obj->i2c.i2c]->RIICn##N
/* RIICnCR1 */
#define CR1_RST (1 << 6)
@ -74,7 +75,6 @@ static const PinMap PinMap_I2C_SCL[] = {
{NC , NC, 0}
};
static inline int i2c_status(i2c_t *obj) {
return REG(SR2.UINT8[0]);
}
@ -89,9 +89,9 @@ static void i2c_reg_reset(i2c_t *obj) {
REG(SER.UINT8[0]) = 0x00; // no slave addr enabled
/* set frequency */
REG(MR1.UINT8[0]) |= obj->pclk_bit;
REG(BRL.UINT8[0]) = obj->width_low;
REG(BRH.UINT8[0]) = obj->width_hi;
REG(MR1.UINT8[0]) |= obj->i2c.pclk_bit;
REG(BRL.UINT8[0]) = obj->i2c.width_low;
REG(BRH.UINT8[0]) = obj->i2c.width_hi;
REG(MR2.UINT8[0]) = 0x07;
REG(MR3.UINT8[0]) = 0x00;
@ -205,7 +205,7 @@ static void i2c_set_MR3_ACK(i2c_t *obj) {
static inline void i2c_power_enable(i2c_t *obj) {
volatile uint8_t dummy;
switch ((int)obj->i2c) {
switch ((int)obj->i2c.i2c) {
case I2C_0:
CPGSTBCR9 &= ~(0x80);
break;
@ -226,8 +226,8 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
/* determine the I2C to use */
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
obj->i2c = pinmap_merge(i2c_sda, i2c_scl);
MBED_ASSERT((int)obj->i2c != NC);
obj->i2c.i2c = pinmap_merge(i2c_sda, i2c_scl);
MBED_ASSERT((int)obj->i2c.i2c != NC);
/* enable power */
i2c_power_enable(obj);
@ -238,7 +238,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
pinmap_pinout(sda, PinMap_I2C_SDA);
pinmap_pinout(scl, PinMap_I2C_SCL);
obj->last_stop_flag = 1;
obj->i2c.last_stop_flag = 1;
}
inline int i2c_start(i2c_t *obj) {
@ -246,7 +246,7 @@ inline int i2c_start(i2c_t *obj) {
while ((REG(CR2.UINT32) & CR2_BBSY) != 0) {
timeout ++;
if (timeout >= obj->bbsy_wait_cnt) {
if (timeout >= obj->i2c.bbsy_wait_cnt) {
break;
}
}
@ -277,7 +277,7 @@ static void i2c_set_err_noslave(i2c_t *obj) {
(void)i2c_set_STOP(obj);
(void)i2c_wait_STOP(obj);
i2c_set_SR2_NACKF_STOP(obj);
obj->last_stop_flag = 1;
obj->i2c.last_stop_flag = 1;
}
static inline int i2c_do_write(i2c_t *obj, int value) {
@ -395,16 +395,16 @@ void i2c_frequency(i2c_t *obj, int hz) {
wait_utime = (L_time * 2) * 1000000;
/* 1 wait of BBSY bit is about 0.3us. if it's below 0.3us, wait count is set as 1. */
if (wait_utime <= 0.3) {
obj->bbsy_wait_cnt = 1;
obj->i2c.bbsy_wait_cnt = 1;
} else {
obj->bbsy_wait_cnt = (int)(wait_utime / 0.3);
obj->i2c.bbsy_wait_cnt = (int)(wait_utime / 0.3);
}
/* I2C Rate */
obj->pclk_bit = (uint8_t)(0x10 * wk_cks); /* P_phi / xx */
obj->width_low = (uint8_t)(tmp_L_width | 0x000000E0);
obj->width_hi = (uint8_t)(tmp_H_width | 0x000000E0);
obj->i2c.pclk_bit = (uint8_t)(0x10 * wk_cks); /* P_phi / xx */
obj->i2c.width_low = (uint8_t)(tmp_L_width | 0x000000E0);
obj->i2c.width_hi = (uint8_t)(tmp_H_width | 0x000000E0);
/* full reset */
i2c_reg_reset(obj);
@ -421,14 +421,14 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
}
i2c_set_MR3_ACK(obj);
/* There is a STOP condition for last processing */
if (obj->last_stop_flag != 0) {
if (obj->i2c.last_stop_flag != 0) {
status = i2c_start(obj);
if (status != 0) {
i2c_set_err_noslave(obj);
return I2C_ERROR_BUS_BUSY;
}
}
obj->last_stop_flag = stop;
obj->i2c.last_stop_flag = stop;
/* Send Slave address */
status = i2c_read_address_write(obj, (address | 0x01));
if (status != 0) {
@ -445,7 +445,7 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
value = REG(DRR.UINT32);
(void)i2c_wait_STOP(obj);
i2c_set_SR2_NACKF_STOP(obj);
obj->last_stop_flag = 1;
obj->i2c.last_stop_flag = 1;
return I2C_ERROR_NO_SLAVE;
}
/* Read in all except last byte */
@ -470,7 +470,7 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
data[count] = (char)value;
}
} else if (length == 2) {
/* Set MR3 WATI bit is 1 */
/* Set MR3 WAIT bit is 1 */
REG(MR3.UINT32) |= MR3_WAIT;
/* dummy read */
value = REG(DRR.UINT32);
@ -485,7 +485,7 @@ int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
count++;
} else {
/* length == 1 */
/* Set MR3 WATI bit is 1 */;
/* Set MR3 WAIT bit is 1 */;
REG(MR3.UINT32) |= MR3_WAIT;
i2c_set_MR3_NACK(obj);
/* dummy read */
@ -532,14 +532,14 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
}
/* There is a STOP condition for last processing */
if (obj->last_stop_flag != 0) {
if (obj->i2c.last_stop_flag != 0) {
status = i2c_start(obj);
if (status != 0) {
i2c_set_err_noslave(obj);
return I2C_ERROR_BUS_BUSY;
}
}
obj->last_stop_flag = stop;
obj->i2c.last_stop_flag = stop;
/* Send Slave address */
status = i2c_do_write(obj, address);
if (status != 0) {
@ -749,3 +749,392 @@ int i2c_slave_write(i2c_t *obj, const char *data, int length) {
void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
REG(SAR0.UINT32) = (address & 0xfffffffe);
}
#if DEVICE_I2C_ASYNCH
#define IRQ_NUM 4
#define IRQ_TX 0
#define IRQ_RX 1
#define IRQ_ERR1 2
#define IRQ_ERR2 3
static void i2c_irqs_set(i2c_t *obj, uint32_t enable);
static void i2c0_tx_irq(void);
static void i2c1_tx_irq(void);
static void i2c2_tx_irq(void);
static void i2c3_tx_irq(void);
static void i2c0_rx_irq(void);
static void i2c1_rx_irq(void);
static void i2c2_rx_irq(void);
static void i2c3_rx_irq(void);
static void i2c0_al_irq(void);
static void i2c1_al_irq(void);
static void i2c2_al_irq(void);
static void i2c3_al_irq(void);
static void i2c0_to_irq(void);
static void i2c1_to_irq(void);
static void i2c2_to_irq(void);
static void i2c3_to_irq(void);
static const IRQn_Type irq_set_tbl[RIIC_COUNT][IRQ_NUM] = {
{INTIICTEI0_IRQn, INTIICRI0_IRQn, INTIICALI0_IRQn, INTIICTMOI0_IRQn},
{INTIICTEI1_IRQn, INTIICRI1_IRQn, INTIICALI1_IRQn, INTIICTMOI1_IRQn},
{INTIICTEI2_IRQn, INTIICRI2_IRQn, INTIICALI2_IRQn, INTIICTMOI2_IRQn},
{INTIICTEI3_IRQn, INTIICRI3_IRQn, INTIICALI3_IRQn, INTIICTMOI3_IRQn},
};
static const IRQHandler hander_set_tbl[RIIC_COUNT][IRQ_NUM] = {
{i2c0_tx_irq, i2c0_rx_irq, i2c0_al_irq, i2c0_to_irq},
{i2c1_tx_irq, i2c1_rx_irq, i2c1_al_irq, i2c1_to_irq},
{i2c2_tx_irq, i2c2_rx_irq, i2c2_al_irq, i2c2_to_irq},
{i2c3_tx_irq, i2c3_rx_irq, i2c3_al_irq, i2c3_to_irq},
};
struct i2c_global_data_s {
i2c_t *async_obj;
uint32_t async_callback, event, shouldStop, address;
};
static struct i2c_global_data_s i2c_data[RIIC_COUNT];
static void i2c_transfer_finished(i2c_t *obj)
{
i2c_irqs_set(obj, 0);
uint32_t index = obj->i2c.i2c;
i2c_data[index].event = I2C_EVENT_TRANSFER_COMPLETE;
i2c_data[index].async_obj = NULL;
((void (*)())i2c_data[index].async_callback)();
}
static void i2c_tx_irq(IRQn_Type irq_num, uint32_t index)
{
i2c_t *obj = i2c_data[index].async_obj;
if ((REG(SR2.UINT32) & SR2_NACKF)) {
/* Slave sends NACK */
i2c_set_err_noslave(obj);
i2c_data[index].event = I2C_EVENT_ERROR | I2C_EVENT_TRANSFER_EARLY_NACK;
i2c_abort_asynch(obj);
((void (*)())i2c_data[index].async_callback)();
return;
}
if (obj->tx_buff.pos == obj->tx_buff.length) {
/* All datas have tranferred */
/* Clear TEND */
REG(SR2.UINT32) &= ~(SR2_TEND);
/* If not repeated start, send stop. */
if (i2c_data[index].shouldStop && obj->rx_buff.length == 0) {
(void)i2c_set_STOP(obj);
(void)i2c_wait_STOP(obj);
i2c_set_SR2_NACKF_STOP(obj);
i2c_transfer_finished(obj);
} else {
(void)i2c_restart(obj);
(void)i2c_wait_START(obj);
/* SR2.START = 0 */
REG(SR2.UINT32) &= ~SR2_START;
if (obj->rx_buff.length) {
/* Ready to read */
i2c_set_MR3_ACK(obj);
/* Disable INTRIICTEI */
REG(IER.UINT8[0]) &= ~(1 << 6);
/* Send Slave address */
if (i2c_read_address_write(obj, (i2c_data[index].address | 0x01)) != 0) {
i2c_set_err_noslave(obj);
i2c_data[index].event = I2C_EVENT_ERROR | I2C_EVENT_ERROR_NO_SLAVE;
i2c_abort_asynch(obj);
((void (*)())i2c_data[index].async_callback)();
return;
}
} else {
i2c_transfer_finished(obj);
}
}
} else {
/* Send next 1 byte */
if (i2c_do_write(obj, *(uint8_t *)obj->tx_buff.buffer) != 0) {
i2c_set_err_noslave(obj);
i2c_data[index].event = I2C_EVENT_ERROR | I2C_EVENT_ERROR_NO_SLAVE;
i2c_abort_asynch(obj);
((void (*)())i2c_data[index].async_callback)();
return;
}
obj->tx_buff.buffer = (uint8_t *)obj->tx_buff.buffer + 1;
++obj->tx_buff.pos;
}
}
static void i2c_rx_irq(IRQn_Type irq_num, uint32_t index)
{
i2c_t *obj = i2c_data[index].async_obj;
if (obj->rx_buff.pos == SIZE_MAX) {
if ((REG(SR2.UINT32) & SR2_NACKF) != 0) {
/* Slave sends NACK */
(void)i2c_set_STOP(obj);
/* dummy read */
if (REG(DRR.UINT32)) {}
(void)i2c_wait_STOP(obj);
i2c_set_SR2_NACKF_STOP(obj);
obj->i2c.last_stop_flag = 1;
i2c_data[index].event = I2C_EVENT_ERROR | I2C_EVENT_TRANSFER_EARLY_NACK;
i2c_abort_asynch(obj);
((void (*)())i2c_data[index].async_callback)();
return;
}
if (obj->rx_buff.length == 1) {
/* length == 1 */
/* Set MR3 WAIT bit is 1 */;
REG(MR3.UINT32) |= MR3_WAIT;
i2c_set_MR3_NACK(obj);
} else if (obj->rx_buff.length == 2) {
/* Set MR3 WAIT bit is 1 */
REG(MR3.UINT32) |= MR3_WAIT;
}
/* dummy read */
if (REG(DRR.UINT32)) {}
obj->rx_buff.pos = 0;
return;
}
if ((REG(SR2.UINT32) & SR2_NACKF) != 0) {
/* Slave sends NACK */
i2c_set_err_noslave(obj);
i2c_data[index].event = I2C_EVENT_ERROR | I2C_EVENT_TRANSFER_EARLY_NACK;
i2c_abort_asynch(obj);
((void (*)())i2c_data[index].async_callback)();
return;
} else {
switch (obj->rx_buff.length - obj->rx_buff.pos) {
case 1:
/* Finished */
/* If not repeated start, send stop. */
if (i2c_data[index].shouldStop) {
(void)i2c_set_STOP(obj);
/* RIICnDRR read */
*(uint8_t *)obj->rx_buff.buffer = REG(DRR.UINT32) & 0xFF;
/* RIICnMR3.WAIT = 0 */
REG(MR3.UINT32) &= ~MR3_WAIT;
(void)i2c_wait_STOP(obj);
i2c_set_SR2_NACKF_STOP(obj);
} else {
(void)i2c_restart(obj);
/* RIICnDRR read */
*(uint8_t *)obj->rx_buff.buffer = REG(DRR.UINT32) & 0xFF;
/* RIICnMR3.WAIT = 0 */
REG(MR3.UINT32) &= ~MR3_WAIT;
(void)i2c_wait_START(obj);
/* SR2.START = 0 */
REG(SR2.UINT32) &= ~SR2_START;
}
i2c_transfer_finished(obj);
return;
case 2:
i2c_set_MR3_NACK(obj);
break;
case 3:
/* this time is befor last byte read */
/* Set MR3 WAIT bit is 1 */
REG(MR3.UINT32) |= MR3_WAIT;
break;
default:
i2c_set_MR3_ACK(obj);
break;
}
*(uint8_t *)obj->rx_buff.buffer = REG(DRR.UINT32) & 0xFF;
obj->rx_buff.buffer = (uint8_t *)obj->rx_buff.buffer + 1;
++obj->rx_buff.pos;
}
}
static void i2c_err_irq(IRQn_Type irq_num, uint32_t index)
{
i2c_t *obj = i2c_data[index].async_obj;
i2c_abort_asynch(obj);
i2c_data[index].event = I2C_EVENT_ERROR;
((void (*)())i2c_data[index].async_callback)();
}
/* TX handler */
static void i2c0_tx_irq(void)
{
i2c_tx_irq(INTIICTEI0_IRQn, 0);
}
static void i2c1_tx_irq(void)
{
i2c_tx_irq(INTIICTEI1_IRQn, 1);
}
static void i2c2_tx_irq(void)
{
i2c_tx_irq(INTIICTEI2_IRQn, 2);
}
static void i2c3_tx_irq(void)
{
i2c_tx_irq(INTIICTEI3_IRQn, 3);
}
/* RX handler */
static void i2c0_rx_irq(void)
{
i2c_rx_irq(INTIICRI0_IRQn, 0);
}
static void i2c1_rx_irq(void)
{
i2c_rx_irq(INTIICRI1_IRQn, 1);
}
static void i2c2_rx_irq(void)
{
i2c_rx_irq(INTIICRI2_IRQn, 2);
}
static void i2c3_rx_irq(void)
{
i2c_rx_irq(INTIICRI3_IRQn, 3);
}
/* Arbitration Lost handler */
static void i2c0_al_irq(void)
{
i2c_err_irq(INTIICALI0_IRQn, 0);
}
static void i2c1_al_irq(void)
{
i2c_err_irq(INTIICALI1_IRQn, 1);
}
static void i2c2_al_irq(void)
{
i2c_err_irq(INTIICALI2_IRQn, 2);
}
static void i2c3_al_irq(void)
{
i2c_err_irq(INTIICALI3_IRQn, 3);
}
/* Timeout handler */
static void i2c0_to_irq(void)
{
i2c_err_irq(INTIICTMOI0_IRQn, 0);
}
static void i2c1_to_irq(void)
{
i2c_err_irq(INTIICTMOI1_IRQn, 1);
}
static void i2c2_to_irq(void)
{
i2c_err_irq(INTIICTMOI2_IRQn, 2);
}
static void i2c3_to_irq(void)
{
i2c_err_irq(INTIICTMOI3_IRQn, 3);
}
static void i2c_irqs_set(i2c_t *obj, uint32_t enable)
{
int i;
const IRQn_Type *irqTable = irq_set_tbl[obj->i2c.i2c];
const IRQHandler *handlerTable = hander_set_tbl[obj->i2c.i2c];
for (i = 0; i < IRQ_NUM; ++i) {
if (enable) {
InterruptHandlerRegister(irqTable[i], handlerTable[i]);
GIC_SetPriority(irqTable[i], 5);
GIC_EnableIRQ(irqTable[i]);
} else {
GIC_DisableIRQ(irqTable[i]);
}
}
REG(IER.UINT8[0]) = enable ? 0x63 : 0x00;
}
/******************************************************************************
* ASYNCHRONOUS HAL
******************************************************************************/
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)
{
MBED_ASSERT(obj);
MBED_ASSERT(tx ? tx_length : 1);
MBED_ASSERT(rx ? rx_length : 1);
MBED_ASSERT((REG(SER.UINT32) & SER_SAR0E) == 0); /* Slave mode */
obj->tx_buff.buffer = (void *)tx;
obj->tx_buff.length = tx_length;
obj->tx_buff.pos = 0;
obj->tx_buff.width = 8;
obj->rx_buff.buffer = rx;
obj->rx_buff.length = rx_length;
obj->rx_buff.pos = SIZE_MAX;
obj->rx_buff.width = 8;
i2c_data[obj->i2c.i2c].async_obj = obj;
i2c_data[obj->i2c.i2c].async_callback = handler;
i2c_data[obj->i2c.i2c].event = 0;
i2c_data[obj->i2c.i2c].shouldStop = stop;
i2c_data[obj->i2c.i2c].address = address;
i2c_irqs_set(obj, 1);
/* There is a STOP condition for last processing */
if (obj->i2c.last_stop_flag != 0) {
if (i2c_start(obj) != 0) {
i2c_set_err_noslave(obj);
i2c_data[obj->i2c.i2c].event = I2C_EVENT_ERROR | I2C_EVENT_ERROR_NO_SLAVE;
i2c_abort_asynch(obj);
((void (*)())handler)();
return;
}
}
obj->i2c.last_stop_flag = stop;
if (rx_length && tx_length == 0) {
/* Ready to read */
i2c_set_MR3_ACK(obj);
/* Disable INTRIICTEI */
REG(IER.UINT8[0]) &= ~(1 << 6);
address |= 0x01;
}
/* Send Slave address */
if (i2c_do_write(obj, address) != 0) {
i2c_set_err_noslave(obj);
i2c_data[obj->i2c.i2c].event = I2C_EVENT_ERROR | I2C_EVENT_ERROR_NO_SLAVE;
i2c_abort_asynch(obj);
((void (*)())handler)();
return;
}
}
uint32_t i2c_irq_handler_asynch(i2c_t *obj)
{
return i2c_data[obj->i2c.i2c].event;
}
uint8_t i2c_active(i2c_t *obj)
{
return i2c_data[obj->i2c.i2c].async_obj != NULL;
}
void i2c_abort_asynch(i2c_t *obj)
{
i2c_data[obj->i2c.i2c].async_obj = NULL;
i2c_irqs_set(obj, 0);
i2c_reg_reset(obj);
}
#endif

View File

@ -41,6 +41,7 @@ struct i2c_s {
struct spi_s {
struct st_rspi *spi;
uint32_t bits;
int index;
};
struct gpio_irq_s {

View File

@ -33,7 +33,7 @@
#define PCLK (66666666) // Define the peripheral clock P1 frequency.
#define UART_NUM 8
#define IRQ_NUM 2
#define IRQ_NUM 4
static void uart0_tx_irq(void);
static void uart1_tx_irq(void);
@ -51,7 +51,18 @@ static void uart4_rx_irq(void);
static void uart5_rx_irq(void);
static void uart6_rx_irq(void);
static void uart7_rx_irq(void);
static void uart0_er_irq(void);
static void uart1_er_irq(void);
static void uart2_er_irq(void);
static void uart3_er_irq(void);
static void uart4_er_irq(void);
static void uart5_er_irq(void);
static void uart6_er_irq(void);
static void uart7_er_irq(void);
static void serial_put_done(serial_t *obj);
static uint8_t serial_available_buffer(serial_t *obj);
static void serial_irq_err_set(serial_t *obj, uint32_t enable);
static const PinMap PinMap_UART_TX[] = {
{P2_14 , UART0, 6},
@ -115,31 +126,34 @@ 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;
uint8_t rx_irq_set_flow, rx_irq_set_api;
serial_t *tranferring_obj, *receiving_obj;
uint32_t async_tx_callback, async_rx_callback;
int event, wanted_rx_events;
};
static struct serial_global_data_s uart_data[UART_NUM];
static const IRQn_Type irq_set_tbl[UART_NUM][IRQ_NUM] = {
{SCIFRXI0_IRQn, SCIFTXI0_IRQn},
{SCIFRXI1_IRQn, SCIFTXI1_IRQn},
{SCIFRXI2_IRQn, SCIFTXI2_IRQn},
{SCIFRXI3_IRQn, SCIFTXI3_IRQn},
{SCIFRXI4_IRQn, SCIFTXI4_IRQn},
{SCIFRXI5_IRQn, SCIFTXI5_IRQn},
{SCIFRXI6_IRQn, SCIFTXI6_IRQn},
{SCIFRXI7_IRQn, SCIFTXI7_IRQn}
{SCIFRXI0_IRQn, SCIFTXI0_IRQn, SCIFBRI0_IRQn, SCIFERI0_IRQn},
{SCIFRXI1_IRQn, SCIFTXI1_IRQn, SCIFBRI1_IRQn, SCIFERI1_IRQn},
{SCIFRXI2_IRQn, SCIFTXI2_IRQn, SCIFBRI2_IRQn, SCIFERI2_IRQn},
{SCIFRXI3_IRQn, SCIFTXI3_IRQn, SCIFBRI3_IRQn, SCIFERI3_IRQn},
{SCIFRXI4_IRQn, SCIFTXI4_IRQn, SCIFBRI4_IRQn, SCIFERI4_IRQn},
{SCIFRXI5_IRQn, SCIFTXI5_IRQn, SCIFBRI5_IRQn, SCIFERI5_IRQn},
{SCIFRXI6_IRQn, SCIFTXI6_IRQn, SCIFBRI6_IRQn, SCIFERI6_IRQn},
{SCIFRXI7_IRQn, SCIFTXI7_IRQn, SCIFBRI7_IRQn, SCIFERI7_IRQn}
};
static const IRQHandler hander_set_tbl[UART_NUM][IRQ_NUM] = {
{uart0_rx_irq, uart0_tx_irq},
{uart1_rx_irq, uart1_tx_irq},
{uart2_rx_irq, uart2_tx_irq},
{uart3_rx_irq, uart3_tx_irq},
{uart4_rx_irq, uart4_tx_irq},
{uart5_rx_irq, uart5_tx_irq},
{uart6_rx_irq, uart6_tx_irq},
{uart7_rx_irq, uart7_tx_irq}
{uart0_rx_irq, uart0_tx_irq, uart0_er_irq, uart0_er_irq},
{uart1_rx_irq, uart1_tx_irq, uart1_er_irq, uart1_er_irq},
{uart2_rx_irq, uart2_tx_irq, uart2_er_irq, uart2_er_irq},
{uart3_rx_irq, uart3_tx_irq, uart3_er_irq, uart3_er_irq},
{uart4_rx_irq, uart4_tx_irq, uart4_er_irq, uart4_er_irq},
{uart5_rx_irq, uart5_tx_irq, uart5_er_irq, uart5_er_irq},
{uart6_rx_irq, uart6_tx_irq, uart6_er_irq, uart6_er_irq},
{uart7_rx_irq, uart7_tx_irq, uart7_er_irq, uart7_er_irq}
};
static __IO uint16_t *SCSCR_MATCH[] = {
@ -175,7 +189,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
MBED_ASSERT((int)uart != NC);
obj->uart = (struct st_scif *)SCIF[uart];
obj->serial.uart = (struct st_scif *)SCIF[uart];
// enable power
switch (uart) {
case UART0:
@ -208,42 +222,42 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
/* ==== SCIF initial setting ==== */
/* ---- Serial control register (SCSCR) setting ---- */
/* B'00 : Internal CLK */
obj->uart->SCSCR = 0x0000u; /* SCIF transmitting and receiving operations stop */
obj->serial.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;
obj->serial.uart->SCFCR = 0x0006;
/* ---- Serial status register (SCFSR) setting ---- */
dummy = obj->uart->SCFSR;
obj->uart->SCFSR = (dummy & 0xFF6Cu); /* ER,BRK,DR bit clear */
dummy = obj->serial.uart->SCFSR;
obj->serial.uart->SCFSR = (dummy & 0xFF6Cu); /* ER,BRK,DR bit clear */
/* ---- Line status register (SCLSR) setting ---- */
/* ORER bit clear */
obj->uart->SCLSR = 0;
obj->serial.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;
obj->serial.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;
obj->serial.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 = 0x0003u; // SPB2IO = 1, SPB2DT = 1
obj->serial.uart->SCSPTR = 0x0003u; // SPB2IO = 1, SPB2DT = 1
/* ---- Line status register (SCLSR) setting ----
b0 ORER - Overrun error detect : clear */
if (obj->uart->SCLSR & 0x0001) {
obj->uart->SCLSR = 0u; // ORER clear
if (obj->serial.uart->SCLSR & 0x0001) {
obj->serial.uart->SCLSR = 0u; // ORER clear
}
// pinout the chosen uart
@ -252,36 +266,36 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
switch (uart) {
case UART0:
obj->index = 0;
obj->serial.index = 0;
break;
case UART1:
obj->index = 1;
obj->serial.index = 1;
break;
case UART2:
obj->index = 2;
obj->serial.index = 2;
break;
case UART3:
obj->index = 3;
obj->serial.index = 3;
break;
case UART4:
obj->index = 4;
obj->serial.index = 4;
break;
case UART5:
obj->index = 5;
obj->serial.index = 5;
break;
case UART6:
obj->index = 6;
obj->serial.index = 6;
break;
case UART7:
obj->index = 7;
obj->serial.index = 7;
break;
}
uart_data[obj->index].sw_rts.pin = NC;
uart_data[obj->index].sw_cts.pin = NC;
uart_data[obj->serial.index].sw_rts.pin = NC;
uart_data[obj->serial.index].sw_cts.pin = NC;
/* ---- Serial control register (SCSCR) setting ---- */
/* Setting the TE and RE bits enables the TxD and RxD pins to be used. */
obj->uart->SCSCR = 0x00F0;
obj->serial.uart->SCSCR = 0x0070;
is_stdio_uart = (uart == STDIO_UART) ? (1) : (0);
@ -292,7 +306,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
}
void serial_free(serial_t *obj) {
uart_data[obj->index].serial_irq_id = 0;
uart_data[obj->serial.index].serial_irq_id = 0;
}
// serial_baud
@ -300,49 +314,49 @@ void serial_free(serial_t *obj) {
void serial_baud(serial_t *obj, int baudrate) {
uint16_t DL;
obj->uart->SCSMR &= ~0x0003;
obj->serial.uart->SCSMR &= ~0x0003;
if (baudrate > 32552) {
obj->uart->SCEMR = 0x0081; // BGDM = 1, ABCS = 1
obj->serial.uart->SCEMR = 0x0081; // BGDM = 1, ABCS = 1
DL = PCLK / (8 * baudrate);
if (DL > 0) {
DL--;
}
obj->uart->SCBRR = (uint8_t)DL;
obj->serial.uart->SCBRR = (uint8_t)DL;
} else if (baudrate > 16276) {
obj->uart->SCEMR = 0x0080; // BGDM = 1
obj->uart->SCBRR = PCLK / (16 * baudrate) - 1;
obj->serial.uart->SCEMR = 0x0080; // BGDM = 1
obj->serial.uart->SCBRR = PCLK / (16 * baudrate) - 1;
} else if (baudrate > 8138) {
obj->uart->SCEMR = 0x0000;
obj->uart->SCBRR = PCLK / (32 * baudrate) - 1;
obj->serial.uart->SCEMR = 0x0000;
obj->serial.uart->SCBRR = PCLK / (32 * baudrate) - 1;
} else if (baudrate > 4169) {
obj->uart->SCSMR |= 0x0001;
obj->uart->SCEMR = 0x0080; // BGDM = 1
obj->uart->SCBRR = PCLK / (64 * baudrate) - 1;
obj->serial.uart->SCSMR |= 0x0001;
obj->serial.uart->SCEMR = 0x0080; // BGDM = 1
obj->serial.uart->SCBRR = PCLK / (64 * baudrate) - 1;
} else if (baudrate > 2034) {
obj->uart->SCSMR |= 0x0001;
obj->uart->SCEMR = 0x0000;
obj->uart->SCBRR = PCLK / (128 * baudrate) - 1;
obj->serial.uart->SCSMR |= 0x0001;
obj->serial.uart->SCEMR = 0x0000;
obj->serial.uart->SCBRR = PCLK / (128 * baudrate) - 1;
} else if (baudrate > 1017) {
obj->uart->SCSMR |= 0x0002;
obj->uart->SCEMR = 0x0080; // BGDM = 1
obj->uart->SCBRR = PCLK / (256 * baudrate) - 1;
obj->serial.uart->SCSMR |= 0x0002;
obj->serial.uart->SCEMR = 0x0080; // BGDM = 1
obj->serial.uart->SCBRR = PCLK / (256 * baudrate) - 1;
} else if (baudrate > 508) {
obj->uart->SCSMR |= 0x0002;
obj->uart->SCEMR = 0x0000;
obj->uart->SCBRR = PCLK / (512 * baudrate) - 1;
obj->serial.uart->SCSMR |= 0x0002;
obj->serial.uart->SCEMR = 0x0000;
obj->serial.uart->SCBRR = PCLK / (512 * baudrate) - 1;
} else if (baudrate > 254) {
obj->uart->SCSMR |= 0x0003;
obj->uart->SCEMR = 0x0080; // BGDM = 1
obj->uart->SCBRR = PCLK / (1024 * baudrate) - 1;
obj->serial.uart->SCSMR |= 0x0003;
obj->serial.uart->SCEMR = 0x0080; // BGDM = 1
obj->serial.uart->SCBRR = PCLK / (1024 * baudrate) - 1;
} else if (baudrate > 127) {
obj->uart->SCSMR |= 0x0003;
obj->uart->SCEMR = 0x0000;
obj->uart->SCBRR = PCLK / (2048 * baudrate) - 1;
obj->serial.uart->SCSMR |= 0x0003;
obj->serial.uart->SCEMR = 0x0000;
obj->serial.uart->SCBRR = PCLK / (2048 * baudrate) - 1;
} else {
obj->uart->SCSMR |= 0x0003;
obj->uart->SCEMR = 0x0000;
obj->uart->SCBRR = 0xFFu;
obj->serial.uart->SCSMR |= 0x0003;
obj->serial.uart->SCEMR = 0x0000;
obj->serial.uart->SCBRR = 0xFFu;
}
}
@ -384,7 +398,7 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
break;
}
obj->uart->SCSMR = data_bits << 6
obj->serial.uart->SCSMR = data_bits << 6
| parity_enable << 5
| parity_select << 4
| stop_bits << 3;
@ -397,27 +411,133 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
static void uart_tx_irq(IRQn_Type irq_num, uint32_t index) {
__IO uint16_t *dmy_rd_scscr;
__IO uint16_t *dmy_rd_scfsr;
serial_t *obj;
int i;
dmy_rd_scscr = SCSCR_MATCH[index];
*dmy_rd_scscr &= 0x007B; // Clear TIE and Write to bit15~8,2 is always 0
dmy_rd_scfsr = SCFSR_MATCH[index];
*dmy_rd_scfsr = (*dmy_rd_scfsr & ~0x0020); // Clear TDFE
*dmy_rd_scfsr = (*dmy_rd_scfsr & ~0x0020); // Set TEND
obj = uart_data[index].tranferring_obj;
if (obj) {
i = obj->tx_buff.length - obj->tx_buff.pos;
if (0 < i) {
if (serial_available_buffer(obj) < i) {
i = serial_available_buffer(obj);
}
do {
uint8_t c = *(uint8_t *)obj->tx_buff.buffer;
obj->tx_buff.buffer = (uint8_t *)obj->tx_buff.buffer + 1;
++obj->tx_buff.pos;
obj->serial.uart->SCFTDR = c;
} while (--i);
serial_put_done(obj);
} else {
uart_data[index].tranferring_obj = NULL;
uart_data[index].event = SERIAL_EVENT_TX_COMPLETE;
((void (*)())uart_data[index].async_tx_callback)();
}
}
irq_handler(uart_data[index].serial_irq_id, TxIrq);
}
static void uart_rx_irq(IRQn_Type irq_num, uint32_t index) {
__IO uint16_t *dmy_rd_scscr;
__IO uint16_t *dmy_rd_scfsr;
serial_t *obj;
int c;
dmy_rd_scscr = SCSCR_MATCH[index];
*dmy_rd_scscr &= 0x00B3; // Clear RIE,REIE and Write to bit15~8,2 is always 0
dmy_rd_scfsr = SCFSR_MATCH[index];
*dmy_rd_scfsr = (*dmy_rd_scfsr & ~0x0003); // Clear RDF,DR
obj = uart_data[index].receiving_obj;
if (obj) {
if (obj->serial.uart->SCLSR & 1) {
if (uart_data[index].wanted_rx_events & SERIAL_EVENT_RX_OVERRUN_ERROR) {
serial_rx_abort_asynch(obj);
uart_data[index].event = SERIAL_EVENT_RX_OVERRUN_ERROR;
((void (*)())uart_data[index].async_rx_callback)();
}
return;
}
c = serial_getc(obj);
if (c != -1) {
((uint8_t *)obj->rx_buff.buffer)[obj->rx_buff.pos] = c;
++obj->rx_buff.pos;
if (c == obj->char_match && ! obj->char_found) {
obj->char_found = 1;
if (obj->rx_buff.pos == obj->rx_buff.length) {
if (uart_data[index].wanted_rx_events & SERIAL_EVENT_RX_COMPLETE) {
uart_data[index].event = SERIAL_EVENT_RX_COMPLETE;
}
}
if (uart_data[index].wanted_rx_events & SERIAL_EVENT_RX_CHARACTER_MATCH) {
uart_data[index].event |= SERIAL_EVENT_RX_CHARACTER_MATCH;
}
if (uart_data[index].event) {
uart_data[index].receiving_obj = NULL;
((void (*)())uart_data[index].async_rx_callback)();
}
} else if (obj->rx_buff.pos == obj->rx_buff.length) {
uart_data[index].receiving_obj = NULL;
if (uart_data[index].wanted_rx_events & SERIAL_EVENT_RX_COMPLETE) {
uart_data[index].event = SERIAL_EVENT_RX_COMPLETE;
((void (*)())uart_data[index].async_rx_callback)();
}
}
} else {
serial_rx_abort_asynch(obj);
if (uart_data[index].wanted_rx_events & (SERIAL_EVENT_RX_PARITY_ERROR | SERIAL_EVENT_RX_FRAMING_ERROR)) {
uart_data[index].event = SERIAL_EVENT_RX_PARITY_ERROR | SERIAL_EVENT_RX_FRAMING_ERROR;
if (obj->serial.uart->SCFSR & 1 << 2) {
uart_data[index].event = SERIAL_EVENT_RX_PARITY_ERROR;
} else if (obj->serial.uart->SCFSR & 1 << 3) {
uart_data[index].event = SERIAL_EVENT_RX_FRAMING_ERROR;
}
((void (*)())uart_data[index].async_rx_callback)();
}
return;
}
}
irq_handler(uart_data[index].serial_irq_id, RxIrq);
}
static void uart_err_irq(IRQn_Type irq_num, uint32_t index) {
serial_t *obj = uart_data[index].receiving_obj;
int was_masked, err_read;
if (obj) {
serial_irq_err_set(obj, 0);
if (uart_data[index].wanted_rx_events & (SERIAL_EVENT_RX_PARITY_ERROR | SERIAL_EVENT_RX_FRAMING_ERROR)) {
uart_data[index].event = SERIAL_EVENT_RX_PARITY_ERROR | SERIAL_EVENT_RX_FRAMING_ERROR;
if (obj->serial.uart->SCFSR & 1 << 2) {
uart_data[index].event = SERIAL_EVENT_RX_PARITY_ERROR;
} else if (obj->serial.uart->SCFSR & 1 << 3) {
uart_data[index].event = SERIAL_EVENT_RX_FRAMING_ERROR;
}
((void (*)())uart_data[index].async_rx_callback)();
}
serial_rx_abort_asynch(obj);
was_masked = __disable_irq();
if (obj->serial.uart->SCFSR & 0x93) {
err_read = obj->serial.uart->SCFSR;
obj->serial.uart->SCFSR = (err_read & ~0x93);
}
if (obj->serial.uart->SCLSR & 1) {
obj->serial.uart->SCLSR = 0;
}
if (!was_masked) {
__enable_irq();
}
}
}
/* TX handler */
static void uart0_tx_irq(void) {
uart_tx_irq(SCIFTXI0_IRQn, 0);
@ -468,39 +588,83 @@ static void uart6_rx_irq(void) {
static void uart7_rx_irq(void) {
uart_rx_irq(SCIFRXI7_IRQn, 7);
}
/* Error handler */
static void uart0_er_irq(void)
{
uart_err_irq(SCIFERI0_IRQn, 0);
}
static void uart1_er_irq(void)
{
uart_err_irq(SCIFERI0_IRQn, 1);
}
static void uart2_er_irq(void)
{
uart_err_irq(SCIFERI0_IRQn, 2);
}
static void uart3_er_irq(void)
{
uart_err_irq(SCIFERI0_IRQn, 3);
}
static void uart4_er_irq(void)
{
uart_err_irq(SCIFERI0_IRQn, 4);
}
static void uart5_er_irq(void)
{
uart_err_irq(SCIFERI0_IRQn, 5);
}
static void uart6_er_irq(void)
{
uart_err_irq(SCIFERI0_IRQn, 6);
}
static void uart7_er_irq(void)
{
uart_err_irq(SCIFERI0_IRQn, 7);
}
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;
uart_data[obj->serial.index].serial_irq_id = id;
}
static void serial_irq_set_irq(IRQn_Type IRQn, IRQHandler handler, uint32_t enable)
{
if (enable) {
InterruptHandlerRegister(IRQn, (void (*)(uint32_t))handler);
GIC_SetPriority(IRQn, 5);
GIC_EnableIRQ(IRQn);
} else {
GIC_DisableIRQ(IRQn);
}
}
static void serial_irq_set_internal(serial_t *obj, SerialIrq irq, uint32_t enable) {
IRQn_Type IRQn;
IRQHandler handler;
IRQn = irq_set_tbl[obj->index][irq];
handler = hander_set_tbl[obj->index][irq];
IRQn = irq_set_tbl[obj->serial.index][irq];
handler = hander_set_tbl[obj->serial.index][irq];
if ((obj->index >= 0) && (obj->index <= 7)) {
if (enable) {
InterruptHandlerRegister(IRQn, (void (*)(uint32_t))handler);
GIC_SetPriority(IRQn, 5);
GIC_EnableIRQ(IRQn);
} else {
GIC_DisableIRQ(IRQn);
}
if ((obj->serial.index >= 0) && (obj->serial.index <= 7)) {
serial_irq_set_irq(IRQn, handler, enable);
}
}
static void serial_irq_err_set(serial_t *obj, uint32_t enable)
{
serial_irq_set_irq(irq_set_tbl[obj->serial.index][2], hander_set_tbl[obj->serial.index][2], enable);
serial_irq_set_irq(irq_set_tbl[obj->serial.index][3], hander_set_tbl[obj->serial.index][3], enable);
}
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
if (RxIrq == irq) {
uart_data[obj->index].rx_irq_set_api = enable;
uart_data[obj->serial.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;
uart_data[obj->serial.index].rx_irq_set_flow = enable;
serial_irq_set_internal(obj, RxIrq, enable);
}
@ -517,29 +681,29 @@ int serial_getc(serial_t *obj) {
#else
was_masked = __disable_irq();
#endif /* __ICCARM__ */
if (obj->uart->SCFSR & 0x93) {
err_read = obj->uart->SCFSR;
obj->uart->SCFSR = (err_read & ~0x93);
if (obj->serial.uart->SCFSR & 0x93) {
err_read = obj->serial.uart->SCFSR;
obj->serial.uart->SCFSR = (err_read & ~0x93);
}
obj->uart->SCSCR |= 0x0040; // Set RIE
obj->serial.uart->SCSCR |= 0x0040; // Set RIE
if (!was_masked) {
__enable_irq();
}
if (obj->uart->SCLSR & 0x0001) {
obj->uart->SCLSR = 0u; // ORER clear
if (obj->serial.uart->SCLSR & 0x0001) {
obj->serial.uart->SCLSR = 0u; // ORER clear
}
while (!serial_readable(obj));
data = obj->uart->SCFRDR & 0xff;
data = obj->serial.uart->SCFRDR & 0xff;
#if defined ( __ICCARM__ )
was_masked = __disable_irq_iar();
#else
was_masked = __disable_irq();
#endif /* __ICCARM__ */
err_read = obj->uart->SCFSR;
obj->uart->SCFSR = (err_read & 0xfffD); // Clear RDF
err_read = obj->serial.uart->SCFSR;
obj->serial.uart->SCFSR = (err_read & 0xfffD); // Clear RDF
if (!was_masked) {
__enable_irq();
}
@ -551,39 +715,35 @@ int serial_getc(serial_t *obj) {
}
void serial_putc(serial_t *obj, int c) {
uint16_t dummy_read;
int was_masked;
#if defined ( __ICCARM__ )
was_masked = __disable_irq_iar();
#else
was_masked = __disable_irq();
#endif /* __ICCARM__ */
obj->uart->SCSCR |= 0x0080; // Set TIE
if (!was_masked) {
__enable_irq();
}
while (!serial_writable(obj));
obj->uart->SCFTDR = c;
obj->serial.uart->SCFTDR = c;
serial_put_done(obj);
}
static void serial_put_done(serial_t *obj)
{
int was_masked;
volatile uint16_t dummy_read;
#if defined ( __ICCARM__ )
was_masked = __disable_irq_iar();
#else
was_masked = __disable_irq();
#endif /* __ICCARM__ */
dummy_read = obj->uart->SCFSR;
obj->uart->SCFSR = (dummy_read & 0xff9f); // Clear TEND/TDFE
dummy_read = obj->serial.uart->SCFSR;
obj->serial.uart->SCFSR = (dummy_read & 0xff9f); // Clear TEND/TDFE
obj->serial.uart->SCSCR |= 0x0080; // Set TIE
if (!was_masked) {
__enable_irq();
}
uart_data[obj->index].count++;
}
int serial_readable(serial_t *obj) {
return ((obj->uart->SCFSR & 0x02) != 0); // RDF
return ((obj->serial.uart->SCFSR & 0x02) != 0); // RDF
}
int serial_writable(serial_t *obj) {
return ((obj->uart->SCFSR & 0x20) != 0); // TDFE
return ((obj->serial.uart->SCFSR & 0x20) != 0); // TDFE
}
void serial_clear(serial_t *obj) {
@ -594,9 +754,9 @@ void serial_clear(serial_t *obj) {
was_masked = __disable_irq();
#endif /* __ICCARM__ */
obj->uart->SCFCR |= 0x06; // TFRST = 1, RFRST = 1
obj->uart->SCFCR &= ~0x06; // TFRST = 0, RFRST = 0
obj->uart->SCFSR &= ~0x0093u; // ER, BRK, RDF, DR = 0
obj->serial.uart->SCFCR |= 0x06; // TFRST = 1, RFRST = 1
obj->serial.uart->SCFCR &= ~0x06; // TFRST = 0, RFRST = 0
obj->serial.uart->SCFSR &= ~0x0093u; // ER, BRK, RDF, DR = 0
if (!was_masked) {
__enable_irq();
@ -615,8 +775,8 @@ void serial_break_set(serial_t *obj) {
was_masked = __disable_irq();
#endif /* __ICCARM__ */
// TxD Output(L)
obj->uart->SCSPTR &= ~0x0001u; // SPB2DT = 0
obj->uart->SCSCR &= ~0x0020u; // TE = 0 (Output disable)
obj->serial.uart->SCSPTR &= ~0x0001u; // SPB2DT = 0
obj->serial.uart->SCSCR &= ~0x0020u; // TE = 0 (Output disable)
if (!was_masked) {
__enable_irq();
}
@ -629,8 +789,8 @@ void serial_break_clear(serial_t *obj) {
#else
was_masked = __disable_irq();
#endif /* __ICCARM__ */
obj->uart->SCSCR |= 0x0020u; // TE = 1 (Output enable)
obj->uart->SCSPTR |= 0x0001u; // SPB2DT = 1
obj->serial.uart->SCSCR |= 0x0020u; // TE = 1 (Output enable)
obj->serial.uart->SCSPTR |= 0x0001u; // SPB2DT = 1
if (!was_masked) {
__enable_irq();
}
@ -648,7 +808,7 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
#else
was_masked = __disable_irq();
#endif /* __ICCARM__ */
obj->uart->SCFCR = 0x0008u; // CTS/RTS enable
obj->serial.uart->SCFCR = 0x0008u; // CTS/RTS enable
if (!was_masked) {
__enable_irq();
}
@ -660,13 +820,118 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
#else
was_masked = __disable_irq();
#endif /* __ICCARM__ */
obj->uart->SCFCR = 0x0000u; // CTS/RTS diable
obj->serial.uart->SCFCR = 0x0000u; // CTS/RTS diable
if (!was_masked) {
__enable_irq();
}
}
}
static uint8_t serial_available_buffer(serial_t *obj)
{
return 1;
/* Faster but unstable way */
/*
uint16_t ret = 16 - ((obj->serial.uart->SCFDR >> 8) & 0x1F);
while (ret == 0) {
ret = 16 - ((obj->serial.uart->SCFDR >> 8) & 0x1F);
}
MBED_ASSERT(0 < ret && ret <= 16);
return ret;
*/
}
#if DEVICE_SERIAL_ASYNCH
/******************************************************************************
* ASYNCHRONOUS HAL
******************************************************************************/
int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint)
{
int i;
buffer_t *buf = &obj->tx_buff;
struct serial_global_data_s *data = uart_data + obj->serial.index;
if (tx_length == 0) {
return 0;
}
buf->buffer = (void *)tx;
buf->length = tx_length * tx_width / 8;
buf->pos = 0;
buf->width = tx_width;
data->tranferring_obj = obj;
data->async_tx_callback = handler;
serial_irq_set(obj, TxIrq, 1);
while (!serial_writable(obj));
i = buf->length;
if (serial_available_buffer(obj) < i) {
i = serial_available_buffer(obj);
}
do {
uint8_t c = *(uint8_t *)buf->buffer;
obj->tx_buff.buffer = (uint8_t *)obj->tx_buff.buffer + 1;
++buf->pos;
obj->serial.uart->SCFTDR = c;
} while (--i);
serial_put_done(obj);
return buf->length;
}
void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint)
{
buffer_t *buf = &obj->rx_buff;
struct serial_global_data_s *data = uart_data + obj->serial.index;
if (rx_length == 0) {
return;
}
buf->buffer = rx;
buf->length = rx_length * rx_width / 8;
buf->pos = 0;
buf->width = rx_width;
obj->char_match = char_match;
obj->char_found = 0;
data->receiving_obj = obj;
data->async_rx_callback = handler;
data->event = 0;
data->wanted_rx_events = event;
serial_irq_set(obj, RxIrq, 1);
serial_irq_err_set(obj, 1);
}
uint8_t serial_tx_active(serial_t *obj)
{
return uart_data[obj->serial.index].tranferring_obj != NULL;
}
uint8_t serial_rx_active(serial_t *obj)
{
return uart_data[obj->serial.index].receiving_obj != NULL;
}
int serial_irq_handler_asynch(serial_t *obj)
{
return uart_data[obj->serial.index].event;
}
void serial_tx_abort_asynch(serial_t *obj)
{
uart_data[obj->serial.index].tranferring_obj = NULL;
obj->serial.uart->SCFCR |= 1 << 2;
obj->serial.uart->SCFCR &= ~(1 << 2);
}
void serial_rx_abort_asynch(serial_t *obj)
{
uart_data[obj->serial.index].receiving_obj = NULL;
obj->serial.uart->SCFCR |= 1 << 1;
obj->serial.uart->SCFCR &= ~(1 << 1);
}
#endif

View File

@ -76,11 +76,12 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso);
uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel);
uint32_t spi = pinmap_merge(spi_data, spi_cntl);
MBED_ASSERT((int)spi != NC);
obj->spi = (struct st_rspi *)RSPI[spi];
obj->spi.spi = (struct st_rspi *)RSPI[spi];
obj->spi.index = spi;
// enable power and clocking
switch (spi) {
case SPI_0: CPGSTBCR10 &= ~(0x80); break;
@ -89,18 +90,18 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
case SPI_3: CPGSTBCR10 &= ~(0x10); break;
}
dummy = CPGSTBCR10;
obj->spi->SPCR = 0x00; // CTRL to 0
obj->spi->SPSCR = 0x00; // no sequential operation
obj->spi->SSLP = 0x00; // SSL 'L' active
obj->spi->SPDCR = 0x20; // byte access
obj->spi->SPCKD = 0x00; // SSL -> enable CLK delay : 1RSPCK
obj->spi->SSLND = 0x00; // CLK end -> SSL neg delay : 1RSPCK
obj->spi->SPND = 0x00; // delay between CMD : 1RSPCK + 2P1CLK
obj->spi->SPPCR = 0x20; // MOSI Idle fixed value equals 0
obj->spi->SPBFCR = 0xf0; // and set trigger count: read 1, write 1
obj->spi->SPBFCR = 0x30; // and reset buffer
obj->spi.spi->SPCR = 0x00; // CTRL to 0
obj->spi.spi->SPSCR = 0x00; // no sequential operation
obj->spi.spi->SSLP = 0x00; // SSL 'L' active
obj->spi.spi->SPDCR = 0x20; // byte access
obj->spi.spi->SPCKD = 0x00; // SSL -> enable CLK delay : 1RSPCK
obj->spi.spi->SSLND = 0x00; // CLK end -> SSL neg delay : 1RSPCK
obj->spi.spi->SPND = 0x00; // delay between CMD : 1RSPCK + 2P1CLK
obj->spi.spi->SPPCR = 0x20; // MOSI Idle fixed value equals 0
obj->spi.spi->SPBFCR = 0xf0; // and set trigger count: read 1, write 1
obj->spi.spi->SPBFCR = 0x30; // and reset buffer
// pin out the spi pins
pinmap_pinout(mosi, PinMap_SPI_MOSI);
pinmap_pinout(miso, PinMap_SPI_MISO);
@ -120,7 +121,7 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) {
uint16_t mask = 0xf03;
uint16_t wk_spcmd0;
uint8_t splw;
switch (mode) {
case 0:
case 1:
@ -132,7 +133,7 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) {
error("SPI format error");
return;
}
switch (bits) {
case 8:
DSS = 0x7;
@ -153,18 +154,18 @@ void spi_format(spi_t *obj, int bits, int mode, int slave) {
tmp |= phase;
tmp |= (polarity << 1);
tmp |= (DSS << 8);
obj->bits = bits;
obj->spi.bits = bits;
spi_disable(obj);
wk_spcmd0 = obj->spi->SPCMD0;
wk_spcmd0 = obj->spi.spi->SPCMD0;
wk_spcmd0 &= ~mask;
wk_spcmd0 |= (mask & tmp);
obj->spi->SPCMD0 = wk_spcmd0;
obj->spi->SPDCR = splw;
obj->spi.spi->SPCMD0 = wk_spcmd0;
obj->spi.spi->SPDCR = splw;
if (slave) {
obj->spi->SPCR &=~(1 << 3); // MSTR to 0
obj->spi.spi->SPCR &=~(1 << 3); // MSTR to 0
} else {
obj->spi->SPCR |= (1 << 3); // MSTR to 1
obj->spi.spi->SPCR |= (1 << 3); // MSTR to 1
}
spi_enable(obj);
}
@ -177,21 +178,21 @@ void spi_frequency(spi_t *obj, int hz) {
uint32_t hz_min;
uint16_t mask = 0x000c;
uint16_t wk_spcmd0;
/* set PCLK */
if (RZ_A1_IsClockMode0() == false) {
pclk_base = CM1_RENESAS_RZ_A1_P1_CLK;
} else {
pclk_base = CM0_RENESAS_RZ_A1_P1_CLK;
}
hz_min = pclk_base / 2 / 256 / 8;
hz_max = pclk_base / 2;
if ((hz < hz_min) || (hz > hz_max)) {
error("Couldn't setup requested SPI frequency");
return;
}
div = (pclk_base / hz / 2);
while (div > 256) {
div >>= 1;
@ -199,53 +200,53 @@ void spi_frequency(spi_t *obj, int hz) {
}
div -= 1;
brdv = (brdv << 2);
spi_disable(obj);
obj->spi->SPBR = div;
wk_spcmd0 = obj->spi->SPCMD0;
obj->spi.spi->SPBR = div;
wk_spcmd0 = obj->spi.spi->SPCMD0;
wk_spcmd0 &= ~mask;
wk_spcmd0 |= (mask & brdv);
obj->spi->SPCMD0 = wk_spcmd0;
obj->spi.spi->SPCMD0 = wk_spcmd0;
spi_enable(obj);
}
static inline void spi_disable(spi_t *obj) {
obj->spi->SPCR &= ~(1 << 6); // SPE to 0
obj->spi.spi->SPCR &= ~(1 << 6); // SPE to 0
}
static inline void spi_enable(spi_t *obj) {
obj->spi->SPCR |= (1 << 6); // SPE to 1
obj->spi.spi->SPCR |= (1 << 6); // SPE to 1
}
static inline int spi_readable(spi_t *obj) {
return obj->spi->SPSR & (1 << 7); // SPRF
return obj->spi.spi->SPSR & (1 << 7); // SPRF
}
static inline int spi_tend(spi_t *obj) {
return obj->spi->SPSR & (1 << 6); // TEND
return obj->spi.spi->SPSR & (1 << 6); // TEND
}
static inline void spi_write(spi_t *obj, int value) {
if (obj->bits == 8) {
obj->spi->SPDR.UINT8[0] = (uint8_t)value;
} else if (obj->bits == 16) {
obj->spi->SPDR.UINT16[0] = (uint16_t)value;
if (obj->spi.bits == 8) {
obj->spi.spi->SPDR.UINT8[0] = (uint8_t)value;
} else if (obj->spi.bits == 16) {
obj->spi.spi->SPDR.UINT16[0] = (uint16_t)value;
} else {
obj->spi->SPDR.UINT32 = (uint32_t)value;
obj->spi.spi->SPDR.UINT32 = (uint32_t)value;
}
}
static inline int spi_read(spi_t *obj) {
int read_data;
if (obj->bits == 8) {
read_data = obj->spi->SPDR.UINT8[0];
} else if (obj->bits == 16) {
read_data = obj->spi->SPDR.UINT16[0];
if (obj->spi.bits == 8) {
read_data = obj->spi.spi->SPDR.UINT8[0];
} else if (obj->spi.bits == 16) {
read_data = obj->spi.spi->SPDR.UINT16[0];
} else {
read_data = obj->spi->SPDR.UINT32;
read_data = obj->spi.spi->SPDR.UINT32;
}
return read_data;
}
@ -270,3 +271,307 @@ void spi_slave_write(spi_t *obj, int value) {
int spi_busy(spi_t *obj) {
return 0;
}
#if DEVICE_SPI_ASYNCH
#define IRQ_NUM 2
static void spi_irqs_set(spi_t *obj, uint32_t enable);
static void spi_async_write(spi_t *obj);
static void spi_async_read(spi_t *obj);
static void spi0_rx_irq(void);
static void spi1_rx_irq(void);
static void spi2_rx_irq(void);
static void spi3_rx_irq(void);
static void spi4_rx_irq(void);
static void spi0_er_irq(void);
static void spi1_er_irq(void);
static void spi2_er_irq(void);
static void spi3_er_irq(void);
static void spi4_er_irq(void);
static const IRQn_Type irq_set_tbl[RSPI_COUNT][IRQ_NUM] = {
{RSPISPRI0_IRQn, RSPISPEI0_IRQn},
{RSPISPRI1_IRQn, RSPISPEI1_IRQn},
{RSPISPRI2_IRQn, RSPISPEI2_IRQn},
{RSPISPRI3_IRQn, RSPISPEI3_IRQn},
{RSPISPRI4_IRQn, RSPISPEI4_IRQn}
};
static const IRQHandler hander_set_tbl[RSPI_COUNT][IRQ_NUM] = {
{spi0_rx_irq, spi0_er_irq},
{spi1_rx_irq, spi1_er_irq},
{spi2_rx_irq, spi2_er_irq},
{spi3_rx_irq, spi3_er_irq},
{spi4_rx_irq, spi4_er_irq}
};
struct spi_global_data_s {
spi_t *async_obj;
uint32_t async_callback, event, wanted_events;
};
static struct spi_global_data_s spi_data[RSPI_COUNT];
static void spi_rx_irq(IRQn_Type irq_num, uint32_t index)
{
spi_t *obj = spi_data[index].async_obj;
if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) {
spi_async_read(obj);
} else {
if (obj->rx_buff.buffer && obj->tx_buff.buffer && obj->tx_buff.pos < obj->tx_buff.length) {
spi_data[obj->spi.index].event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
if (spi_data[obj->spi.index].wanted_events & SPI_EVENT_COMPLETE) {
spi_data[obj->spi.index].event |= SPI_EVENT_COMPLETE;
}
spi_irqs_set(obj, 0);
spi_data[obj->spi.index].async_obj = NULL;
((void (*)())spi_data[obj->spi.index].async_callback)();
return;
}
spi_read(obj);
}
if (obj->tx_buff.buffer) {
if (obj->tx_buff.pos == obj->tx_buff.length) {
spi_data[obj->spi.index].event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
if (spi_data[obj->spi.index].wanted_events & SPI_EVENT_COMPLETE) {
spi_data[obj->spi.index].event |= SPI_EVENT_COMPLETE;
}
spi_irqs_set(obj, 0);
spi_data[obj->spi.index].async_obj = NULL;
((void (*)())spi_data[obj->spi.index].async_callback)();
} else {
spi_async_write(obj);
}
} else {
if (obj->rx_buff.pos == obj->rx_buff.length) {
spi_data[obj->spi.index].event = SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
if (spi_data[obj->spi.index].wanted_events & SPI_EVENT_COMPLETE) {
spi_data[obj->spi.index].event |= SPI_EVENT_COMPLETE;
}
spi_irqs_set(obj, 0);
spi_data[obj->spi.index].async_obj = NULL;
((void (*)())spi_data[obj->spi.index].async_callback)();
} else {
spi_async_write(obj);
}
}
}
static void spi_err_irq(IRQn_Type irq_num, uint32_t index)
{
spi_t *obj = spi_data[index].async_obj;
spi_abort_asynch(obj);
spi_data[index].event = SPI_EVENT_ERROR;
if (spi_data[index].wanted_events & SPI_EVENT_ERROR) {
((void (*)())spi_data[index].async_callback)();
}
}
static void spi0_rx_irq(void)
{
spi_rx_irq(RSPISPRI0_IRQn, 0);
}
static void spi1_rx_irq(void)
{
spi_rx_irq(RSPISPRI1_IRQn, 1);
}
static void spi2_rx_irq(void)
{
spi_rx_irq(RSPISPRI2_IRQn, 2);
}
static void spi3_rx_irq(void)
{
spi_rx_irq(RSPISPRI3_IRQn, 3);
}
static void spi4_rx_irq(void)
{
spi_rx_irq(RSPISPRI4_IRQn, 4);
}
static void spi0_er_irq(void)
{
spi_err_irq(RSPISPEI0_IRQn, 0);
}
static void spi1_er_irq(void)
{
spi_err_irq(RSPISPEI1_IRQn, 1);
}
static void spi2_er_irq(void)
{
spi_err_irq(RSPISPEI2_IRQn, 2);
}
static void spi3_er_irq(void)
{
spi_err_irq(RSPISPEI3_IRQn, 3);
}
static void spi4_er_irq(void)
{
spi_err_irq(RSPISPEI4_IRQn, 4);
}
static void spi_irqs_set(spi_t *obj, uint32_t enable)
{
int i;
const IRQn_Type *irqTable = irq_set_tbl[obj->spi.index];
const IRQHandler *handlerTable = hander_set_tbl[obj->spi.index];
for (i = 0; i < IRQ_NUM; ++i) {
if (enable) {
InterruptHandlerRegister(irqTable[i], handlerTable[i]);
GIC_SetPriority(irqTable[i], 5);
GIC_EnableIRQ(irqTable[i]);
} else {
GIC_DisableIRQ(irqTable[i]);
}
}
if (enable) {
obj->spi.spi->SPCR |= (1 << 4) | (1 << 7);
} else {
obj->spi.spi->SPCR &= ~((1 << 4) | (1 << 7));
}
}
static void spi_async_write(spi_t *obj)
{
uint8_t **width8;
uint16_t **width16;
uint32_t **width32;
if (obj->tx_buff.buffer) {
switch (obj->tx_buff.width) {
case 8:
width8 = (uint8_t **)&obj->tx_buff.buffer;
spi_write(obj, **width8);
++*width8;
obj->tx_buff.pos += sizeof(uint8_t);
break;
case 16:
width16 = (uint16_t **)&obj->tx_buff.buffer;
spi_write(obj, **width16);
++*width16;
obj->tx_buff.pos += sizeof(uint16_t);
break;
case 32:
width32 = (uint32_t **)&obj->tx_buff.buffer;
spi_write(obj, **width32);
++*width32;
obj->tx_buff.pos += sizeof(uint32_t);
break;
default:
MBED_ASSERT(0);
break;
}
} else {
spi_write(obj, SPI_FILL_WORD);
}
}
static void spi_async_read(spi_t *obj)
{
uint8_t **width8;
uint16_t **width16;
uint32_t **width32;
switch (obj->rx_buff.width) {
case 8:
width8 = (uint8_t **)&obj->rx_buff.buffer;
**width8 = spi_read(obj);
++*width8;
obj->rx_buff.pos += sizeof(uint8_t);
break;
case 16:
width16 = (uint16_t **)&obj->rx_buff.buffer;
**width16 = spi_read(obj);
++*width16;
obj->rx_buff.pos += sizeof(uint16_t);
break;
case 32:
width32 = (uint32_t **)&obj->rx_buff.buffer;
**width32 = spi_read(obj);
++*width32;
obj->rx_buff.pos += sizeof(uint32_t);
break;
default:
MBED_ASSERT(0);
break;
}
}
/******************************************************************************
* ASYNCHRONOUS HAL
******************************************************************************/
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)
{
int i;
MBED_ASSERT(obj);
MBED_ASSERT(tx || rx);
MBED_ASSERT(tx && ! rx ? tx_length : 1);
MBED_ASSERT(rx && ! tx ? rx_length : 1);
MBED_ASSERT(obj->spi.spi->SPCR & (1 << 3)); /* Slave mode */
MBED_ASSERT(bit_width == 8 || bit_width == 16 || bit_width == 32);
if (tx_length) {
obj->tx_buff.buffer = (void *)tx;
} else {
obj->tx_buff.buffer = NULL;
}
obj->tx_buff.length = tx_length * bit_width / 8;
obj->tx_buff.pos = 0;
obj->tx_buff.width = bit_width;
if (rx_length) {
obj->rx_buff.buffer = rx;
} else {
obj->rx_buff.buffer = NULL;
}
obj->rx_buff.length = rx_length * bit_width / 8;
obj->rx_buff.pos = 0;
obj->rx_buff.width = bit_width;
for (i = 0; i < obj->rx_buff.length; i++) {
((uint8_t *)obj->rx_buff.buffer)[i] = SPI_FILL_WORD;
}
spi_data[obj->spi.index].async_callback = handler;
spi_data[obj->spi.index].async_obj = obj;
spi_data[obj->spi.index].event = 0;
spi_data[obj->spi.index].wanted_events = event;
spi_irqs_set(obj, 1);
spi_async_write(obj);
}
uint32_t spi_irq_handler_asynch(spi_t *obj)
{
return spi_data[obj->spi.index].event;
}
uint8_t spi_active(spi_t *obj)
{
return spi_data[obj->spi.index].async_obj != NULL;
}
void spi_abort_asynch(spi_t *obj)
{
spi_disable(obj);
spi_irqs_set(obj, 0);
spi_data[obj->spi.index].async_obj = NULL;
spi_enable(obj);
}
#endif

View File

@ -40,6 +40,13 @@
#define TEST_SDA_PIN PD6
#define TEST_SCL_PIN PD7
#elif defined(TARGET_RZ_A1H)
#define TEST_SDA_PIN P1_3
#define TEST_SCL_PIN P1_2
void sleep()
{
}
#else
#error Target not supported
#endif

View File

@ -43,6 +43,10 @@
#define TEST_SERIAL_ONE_TX_PIN D1 // UART2
#define TEST_SERIAL_TWO_RX_PIN D4 // UART5
#elif defined(TARGET_RZ_A1H)
#define TEST_SERIAL_ONE_TX_PIN P8_14 // UART4
#define TEST_SERIAL_TWO_RX_PIN P8_11 // UART5
#else
#error Target not supported

View File

@ -58,6 +58,12 @@
#define TEST_SCLK_PIN PE12
#define TEST_CS_PIN PE13
#elif defined(TARGET_RZ_A1H)
#define TEST_MOSI_PIN P10_14
#define TEST_MISO_PIN P10_15
#define TEST_SCLK_PIN P10_12
#define TEST_CS_PIN P10_13
#else
#error Target not supported
#endif