Forked.
Fork of mbed-dev by
Diff: targets/TARGET_NUVOTON/TARGET_M451/i2c_api.c
- Revision:
- 153:fa9ff456f731
- Parent:
- 149:156823d33999
- Child:
- 160:d5399cc887bb
diff -r 9a67f0b066fc -r fa9ff456f731 targets/TARGET_NUVOTON/TARGET_M451/i2c_api.c --- a/targets/TARGET_NUVOTON/TARGET_M451/i2c_api.c Thu Dec 15 11:48:27 2016 +0000 +++ b/targets/TARGET_NUVOTON/TARGET_M451/i2c_api.c Tue Dec 20 17:27:56 2016 +0000 @@ -48,6 +48,7 @@ static void i2c1_vec(void); static void i2c_irq(i2c_t *obj); static void i2c_fsm_reset(i2c_t *obj, uint32_t i2c_ctl); +static void i2c_fsm_tranfini(i2c_t *obj, int lastdatanaked); static struct nu_i2c_var i2c0_var = { .obj = NULL, @@ -68,8 +69,6 @@ }; static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastdata); -static int i2c_do_write(i2c_t *obj, char data, int naklastdata); -static int i2c_do_read(i2c_t *obj, char *data, int naklastdata); static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync); #define NU_I2C_TIMEOUT_STAT_INT 500000 #define NU_I2C_TIMEOUT_STOP 500000 @@ -97,6 +96,7 @@ #define TRANCTRL_STARTED (1) #define TRANCTRL_NAKLASTDATA (1 << 1) +#define TRANCTRL_LASTDATANAKED (1 << 2) uint32_t us_ticker_read(void); @@ -168,7 +168,7 @@ return I2C_ERROR_BUS_BUSY; } - if (i2c_do_write(obj, i2c_addr2data(address, 1), 0)) { + if (i2c_byte_write(obj, i2c_addr2data(address, 1)) != 1) { i2c_stop(obj); return I2C_ERROR_NO_SLAVE; } @@ -191,7 +191,7 @@ return I2C_ERROR_BUS_BUSY; } - if (i2c_do_write(obj, i2c_addr2data(address, 0), 0)) { + if (i2c_byte_write(obj, i2c_addr2data(address, 0)) != 1) { i2c_stop(obj); return I2C_ERROR_NO_SLAVE; } @@ -214,14 +214,22 @@ int i2c_byte_read(i2c_t *obj, int last) { char data = 0; - - i2c_do_read(obj, &data, last); + i2c_do_tran(obj, &data, 1, 1, last); return data; } int i2c_byte_write(i2c_t *obj, int data) { - return i2c_do_write(obj, (data & 0xFF), 0); + char data_[1]; + data_[0] = data & 0xFF; + + if (i2c_do_tran(obj, data_, 1, 0, 0) == 1 && + ! (obj->i2c.tran_ctrl & TRANCTRL_LASTDATANAKED)) { + return 1; + } + else { + return 0; + } } #if DEVICE_I2CSLAVE @@ -352,6 +360,10 @@ static int i2c_do_tran(i2c_t *obj, char *buf, int length, int read, int naklastdata) { + if (! buf || ! length) { + return 0; + } + int tran_len = 0; i2c_disable_int(obj); @@ -369,7 +381,6 @@ } else { i2c_disable_int(obj); - obj->i2c.tran_ctrl = 0; tran_len = obj->i2c.tran_pos - obj->i2c.tran_beg; obj->i2c.tran_beg = NULL; obj->i2c.tran_pos = NULL; @@ -380,18 +391,6 @@ return tran_len; } -static int i2c_do_write(i2c_t *obj, char data, int naklastdata) -{ - char data_[1]; - data_[0] = data; - return i2c_do_tran(obj, data_, 1, 0, naklastdata) == 1 ? 0 : I2C_ERROR_BUS_BUSY; -} - -static int i2c_do_read(i2c_t *obj, char *data, int naklastdata) -{ - return i2c_do_tran(obj, data, 1, 1, naklastdata) == 1 ? 0 : I2C_ERROR_BUS_BUSY; -} - static int i2c_do_trsn(i2c_t *obj, uint32_t i2c_ctl, int sync) { I2C_T *i2c_base = (I2C_T *) NU_MODBASE(obj->i2c.i2c); @@ -611,32 +610,30 @@ I2C_SET_CONTROL_REG(i2c_base, I2C_CTL_SI_Msk | I2C_CTL_AA_Msk); } else { - if (status == 0x18) { - obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; - i2c_disable_int(obj); - break; - } - // Go Master Repeat Start - i2c_fsm_reset(obj, I2C_CTL_STA_Msk | I2C_CTL_SI_Msk); + i2c_fsm_tranfini(obj, 0); } } else { i2c_disable_int(obj); } break; + case 0x30: // Master Transmit Data NACK + i2c_fsm_tranfini(obj, 1); + break; + case 0x20: // Master Transmit Address NACK - // Go Master Repeat Start - i2c_fsm_reset(obj, I2C_CTL_STA_Msk | I2C_CTL_SI_Msk); + i2c_fsm_tranfini(obj, 1); break; + case 0x38: // Master Arbitration Lost i2c_fsm_reset(obj, I2C_CTL_SI_Msk | I2C_CTL_AA_Msk); break; case 0x48: // Master Receive Address NACK - // Go Master Repeat Start - i2c_fsm_reset(obj, I2C_CTL_STA_Msk | I2C_CTL_SI_Msk); + i2c_fsm_tranfini(obj, 1); break; + case 0x40: // Master Receive Address ACK case 0x50: // Master Receive Data ACK case 0x58: // Master Receive Data NACK @@ -653,8 +650,7 @@ while (1); } #endif - // Go Master Repeat Start - i2c_fsm_reset(obj, I2C_CTL_STA_Msk | I2C_CTL_SI_Msk); + i2c_fsm_tranfini(obj, 1); } else { uint32_t i2c_ctl = I2C_CTL_SI_Msk | I2C_CTL_AA_Msk; @@ -821,6 +817,16 @@ obj->i2c.slaveaddr_state = NoData; } +static void i2c_fsm_tranfini(i2c_t *obj, int lastdatanaked) +{ + if (lastdatanaked) { + obj->i2c.tran_ctrl |= TRANCTRL_LASTDATANAKED; + } + + obj->i2c.tran_ctrl &= ~TRANCTRL_STARTED; + i2c_disable_int(obj); +} + #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)