diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index ebe57772..7eef4672 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -84,7 +84,24 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { } void unstick_I2C() { - // TODO + /* configure SDA/SCL for GPIO */ + GPIO_BC(GPIOB) |= SDA_Pin|SCL_Pin; + gpio_init(SDA_GPIO_Port,GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); + asm ("nop"); + asm ("nop"); + asm ("nop"); + asm ("nop"); + asm ("nop"); + GPIO_BOP(GPIOB) |= SCL_Pin; + asm ("nop"); + asm ("nop"); + asm ("nop"); + asm ("nop"); + asm ("nop"); + GPIO_BOP(GPIOB) |= SDA_Pin; + /* connect PB6 to I2C0_SCL */ + /* connect PB7 to I2C0_SDA */ + gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); } uint8_t getButtonA() { diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index 8834944b..57cd78c2 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -6,233 +6,15 @@ */ #include "BSP.h" #include "Setup.h" +#include "IRQ.h" #include SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; #define FLAG_TIMEOUT 1000 - void FRToSI2C::CpltCallback() { //TODO } -/** Send START command - * - * @param obj The I2C object - */ -int i2c_start() { - int timeout; - - /* clear I2C_FLAG_AERR Flag */ - i2c_flag_clear(I2C0, I2C_FLAG_AERR); - - /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { - if ((timeout--) == 0) { - - return (int) -1; - } - } - - /* ensure the i2c has been stopped */ - timeout = FLAG_TIMEOUT; - while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) == I2C_CTL0_STOP) { - if ((timeout--) == 0) { - return (int) -1; - } - } - - /* generate a START condition */ - i2c_start_on_bus(I2C0); - - /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { - return (int) -1; - } - } - - return (int) 0; -} - -/** Send STOP command - * - * @param obj The I2C object - */ -int i2c_stop() { - - /* generate a STOP condition */ - i2c_stop_on_bus(I2C0); - - /* wait for STOP bit reset */ - int timeout = FLAG_TIMEOUT; - while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP)) { - if ((timeout--) == 0) { - return -1; - } - } - - return 0; -} - -/** Read one byte - * - * @param obj The I2C object - * @param last Acknoledge - * @return The read byte - */ -int i2c_byte_read(int last) { - int timeout; - - if (last) { - /* disable acknowledge */ - i2c_ack_config(I2C0, I2C_ACK_DISABLE); - } else { - /* enable acknowledge */ - i2c_ack_config(I2C0, I2C_ACK_ENABLE); - } - - /* wait until the byte is received */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_RBNE)) == RESET) { - if ((timeout--) == 0) { - return -1; - } - } - - return (int) i2c_data_receive(I2C0); -} - -/** Write one byte - * - * @param obj The I2C object - * @param data Byte to be written - * @return 0 if NAK was received, 1 if ACK was received, 2 for timeout. - */ -int i2c_byte_write(int data) { - int timeout; - i2c_data_transmit(I2C0, data); - - /* wait until the byte is transmitted */ - timeout = FLAG_TIMEOUT; - while (((i2c_flag_get(I2C0, I2C_FLAG_TBE)) == RESET) || ((i2c_flag_get(I2C0, I2C_FLAG_BTC)) == RESET)) { - if ((timeout--) == 0) { - return 2; - } - } - - return 1; -} - -bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { - if (!lock()) - return false; - - uint32_t count = 0; - int timeout = 0; - - /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } else { - if (timeout % 5 == 0) { - i2c_stop(); - } - } - } - /* generate a START condition */ - i2c_start_on_bus(I2C0); - - /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } - } - - /* send slave address */ - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - - timeout = 0; - /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { - timeout++; - if (timeout > 100000) { - i2c_stop(); - unlock(); - return false; - } - } - bool no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR); - no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR); - if (no_ack) { - i2c_stop(); - unlock(); - return false; - } - /* clear ADDSEND */ - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - int status = i2c_byte_write(MemAddress); - no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR); - no_ack |= i2c_flag_get(I2C0, I2C_FLAG_LOSTARB); - if (status == 2 || no_ack) { - i2c_stop(); - unlock(); - return false; - } -//////////////////////////// //Restart into read - - /* generate a START condition */ - i2c_start_on_bus(I2C0); - - /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } - } - - /* send slave address */ - i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER); - - timeout = 0; - /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { - timeout++; - if (timeout > 100000) { - i2c_stop(); - unlock(); - return false; - } - } - - /* clear ADDSEND */ - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR); - if (no_ack) { - i2c_stop(); - unlock(); - return false; - } - for (count = 0; count < Size; count++) { - pData[count] = i2c_byte_read(count == (Size - 1)); - } - //Have nacked last data, so have to generate the stop sequence - i2c_stop(); - unlock(); - return true; -} bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { return Mem_Write(address, reg, &data, 1); } @@ -242,140 +24,114 @@ uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { Mem_Read(add, reg, &temp, 1); return temp; } -bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { + +bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t read_address, uint8_t *p_buffer, uint16_t number_of_byte) { + if (!lock()) + return false; + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR); + /* wait until I2C bus is idle */ + uint8_t timeout = 0; + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) { + timeout++; + osDelay(1); + if (timeout > 20) { + unlock(); + return false; + } + } + i2c_slave_address = DevAddress; + i2c_read = p_buffer; + i2c_read_dress = read_address; + i2c_nbytes = number_of_byte; + i2c_error_code = 0; + i2c_process_flag = 1; + i2c_write_process = I2C_SEND_ADDRESS_FIRST; + i2c_read_process = I2C_SEND_ADDRESS_FIRST; + +// if (2 == number_of_byte) { +// i2c_ackpos_config(I2C0, I2C_ACKPOS_NEXT); +// } + /* enable the I2C0 interrupt */ + i2c_interrupt_enable(I2C0, I2C_INT_ERR); + i2c_interrupt_enable(I2C0, I2C_INT_EV); + i2c_interrupt_enable(I2C0, I2C_INT_BUF); + /* send a start condition to I2C bus */ + i2c_start_on_bus(I2C0); + while ((i2c_nbytes > 0)) { + osDelay(1); + if (i2c_error_code != 0) { + unlock(); + return false; + } + } + unlock(); + return true; +} + +bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *p_buffer, uint16_t number_of_byte) { if (!lock()) return false; - uint32_t count = 0; - int timeout = 0; - - /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } else { - if (timeout % 5 == 0) { - i2c_stop(); - } - } - } - /* generate a START condition */ - i2c_start_on_bus(I2C0); - - /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } - } - - /* send slave address */ - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - - timeout = 0; - /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { + i2c_slave_address = DevAddress; + i2c_write = p_buffer; + i2c_write_dress = MemAddress; + i2c_nbytes = number_of_byte; + i2c_error_code = 0; + i2c_process_flag = 0; + i2c_write_process = I2C_SEND_ADDRESS_FIRST; + i2c_read_process = I2C_SEND_ADDRESS_FIRST; + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR); + /* enable the I2C0 interrupt */ + i2c_interrupt_enable(I2C0, I2C_INT_ERR); + i2c_interrupt_enable(I2C0, I2C_INT_EV); + i2c_interrupt_enable(I2C0, I2C_INT_BUF); + /* wait until I2C bus is idle */ + uint8_t timeout = 0; + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) { timeout++; - if (timeout > 100000) { - i2c_stop(); + osDelay(1); + if (timeout > 20) { unlock(); return false; } } - /* clear ADDSEND */ - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - int status = i2c_byte_write(MemAddress); - for (count = 0; count < Size; count++) { - status = i2c_byte_write(pData[count]); - if (status != 1) { - i2c_stop(); + /* send a start condition to I2C bus */ + //This sending will kickoff the IRQ's + i2c_start_on_bus(I2C0); + while ((i2c_nbytes > 0)) { + osDelay(1); + if (i2c_error_code != 0) { unlock(); return false; } } - - /* if not sequential write, then send stop */ - - i2c_stop(); unlock(); return true; } bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { - if (!lock()) - return false; - uint32_t count = 0; - int timeout = 0; - - /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } else { - if (timeout % 5 == 0) { - i2c_stop(); - } - } - } - /* generate a START condition */ - i2c_start_on_bus(I2C0); - - /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } - } - - /* send slave address */ - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - - timeout = 0; - /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { - timeout++; - if (timeout > 100000) { - i2c_stop(); - unlock(); - return false; - } - } - - /* clear ADDSEND */ - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - - for (count = 0; count < Size; count++) { - int status = i2c_byte_write(pData[count]); - if (status != 1) { - i2c_stop(); - unlock(); - return false; - } - } - - /* if not sequential write, then send stop */ - - i2c_stop(); - unlock(); - return true; + return Mem_Write(DevAddress, pData[0], pData + 1, Size - 1); } bool FRToSI2C::probe(uint16_t DevAddress) { - uint8_t temp = 0; - return Mem_Read(DevAddress, 0x00, &temp, 1); + uint8_t temp[1]; + return Mem_Read(DevAddress, 0x00, temp, sizeof(temp)); } void FRToSI2C::I2C_Unstick() { @@ -384,15 +140,12 @@ void FRToSI2C::I2C_Unstick() { bool FRToSI2C::lock() { if (I2CSemaphore == nullptr) { - for (;;) { // - } + return false; } return xSemaphoreTake(I2CSemaphore,1000) == pdTRUE; } void FRToSI2C::unlock() { - if (I2CSemaphore == nullptr) - return; xSemaphoreGive(I2CSemaphore); } diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp index 380f51e6..60ef5f8b 100644 --- a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp @@ -8,6 +8,16 @@ #include "IRQ.h" #include "Pins.h" #include "int_n.h" +volatile uint8_t i2c_read_process = 0; +volatile uint8_t i2c_write_process = 0; +volatile uint8_t i2c_slave_address = 0; +volatile uint8_t i2c_error_code = 0; +volatile uint8_t* i2c_write; +volatile uint8_t* i2c_read; +volatile uint16_t i2c_nbytes; +volatile uint16_t i2c_write_dress; +volatile uint16_t i2c_read_dress; +volatile uint8_t i2c_process_flag = 0; void ADC0_1_IRQHandler(void) { adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); @@ -39,8 +49,7 @@ void TIMER1_IRQHandler(void) { timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0); if (pendingPWM) { - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, - pendingPWM); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, pendingPWM); } } } @@ -53,16 +62,221 @@ void setTipPWM(uint8_t pulse) { pendingPWM = pulse; } - -void EXTI5_9_IRQHandler(void) -{ +void EXTI5_9_IRQHandler(void) { #ifdef POW_PD - if (RESET != exti_interrupt_flag_get(EXTI_5)){ - exti_interrupt_flag_clear(EXTI_5); + if (RESET != exti_interrupt_flag_get(EXTI_5)) { + exti_interrupt_flag_clear(EXTI_5); - if(RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin)){ - InterruptHandler::irqCallback(); - } - } + if (RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin)) { + InterruptHandler::irqCallback(); + } + } #endif } + +/*! + \brief handle I2C0 event interrupt request + \param[in] none + \param[out] none + \retval none + */ +void I2C0_EV_IRQHandler(void) { + if (RESET == i2c_process_flag) { + switch (i2c_write_process) { + case I2C_SEND_ADDRESS_FIRST: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) { + /* send slave address */ + i2c_master_addressing(I2C0, i2c_slave_address, I2C_TRANSMITTER); + i2c_write_process = I2C_CLEAR_ADDRESS_FLAG_FIRST; + } + break; + case I2C_CLEAR_ADDRESS_FLAG_FIRST: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) { + /*clear ADDSEND bit */ + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND); + i2c_write_process = I2C_TRANSMIT_WRITE_READ_ADD; + } + break; + case I2C_TRANSMIT_WRITE_READ_ADD: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { + i2c_data_transmit(I2C0, i2c_write_dress); + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) + ; + i2c_write_process = I2C_TRANSMIT_DATA; + } + break; + case I2C_TRANSMIT_DATA: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { + /* the master sends a data byte */ + i2c_data_transmit(I2C0, *i2c_write++); + i2c_nbytes--; + if (RESET == i2c_nbytes) { + i2c_write_process = I2C_STOP; + } + } + break; + case I2C_STOP: + /* the master sends a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* disable the I2C0 interrupt */ + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_write_process = I2C_SEND_ADDRESS_FIRST; + break; + default: + break; + } + } else if (SET == i2c_process_flag) { + switch (i2c_read_process) { + case I2C_SEND_ADDRESS_FIRST: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) { + /* send slave address */ + i2c_master_addressing(I2C0, i2c_slave_address, I2C_TRANSMITTER); + i2c_read_process = I2C_CLEAR_ADDRESS_FLAG_FIRST; + } + break; + case I2C_CLEAR_ADDRESS_FLAG_FIRST: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) { + /*clear ADDSEND bit */ + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND); + i2c_read_process = I2C_TRANSMIT_WRITE_READ_ADD; + } + break; + case I2C_TRANSMIT_WRITE_READ_ADD: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { + i2c_data_transmit(I2C0, i2c_read_dress); + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) + ; + /* send a start condition to I2C bus */ + i2c_start_on_bus(I2C0); + i2c_read_process = I2C_SEND_ADDRESS_SECOND; + } + break; + case I2C_SEND_ADDRESS_SECOND: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) { + i2c_master_addressing(I2C0, i2c_slave_address, I2C_RECEIVER); + if ((1 == i2c_nbytes) || (2 == i2c_nbytes)) { + i2c_ackpos_config(I2C0, i2c_nbytes == 1 ? I2C_ACKPOS_CURRENT : I2C_ACKPOS_NEXT); + /* clear the ACKEN before the ADDSEND is cleared */ + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + } else { + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + + } + i2c_read_process = I2C_CLEAR_ADDRESS_FLAG_SECOND; + } + break; + case I2C_CLEAR_ADDRESS_FLAG_SECOND: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) { + + /*clear ADDSEND bit */ + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND); + i2c_read_process = I2C_TRANSMIT_DATA; + + } + break; + case I2C_TRANSMIT_DATA: + if (i2c_nbytes > 0) { + /* read a byte from the EEPROM */ + if (i2c_nbytes == 2) { + /* wait until BTC bit is set */ + i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT); + /* clear the ACKEN before the ADDSEND is cleared */ + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + } + *i2c_read = i2c_data_receive(I2C0); + i2c_read++; + i2c_nbytes--; + if (i2c_nbytes == 0) { + /* the master sends a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* disable the I2C0 interrupt */ + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_process_flag = RESET; + i2c_read_process = I2C_DONE; + } + } else { + i2c_read_process = I2C_STOP; + /* the master sends a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* disable the I2C0 interrupt */ + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_process_flag = RESET; + i2c_read_process = I2C_DONE; + } + break; + case I2C_STOP: + /* the master sends a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* disable the I2C0 interrupt */ + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_process_flag = RESET; + i2c_read_process = I2C_DONE; + break; + default: + break; + } + } +} + +/*! + \brief handle I2C0 error interrupt request + \param[in] none + \param[out] none + \retval none + */ +void I2C0_ER_IRQHandler(void) { + /* no acknowledge received */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR); + i2c_error_code = 1; //NAK + } + + /* SMBus alert */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBALT)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT); + i2c_error_code = 2; //SMB Alert + } + + /* bus timeout in SMBus mode */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBTO)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO); + i2c_error_code = 3; //SMB Timeout + } + + /* over-run or under-run when SCL stretch is disabled */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_OUERR)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR); + i2c_error_code = 4; //OverRun + } + + /* arbitration lost */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_LOSTARB)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB); + i2c_error_code = 5; //Lost ARB -- multi master -- shouldnt happen + } + + /* bus error */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_BERR)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR); + i2c_error_code = 6; //Bus Error + } + + /* CRC value doesn't match */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_PECERR)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR); + i2c_error_code = 7; //CRC Fail -- Shouldnt Happen + } + + i2c_stop_on_bus(I2C0); + +} diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.h b/workspace/TS100/Core/BSP/Pine64/IRQ.h index f1490828..354a8d6a 100644 --- a/workspace/TS100/Core/BSP/Pine64/IRQ.h +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.h @@ -20,6 +20,31 @@ extern "C" { void ADC0_1_IRQHandler(void); void TIMER1_IRQHandler(void); void EXTI5_9_IRQHandler(void); +/* handle I2C0 event interrupt request */ +void I2C0_EV_IRQHandler(void); +/* handle I2C0 error interrupt request */ +void I2C0_ER_IRQHandler(void); +typedef enum { + I2C_SEND_ADDRESS_FIRST = 0, //Sending slave address + I2C_CLEAR_ADDRESS_FLAG_FIRST, // Clear address send + I2C_TRANSMIT_WRITE_READ_ADD, //Transmit the memory address to read/write from + I2C_SEND_ADDRESS_SECOND, //Send address again for read + I2C_CLEAR_ADDRESS_FLAG_SECOND, //Clear address again + I2C_TRANSMIT_DATA, //Transmit recieve data + I2C_STOP, //Send stop + I2C_ABORTED, // + I2C_DONE,// I2C transfer is complete +} i2c_process_enum; +extern volatile uint8_t i2c_slave_address; +extern volatile uint8_t i2c_read_process; +extern volatile uint8_t i2c_write_process; +extern volatile uint8_t i2c_error_code; +extern volatile uint8_t* i2c_write; +extern volatile uint8_t* i2c_read; +extern volatile uint16_t i2c_nbytes; +extern volatile uint16_t i2c_write_dress; +extern volatile uint16_t i2c_read_dress; +extern volatile uint8_t i2c_process_flag; #ifdef __cplusplus } #endif diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index d45fd4e7..2abb9142 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -20,6 +20,8 @@ #define POW_QC #define TEMP_TMP36 #define ACCEL_BMA + + #define BATTFILTERDEPTH 32 #endif diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index f202d302..08a2c7d4 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -65,8 +65,7 @@ void setup_gpio() { gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, OLED_RESET_Pin); //I2C as AF Open Drain - gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin); - gpio_init(SCL_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SCL_Pin); + gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); //PWM output as AF Push Pull gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_Out_Pin); @@ -126,11 +125,13 @@ void setup_i2c() { /* enable I2C0 clock */ rcu_periph_clock_enable(RCU_I2C0); //Setup I20 at 400kHz - i2c_clock_config(I2C0, 100 * 1000, I2C_DTCY_16_9); + i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_2); i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); i2c_enable(I2C0); /* enable acknowledge */ i2c_ack_config(I2C0, I2C_ACK_ENABLE); + eclic_irq_enable(I2C0_EV_IRQn,1,0); + eclic_irq_enable(I2C0_ER_IRQn,2,0); } void setup_adc() { diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c deleted file mode 100644 index f48da3d2..00000000 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c +++ /dev/null @@ -1,117 +0,0 @@ -/*! - \file I2C0_IE.c - \brief I2C0 master transmitter interrupt program - - \version 2019-06-05, V1.0.0, firmware for GD32VF103 - -*/ - -/* - Copyright (c) 2019, GigaDevice Semiconductor Inc. - - Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - -#include "gd32vf103_i2c.h" - -#include "I2C_IE.h" - -uint32_t event1; - -/*! - \brief handle I2C0 event interrupt request - \param[in] none - \param[out] none - \retval none -*/ -void I2C0_EventIRQ_Handler(void) { - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) { - /* send slave address */ - i2c_master_addressing(I2C0, I2C1_SLAVE_ADDRESS7, I2C_TRANSMITTER); - } else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) { - /*clear ADDSEND bit */ - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND); - } else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { - if (I2C_nBytes > 0) { - /* the master sends a data byte */ - i2c_data_transmit(I2C0, *i2c_txbuffer++); - I2C_nBytes--; - } else { - /* the master sends a stop condition to I2C bus */ - i2c_stop_on_bus(I2C0); - /* disable the I2C0 interrupt */ - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - } - } -} - -/*! - \brief handle I2C0 error interrupt request - \param[in] none - \param[out] none - \retval none -*/ -void I2C0_ErrorIRQ_Handler(void) { - /* no acknowledge received */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR); - } - - /* SMBus alert */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBALT)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT); - } - - /* bus timeout in SMBus mode */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBTO)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO); - } - - /* over-run or under-run when SCL stretch is disabled */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_OUERR)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR); - } - - /* arbitration lost */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_LOSTARB)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB); - } - - /* bus error */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_BERR)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR); - } - - /* CRC value doesn't match */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_PECERR)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR); - } - - /* disable the error interrupt */ - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - i2c_interrupt_disable(I2C0, I2C_INT_EV); -} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c deleted file mode 100644 index 096d771b..00000000 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c +++ /dev/null @@ -1,112 +0,0 @@ -/*! - \file I2C1_IE.c - \brief I2C1 slave receiver interrupt program - - \version 2019-06-05, V1.0.0, firmware for GD32VF103 - -*/ - -/* - Copyright (c) 2019, GigaDevice Semiconductor Inc. - - Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - -#include "gd32vf103_i2c.h" - -#include "I2C_IE.h" - -uint32_t event2; - -/*! - \brief handle I2C1 event interrupt request - \param[in] none - \param[out] none - \retval none -*/ -void I2C1_EventIRQ_Handler(void) { - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_ADDSEND)) { - /* clear the ADDSEND bit */ - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_ADDSEND); - } else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_RBNE)) { - /* if reception data register is not empty ,I2C1 will read a data from I2C_DATA */ - *i2c_rxbuffer++ = i2c_data_receive(I2C1); - } else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_STPDET)) { - status = SUCCESS; - /* clear the STPDET bit */ - i2c_enable(I2C1); - /* disable I2C1 interrupt */ - i2c_interrupt_disable(I2C1, I2C_INT_ERR); - i2c_interrupt_disable(I2C1, I2C_INT_BUF); - i2c_interrupt_disable(I2C1, I2C_INT_EV); - } -} - -/*! - \brief handle I2C1 error interrupt request - \param[in] none - \param[out] none - \retval none -*/ -void I2C1_ErrorIRQ_Handler(void) { - /* no acknowledge received */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_AERR)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_AERR); - } - - /* SMBus alert */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_SMBALT)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_SMBALT); - } - - /* bus timeout in SMBus mode */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_SMBTO)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_SMBTO); - } - - /* over-run or under-run when SCL stretch is disabled */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_OUERR)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_OUERR); - } - - /* arbitration lost */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_LOSTARB)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_LOSTARB); - } - - /* bus error */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_BERR)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_BERR); - } - - /* CRC value doesn't match */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_PECERR)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_PECERR); - } - - /* disable the error interrupt */ - i2c_interrupt_disable(I2C1, I2C_INT_ERR); - i2c_interrupt_disable(I2C1, I2C_INT_BUF); - i2c_interrupt_disable(I2C1, I2C_INT_EV); -} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h deleted file mode 100644 index 09eb5ea9..00000000 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h +++ /dev/null @@ -1,65 +0,0 @@ -/*! - \file I2C1_IE.c - \brief The header file of I2C0 and I2C1 interrupt - - \version 2019-06-05, V1.0.0, firmware for GD32VF103 - -*/ - -/* - Copyright (c) 2019, GigaDevice Semiconductor Inc. - - Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ -#ifdef __cplusplus -extern "C" { -#endif -#ifndef I2C_IE_H -#define I2C_IE_H - -#include "gd32vf103.h" - -#define I2C0_SLAVE_ADDRESS7 0x82 -#define I2C1_SLAVE_ADDRESS7 0x72 - -extern volatile ErrStatus status; -extern volatile uint8_t *i2c_txbuffer; -extern volatile uint8_t *i2c_rxbuffer; -extern volatile uint16_t I2C_nBytes; - -/* function declarations */ -/* handle I2C0 event interrupt request */ -void I2C0_EventIRQ_Handler(void); -/* handle I2C0 error interrupt request */ -void I2C0_ErrorIRQ_Handler(void); -/* handle I2C1 event interrupt request */ -void I2C1_EventIRQ_Handler(void); -/* handle I2C1 error interrupt request */ -void I2C1_ErrorIRQ_Handler(void); - -#endif /* I2C_IE_H */ - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c index 04cf7be5..6dca26be 100644 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c @@ -1,37 +1,37 @@ /*! - \file gd32vf103_i2c.c - \brief I2C driver + \file gd32vf103_i2c.c + \brief I2C driver - \version 2019-06-05, V1.0.0, firmware for GD32VF103 - \version 2019-09-18, V1.0.1, firmware for GD32VF103 -*/ + \version 2019-06-05, V1.0.0, firmware for GD32VF103 + \version 2019-09-18, V1.0.1, firmware for GD32VF103 + */ /* - Copyright (c) 2019, GigaDevice Semiconductor Inc. + Copyright (c) 2019, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + OF SUCH DAMAGE. + */ #include "gd32vf103_i2c.h" @@ -46,685 +46,655 @@ OF SUCH DAMAGE. #define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */ /*! - \brief reset I2C - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval none + \brief reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none */ -void i2c_deinit(uint32_t i2c_periph) -{ - switch (i2c_periph) { - case I2C0: - /* reset I2C0 */ - rcu_periph_reset_enable(RCU_I2C0RST); - rcu_periph_reset_disable(RCU_I2C0RST); - break; - case I2C1: - /* reset I2C1 */ - rcu_periph_reset_enable(RCU_I2C1RST); - rcu_periph_reset_disable(RCU_I2C1RST); - break; - default: - break; - } +void i2c_deinit(uint32_t i2c_periph) { + switch (i2c_periph) { + case I2C0: + /* reset I2C0 */ + rcu_periph_reset_enable(RCU_I2C0RST); + rcu_periph_reset_disable(RCU_I2C0RST); + break; + case I2C1: + /* reset I2C1 */ + rcu_periph_reset_enable(RCU_I2C1RST); + rcu_periph_reset_disable(RCU_I2C1RST); + break; + default: + break; + } } /*! - \brief configure I2C clock - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) - and fast mode plus (up to 1MHz) - \param[in] dutycyc: duty cycle in fast mode or fast mode plus - only one parameter can be selected which is shown as below: - \arg I2C_DTCY_2: T_low/T_high=2 - \arg I2C_DTCY_16_9: T_low/T_high=16/9 - \param[out] none - \retval none + \brief configure I2C clock + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) + and fast mode plus (up to 1MHz) + \param[in] dutycyc: duty cycle in fast mode or fast mode plus + only one parameter can be selected which is shown as below: + \arg I2C_DTCY_2: T_low/T_high=2 + \arg I2C_DTCY_16_9: T_low/T_high=16/9 + \param[out] none + \retval none */ -void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc) -{ - uint32_t pclk1, clkc, freq, risetime; - uint32_t temp; - - pclk1 = rcu_clock_freq_get(CK_APB1); - /* I2C peripheral clock frequency */ - freq = (uint32_t) (pclk1 / 1000000U); - if (freq >= I2CCLK_MAX) { - freq = I2CCLK_MAX; - } - temp = I2C_CTL1(i2c_periph); - temp &= ~I2C_CTL1_I2CCLK; - temp |= freq; - - I2C_CTL1(i2c_periph) = temp; - - if (100000U >= clkspeed) { - /* the maximum SCL rise time is 1000ns in standard mode */ - risetime = (uint32_t) ((pclk1 / 1000000U) + 1U); - if (risetime >= I2CCLK_MAX) { - I2C_RT(i2c_periph) = I2CCLK_MAX; - } else if (risetime <= I2CCLK_MIN) { - I2C_RT(i2c_periph) = I2CCLK_MIN; - } else { - I2C_RT(i2c_periph) = risetime; - } - clkc = (uint32_t) (pclk1 / (clkspeed * 2U)); - if (clkc < 0x04U) { - /* the CLKC in standard mode minmum value is 4 */ - clkc = 0x04U; - } - I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc) { + uint32_t pclk1, clkc, freq, risetime; + uint32_t temp; - } else if (400000U >= clkspeed) { - /* the maximum SCL rise time is 300ns in fast mode */ - I2C_RT(i2c_periph) = (uint32_t) (((freq * (uint32_t) 300U)/(uint32_t)1000U)+(uint32_t)1U); - if (I2C_DTCY_2 == dutycyc){ - /* I2C duty cycle is 2 */ - clkc = (uint32_t) (pclk1 / (clkspeed * 3U)); - I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; - } else { - /* I2C duty cycle is 16/9 */ - clkc = (uint32_t) (pclk1 / (clkspeed * 25U)); - I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; - } - if (0U == (clkc & I2C_CKCFG_CLKC)) { - /* the CLKC in fast mode minmum value is 1 */ - clkc |= 0x0001U; - } - I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; - I2C_CKCFG(i2c_periph) |= clkc; - } else { - /* fast mode plus, the maximum SCL rise time is 120ns */ - I2C_RT (i2c_periph) = (uint32_t) (((freq * (uint32_t) 120U) / (uint32_t) 1000U)+(uint32_t) 1U); - if (I2C_DTCY_2 == dutycyc) { - /* I2C duty cycle is 2 */ - clkc = (uint32_t) (pclk1 / (clkspeed * 3U)); - I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; - } else { - /* I2C duty cycle is 16/9 */ - clkc = (uint32_t) (pclk1 / (clkspeed * 25U)); - I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; - } - /* enable fast mode */ - I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; - I2C_CKCFG(i2c_periph) |= clkc; - /* enable I2C fast mode plus */ - I2C_FMPCFG(i2c_periph) |= I2C_FMPCFG_FMPEN; - } + pclk1 = rcu_clock_freq_get(CK_APB1); + /* I2C peripheral clock frequency */ + freq = (uint32_t) (pclk1 / 1000000U); + if (freq >= I2CCLK_MAX) { + freq = I2CCLK_MAX; + } + temp = I2C_CTL1(i2c_periph); + temp &= ~I2C_CTL1_I2CCLK; + temp |= freq; + + I2C_CTL1(i2c_periph) = temp; + + if (100000U >= clkspeed) { + /* the maximum SCL rise time is 1000ns in standard mode */ + risetime = (uint32_t) ((pclk1 / 1000000U) + 1U); + if (risetime >= I2CCLK_MAX) { + I2C_RT(i2c_periph) = I2CCLK_MAX; + } else if (risetime <= I2CCLK_MIN) { + I2C_RT(i2c_periph) = I2CCLK_MIN; + } else { + I2C_RT(i2c_periph) = risetime; + } + clkc = (uint32_t) (pclk1 / (clkspeed * 2U)); + if (clkc < 0x04U) { + /* the CLKC in standard mode minmum value is 4 */ + clkc = 0x04U; + } + I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); + + } else if (400000U >= clkspeed) { + /* the maximum SCL rise time is 300ns in fast mode */ + I2C_RT(i2c_periph) = (uint32_t) (((freq * (uint32_t) 300U) / (uint32_t) 1000U) + (uint32_t) 1U); + if (I2C_DTCY_2 == dutycyc) { + /* I2C duty cycle is 2 */ + clkc = (uint32_t) (pclk1 / (clkspeed * 3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + } else { + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t) (pclk1 / (clkspeed * 25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + if (0U == (clkc & I2C_CKCFG_CLKC)) { + /* the CLKC in fast mode minmum value is 1 */ + clkc |= 0x0001U; + } + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + } else { + /* fast mode plus, the maximum SCL rise time is 120ns */ + I2C_RT (i2c_periph) = (uint32_t) (((freq * (uint32_t) 120U) / (uint32_t) 1000U) + (uint32_t) 1U); + if (I2C_DTCY_2 == dutycyc) { + /* I2C duty cycle is 2 */ + clkc = (uint32_t) (pclk1 / (clkspeed * 3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + } else { + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t) (pclk1 / (clkspeed * 25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + /* enable fast mode */ + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + /* enable I2C fast mode plus */ + I2C_FMPCFG(i2c_periph) |= I2C_FMPCFG_FMPEN; + } } /*! - \brief configure I2C address - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] mode: - only one parameter can be selected which is shown as below: - \arg I2C_I2CMODE_ENABLE: I2C mode - \arg I2C_SMBUSMODE_ENABLE: SMBus mode - \param[in] addformat: 7bits or 10bits - only one parameter can be selected which is shown as below: - \arg I2C_ADDFORMAT_7BITS: 7bits - \arg I2C_ADDFORMAT_10BITS: 10bits - \param[in] addr: I2C address - \param[out] none - \retval none + \brief configure I2C address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] mode: + only one parameter can be selected which is shown as below: + \arg I2C_I2CMODE_ENABLE: I2C mode + \arg I2C_SMBUSMODE_ENABLE: SMBus mode + \param[in] addformat: 7bits or 10bits + only one parameter can be selected which is shown as below: + \arg I2C_ADDFORMAT_7BITS: 7bits + \arg I2C_ADDFORMAT_10BITS: 10bits + \param[in] addr: I2C address + \param[out] none + \retval none */ -void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode,uint32_t addformat, uint32_t addr) -{ - /* SMBus/I2C mode selected */ - uint32_t ctl = 0U; +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr) { + /* SMBus/I2C mode selected */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_SMBEN); - ctl |= mode; - I2C_CTL0(i2c_periph) = ctl; - /* configure address */ - addr = addr & I2C_ADDRESS_MASK; - I2C_SADDR0(i2c_periph) = (addformat | addr); + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SMBEN); + ctl |= mode; + I2C_CTL0(i2c_periph) = ctl; + /* configure address */ + addr = addr & I2C_ADDRESS_MASK; + I2C_SADDR0(i2c_periph) = (addformat | addr); } /*! - \brief SMBus type selection - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] type: - only one parameter can be selected which is shown as below: - \arg I2C_SMBUS_DEVICE: device - \arg I2C_SMBUS_HOST: host - \param[out] none - \retval none + \brief SMBus type selection + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] type: + only one parameter can be selected which is shown as below: + \arg I2C_SMBUS_DEVICE: device + \arg I2C_SMBUS_HOST: host + \param[out] none + \retval none */ -void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) -{ - if (I2C_SMBUS_HOST == type) { - I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; - } else { - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); - } +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) { + if (I2C_SMBUS_HOST == type) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; + } else { + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); + } } /*! - \brief whether or not to send an ACK - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] ack: - only one parameter can be selected which is shown as below: - \arg I2C_ACK_ENABLE: ACK will be sent - \arg I2C_ACK_DISABLE: ACK will not be sent - \param[out] none - \retval none + \brief whether or not to send an ACK + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] ack: + only one parameter can be selected which is shown as below: + \arg I2C_ACK_ENABLE: ACK will be sent + \arg I2C_ACK_DISABLE: ACK will not be sent + \param[out] none + \retval none */ -void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) -{ - if (I2C_ACK_ENABLE == ack) { - I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; - } else { - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); - } +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) { + if (I2C_ACK_ENABLE == ack) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; + } else { + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); + } } /*! - \brief configure I2C POAP position - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] pos: - only one parameter can be selected which is shown as below: - \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current - \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte - \param[out] none - \retval none + \brief configure I2C POAP position + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pos: + only one parameter can be selected which is shown as below: + \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current + \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte + \param[out] none + \retval none */ -void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) -{ - /* configure I2C POAP position */ - if (I2C_ACKPOS_NEXT == pos) { - I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; - } else { - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); - } +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) { + /* configure I2C POAP position */ + if (I2C_ACKPOS_NEXT == pos) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; + } else { + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); + } } /*! - \brief master sends slave address - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] addr: slave address - \param[in] trandirection: transmitter or receiver - only one parameter can be selected which is shown as below: - \arg I2C_TRANSMITTER: transmitter - \arg I2C_RECEIVER: receiver - \param[out] none - \retval none + \brief master sends slave address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] addr: slave address + \param[in] trandirection: transmitter or receiver + only one parameter can be selected which is shown as below: + \arg I2C_TRANSMITTER: transmitter + \arg I2C_RECEIVER: receiver + \param[out] none + \retval none */ -void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr,uint32_t trandirection) -{ - /* master is a transmitter or a receiver */ - if (I2C_TRANSMITTER == trandirection) { - addr = addr & I2C_TRANSMITTER; - } else { - addr = addr | I2C_RECEIVER; - } - /* send slave address */ - I2C_DATA(i2c_periph) = addr; +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection) { + /* master is a transmitter or a receiver */ + if (I2C_TRANSMITTER == trandirection) { + addr = addr & I2C_TRANSMITTER; + } else { + addr = addr | I2C_RECEIVER; + } + /* send slave address */ + I2C_DATA(i2c_periph) = addr; } /*! - \brief enable dual-address mode - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] addr: the second address in dual-address mode - \param[out] none - \retval none -*/ -void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr) -{ - /* configure address */ - addr = addr & I2C_ADDRESS2_MASK; - I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr); -} - -/*! - \brief disable dual-address mode - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval none -*/ -void i2c_dualaddr_disable(uint32_t i2c_periph) -{ - I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); -} - -/*! - \brief enable I2C - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval none + \brief enable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] addr: the second address in dual-address mode + \param[out] none + \retval none */ -void i2c_enable(uint32_t i2c_periph) -{ - I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN; +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr) { + /* configure address */ + addr = addr & I2C_ADDRESS2_MASK; + I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr); } /*! - \brief disable I2C - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval none + \brief disable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none */ -void i2c_disable(uint32_t i2c_periph) -{ - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); +void i2c_dualaddr_disable(uint32_t i2c_periph) { + I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); } /*! - \brief generate a START condition on I2C bus - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval none + \brief enable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none */ -void i2c_start_on_bus(uint32_t i2c_periph) -{ - I2C_CTL0(i2c_periph) |= I2C_CTL0_START; +void i2c_enable(uint32_t i2c_periph) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN; } /*! - \brief generate a STOP condition on I2C bus - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval none + \brief disable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none */ -void i2c_stop_on_bus(uint32_t i2c_periph) -{ - I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP; +void i2c_disable(uint32_t i2c_periph) { + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); } /*! - \brief I2C transmit data function - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] data: data of transmission - \param[out] none - \retval none + \brief generate a START condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none */ -void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) -{ - I2C_DATA(i2c_periph) = DATA_TRANS(data); +void i2c_start_on_bus(uint32_t i2c_periph) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_START; } /*! - \brief I2C receive data function - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval data of received + \brief generate a STOP condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none */ -uint8_t i2c_data_receive(uint32_t i2c_periph) -{ - return (uint8_t) DATA_RECV(I2C_DATA(i2c_periph)); +void i2c_stop_on_bus(uint32_t i2c_periph) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP; } /*! - \brief enable I2C DMA mode - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] dmastate: - only one parameter can be selected which is shown as below: - \arg I2C_DMA_ON: DMA mode enable - \arg I2C_DMA_OFF: DMA mode disable - \param[out] none - \retval none + \brief I2C transmit data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] data: data of transmission + \param[out] none + \retval none */ -void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) -{ - /* configure I2C DMA function */ - uint32_t ctl = 0U; - - ctl = I2C_CTL1(i2c_periph); - ctl &= ~(I2C_CTL1_DMAON); - ctl |= dmastate; - I2C_CTL1(i2c_periph) = ctl; +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) { + I2C_DATA(i2c_periph) = DATA_TRANS(data); } /*! - \brief configure whether next DMA EOT is DMA last transfer or not - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] dmalast: - only one parameter can be selected which is shown as below: - \arg I2C_DMALST_ON: next DMA EOT is the last transfer - \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer - \param[out] none - \retval none + \brief I2C receive data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval data of received */ -void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) -{ - /* configure DMA last transfer */ - uint32_t ctl = 0U; - - ctl = I2C_CTL1(i2c_periph); - ctl &= ~(I2C_CTL1_DMALST); - ctl |= dmalast; - I2C_CTL1(i2c_periph) = ctl; +uint8_t i2c_data_receive(uint32_t i2c_periph) { + return (uint8_t) DATA_RECV(I2C_DATA(i2c_periph)); } /*! - \brief whether to stretch SCL low when data is not ready in slave mode - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] stretchpara: - only one parameter can be selected which is shown as below: - \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled - \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled - \param[out] none - \retval none + \brief enable I2C DMA mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmastate: + only one parameter can be selected which is shown as below: + \arg I2C_DMA_ON: DMA mode enable + \arg I2C_DMA_OFF: DMA mode disable + \param[out] none + \retval none */ -void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) -{ - /* configure I2C SCL strerching enable or disable */ - uint32_t ctl = 0U; +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) { + /* configure I2C DMA function */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_SS); - ctl |= stretchpara; - I2C_CTL0(i2c_periph) = ctl; + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMAON); + ctl |= dmastate; + I2C_CTL1(i2c_periph) = ctl; } /*! - \brief whether or not to response to a general call - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] gcallpara: - only one parameter can be selected which is shown as below: - \arg I2C_GCEN_ENABLE: slave will response to a general call - \arg I2C_GCEN_DISABLE: slave will not response to a general call - \param[out] none - \retval none + \brief configure whether next DMA EOT is DMA last transfer or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmalast: + only one parameter can be selected which is shown as below: + \arg I2C_DMALST_ON: next DMA EOT is the last transfer + \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer + \param[out] none + \retval none */ -void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) -{ - /* configure slave response to a general call enable or disable */ - uint32_t ctl = 0U; +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) { + /* configure DMA last transfer */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_GCEN); - ctl |= gcallpara; - I2C_CTL0(i2c_periph) = ctl; + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMALST); + ctl |= dmalast; + I2C_CTL1(i2c_periph) = ctl; } /*! - \brief software reset I2C - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] sreset: - only one parameter can be selected which is shown as below: - \arg I2C_SRESET_SET: I2C is under reset - \arg I2C_SRESET_RESET: I2C is not under reset - \param[out] none - \retval none + \brief whether to stretch SCL low when data is not ready in slave mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] stretchpara: + only one parameter can be selected which is shown as below: + \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled + \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled + \param[out] none + \retval none */ -void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) -{ - /* modify CTL0 and configure software reset I2C state */ - uint32_t ctl = 0U; +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) { + /* configure I2C SCL strerching enable or disable */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_SRESET); - ctl |= sreset; - I2C_CTL0(i2c_periph) = ctl; + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SS); + ctl |= stretchpara; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief I2C PEC calculation on or off - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] pecpara: - only one parameter can be selected which is shown as below: - \arg I2C_PEC_ENABLE: PEC calculation on - \arg I2C_PEC_DISABLE: PEC calculation off - \param[out] none - \retval none + \brief whether or not to response to a general call + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] gcallpara: + only one parameter can be selected which is shown as below: + \arg I2C_GCEN_ENABLE: slave will response to a general call + \arg I2C_GCEN_DISABLE: slave will not response to a general call + \param[out] none + \retval none */ -void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate) -{ - /* on/off PEC calculation */ - uint32_t ctl = 0U; +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) { + /* configure slave response to a general call enable or disable */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_PECEN); - ctl |= pecstate; - I2C_CTL0(i2c_periph) = ctl; + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_GCEN); + ctl |= gcallpara; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief I2C whether to transfer PEC value - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] pecpara: - only one parameter can be selected which is shown as below: - \arg I2C_PECTRANS_ENABLE: transfer PEC - \arg I2C_PECTRANS_DISABLE: not transfer PEC - \param[out] none - \retval none + \brief software reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] sreset: + only one parameter can be selected which is shown as below: + \arg I2C_SRESET_SET: I2C is under reset + \arg I2C_SRESET_RESET: I2C is not under reset + \param[out] none + \retval none */ -void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara) -{ - /* whether to transfer PEC */ - uint32_t ctl = 0U; +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) { + /* modify CTL0 and configure software reset I2C state */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_PECTRANS); - ctl |= pecpara; - I2C_CTL0(i2c_periph) = ctl; + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SRESET); + ctl |= sreset; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief get packet error checking value - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval PEC value + \brief I2C PEC calculation on or off + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PEC_ENABLE: PEC calculation on + \arg I2C_PEC_DISABLE: PEC calculation off + \param[out] none + \retval none */ -uint8_t i2c_pec_value_get(uint32_t i2c_periph) -{ - return (uint8_t) ((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV)>> STAT1_PECV_OFFSET); +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate) { + /* on/off PEC calculation */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECEN); + ctl |= pecstate; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief I2C issue alert through SMBA pin - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] smbuspara: - only one parameter can be selected which is shown as below: - \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin - \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin - \param[out] none - \retval none + \brief I2C whether to transfer PEC value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PECTRANS_ENABLE: transfer PEC + \arg I2C_PECTRANS_DISABLE: not transfer PEC + \param[out] none + \retval none */ -void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) -{ - /* issue alert through SMBA pin configure*/ - uint32_t ctl = 0U; +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara) { + /* whether to transfer PEC */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_SALT); - ctl |= smbuspara; - I2C_CTL0(i2c_periph) = ctl; + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECTRANS); + ctl |= pecpara; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief enable or disable I2C ARP protocol in SMBus switch - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] arpstate: - only one parameter can be selected which is shown as below: - \arg I2C_ARP_ENABLE: enable ARP - \arg I2C_ARP_DISABLE: disable ARP - \param[out] none - \retval none + \brief get packet error checking value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval PEC value */ -void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate) -{ - /* enable or disable I2C ARP protocol*/ - uint32_t ctl = 0U; - - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_ARPEN); - ctl |= arpstate; - I2C_CTL0(i2c_periph) = ctl; +uint8_t i2c_pec_value_get(uint32_t i2c_periph) { + return (uint8_t) ((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV) >> STAT1_PECV_OFFSET); } /*! - \brief check I2C flag is set or not - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] flag: I2C flags, refer to i2c_flag_enum - only one parameter can be selected which is shown as below: - \arg I2C_FLAG_SBSEND: start condition send out - \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode - \arg I2C_FLAG_BTC: byte transmission finishes - \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode - \arg I2C_FLAG_STPDET: stop condition detected in slave mode - \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving - \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting - \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus - \arg I2C_FLAG_LOSTARB: arbitration lost in master mode - \arg I2C_FLAG_AERR: acknowledge error - \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode - \arg I2C_FLAG_PECERR: PEC error when receiving data - \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode - \arg I2C_FLAG_SMBALT: SMBus alert status - \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode - \arg I2C_FLAG_I2CBSY: busy flag - \arg I2C_FLAG_TR: whether the I2C is a transmitter or a receiver - \arg I2C_FLAG_RXGC: general call address (00h) received - \arg I2C_FLAG_DEFSMB: default address of SMBus device - \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode - \arg I2C_FLAG_DUMODF: dual flag in slave mode indicating which address is matched in dual-address mode - \param[out] none - \retval FlagStatus: SET or RESET + \brief I2C issue alert through SMBA pin + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] smbuspara: + only one parameter can be selected which is shown as below: + \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin + \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin + \param[out] none + \retval none */ -FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) -{ - if (RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))) { - return SET; - } else { - return RESET; - } +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) { + /* issue alert through SMBA pin configure*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SALT); + ctl |= smbuspara; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief clear I2C flag - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] flag: I2C flags, refer to i2c_flag_enum - only one parameter can be selected which is shown as below: - \arg I2C_FLAG_SMBALT: SMBus Alert status - \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode - \arg I2C_FLAG_PECERR: PEC error when receiving data - \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode - \arg I2C_FLAG_AERR: acknowledge error - \arg I2C_FLAG_LOSTARB: arbitration lost in master mode - \arg I2C_FLAG_BERR: a bus error - \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 - \param[out] none - \retval none + \brief enable or disable I2C ARP protocol in SMBus switch + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] arpstate: + only one parameter can be selected which is shown as below: + \arg I2C_ARP_ENABLE: enable ARP + \arg I2C_ARP_DISABLE: disable ARP + \param[out] none + \retval none */ -void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) -{ - uint32_t temp; - if (I2C_FLAG_ADDSEND == flag) { - /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ - temp = I2C_STAT0(i2c_periph); - temp = I2C_STAT1(i2c_periph); - } else { - I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); - } +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate) { + /* enable or disable I2C ARP protocol*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_ARPEN); + ctl |= arpstate; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief enable I2C interrupt - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum - only one parameter can be selected which is shown as below: - \arg I2C_INT_ERR: error interrupt enable - \arg I2C_INT_EV: event interrupt enable - \arg I2C_INT_BUF: buffer interrupt enable - \param[out] none - \retval none + \brief check I2C flag is set or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SBSEND: start condition send out + \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode + \arg I2C_FLAG_BTC: byte transmission finishes + \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode + \arg I2C_FLAG_STPDET: stop condition detected in slave mode + \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving + \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting + \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_SMBALT: SMBus alert status + \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode + \arg I2C_FLAG_I2CBSY: busy flag + \arg I2C_FLAG_TR: whether the I2C is a transmitter or a receiver + \arg I2C_FLAG_RXGC: general call address (00h) received + \arg I2C_FLAG_DEFSMB: default address of SMBus device + \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode + \arg I2C_FLAG_DUMODF: dual flag in slave mode indicating which address is matched in dual-address mode + \param[out] none + \retval FlagStatus: SET or RESET */ -void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) -{ - I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) { + if (RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))) { + return SET; + } else { + return RESET; + } } /*! - \brief disable I2C interrupt - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum - only one parameter can be selected which is shown as below: - \arg I2C_INT_ERR: error interrupt enable - \arg I2C_INT_EV: event interrupt enable - \arg I2C_INT_BUF: buffer interrupt enable - \param[out] none - \retval none + \brief clear I2C flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SMBALT: SMBus Alert status + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_BERR: a bus error + \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 + \param[out] none + \retval none */ -void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) -{ - I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) { + uint32_t temp; + if (I2C_FLAG_ADDSEND == flag) { + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + temp = I2C_STAT0(i2c_periph); + temp = I2C_STAT1(i2c_periph); + } else { + I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); + } } /*! - \brief check I2C interrupt flag - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag - \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag - \arg I2C_INT_FLAG_BTC: byte transmission finishes - \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag - \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag - \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag - \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag - \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag - \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag - \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag - \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag - \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag - \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag - \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag - \param[out] none - \retval FlagStatus: SET or RESET + \brief enable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none */ -FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag) -{ - uint32_t intenable = 0U, flagstatus = 0U, bufie; - - /* check BUFIE */ - bufie = I2C_CTL1(i2c_periph) & I2C_CTL1_BUFIE; - - /* get the interrupt enable bit status */ - intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); - /* get the corresponding flag bit status */ - flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag)& BIT(I2C_BIT_POS2(int_flag))); - - if ((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)) { - if (intenable && bufie) { - intenable = 1U; - } else { - intenable = 0U; - } - } - if ((0U != flagstatus) && (0U != intenable)) { - return SET; - } else { - return RESET; - } +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) { + I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); } /*! - \brief clear I2C interrupt flag - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag - \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag - \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag - \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag - \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag - \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag - \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag - \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag - \param[out] none - \retval none + \brief disable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none */ -void i2c_interrupt_flag_clear(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag) -{ - uint32_t temp; - if (I2C_INT_FLAG_ADDSEND == int_flag) { - /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ - temp = I2C_STAT0(i2c_periph); - temp = I2C_STAT1(i2c_periph); - } else { - I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); - } +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) { + I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief check I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BTC: byte transmission finishes + \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag + \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag + \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag + \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET + */ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) { + uint32_t intenable = 0U, flagstatus = 0U, bufie; + + /* check BUFIE */ + bufie = I2C_CTL1(i2c_periph) & I2C_CTL1_BUFIE; + + /* get the interrupt enable bit status */ + intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + volatile uint32_t reg = I2C_REG_VAL2(i2c_periph, int_flag); + flagstatus = (reg & BIT(I2C_BIT_POS2(int_flag))); + + if ((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)) { + if (intenable && bufie) { + intenable = 1U; + } else { + intenable = 0U; + } + } + if ((0U != flagstatus) && (0U != intenable)) { + return SET; + } else { + return RESET; + } +} + +/*! + \brief clear I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval none + */ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) { + uint32_t temp; + if (I2C_INT_FLAG_ADDSEND == int_flag) { + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + temp = I2C_STAT0(i2c_periph); + temp = I2C_STAT1(i2c_periph); + } else { + I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); + } } diff --git a/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp index fae5882a..2d1a89b8 100644 --- a/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp @@ -134,12 +134,19 @@ void fusb_send_hardrst() { } void fusb_setup() { - + if (!FRToSI2C::probe(FUSB302B_ADDR)) { + return; + } /* Fully reset the FUSB302B */ fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES); osDelay(2); + uint8_t tries = 0; while (!fusb_read_id()) { osDelay(10); + tries++; + if (tries > 5) { + return; //Welp :( + } } /* Turn on all power */ diff --git a/workspace/TS100/Core/Drivers/BMA223.cpp b/workspace/TS100/Core/Drivers/BMA223.cpp index b15161b3..8abe543f 100644 --- a/workspace/TS100/Core/Drivers/BMA223.cpp +++ b/workspace/TS100/Core/Drivers/BMA223.cpp @@ -8,7 +8,7 @@ #include #include "BMA223_defines.h" #include -#define BMA223_ADDRESS 0b00110000 +#define BMA223_ADDRESS 0x18<<1 bool BMA223::detect() { return FRToSI2C::probe(BMA223_ADDRESS); @@ -16,16 +16,17 @@ bool BMA223::detect() { static const FRToSI2C::I2C_REG i2c_registers[] = { // // - { BMA223_PMU_RANGE, 0b0011, 0 }, //2G range - { BMA223_PMU_BW, 0b1101, 0 }, //250Hz filter - { BMA223_PMU_LPW, 0x00, 0 }, //Full power - { BMA223_ACCD_HBW, 0b01000000, 0 }, //filtered data out - { BMA223_INT_OUT_CTRL, 0b1111, 0 }, //interrupt active high and OD to get it hi-z - { BMA223_OFC_CTRL, 0b00000111, 0 }, //High pass en + { BMA223_PMU_RANGE, 0b00000011, 0 }, //2G range + { BMA223_PMU_BW, 0b00001101, 0 }, //250Hz filter + { BMA223_PMU_LPW, 0b00000000, 0 }, //Full power + { BMA223_ACCD_HBW, 0b00000000, 0 }, //filtered data out + { BMA223_INT_OUT_CTRL, 0b00001010, 0 }, //interrupt active low and OD to get it hi-z + { BMA223_INT_RST_LATCH, 0b10000000, 0 }, //interrupt active low and OD to get it hi-z +// { BMA223_OFC_CTRL, 0b00000111, 0 }, //High pass en // }; -void BMA223::initalize() { +bool BMA223::initalize() { //Setup acceleration readings //2G range //bandwidth = 250Hz @@ -35,19 +36,22 @@ void BMA223::initalize() { // Hysteresis is set to ~ 16 counts //Theta blocking is set to 0b10 - FRToSI2C::writeRegistersBulk(BMA223_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); + return FRToSI2C::writeRegistersBulk(BMA223_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); } void BMA223::getAxisReadings(int16_t& x, int16_t& y, int16_t& z) { //The BMA is odd in that its output data width is only 8 bits //And yet there are MSB and LSB registers _sigh_. - uint8_t sensorData[6]; + uint8_t sensorData[6] = { 0, 0, 0, 0, 0, 0 }; - FRToSI2C::Mem_Read(BMA223_ADDRESS, BMA223_ACCD_X_LSB, sensorData, 6); + if (FRToSI2C::Mem_Read(BMA223_ADDRESS, BMA223_ACCD_X_LSB, sensorData, 6) == false) { + x = 0xAAFF; + return; + } - x = sensorData[1] << 2; - y = sensorData[3] << 2; - z = sensorData[5] << 2; + x = sensorData[1] << 4; + y = sensorData[3] << 4; + z = sensorData[5] << 4; } diff --git a/workspace/TS100/Core/Drivers/BMA223.hpp b/workspace/TS100/Core/Drivers/BMA223.hpp index 5578d89a..06af2436 100644 --- a/workspace/TS100/Core/Drivers/BMA223.hpp +++ b/workspace/TS100/Core/Drivers/BMA223.hpp @@ -15,7 +15,7 @@ class BMA223 { public: static bool detect(); - static void initalize(); + static bool initalize(); //1 = rh, 2,=lh, 8=flat static Orientation getOrientation() { #ifdef ACCEL_ORI_FLIP diff --git a/workspace/TS100/Core/Drivers/LIS2DH12.cpp b/workspace/TS100/Core/Drivers/LIS2DH12.cpp index 89cdd9a6..02aad5b6 100644 --- a/workspace/TS100/Core/Drivers/LIS2DH12.cpp +++ b/workspace/TS100/Core/Drivers/LIS2DH12.cpp @@ -24,8 +24,8 @@ static const FRToSI2C::I2C_REG i2c_registers[] = { { LIS_CTRL_REG1, 0x17, 0 }, / { LIS_INT1_THS, 0x28, 0 }, // { LIS_INT1_DURATION, 64, 0 } }; -void LIS2DH12::initalize() { - FRToSI2C::writeRegistersBulk(LIS2DH_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); +bool LIS2DH12::initalize() { + return FRToSI2C::writeRegistersBulk(LIS2DH_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); } void LIS2DH12::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) { diff --git a/workspace/TS100/Core/Drivers/LIS2DH12.hpp b/workspace/TS100/Core/Drivers/LIS2DH12.hpp index 8586ec21..e4cccd48 100644 --- a/workspace/TS100/Core/Drivers/LIS2DH12.hpp +++ b/workspace/TS100/Core/Drivers/LIS2DH12.hpp @@ -14,7 +14,7 @@ class LIS2DH12 { public: static bool detect(); - static void initalize(); + static bool initalize(); //1 = rh, 2,=lh, 8=flat static Orientation getOrientation() { #ifdef LIS_ORI_FLIP diff --git a/workspace/TS100/Core/Drivers/MMA8652FC.cpp b/workspace/TS100/Core/Drivers/MMA8652FC.cpp index 83e922e1..fa8b91fe 100644 --- a/workspace/TS100/Core/Drivers/MMA8652FC.cpp +++ b/workspace/TS100/Core/Drivers/MMA8652FC.cpp @@ -26,8 +26,8 @@ static const FRToSI2C::I2C_REG i2c_registers[] = { { CTRL_REG2, 0, 0 }, //Nor { CTRL_REG1, 0x19, 0 } // ODR=12 Hz, Active mode }; -void MMA8652FC::initalize() { - FRToSI2C::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); +bool MMA8652FC::initalize() { + return FRToSI2C::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); } diff --git a/workspace/TS100/Core/Drivers/MMA8652FC.hpp b/workspace/TS100/Core/Drivers/MMA8652FC.hpp index ec160ab5..9b5f44d1 100644 --- a/workspace/TS100/Core/Drivers/MMA8652FC.hpp +++ b/workspace/TS100/Core/Drivers/MMA8652FC.hpp @@ -17,7 +17,7 @@ public: //Returns true if this accelerometer is detected static bool detect(); //Init any internal state - static void initalize(); + static bool initalize(); static Orientation getOrientation(); // Reads the I2C register and returns the orientation (true == left) static void getAxisReadings(int16_t &x, int16_t &y, int16_t &z); diff --git a/workspace/TS100/Core/Src/main.cpp b/workspace/TS100/Core/Src/main.cpp index 9c9da2dc..e9e3d62f 100644 --- a/workspace/TS100/Core/Src/main.cpp +++ b/workspace/TS100/Core/Src/main.cpp @@ -25,7 +25,7 @@ static const size_t PIDTaskStackSize = 512 / 4; uint32_t PIDTaskBuffer[PIDTaskStackSize]; osStaticThreadDef_t PIDTaskControlBlock; osThreadId MOVTaskHandle; -static const size_t MOVTaskStackSize = 512 / 4; +static const size_t MOVTaskStackSize = 1024 / 4; uint32_t MOVTaskBuffer[MOVTaskStackSize]; osStaticThreadDef_t MOVTaskControlBlock; diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index e04340a9..e24663fe 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -603,7 +603,9 @@ uint8_t idleScreenBGF[sizeof(idleScreenBG)]; /* StartGUITask function */ void startGUITask(void const *argument __unused) { OLED::initialize(); // start up the LCD - +// for (;;) { +// osDelay(2000); +// } uint8_t tempWarningState = 0; bool buttonLockout = false; bool tempOnDisplay = false; diff --git a/workspace/TS100/Core/Threads/MOVThread.cpp b/workspace/TS100/Core/Threads/MOVThread.cpp index 01a36b2e..7c09d17b 100644 --- a/workspace/TS100/Core/Threads/MOVThread.cpp +++ b/workspace/TS100/Core/Threads/MOVThread.cpp @@ -27,21 +27,27 @@ void detectAccelerometerVersion() { #ifdef ACCEL_MMA if (MMA8652FC::detect()) { PCBVersion = 1; - MMA8652FC::initalize(); // this sets up the I2C registers + if(!MMA8652FC::initalize()) { + PCBVersion = 99; + } } else #endif #ifdef ACCEL_LIS if (LIS2DH12::detect()) { PCBVersion = 2; // Setup the ST Accelerometer - LIS2DH12::initalize();// startup the accelerometer + if(!LIS2DH12::initalize()) { + PCBVersion = 99; + } } else #endif #ifdef ACCEL_BMA if (BMA223::detect()) { PCBVersion = 3; // Setup the ST Accelerometer - BMA223::initalize(); // startup the accelerometer + if (!BMA223::initalize()) { + PCBVersion = 99; + } } else #endif { @@ -76,7 +82,7 @@ inline void readAccelerometer(int16_t& tx, int16_t& ty, int16_t& tz, Orientation } } void startMOVTask(void const *argument __unused) { - + osDelay(10);//Make oled init happen first postRToSInit(); OLED::setRotation(systemSettings.OrientationMode & 1); detectAccelerometerVersion(); @@ -93,6 +99,17 @@ void startMOVTask(void const *argument __unused) { if (systemSettings.sensitivity > 9) systemSettings.sensitivity = 9; Orientation rotation = ORIENTATION_FLAT; +// OLED::setFont(1); +// for (;;) { +// OLED::clearScreen(); +// OLED::setCursor(0, 0); +// readAccelerometer(tx, ty, tz, rotation); +// OLED::printNumber(tx, 5, 0); +// OLED::setCursor(0, 8); +// OLED::printNumber(xTaskGetTickCount() / 10, 5, 1); +// OLED::refresh(); +// osDelay(50); +// } for (;;) { int32_t threshold = 1500 + (9 * 200); threshold -= systemSettings.sensitivity * 200; // 200 is the step size