diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index c82dbe4..10ee740 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -4,31 +4,9 @@ extern "C" #include #include #include -#include "utility/twi.h" } #include "Wire.h" -// Initialize Class Variables -uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::rxBufferIndex = 0; -uint8_t TwoWire::rxBufferLength = 0; - -uint8_t TwoWire::txAddress = 0; // 7 bits without shift -uint8_t TwoWire::txBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::txBufferIndex = 0; -uint8_t TwoWire::txBufferLength = 0; - -uint8_t TwoWire::transmitting = 0; -uint8_t TwoWire::slaveAddress = 0; // 7 bits without shift in slave mode - -void (*TwoWire::user_onRequest)(void); -void (*TwoWire::user_onReceive)(int); - -// Constructors -TwoWire::TwoWire() -{ -} - // --------------------------- Public Methods --------------------------- // void TwoWire::begin(void) { @@ -36,10 +14,7 @@ void TwoWire::begin(void) rxBufferLength = 0; txBufferIndex = 0; txBufferLength = 0; - twi_init(slaveAddress); - - twi_attachSlaveTxEvent(onRequestService); // default callback must exist - twi_attachSlaveRxEvent(onReceiveService); // default callback must exist + twi_init(&wireHandler, slaveAddress); } void TwoWire::begin(uint8_t address) @@ -56,13 +31,13 @@ void TwoWire::begin(int address) void TwoWire::end(void) { flush(); // wait for transmission complete - twi_deinit(); + twi_deinit(&wireHandler); slaveAddress = 0; } void TwoWire::setClock(uint32_t clock) { - if (twi_setFrequency(clock, false) != I2C_OK) + if (twi_setFrequency(&wireHandler, clock, false) != I2C_OK) ErrorMsgHandler("Wire.setClock(): invalid frequency or Wire was not begin"); } @@ -88,7 +63,7 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres quantity = BUFFER_LENGTH; // perform blocking read into buffer - uint8_t read = twi_masterReadFrom(address, rxBuffer, quantity, sendStop); + uint8_t read = twi_masterReadFrom(&(wireHandler.i2c_param), address, rxBuffer, quantity, sendStop); // set rx buffer iterator vars rxBufferIndex = 0; @@ -147,7 +122,7 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop) if (transmitting) { // transmit buffer (blocking) - ret = twi_masterWriteTo(txAddress, txBuffer, txBufferLength, sendStop); + ret = twi_masterWriteTo(&(wireHandler.i2c_param), txAddress, txBuffer, txBufferLength, sendStop); // reset tx buffer iterator vars txBufferIndex = 0; txBufferLength = 0; @@ -189,7 +164,7 @@ size_t TwoWire::write(uint8_t data) else { // in slave send mode - reply to master - if (twi_slaveWrite(&data, 1) != I2C_OK) + if (twi_slaveWrite(&(wireHandler.i2c_param), &data, 1) != I2C_OK) ret = 0; } return ret; @@ -215,7 +190,7 @@ size_t TwoWire::write(const uint8_t *data, size_t quantity) else { // in slave send mode - reply to master - if (twi_slaveWrite((uint8_t *)data, quantity) != I2C_OK) + if (twi_slaveWrite(&(wireHandler.i2c_param), (uint8_t *)data, quantity) != I2C_OK) ret = 0; } return ret; @@ -309,10 +284,18 @@ void TwoWire::onRequest( void (*function)(void) ) } // ะก function for trap handler -extern "C" void __attribute__((optimize("O3"))) wire_interrupt_handler(void) +extern "C" void __attribute__((optimize("O3"))) wire_interrupt_handler(uint8_t num) { - twi_interruptHandler(); + if (num == 1) + twi_interruptHandler(Wire.getHandler()); +#if I2C_COMMON_QTY>1 + else if (num == 0) + twi_interruptHandler(Wire1.getHandler()); +#endif } // ----------------------------- Preinstantiate Objects ----------------------------- // -TwoWire Wire = TwoWire( ); +TwoWire Wire = TwoWire(1); +#if I2C_COMMON_QTY>1 +TwoWire Wire1 = TwoWire(0); +#endif diff --git a/libraries/Wire/src/Wire.h b/libraries/Wire/src/Wire.h index ba99bbf..ca62b8e 100644 --- a/libraries/Wire/src/Wire.h +++ b/libraries/Wire/src/Wire.h @@ -4,6 +4,10 @@ #include "Stream.h" #include "Arduino.h" +extern "C" +{ +#include "utility/twi.h" +} #define BUFFER_LENGTH 32 @@ -13,23 +17,45 @@ class TwoWire : public Stream { private: - static uint8_t rxBuffer[]; - static uint8_t rxBufferIndex; - static uint8_t rxBufferLength; + WireHandler_TypeDef wireHandler; - static uint8_t txAddress; - static uint8_t txBuffer[]; - static uint8_t txBufferIndex; - static uint8_t txBufferLength; + uint8_t rxBuffer[BUFFER_LENGTH]; + uint8_t rxBufferIndex = 0; + uint8_t rxBufferLength = 0; - static uint8_t transmitting; - static uint8_t slaveAddress; - static void (*user_onRequest)(void); - static void (*user_onReceive)(int numBytes); - static void onRequestService(void); - static void onReceiveService(uint8_t* inBytes, int numBytes); + uint8_t txAddress = 0; // 7 bits without shift + uint8_t txBuffer[BUFFER_LENGTH]; + uint8_t txBufferIndex = 0; + uint8_t txBufferLength = 0; + + uint8_t transmitting = 0; + uint8_t slaveAddress = 0; + void (*user_onRequest)(void); + void (*user_onReceive)(int numBytes); + void onRequestService(void); + void onReceiveService(uint8_t* inBytes, int numBytes); + static inline void staticOnRequestService(void* instance) + { + // cast pointer to TwoWire type and call method + static_cast(instance)->onRequestService(); + } + static inline void staticOnReceiveService(void* instance, uint8_t* inBytes, int numBytes) + { + static_cast(instance)->onReceiveService(inBytes, numBytes); + } public: - TwoWire(); + inline TwoWire(uint8_t num) + { + wireHandler.i2c_num = (num < I2C_COMMON_QTY) ? num : 1; // I2C1 by default + wireHandler.instance = this; + // save pointers to static functions to wire handler + wireHandler.onSlaveTransmit = &TwoWire::staticOnRequestService; + wireHandler.onSlaveReceive = &TwoWire::staticOnReceiveService; + } + WireHandler_TypeDef* getHandler() + { + return &wireHandler; + } void begin(); void begin(uint8_t); void begin(int); @@ -65,5 +91,8 @@ class TwoWire : public Stream }; extern TwoWire Wire; +#if I2C_COMMON_QTY>1 +extern TwoWire Wire1; +#endif #endif diff --git a/libraries/Wire/src/utility/twi.c b/libraries/Wire/src/utility/twi.c index 1978655..ed8fb69 100644 --- a/libraries/Wire/src/utility/twi.c +++ b/libraries/Wire/src/utility/twi.c @@ -2,162 +2,149 @@ #include #include "Arduino.h" #include "twi.h" -#include "mik32_hal_i2c.h" #include "mik32_hal_irq.h" #define TIMEOUT_TICKS 1000000 #define TWI_FREQ_DEF WIRE_FREQ_100K // default is 100 kHz -static void (*twi_onSlaveTransmit)(void); -static void (*twi_onSlaveReceive)(uint8_t*, int); - -static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; -static volatile uint8_t twi_rxBufferIndex; - -I2C_HandleTypeDef hi2c; -static uint32_t CurrentFrequency = TWI_FREQ_DEF; -static bool twiIsOn = false; - // ---------------------------------------------------------------- // /* * Function twi_init * Desc readys twi pins and sets twi bitrate - * Input slaveAddress - address of Arduino if working in slave mode + * Input handler - pointer to wire common handler, + * slaveAddress - address of Arduino if working in slave mode * Output none */ -uint8_t twi_init(uint8_t slaveAddress) +uint8_t twi_init(WireHandler_TypeDef* handler, uint8_t slaveAddress) { // Common settings uint32_t EPICmask; -#if I2C_NUM == 0 - hi2c.Instance = I2C_0; - EPICmask = HAL_EPIC_I2C_0_MASK; -#elif I2C_NUM == 1 - hi2c.Instance = I2C_1; - EPICmask = HAL_EPIC_I2C_1_MASK; -#else - #error "Unsupported I2C_NUM value in pins_arduino.h" -#endif + if (handler->i2c_num == 0) + { + handler->i2c_param.Instance = I2C_0; + EPICmask = HAL_EPIC_I2C_0_MASK; + } + else if (handler->i2c_num == 1) + { + handler->i2c_param.Instance = I2C_1; + EPICmask = HAL_EPIC_I2C_1_MASK; + } + else + return I2C_ERROR; - hi2c.Init.DigitalFilter = I2C_DIGITALFILTER_2CLOCKCYCLES; - hi2c.Init.AnalogFilter = I2C_ANALOGFILTER_DISABLE; + handler->i2c_param.Init.DigitalFilter = I2C_DIGITALFILTER_2CLOCKCYCLES; + handler->i2c_param.Init.AnalogFilter = I2C_ANALOGFILTER_DISABLE; if (slaveAddress == 0) // if there is no address - master mode { - hi2c.Init.Mode = HAL_I2C_MODE_MASTER; - hi2c.Init.AutoEnd = I2C_AUTOEND_ENABLE; + handler->i2c_param.Init.Mode = HAL_I2C_MODE_MASTER; + handler->i2c_param.Init.AutoEnd = I2C_AUTOEND_ENABLE; } else { // 7-bit address without any additional bits - hi2c.Init.Mode = HAL_I2C_MODE_SLAVE; - hi2c.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // stretch is used - hi2c.Init.OwnAddress1 = slaveAddress; + handler->i2c_param.Init.Mode = HAL_I2C_MODE_SLAVE; + handler->i2c_param.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // stretch is used + handler->i2c_param.Init.OwnAddress1 = slaveAddress; } // set the frequency - if (hi2c.Init.Mode == HAL_I2C_MODE_MASTER) - twi_setFrequency(CurrentFrequency, true); + if (handler->i2c_param.Init.Mode == HAL_I2C_MODE_MASTER) + twi_setFrequency(handler, TWI_FREQ_DEF, true); else - twi_setFrequency(0, true); + twi_setFrequency(handler, 0, true); - if (HAL_I2C_Init(&hi2c) != HAL_OK) + if (HAL_I2C_Init(&(handler->i2c_param)) != HAL_OK) return I2C_ERROR; // enable interrupts for slave mode - if (hi2c.Init.Mode == HAL_I2C_MODE_SLAVE) + if (handler->i2c_param.Init.Mode == HAL_I2C_MODE_SLAVE) { // enable interrupts for addressing, byte reception and transfer completion - HAL_I2C_InterruptDisable(&hi2c, I2C_INTMASK); - HAL_I2C_InterruptEnable(&hi2c, I2C_CR1_ADDRIE_M | I2C_CR1_RXIE_M | I2C_CR1_STOPIE_M); + HAL_I2C_InterruptDisable(&(handler->i2c_param), I2C_INTMASK); + HAL_I2C_InterruptEnable(&(handler->i2c_param), I2C_CR1_ADDRIE_M | I2C_CR1_RXIE_M | I2C_CR1_STOPIE_M); // enable interrupt from i2c HAL_EPIC_MaskLevelSet(EPICmask); } - twiIsOn = true; + handler->isInited = true; return I2C_OK; } /* * Function twi_deinit * Desc disables twi pins - * Input none + * Input handler - pointer to wire common handler * Output none */ -void twi_deinit(void) +void twi_deinit(WireHandler_TypeDef* handler) { - uint32_t EPICmask; - -#if I2C_NUM == 0 - hi2c.Instance = I2C_0; - EPICmask = HAL_EPIC_I2C_0_MASK; -#elif I2C_NUM == 1 - hi2c.Instance = I2C_1; - EPICmask = HAL_EPIC_I2C_1_MASK; -#else - #error "Unsupported I2C_NUM value in pins_arduino.h" -#endif - - HAL_I2C_Deinit(&hi2c); + HAL_I2C_Deinit(&(handler->i2c_param)); // for slave mode disable interrupts from i2c - if (hi2c.Init.Mode == HAL_I2C_MODE_SLAVE) - HAL_EPIC_MaskLevelClear(EPICmask); + if (handler->i2c_param.Init.Mode == HAL_I2C_MODE_SLAVE) + { + if (handler->i2c_num == 0) + HAL_EPIC_MaskLevelClear(HAL_EPIC_I2C_0_MASK); + else + HAL_EPIC_MaskLevelClear(HAL_EPIC_I2C_1_MASK); + } - twiIsOn = false; + handler->isInited = false; } /* * Function twi_setClock * Desc sets twi bit rate - * Input Clock Frequency - 100000 / 400000 / 1000000, + * Input handler - pointer to wire common handler + * Clock Frequency - 100000 / 400000 / 1000000, * onInit = true only if function is called from twi_init() * Output I2C_OK - frequency changed, I2C_ERROR - frequency didn't change */ -uint8_t twi_setFrequency(uint32_t frequency, bool onInit) +uint8_t twi_setFrequency(WireHandler_TypeDef* handler, uint32_t frequency, bool onInit) { uint8_t ret = I2C_OK; // change the frequency only during or after bus initialization - if (twiIsOn || onInit) + if (handler->isInited || onInit) { // You can change the frequency only when the interface is turned off - HAL_I2C_Disable(&hi2c); + HAL_I2C_Disable(&(handler->i2c_param)); if (frequency == WIRE_FREQ_100K) // 100 kHz { - hi2c.Clock.PRESC = 2; - hi2c.Clock.SCLDEL = 8; - hi2c.Clock.SDADEL = 2; - hi2c.Clock.SCLH = 49; - hi2c.Clock.SCLL = 49; - CurrentFrequency = WIRE_FREQ_100K; + handler->i2c_param.Clock.PRESC = 2; + handler->i2c_param.Clock.SCLDEL = 8; + handler->i2c_param.Clock.SDADEL = 2; + handler->i2c_param.Clock.SCLH = 49; + handler->i2c_param.Clock.SCLL = 49; + // CurrentFrequency = WIRE_FREQ_100K; } else if (frequency == WIRE_FREQ_400K) // 400 kHz { - hi2c.Clock.PRESC = 0; - hi2c.Clock.SCLDEL = 3; - hi2c.Clock.SDADEL = 2; - hi2c.Clock.SCLH = 30; - hi2c.Clock.SCLL = 30; - CurrentFrequency = WIRE_FREQ_400K; + handler->i2c_param.Clock.PRESC = 0; + handler->i2c_param.Clock.SCLDEL = 3; + handler->i2c_param.Clock.SDADEL = 2; + handler->i2c_param.Clock.SCLH = 30; + handler->i2c_param.Clock.SCLL = 30; + // CurrentFrequency = WIRE_FREQ_400K; } else if (frequency == WIRE_FREQ_1000K)// 1000 kHz { - hi2c.Clock.PRESC = 0; - hi2c.Clock.SCLDEL = 1; - hi2c.Clock.SDADEL = 2; - hi2c.Clock.SCLH = 6; - hi2c.Clock.SCLL = 6; - CurrentFrequency = WIRE_FREQ_1000K; + handler->i2c_param.Clock.PRESC = 0; + handler->i2c_param.Clock.SCLDEL = 1; + handler->i2c_param.Clock.SDADEL = 2; + handler->i2c_param.Clock.SCLH = 6; + handler->i2c_param.Clock.SCLL = 6; + // CurrentFrequency = WIRE_FREQ_1000K; } else if (frequency == 0) // slave mode { - hi2c.Clock.PRESC = 0; - hi2c.Clock.SCLDEL = 0; - hi2c.Clock.SDADEL = 2; - hi2c.Clock.SCLH = 0; - hi2c.Clock.SCLL = 0; + handler->i2c_param.Clock.PRESC = 0; + handler->i2c_param.Clock.SCLDEL = 0; + handler->i2c_param.Clock.SDADEL = 2; + handler->i2c_param.Clock.SCLH = 0; + handler->i2c_param.Clock.SCLL = 0; } else // frequency does not change @@ -165,11 +152,11 @@ uint8_t twi_setFrequency(uint32_t frequency, bool onInit) // write the timings to the register if everything is OK if (ret == I2C_OK) - HAL_I2C_SetClockSpeed(&hi2c); + HAL_I2C_SetClockSpeed(&(handler->i2c_param)); //turn the interface back only if initialization has already passed - if (twiIsOn) - HAL_I2C_Enable(&hi2c); + if (handler->isInited) + HAL_I2C_Enable(&(handler->i2c_param)); } else ret = I2C_ERROR; @@ -181,26 +168,27 @@ uint8_t twi_setFrequency(uint32_t frequency, bool onInit) * Function twi_masterReadFrom * Desc attempts to become twi bus master and read a * series of bytes from a device on the bus - * Input address: 7bit i2c device address + * Input hi2c: pointer to hardware i2c handler + * address: 7bit i2c device address * data: pointer to byte array * length: number of bytes to read into array * sendStop: Boolean indicating whether to send a stop at the end * Output number of bytes read */ -uint8_t twi_masterReadFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) +uint8_t twi_masterReadFrom(I2C_HandleTypeDef* hi2c, uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) { uint8_t ret = 0; // if there are errors left from previous transactions, you need to restart // the interface for correct operation - if (hi2c.ErrorCode != I2C_ERROR_NONE) - HAL_I2C_Reset(&hi2c); + if (hi2c->ErrorCode != I2C_ERROR_NONE) + HAL_I2C_Reset(hi2c); - if (sendStop) hi2c.Init.AutoEnd = 1; - else hi2c.Init.AutoEnd = 0; + if (sendStop) hi2c->Init.AutoEnd = 1; + else hi2c->Init.AutoEnd = 0; // put the data directly into the external buffer - if (HAL_I2C_Master_Receive(&hi2c, address, data, length, TIMEOUT_TICKS) == HAL_OK) + if (HAL_I2C_Master_Receive(hi2c, address, data, length, TIMEOUT_TICKS) == HAL_OK) ret = length; return ret; @@ -210,7 +198,8 @@ uint8_t twi_masterReadFrom(uint8_t address, uint8_t* data, uint8_t length, uint8 * Function twi_masterWriteTo * Desc attempts to become twi bus master and write a * series of bytes to a device on the bus - * Input address: 7bit i2c device address + * Input hi2c: pointer to hardware i2c handler + * address: 7bit i2c device address * data: pointer to byte array * length: number of bytes in array * sendStop: boolean indicating whether or not to send a stop at the end @@ -221,28 +210,28 @@ uint8_t twi_masterReadFrom(uint8_t address, uint8_t* data, uint8_t length, uint8 * 4 .. other twi error (lost bus arbitration, bus error, ..) * 5 .. timeout */ -uint8_t twi_masterWriteTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) +uint8_t twi_masterWriteTo(I2C_HandleTypeDef* hi2c, uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) { uint8_t ret = I2C_OK; // if there are errors left from previous transactions, you need to restart // the interface for correct operation - if (hi2c.ErrorCode != I2C_ERROR_NONE) - HAL_I2C_Reset(&hi2c); + if (hi2c->ErrorCode != I2C_ERROR_NONE) + HAL_I2C_Reset(hi2c); - if (sendStop) hi2c.Init.AutoEnd = 1; - else hi2c.Init.AutoEnd = 0; + if (sendStop) hi2c->Init.AutoEnd = 1; + else hi2c->Init.AutoEnd = 0; // take data from an external buffer - HAL_I2C_Master_Transmit(&hi2c, address, data, length, TIMEOUT_TICKS); + HAL_I2C_Master_Transmit(hi2c, address, data, length, TIMEOUT_TICKS); // parse errors // check separately, because in hal libraries not all functions look at this - if (HAL_I2C_Get_Interrupts_Status(&hi2c) & I2C_ISR_NACKF_M) - hi2c.ErrorCode = I2C_ERROR_NACK; - if (hi2c.ErrorCode == (HAL_I2C_ErrorTypeDef)I2C_ERROR_TIMEOUT) ret = I2C_TIMEOUT; // timeout - else if (hi2c.ErrorCode == (HAL_I2C_ErrorTypeDef)I2C_ERROR_NACK) ret = I2C_NACK_DATA; // didn't receive ACK - else if (hi2c.ErrorCode != (HAL_I2C_ErrorTypeDef)I2C_OK) ret = I2C_ERROR; // any other error + if (HAL_I2C_Get_Interrupts_Status(hi2c) & I2C_ISR_NACKF_M) + hi2c->ErrorCode = I2C_ERROR_NACK; + if (hi2c->ErrorCode == (HAL_I2C_ErrorTypeDef)I2C_ERROR_TIMEOUT) ret = I2C_TIMEOUT; // timeout + else if (hi2c->ErrorCode == (HAL_I2C_ErrorTypeDef)I2C_ERROR_NACK) ret = I2C_NACK_DATA; // didn't receive ACK + else if (hi2c->ErrorCode != (HAL_I2C_ErrorTypeDef)I2C_OK) ret = I2C_ERROR; // any other error return ret; } @@ -251,97 +240,79 @@ uint8_t twi_masterWriteTo(uint8_t address, uint8_t* data, uint8_t length, uint8_ * Function twi_slaveWrite * Desc attempts to become twi bus slave and write a * series of bytes to a master after it asks - * Input txData: pointer to byte array + * Input hi2c: pointer to hardware i2c handler + * txData: pointer to byte array * bytesNum: number of bytes in array * Output 0 .. success * 5 .. timeout */ -i2c_status_e twi_slaveWrite(uint8_t *txData, uint8_t bytesNum) +i2c_status_e twi_slaveWrite(I2C_HandleTypeDef* hi2c, uint8_t *txData, uint8_t bytesNum) { - if ((hi2c.ErrorCode != I2C_ERROR_NONE)) - HAL_I2C_Reset(&hi2c); + if ((hi2c->ErrorCode != I2C_ERROR_NONE)) + HAL_I2C_Reset(hi2c); // send data HAL_StatusTypeDef error_code = HAL_OK; - HAL_I2C_Clear_Reload(&hi2c); - if (!(HAL_I2C_Get_CR1_Content(&hi2c) & I2C_CR1_NOSTRETCH_M)) // NOSTRETCH = 0 - HAL_I2C_Reset_TXDR_Content(&hi2c); - HAL_I2C_Write_TXDR(&hi2c, txData[0]); // first recording is made in advance + HAL_I2C_Clear_Reload(hi2c); + if (!(HAL_I2C_Get_CR1_Content(hi2c) & I2C_CR1_NOSTRETCH_M)) // NOSTRETCH = 0 + HAL_I2C_Reset_TXDR_Content(hi2c); + HAL_I2C_Write_TXDR(hi2c, txData[0]); // first recording is made in advance // write byte for (uint32_t tx_count = 1; tx_count < bytesNum; tx_count++) { - if ((error_code = HAL_I2C_Slave_WaitTXIS(&hi2c, TIMEOUT_TICKS)) != HAL_OK) + if ((error_code = HAL_I2C_Slave_WaitTXIS(hi2c, TIMEOUT_TICKS)) != HAL_OK) { // failed to write - HAL_I2C_Reset_TXDR_Content(&hi2c); - HAL_I2C_Reset_Interrupt_Flag(&hi2c, I2C_ICR_STOPCF_M); // Clear the STOP detection flag on the bus - HAL_I2C_Reset(&hi2c); + HAL_I2C_Reset_TXDR_Content(hi2c); + HAL_I2C_Reset_Interrupt_Flag(hi2c, I2C_ICR_STOPCF_M); // Clear the STOP detection flag on the bus + HAL_I2C_Reset(hi2c); return I2C_TIMEOUT; } - HAL_I2C_Write_TXDR(&hi2c, txData[tx_count]); + HAL_I2C_Write_TXDR(hi2c, txData[tx_count]); } - if ((error_code = HAL_I2C_WaitBusy(&hi2c, TIMEOUT_TICKS)) != HAL_OK) + if ((error_code = HAL_I2C_WaitBusy(hi2c, TIMEOUT_TICKS)) != HAL_OK) { // failed to complete transaction - HAL_I2C_Reset(&hi2c); + HAL_I2C_Reset(hi2c); return I2C_TIMEOUT; } - HAL_I2C_Reset_TXDR_Content(&hi2c); - HAL_I2C_Reset_Interrupt_Flag(&hi2c, I2C_ICR_STOPCF_M); // Clear the STOP detection flag on the bus + HAL_I2C_Reset_TXDR_Content(hi2c); + HAL_I2C_Reset_Interrupt_Flag(hi2c, I2C_ICR_STOPCF_M); // Clear the STOP detection flag on the bus return I2C_OK; } -/* - * Function twi_attachSlaveRxEvent - * Desc sets function called before a slave read operation - * Input function: callback function to use - * Output none - */ -void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) -{ - twi_onSlaveReceive = function; -} - -/* - * Function twi_attachSlaveTxEvent - * Desc sets function called before a slave write operation - * Input function: callback function to use - * Output none - */ -void twi_attachSlaveTxEvent( void (*function)(void) ) -{ - twi_onSlaveTransmit = function; -} - - /* * Function twi_interruptHandler * Desc handles an interrupts from twi - * Input none + * Input handler - pointer to wire common handler * Output none */ -void __attribute__((optimize("O3"))) twi_interruptHandler(void) +void __attribute__((optimize("O3"))) twi_interruptHandler(WireHandler_TypeDef* handler) { - uint32_t int_mask = HAL_I2C_Get_CR1_Content(&hi2c) & I2C_INTMASK; // interrupts allowed - uint32_t interrupt_status = HAL_I2C_Get_Interrupts_Status(&hi2c); // current flags + uint32_t int_mask = HAL_I2C_Get_CR1_Content(&(handler->i2c_param)) & I2C_INTMASK; // interrupts allowed + uint32_t interrupt_status = HAL_I2C_Get_Interrupts_Status(&(handler->i2c_param)); // current flags // master calls by address, device in slave mode if ((interrupt_status & I2C_ISR_ADDR_M) && (int_mask & I2C_CR1_ADDRIE_M)) { // reset ADDR flag - HAL_I2C_Reset_Interrupt_Flag(&hi2c, I2C_ICR_ADDRCF_M); + HAL_I2C_Reset_Interrupt_Flag(&(handler->i2c_param), I2C_ICR_ADDRCF_M); // look at the transmission direction and respond to the request if (interrupt_status & I2C_ISR_DIR_M) // master reads, slave sends - twi_onSlaveTransmit(); // slave send data + { + // twi_onSlaveTransmit(); // slave send data + if (handler->onSlaveTransmit) + handler->onSlaveTransmit(handler->instance); + } else // master writes, slave reads { - twi_rxBufferIndex = 0; // write from the beginning of the buffer - hi2c.State = HAL_I2C_STATE_BUSY; - HAL_I2C_Clear_Reload(&hi2c); + handler->rxBufferIndex = 0; // write from the beginning of the buffer + handler->i2c_param.State = HAL_I2C_STATE_BUSY; + HAL_I2C_Clear_Reload(&(handler->i2c_param)); // wait for interrupts by receiving a byte or a stop condition } } @@ -350,16 +321,16 @@ void __attribute__((optimize("O3"))) twi_interruptHandler(void) if ((interrupt_status & I2C_ISR_RXNE_M) && (int_mask & I2C_CR1_RXIE_M)) { // put new byte into buffer - twi_rxBuffer[twi_rxBufferIndex++] = HAL_I2C_Get_RXDR(&hi2c); + handler->rxBuffer[handler->rxBufferIndex++] = HAL_I2C_Get_RXDR(&(handler->i2c_param)); } // master sent a STOP to the bus if ((interrupt_status & I2C_ISR_STOPF_M) && (int_mask & I2C_CR1_STOPIE_M)) { - hi2c.State = HAL_I2C_STATE_END; - HAL_I2C_Reset_TXDR_Content(&hi2c); - HAL_I2C_Reset_Interrupt_Flag(&hi2c, I2C_ICR_STOPCF_M); // Clear the STOP detection flag on the bus + handler->i2c_param.State = HAL_I2C_STATE_END; + HAL_I2C_Reset_TXDR_Content(&(handler->i2c_param)); + HAL_I2C_Reset_Interrupt_Flag(&(handler->i2c_param), I2C_ICR_STOPCF_M); // Clear the STOP detection flag on the bus // pass the received data to callback function - twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); + handler->onSlaveReceive(handler->instance, handler->rxBuffer, handler->rxBufferIndex); } } \ No newline at end of file diff --git a/libraries/Wire/src/utility/twi.h b/libraries/Wire/src/utility/twi.h index 4d83a97..e4a814d 100644 --- a/libraries/Wire/src/utility/twi.h +++ b/libraries/Wire/src/utility/twi.h @@ -5,10 +5,24 @@ extern "C" { #endif +#include "mik32_hal_i2c.h" + #ifndef TWI_BUFFER_LENGTH #define TWI_BUFFER_LENGTH 32 #endif +typedef struct +{ + I2C_HandleTypeDef i2c_param; + uint8_t i2c_num; + bool isInited; + uint8_t rxBuffer[TWI_BUFFER_LENGTH]; + volatile uint8_t rxBufferIndex; + void (*onSlaveTransmit)(void*); + void (*onSlaveReceive) (void*, uint8_t*, int); + void *instance; +}WireHandler_TypeDef; + // I2C state typedef enum { @@ -21,17 +35,16 @@ typedef enum I2C_BUSY = 6 } i2c_status_e; -uint8_t twi_init(uint8_t slaveAddress); -void twi_deinit(void); -uint8_t twi_setFrequency(uint32_t frequency, bool onInit); +uint8_t twi_init (WireHandler_TypeDef* handler, uint8_t slaveAddress); +void twi_deinit(WireHandler_TypeDef* handler); -uint8_t twi_masterReadFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop); -uint8_t twi_masterWriteTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop); -i2c_status_e twi_slaveWrite(uint8_t *txData, uint8_t bytesNum); +uint8_t twi_setFrequency(WireHandler_TypeDef* handler, uint32_t frequency, bool onInit); -void twi_attachSlaveRxEvent(void (*function)(uint8_t*, int)); -void twi_attachSlaveTxEvent(void (*function)(void)); -void twi_interruptHandler(void); +uint8_t twi_masterReadFrom (I2C_HandleTypeDef* hi2c, uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop); +uint8_t twi_masterWriteTo (I2C_HandleTypeDef* hi2c, uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop); +i2c_status_e twi_slaveWrite (I2C_HandleTypeDef* hi2c, uint8_t *txData, uint8_t bytesNum); + +void twi_interruptHandler(WireHandler_TypeDef* handler); #ifdef __cplusplus }