/* PMU task entry */ void PMU_IndHandler(void) { u8 status; #ifndef DEBUG /* read pmu interrupt status */ I2C_ReadFrom(PMU_I2C_ADDR(OOL0)); status = I2C_GetByte(I2C_LAST); /* clear pmu interrupt */ I2C_WriteTo(PMU_I2C_ADDR(OOL2)); I2C_PutByte(status); #else /* read interrupt status */ status = I2C_ReadFrom(PMU_I2C_ADDR(OOL0)); puthex(PMU_I2C_ADDR(OOL0)); putch(':'); puthex(status); putch(','); status = I2C_GetByte(I2C_LAST); puthex(status); putch('\r'); /* clear pmu interrupt */ status = I2C_WriteTo(PMU_I2C_ADDR(OOL2)); puthex(PMU_I2C_ADDR(OOL2)); putch(':'); puthex(status); putch(','); status = I2C_PutByte(status); puthex(status); putch('\r'); #endif /* send msg to main loop */ Task_Push(MSG_ID_BATT_IND, status, 0); }
/** * @brief I2C read mutiple data * \param[in] instance instance of i2c moudle * \param[in] chipAddr i2c slave addr * \param[in] addr i2c slave register offset * \param[in] addrLen len of slave register addr(in byte) * \param[out] buf data buf * \param[in] len data length * \retval 0 success * \retval 1 failure */ int I2C_BurstRead(uint32_t instance ,uint8_t chipAddr, uint32_t addr, uint32_t addrLen, uint8_t *buf, uint32_t len) { uint8_t *p; uint8_t err; p = (uint8_t*)&addr; err = 0; chipAddr <<= 1; I2C_Start(); I2C_SendByte(chipAddr); err += I2C_WaitAck(); while(addrLen--) { I2C_SendByte(*p++); err += I2C_WaitAck(); } I2C_Start(); I2C_SendByte(chipAddr+1); err += I2C_WaitAck(); while(len--) { *buf++ = I2C_GetByte(); if(len) { I2C_Ack(); } } I2C_NAck(); I2C_Stop(); return err; }
/** * @brief SCCB(protocol,the same as i2c) read single register value * \param[in] instance instance of i2c moudle * \param[in] chipAddr i2c slave addr * \param[in] addr i2c slave register offset * \param[out] data data pointer * @note usually used on i2c sensor devices * \retval 0 success * \retval 1 failure */ int SCCB_ReadSingleRegister(uint32_t instance, uint8_t chipAddr, uint8_t addr, uint8_t* data) { uint8_t err; uint8_t retry; retry = 10; chipAddr <<= 1; while(retry--) { err = 0; I2C_Start(); I2C_SendByte(chipAddr); err += I2C_WaitAck(); I2C_SendByte(addr); err += I2C_WaitAck(); I2C_Stop(); I2C_Start(); I2C_SendByte(chipAddr+1); err += I2C_WaitAck(); *data = I2C_GetByte(); // err += I2C_WaitAck(); I2C_NAck(); I2C_Stop(); if(!err) { break; } } return err; }
/*********************************************************************//** * @brief Transmit and Receive data in master mode * @param[in] I2Cx I2C peripheral selected, should be: * - LPC_I2C0 * - LPC_I2C1 * - LPC_I2C2 * @param[in] TransferCfg Pointer to a I2C_M_SETUP_Type structure that * contains specified information about the * configuration for master transfer. * @param[in] Opt a I2C_TRANSFER_OPT_Type type that selected for * interrupt or polling mode. * @return SUCCESS or ERROR * * Note: * - In case of using I2C to transmit data only, either transmit length set to 0 * or transmit data pointer set to NULL. * - In case of using I2C to receive data only, either receive length set to 0 * or receive data pointer set to NULL. * - In case of using I2C to transmit followed by receive data, transmit length, * transmit data pointer, receive length and receive data pointer should be set * corresponding. **********************************************************************/ Status I2C_MasterTransferData(LPC_I2C_TypeDef *I2Cx, I2C_M_SETUP_Type *TransferCfg, \ I2C_TRANSFER_OPT_Type Opt) { uint8_t *txdat; uint8_t *rxdat; uint32_t CodeStatus; uint8_t tmp; // reset all default state txdat = (uint8_t *) TransferCfg->tx_data; rxdat = (uint8_t *) TransferCfg->rx_data; // Reset I2C setup value to default state TransferCfg->tx_count = 0; TransferCfg->rx_count = 0; TransferCfg->status = 0; if (Opt == I2C_TRANSFER_POLLING){ /* First Start condition -------------------------------------------------------------- */ TransferCfg->retransmissions_count = 0; retry: // reset all default state txdat = (uint8_t *) TransferCfg->tx_data; rxdat = (uint8_t *) TransferCfg->rx_data; // Reset I2C setup value to default state TransferCfg->tx_count = 0; TransferCfg->rx_count = 0; CodeStatus = 0; // Start command CodeStatus = I2C_Start(I2Cx); if ((CodeStatus != I2C_I2STAT_M_TX_START) \ && (CodeStatus != I2C_I2STAT_M_TX_RESTART)){ TransferCfg->retransmissions_count++; if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ // save status TransferCfg->status = CodeStatus; goto error; } else { goto retry; } } /* In case of sending data first --------------------------------------------------- */ if ((TransferCfg->tx_length != 0) && (TransferCfg->tx_data != NULL)){ /* Send slave address + WR direction bit = 0 ----------------------------------- */ CodeStatus = I2C_SendByte(I2Cx, (TransferCfg->sl_addr7bit << 1)); if (CodeStatus != I2C_I2STAT_M_TX_SLAW_ACK){ TransferCfg->retransmissions_count++; if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ // save status TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF; goto error; } else { goto retry; } } /* Send a number of data bytes ---------------------------------------- */ while (TransferCfg->tx_count < TransferCfg->tx_length) { CodeStatus = I2C_SendByte(I2Cx, *txdat); if (CodeStatus != I2C_I2STAT_M_TX_DAT_ACK){ TransferCfg->retransmissions_count++; if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ // save status TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF; goto error; } else { goto retry; } } txdat++; TransferCfg->tx_count++; } } /* Second Start condition (Repeat Start) ------------------------------------------- */ if ((TransferCfg->tx_length != 0) && (TransferCfg->tx_data != NULL) \ && (TransferCfg->rx_length != 0) && (TransferCfg->rx_data != NULL)){ CodeStatus = I2C_Start(I2Cx); if ((CodeStatus != I2C_I2STAT_M_RX_START) \ && (CodeStatus != I2C_I2STAT_M_RX_RESTART)){ TransferCfg->retransmissions_count++; if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ // Update status TransferCfg->status = CodeStatus; goto error; } else { goto retry; } } } /* Then, start reading after sending data -------------------------------------- */ if ((TransferCfg->rx_length != 0) && (TransferCfg->rx_data != NULL)){ /* Send slave address + RD direction bit = 1 ----------------------------------- */ CodeStatus = I2C_SendByte(I2Cx, ((TransferCfg->sl_addr7bit << 1) | 0x01)); if (CodeStatus != I2C_I2STAT_M_RX_SLAR_ACK){ TransferCfg->retransmissions_count++; if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ // update status TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF; goto error; } else { goto retry; } } /* Receive a number of data bytes ------------------------------------------------- */ while (TransferCfg->rx_count < TransferCfg->rx_length){ /* * Note that: if data length is only one, the master should not * issue an ACK signal on bus after reading to avoid of next data frame * on slave side */ if (TransferCfg->rx_count < (TransferCfg->rx_length - 1)){ // Issue an ACK signal for next data frame CodeStatus = I2C_GetByte(I2Cx, &tmp, TRUE); if (CodeStatus != I2C_I2STAT_M_RX_DAT_ACK){ TransferCfg->retransmissions_count++; if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ // update status TransferCfg->status = CodeStatus; goto error; } else { goto retry; } } } else { // Do not issue an ACK signal CodeStatus = I2C_GetByte(I2Cx, &tmp, FALSE); if (CodeStatus != I2C_I2STAT_M_RX_DAT_NACK){ TransferCfg->retransmissions_count++; if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ // update status TransferCfg->status = CodeStatus; goto error; } else { goto retry; } } } *rxdat++ = tmp; TransferCfg->rx_count++; } } /* Send STOP condition ------------------------------------------------- */ I2C_Stop(I2Cx); return SUCCESS; error: // Send stop condition I2C_Stop(I2Cx); return ERROR; } else if (Opt == I2C_TRANSFER_INTERRUPT){ // Setup tx_rx data, callback and interrupt handler tmp = I2C_getNum(I2Cx); i2cdat[tmp].txrx_setup = (uint32_t) TransferCfg; // Set direction phase, write first i2cdat[tmp].dir = 0; /* First Start condition -------------------------------------------------------------- */ I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; I2Cx->I2CONSET = I2C_I2CONSET_STA; I2C_IntCmd(I2Cx, TRUE); return (SUCCESS); } return ERROR; }
/*********************************************************************//** * @brief Handle I2C Master states. * @param[in] I2Cx I2C peripheral selected, should be: * - I2C_0 * - I2C_1 * - I2C_2 * @param[in] CodeStatus I2C state * @param[in] TransferCfg Pointer to a I2C_S_SETUP_Type structure that * contains specified information about the * configuration for master transfer. * @param[in] Opt a I2C_TRANSFER_OPT_Type type that selected for * interrupt or polling mode. * @return It can be * - I2C_OK * -I2C_BYTE_RECV * -I2C_BYTE_SENT * -I2C_SEND_END * -I2C_RECV_END * - I2C_ERR * - I2C_NAK_RECV **********************************************************************/ int32_t I2C_MasterHanleStates(en_I2C_unitId i2cId, uint32_t CodeStatus, I2C_M_SETUP_Type *TransferCfg, I2C_TRANSFER_OPT_Type Opt ) { LPC_I2C_TypeDef* I2Cx = I2C_GetPointer(i2cId); uint8_t *txdat; uint8_t *rxdat; uint8_t tmp; int32_t Ret = I2C_OK; //get buffer to send/receive txdat = (uint8_t *) &TransferCfg->tx_data[TransferCfg->tx_count]; rxdat = (uint8_t *) &TransferCfg->rx_data[TransferCfg->rx_count]; switch(CodeStatus) { case I2C_I2STAT_M_TX_START: case I2C_I2STAT_M_TX_RESTART: //case I2C_I2STAT_M_RX_START: //case I2C_I2STAT_M_RX_RESTART // Send data first if(TransferCfg->tx_count < TransferCfg->tx_length) { /* Send slave address + WR direction bit = 0 ----------------------------------- */ //I2C_SendByte(I2Cx, (TransferCfg->sl_addr7bit << 1));/////////////////////////////// I2C_SendByte(I2Cx, (TransferCfg->sl_addr7bit )); Ret = I2C_BYTE_SENT; } else if (TransferCfg->rx_count < TransferCfg->rx_length) { /* Send slave address + RD direction bit = 1 ----------------------------------- */ //I2C_SendByte(I2Cx, ((TransferCfg->sl_addr7bit << 1) | 0x01));//////////////// I2C_SendByte(I2Cx, (TransferCfg->sl_addr7bit)); Ret = I2C_BYTE_SENT; } // Clear STA bit after the slave address is sent I2Cx->CONCLR = I2C_I2CONCLR_STAC; break; case I2C_I2STAT_M_TX_SLAW_ACK: case I2C_I2STAT_M_TX_DAT_ACK: if(TransferCfg->tx_count < TransferCfg->tx_length) { I2C_SendByte(I2Cx, *txdat); txdat++; TransferCfg->tx_count++; Ret = I2C_BYTE_SENT; } else { if(TransferCfg->rx_count >= TransferCfg->rx_length) { I2C_Stop(I2Cx, Opt); } Ret = I2C_SEND_END; } break; case I2C_I2STAT_M_TX_DAT_NACK: if(TransferCfg->rx_count >= TransferCfg->rx_length) { I2C_Stop(I2Cx, Opt); } Ret = I2C_SEND_END; break; case I2C_I2STAT_M_RX_ARB_LOST: case I2C_I2STAT_S_RX_ARB_LOST_M_GENCALL: case I2C_I2STAT_S_TX_ARB_LOST_M_SLA: //case I2C_I2STAT_M_TX_ARB_LOST: I2C_Stop(I2Cx, Opt); Ret = I2C_ERR; break; case I2C_I2STAT_M_RX_SLAR_ACK: if(TransferCfg->rx_length > 1) I2Cx->CONSET = I2C_I2CONSET_AA; else I2Cx->CONCLR = I2C_I2CONCLR_AAC; I2Cx->CONCLR = I2C_I2CONCLR_SIC; Ret = I2C_BYTE_RECV; break; case I2C_I2STAT_M_RX_DAT_ACK: if (TransferCfg->rx_count <TransferCfg->rx_length) { if ((TransferCfg->rx_length > 1) && (TransferCfg->rx_count < (TransferCfg->rx_length - 2))) { I2C_GetByte(I2Cx, &tmp, TRUE); Ret = I2C_BYTE_RECV; } else // the next byte is the last byte, send NACK instead. { I2C_GetByte(I2Cx, &tmp, FALSE); Ret = I2C_BYTE_RECV; } *rxdat++ = tmp; TransferCfg->rx_count++; } else { I2C_Stop(I2Cx, Opt); Ret = I2C_RECV_END; } break; case I2C_I2STAT_M_RX_DAT_NACK: I2C_GetByte(I2Cx, &tmp, FALSE); if (TransferCfg->rx_count < TransferCfg->rx_length) { *rxdat++ = tmp; TransferCfg->rx_count++; } I2C_Stop(I2Cx, Opt); Ret = I2C_RECV_END; break; case I2C_I2STAT_M_RX_SLAR_NACK: case I2C_I2STAT_M_TX_SLAW_NACK: case I2C_I2STAT_BUS_ERROR: // Send STOP condition I2C_Stop(I2Cx, Opt); Ret = I2C_ERR; break; /* No status information */ case I2C_I2STAT_NO_INF: if ((TransferCfg->tx_count <TransferCfg->tx_length)|| (TransferCfg->rx_count <TransferCfg->rx_length)) { I2C_Stop(I2Cx, Opt); Ret = I2C_ERR; } else { Ret = I2C_RECV_END; } break; default: I2Cx->CONCLR = I2C_I2CONCLR_SIC; break; } return Ret; }
/* PMU module initialization */ void PMU_Init(void) { #ifdef DEBUG u8 res; u8 i = 0; #endif TRISA2 = 1; /* config RA2/INT as input */ RABPU = 0; /* PORTA/B pull-up enable */ WPUA2 = 1; /* RA2 weak pull-up enable */ INTEDG = 0; /* interrupt on falling edge of INT pin */ INTE = 1; /* RA2/INT external interrupt enable */ GIE = 1; /* enable global interrupt */ #ifndef DEBUG /* config AS7100 interrupt enable bits */ I2C_WriteTo(PMU_I2C_ADDR(OOL1)); I2C_PutByte(PMU_INT_POWON | PMU_INT_POWOFF | PMU_INT_LVDSTATE | PMU_INT_OPTSTATE); /* config AS7100 IRQ mode */ I2C_WriteTo(PMU_I2C_ADDR(OOL3)); I2C_PutByte(PMU_IRQ_MODE_PULSE); /* enable P**N(RESETN) signal output */ I2C_WriteTo(PMU_I2C_ADDR(OOL5)); I2C_PutByte(PMU_PRON_ENABLE); #else /* config AS7100 interrupt enable bits */ res = I2C_WriteTo(PMU_I2C_ADDR(OOL1)); puthex(PMU_I2C_ADDR(OOL1)); putch(':'); puthex(res); putch(','); res = I2C_PutByte(PMU_INT_POWON | PMU_INT_POWOFF | PMU_INT_LVDSTATE | PMU_INT_OPTSTATE); puthex(res); putch('\r'); /* config AS7100 IRQ mode */ res = I2C_WriteTo(PMU_I2C_ADDR(OOL3)); puthex(PMU_I2C_ADDR(OOL3)); putch(':'); puthex(res); putch(','); res = I2C_PutByte(PMU_IRQ_MODE_PULSE); puthex(res); putch('\r'); /* enable P**N(RESETN) signal output */ res = I2C_WriteTo(PMU_I2C_ADDR(OOL5)); puthex(PMU_I2C_ADDR(OOL5)); putch(':'); puthex(res); putch(','); res = I2C_PutByte(PMU_PRON_ENABLE); puthex(res); putch('\r'); #endif #ifdef DEBUG /* read all register */ for (i = 0; i < 0x10; i++) { u8 addr = 0x60 | i; res = I2C_ReadFrom(addr); puthex(addr); putch(':'); puthex(res); putch(','); res = I2C_GetByte(I2C_LAST); puthex(res); putch('\r'); } #endif }