-
Notifications
You must be signed in to change notification settings - Fork 1k
I2C IT mode #135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
I2C IT mode #135
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -101,7 +101,16 @@ | |
*/ | ||
|
||
/* Family specific description for I2C */ | ||
#define I2C_NUM (5) | ||
#if defined(STM32F7xx) || defined(STM32L4xx) | ||
#define I2C_NUM (4) | ||
#elif defined(STM32F2xx) || defined(STM32F3xx) || defined(STM32F4xx) || defined(STM32L0xx) | ||
#define I2C_NUM (3) | ||
#elif defined(STM32F0xx) || defined(STM32F1xx) || defined(STM32L1xx) | ||
#define I2C_NUM (2) | ||
#else | ||
#error "Unknown Family - unknown I2C_NUM" | ||
#endif | ||
|
||
static I2C_HandleTypeDef* i2c_handles[I2C_NUM]; | ||
|
||
/** | ||
|
@@ -142,7 +151,6 @@ void i2c_init(i2c_t *obj) | |
*/ | ||
void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode, uint32_t ownAddress, uint8_t master) | ||
{ | ||
UNUSED(master); | ||
if(obj == NULL) | ||
return; | ||
|
||
|
@@ -170,53 +178,56 @@ void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode, u | |
#if defined I2C1_BASE | ||
// Enable I2C1 clock if not done | ||
if (obj->i2c == I2C1) { | ||
__HAL_RCC_I2C1_CLK_ENABLE(); | ||
__HAL_RCC_I2C1_FORCE_RESET(); | ||
__HAL_RCC_I2C1_RELEASE_RESET(); | ||
obj->irq = I2C1_EV_IRQn; | ||
#ifdef STM32F1xx | ||
obj->irqER = I2C1_ER_IRQn; | ||
#endif | ||
i2c_handles[0] = handle; | ||
__HAL_RCC_I2C1_CLK_ENABLE(); | ||
__HAL_RCC_I2C1_FORCE_RESET(); | ||
__HAL_RCC_I2C1_RELEASE_RESET(); | ||
|
||
obj->irq = I2C1_EV_IRQn; | ||
#if !defined(STM32F0xx) && !defined(STM32L0xx) | ||
obj->irqER = I2C1_ER_IRQn; | ||
#endif // !defined(STM32F0xx) && !defined(STM32L0xx) | ||
i2c_handles[0] = handle; | ||
} | ||
#endif | ||
#endif // I2C1_BASE | ||
#if defined I2C2_BASE | ||
// Enable I2C2 clock if not done | ||
if (obj->i2c == I2C2) { | ||
__HAL_RCC_I2C2_CLK_ENABLE(); | ||
__HAL_RCC_I2C2_FORCE_RESET(); | ||
__HAL_RCC_I2C2_RELEASE_RESET(); | ||
#ifdef STM32F0xx | ||
obj->irq = I2C2_IRQn; | ||
#else | ||
obj->irq = I2C2_EV_IRQn; | ||
#ifdef STM32F1xx | ||
obj->irqER = I2C2_ER_IRQn; | ||
#endif | ||
#endif | ||
i2c_handles[1] = handle; | ||
__HAL_RCC_I2C2_CLK_ENABLE(); | ||
__HAL_RCC_I2C2_FORCE_RESET(); | ||
__HAL_RCC_I2C2_RELEASE_RESET(); | ||
obj->irq = I2C2_EV_IRQn; | ||
#if !defined(STM32F0xx) && !defined(STM32L0xx) | ||
obj->irqER = I2C2_ER_IRQn; | ||
#endif // !defined(STM32F0xx) && !defined(STM32L0xx) | ||
i2c_handles[1] = handle; | ||
} | ||
#endif | ||
#endif // I2C2_BASE | ||
#if defined I2C3_BASE | ||
// Enable I2C3 clock if not done | ||
if (obj->i2c == I2C3) { | ||
__HAL_RCC_I2C3_CLK_ENABLE(); | ||
__HAL_RCC_I2C3_FORCE_RESET(); | ||
__HAL_RCC_I2C3_RELEASE_RESET(); | ||
obj->irq = I2C3_EV_IRQn; | ||
i2c_handles[2] = handle; | ||
__HAL_RCC_I2C3_CLK_ENABLE(); | ||
__HAL_RCC_I2C3_FORCE_RESET(); | ||
__HAL_RCC_I2C3_RELEASE_RESET(); | ||
obj->irq = I2C3_EV_IRQn; | ||
#if !defined(STM32F0xx) && !defined(STM32L0xx) | ||
obj->irqER = I2C3_ER_IRQn; | ||
#endif // !defined(STM32F0xx) && !defined(STM32L0xx) | ||
i2c_handles[2] = handle; | ||
} | ||
#endif | ||
#endif // I2C3_BASE | ||
#if defined I2C4_BASE | ||
// Enable I2C3 clock if not done | ||
// Enable I2C4 clock if not done | ||
if (obj->i2c == I2C4) { | ||
__HAL_RCC_I2C4_CLK_ENABLE(); | ||
__HAL_RCC_I2C4_FORCE_RESET(); | ||
__HAL_RCC_I2C4_RELEASE_RESET(); | ||
obj->irq = I2C4_EV_IRQn; | ||
i2c_handles[3] = handle; | ||
__HAL_RCC_I2C4_CLK_ENABLE(); | ||
__HAL_RCC_I2C4_FORCE_RESET(); | ||
__HAL_RCC_I2C4_RELEASE_RESET(); | ||
obj->irq = I2C4_EV_IRQn; | ||
#if !defined(STM32F0xx) && !defined(STM32L0xx) | ||
obj->irqER = I2C4_ER_IRQn; | ||
#endif // !defined(STM32F0xx) && !defined(STM32L0xx) | ||
i2c_handles[3] = handle; | ||
} | ||
#endif | ||
#endif // I2C4_BASE | ||
|
||
//SCL | ||
port = set_GPIO_Port_Clock(STM_PORT(obj->scl)); | ||
|
@@ -250,7 +261,7 @@ void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode, u | |
handle->Init.Timing = timing; | ||
#else | ||
handle->Init.ClockSpeed = timing; | ||
handle->Init.DutyCycle = I2C_DUTYCYCLE_2;//16_9; | ||
handle->Init.DutyCycle = I2C_DUTYCYCLE_2; | ||
#endif | ||
handle->Init.OwnAddress1 = ownAddress; | ||
handle->Init.OwnAddress2 = 0xFF; | ||
|
@@ -261,17 +272,17 @@ void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode, u | |
|
||
handle->State = HAL_I2C_STATE_RESET; | ||
|
||
if(master == 0) { | ||
HAL_NVIC_SetPriority(obj->irq, 0, 1); | ||
HAL_NVIC_EnableIRQ(obj->irq); | ||
#ifdef STM32F1xx | ||
HAL_NVIC_SetPriority(obj->irqER, 0, 1); | ||
HAL_NVIC_EnableIRQ(obj->irqER); | ||
#endif | ||
} | ||
HAL_NVIC_SetPriority(obj->irq, 0, 1); | ||
HAL_NVIC_EnableIRQ(obj->irq); | ||
#if !defined(STM32F0xx) && !defined(STM32L0xx) | ||
HAL_NVIC_SetPriority(obj->irqER, 0, 1); | ||
HAL_NVIC_EnableIRQ(obj->irqER); | ||
#endif // !defined(STM32F0xx) && !defined(STM32L0xx) | ||
|
||
// Init the I2C | ||
HAL_I2C_Init(handle); | ||
|
||
obj->isMaster = master; | ||
} | ||
|
||
/** | ||
|
@@ -282,9 +293,9 @@ void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode, u | |
void i2c_deinit(i2c_t *obj) | ||
{ | ||
HAL_NVIC_DisableIRQ(obj->irq); | ||
#ifdef STM32F1xx | ||
#if !defined(STM32F0xx) && !defined(STM32L0xx) | ||
HAL_NVIC_DisableIRQ(obj->irqER); | ||
#endif | ||
#endif // !defined(STM32F0xx) && !defined(STM32L0xx) | ||
HAL_I2C_DeInit(&(obj->handle)); | ||
} | ||
|
||
|
@@ -341,17 +352,20 @@ i2c_status_e i2c_master_write(i2c_t *obj, uint8_t dev_address, | |
|
||
{ | ||
i2c_status_e ret = I2C_ERROR; | ||
HAL_StatusTypeDef status = HAL_OK; | ||
uint32_t tickstart = HAL_GetTick(); | ||
|
||
// Check the communication status | ||
status = HAL_I2C_Master_Transmit(&(obj->handle), dev_address, data, size, I2C_TIMEOUT_TICK); | ||
|
||
if(status == HAL_OK) | ||
if(HAL_I2C_Master_Transmit_IT(&(obj->handle), dev_address, data, size) == HAL_OK){ | ||
ret = I2C_OK; | ||
else if(status == HAL_TIMEOUT) | ||
ret = I2C_TIMEOUT; | ||
else | ||
ret = I2C_ERROR; | ||
// wait for transfer completion | ||
while((HAL_I2C_GetState(&(obj->handle)) != HAL_I2C_STATE_READY) | ||
&& (ret == I2C_OK)){ | ||
if((HAL_GetTick() - tickstart) > I2C_TIMEOUT_TICK) { | ||
ret = I2C_TIMEOUT; | ||
} else if(HAL_I2C_GetError(&(obj->handle)) != HAL_I2C_ERROR_NONE) { | ||
ret = I2C_ERROR; | ||
} | ||
} | ||
} | ||
|
||
return ret; | ||
} | ||
|
@@ -385,9 +399,19 @@ void i2c_slave_write_IT(i2c_t *obj, uint8_t *data, uint8_t size) | |
i2c_status_e i2c_master_read(i2c_t *obj, uint8_t dev_address, uint8_t *data, uint8_t size) | ||
{ | ||
i2c_status_e ret = I2C_ERROR; | ||
uint32_t tickstart = HAL_GetTick(); | ||
|
||
if(HAL_I2C_Master_Receive(&(obj->handle), dev_address, data, size, I2C_TIMEOUT_TICK) == HAL_OK) { | ||
if(HAL_I2C_Master_Receive_IT(&(obj->handle), dev_address, data, size) == HAL_OK) { | ||
ret = I2C_OK; | ||
// wait for transfer completion | ||
while((HAL_I2C_GetState(&(obj->handle)) != HAL_I2C_STATE_READY) | ||
&& (ret == I2C_OK)){ | ||
if((HAL_GetTick() - tickstart) > I2C_TIMEOUT_TICK) { | ||
ret = I2C_TIMEOUT; | ||
} else if(HAL_I2C_GetError(&(obj->handle)) != HAL_I2C_ERROR_NONE) { | ||
ret = I2C_ERROR; | ||
} | ||
} | ||
} | ||
|
||
return ret; | ||
|
@@ -506,15 +530,24 @@ void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) | |
|
||
/** | ||
* @brief I2C error callback. | ||
* @note In master mode, the callback is not used because the error is reported | ||
* to the Arduino API from i2c_master_write() and i2c_master_read(). | ||
* In slave mode, there is no mechanism in Arduino API to report an error | ||
* so the error callback forces the slave to listen again. | ||
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains | ||
* the configuration information for the specified I2C. | ||
* @retval None | ||
*/ | ||
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) | ||
{ | ||
HAL_I2C_EnableListen_IT(hi2c); | ||
i2c_t *obj = get_i2c_obj(hi2c); | ||
|
||
if(obj->isMaster == 0) { | ||
HAL_I2C_EnableListen_IT(hi2c); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you comment or explain this ErrorCallback management ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In master mode, the callback is useless because the error is reported to the Arduino API with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok Good. So please explain this either with comments in the code, or in the commit message, this is useful information that we cannot guess when reading the code There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok - good - I see it now ! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Above in the header of the function. |
||
} | ||
} | ||
|
||
#if defined(I2C1_BASE) | ||
/** | ||
* @brief This function handles I2C1 interrupt. | ||
* @param None | ||
|
@@ -524,8 +557,12 @@ void I2C1_EV_IRQHandler(void) | |
{ | ||
I2C_HandleTypeDef * handle = i2c_handles[0]; | ||
HAL_I2C_EV_IRQHandler(handle); | ||
#if defined(STM32F0xx) || defined(STM32L0xx) | ||
HAL_I2C_ER_IRQHandler(handle); | ||
#endif // defined(STM32F0xx) || defined(STM32L0xx) | ||
} | ||
|
||
#if !defined(STM32F0xx) && !defined(STM32L0xx) | ||
/** | ||
* @brief This function handles I2C1 interrupt. | ||
* @param None | ||
|
@@ -536,7 +573,10 @@ void I2C1_ER_IRQHandler(void) | |
I2C_HandleTypeDef * handle = i2c_handles[0]; | ||
HAL_I2C_ER_IRQHandler(handle); | ||
} | ||
#endif // !defined(STM32F0xx) && !defined(STM32L0xx) | ||
#endif // I2C1_BASE | ||
|
||
#if defined(I2C2_BASE) | ||
/** | ||
* @brief This function handles I2C2 interrupt. | ||
* @param None | ||
|
@@ -546,8 +586,12 @@ void I2C2_EV_IRQHandler(void) | |
{ | ||
I2C_HandleTypeDef * handle = i2c_handles[1]; | ||
HAL_I2C_EV_IRQHandler(handle); | ||
#if defined(STM32F0xx) || defined(STM32L0xx) | ||
HAL_I2C_ER_IRQHandler(handle); | ||
#endif // defined(STM32F0xx) || defined(STM32L0xx) | ||
} | ||
|
||
#if !defined(STM32F0xx) && !defined(STM32L0xx) | ||
/** | ||
* @brief This function handles I2C2 interrupt. | ||
* @param None | ||
|
@@ -558,7 +602,10 @@ void I2C2_ER_IRQHandler(void) | |
I2C_HandleTypeDef * handle = i2c_handles[1]; | ||
HAL_I2C_ER_IRQHandler(handle); | ||
} | ||
#endif // !defined(STM32F0xx) && !defined(STM32L0xx) | ||
#endif // I2C2_BASE | ||
|
||
#if defined(I2C3_BASE) | ||
/** | ||
* @brief This function handles I2C3 interrupt. | ||
* @param None | ||
|
@@ -568,8 +615,12 @@ void I2C3_EV_IRQHandler(void) | |
{ | ||
I2C_HandleTypeDef * handle = i2c_handles[2]; | ||
HAL_I2C_EV_IRQHandler(handle); | ||
#if defined(STM32F0xx) || defined(STM32L0xx) | ||
HAL_I2C_ER_IRQHandler(handle); | ||
#endif // defined(STM32F0xx) || defined(STM32L0xx) | ||
} | ||
|
||
#if !defined(STM32F0xx) && !defined(STM32L0xx) | ||
/** | ||
* @brief This function handles I2C3 interrupt. | ||
* @param None | ||
|
@@ -580,7 +631,10 @@ void I2C3_ER_IRQHandler(void) | |
I2C_HandleTypeDef * handle = i2c_handles[2]; | ||
HAL_I2C_ER_IRQHandler(handle); | ||
} | ||
#endif // !defined(STM32F0xx) && !defined(STM32L0xx) | ||
#endif // I2C3_BASE | ||
|
||
#if defined(I2C4_BASE) | ||
/** | ||
* @brief This function handles I2C4 interrupt. | ||
* @param None | ||
|
@@ -590,8 +644,12 @@ void I2C4_EV_IRQHandler(void) | |
{ | ||
I2C_HandleTypeDef * handle = i2c_handles[3]; | ||
HAL_I2C_EV_IRQHandler(handle); | ||
#if defined(STM32F0xx) || defined(STM32L0xx) | ||
HAL_I2C_ER_IRQHandler(handle); | ||
#endif // defined(STM32F0xx) || defined(STM32L0xx) | ||
} | ||
|
||
#if !defined(STM32F0xx) && !defined(STM32L0xx) | ||
/** | ||
* @brief This function handles I2C4 interrupt. | ||
* @param None | ||
|
@@ -602,6 +660,8 @@ void I2C4_ER_IRQHandler(void) | |
I2C_HandleTypeDef * handle = i2c_handles[3]; | ||
HAL_I2C_ER_IRQHandler(handle); | ||
} | ||
#endif // !defined(STM32F0xx) && !defined(STM32L0xx) | ||
#endif // I2C4_BASE | ||
|
||
/** | ||
* @} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one new proposal : in every place where I2Cx_ER_IRQn is being used couldn't you use
#if defined (I2C1_ER_IRQn)
obj->irqER = I2C1_ER_IRQn;
#endif
this would be more future proof I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I2C1_ER_IRQn is a enum value this could not be done.