Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
Diff: targets/TARGET_NUVOTON/TARGET_NUC472/i2c_api.c
- Revision:
- 153:fa9ff456f731
- Parent:
- 149:156823d33999
- Child:
- 160:d5399cc887bb
diff -r 9a67f0b066fc -r fa9ff456f731 targets/TARGET_NUVOTON/TARGET_NUC472/i2c_api.c --- a/targets/TARGET_NUVOTON/TARGET_NUC472/i2c_api.c Thu Dec 15 11:48:27 2016 +0000 +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/i2c_api.c Tue Dec 20 17:27:56 2016 +0000 @@ -51,6 +51,7 @@ static void i2c4_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, @@ -86,8 +87,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 @@ -114,6 +113,7 @@ #define TRANCTRL_STARTED (1) #define TRANCTRL_NAKLASTDATA (1 << 1) +#define TRANCTRL_LASTDATANAKED (1 << 2) uint32_t us_ticker_read(void); @@ -185,7 +185,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; } @@ -208,7 +208,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; } @@ -231,14 +231,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 @@ -369,6 +377,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); @@ -386,7 +398,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; @@ -397,18 +408,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); @@ -641,33 +640,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 Stop. - // 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 @@ -684,8 +680,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; @@ -852,6 +847,15 @@ 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