1
0
forked from me/IronOS
Files
IronOS/workspace/TS100/Core/Src/FRToSI2C.cpp
Ben V. Brown a49c4e9740 WiP some general cleanup with help of new IDE
Static'ing more of the code where possible
2019-08-19 18:53:29 +10:00

190 lines
5.0 KiB
C++

/*
* FRToSI2C.cpp
*
* Created on: 14Apr.,2018
* Author: Ralim
*/
#include "hardware.h"
#include "FRToSI2C.hpp"
#define I2CUSESDMA
I2C_HandleTypeDef* FRToSI2C::i2c;
SemaphoreHandle_t FRToSI2C::I2CSemaphore;
StaticSemaphore_t FRToSI2C::xSemaphoreBuffer;
void FRToSI2C::CpltCallback() {
i2c->State = HAL_I2C_STATE_READY; // Force state reset (even if tx error)
if (I2CSemaphore) {
xSemaphoreGiveFromISR(I2CSemaphore, NULL);
}
}
void FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
uint16_t MemAddSize, uint8_t* pData, uint16_t Size) {
if (I2CSemaphore == NULL) {
// no RToS, run blocking code
HAL_I2C_Mem_Read(i2c, DevAddress, MemAddress, MemAddSize, pData, Size,
5000);
} else {
// RToS is active, run threading
// Get the mutex so we can use the I2C port
// Wait up to 1 second for the mutex
if (xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE) {
#ifdef I2CUSESDMA
if (HAL_I2C_Mem_Read(i2c, DevAddress, MemAddress, MemAddSize, pData,
Size, 500) != HAL_OK) {
I2C1_ClearBusyFlagErratum();
xSemaphoreGive(I2CSemaphore);
}
xSemaphoreGive(I2CSemaphore);
#else
HAL_I2C_Mem_Read(i2c, DevAddress, MemAddress, MemAddSize, pData, Size,
5000);
xSemaphoreGive(I2CSemaphore);
#endif
} else {
}
}
}
void FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) {
Mem_Write(address, reg, I2C_MEMADD_SIZE_8BIT, &data, 1);
}
uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) {
uint8_t tx_data[1];
Mem_Read(add, reg, I2C_MEMADD_SIZE_8BIT, tx_data, 1);
return tx_data[0];
}
void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress,
uint16_t MemAddSize, uint8_t* pData, uint16_t Size) {
if (I2CSemaphore == NULL) {
// no RToS, run blocking code
HAL_I2C_Mem_Write(i2c, DevAddress, MemAddress, MemAddSize, pData, Size,
5000);
} else {
// RToS is active, run threading
// Get the mutex so we can use the I2C port
// Wait up to 1 second for the mutex
if (xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE) {
#ifdef I2CUSESDMA
if (HAL_I2C_Mem_Write(i2c, DevAddress, MemAddress, MemAddSize,
pData, Size, 500) != HAL_OK) {
I2C1_ClearBusyFlagErratum();
xSemaphoreGive(I2CSemaphore);
}
xSemaphoreGive(I2CSemaphore);
#else
if (HAL_I2C_Mem_Write(i2c, DevAddress, MemAddress, MemAddSize, pData,
Size, 5000) != HAL_OK) {
}
xSemaphoreGive(I2CSemaphore);
#endif
} else {
}
}
}
void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t* pData, uint16_t Size) {
if (I2CSemaphore == NULL) {
// no RToS, run blocking code
HAL_I2C_Master_Transmit(i2c, DevAddress, pData, Size, 5000);
} else {
// RToS is active, run threading
// Get the mutex so we can use the I2C port
// Wait up to 1 second for the mutex
if (xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE) {
#ifdef I2CUSESDMA
if (HAL_I2C_Master_Transmit_DMA(i2c, DevAddress, pData, Size)
!= HAL_OK) {
I2C1_ClearBusyFlagErratum();
xSemaphoreGive(I2CSemaphore);
}
#else
HAL_I2C_Master_Transmit(i2c, DevAddress, pData, Size, 5000);
xSemaphoreGive(I2CSemaphore);
#endif
} else {
}
}
}
void FRToSI2C::I2C1_ClearBusyFlagErratum() {
GPIO_InitTypeDef GPIO_InitStruct;
int timeout = 100;
int timeout_cnt = 0;
// 1. Clear PE bit.
i2c->Instance->CR1 &= ~(0x0001);
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
// 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Pin = SCL_Pin;
HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
GPIO_InitStruct.Pin = SDA_Pin;
HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
while (GPIO_PIN_SET != HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin)) {
//Move clock to release I2C
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET);
asm("nop");
asm("nop");
asm("nop");
asm("nop");
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
timeout_cnt++;
if (timeout_cnt > timeout)
return;
}
// 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Pin = SCL_Pin;
HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SDA_Pin;
HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET);
// 13. Set SWRST bit in I2Cx_CR1 register.
i2c->Instance->CR1 |= 0x8000;
asm("nop");
// 14. Clear SWRST bit in I2Cx_CR1 register.
i2c->Instance->CR1 &= ~0x8000;
asm("nop");
// 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register
i2c->Instance->CR1 |= 0x0001;
// Call initialization function.
HAL_I2C_Init(i2c);
}