I2C protection
This commit is contained in:
@@ -6,14 +6,16 @@
|
||||
*/
|
||||
|
||||
#include <I2CBB.hpp>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#define SCL_HIGH() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_SET)
|
||||
#define SCL_LOW() HAL_GPIO_WritePin(SCL2_GPIO_Port, SCL2_Pin, GPIO_PIN_RESET)
|
||||
#define SDA_HIGH() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_SET)
|
||||
#define SDA_LOW() HAL_GPIO_WritePin(SDA2_GPIO_Port, SDA2_Pin, GPIO_PIN_RESET)
|
||||
#define SDA_READ() (HAL_GPIO_ReadPin(SDA2_GPIO_Port,SDA2_Pin)==GPIO_PIN_SET?1:0)
|
||||
#define SCL_READ() (HAL_GPIO_ReadPin(SCL2_GPIO_Port,SCL2_Pin)==GPIO_PIN_SET?1:0)
|
||||
#define I2C_DELAY() {for(int xx=0;xx<100;xx++){asm("nop");}}
|
||||
#define I2C_DELAY() {for(int xx=0;xx<700;xx++){asm("nop");}}
|
||||
SemaphoreHandle_t I2CBB::I2CSemaphore = NULL;
|
||||
StaticSemaphore_t I2CBB::xSemaphoreBuffer;
|
||||
void I2CBB::init() {
|
||||
//Set GPIO's to output open drain
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
@@ -25,6 +27,9 @@ void I2CBB::init() {
|
||||
HAL_GPIO_Init(SDA2_GPIO_Port, &GPIO_InitStruct);
|
||||
SDA_HIGH();
|
||||
SCL_HIGH();
|
||||
I2CSemaphore = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer);
|
||||
xSemaphoreGive(I2CSemaphore);
|
||||
unlock();
|
||||
}
|
||||
|
||||
bool I2CBB::probe(uint8_t address) {
|
||||
@@ -36,15 +41,26 @@ bool I2CBB::probe(uint8_t address) {
|
||||
|
||||
bool I2CBB::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData,
|
||||
uint16_t Size) {
|
||||
if (!lock())
|
||||
return false;
|
||||
start();
|
||||
bool ack = send(DevAddress | 1);
|
||||
bool ack = send(DevAddress);
|
||||
if (!ack) {
|
||||
stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
ack = send(MemAddress);
|
||||
if (!ack) {
|
||||
stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
start();
|
||||
ack = send(DevAddress | 1);
|
||||
if (!ack) {
|
||||
stop();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
while (Size) {
|
||||
@@ -53,20 +69,27 @@ bool I2CBB::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData,
|
||||
Size--;
|
||||
}
|
||||
stop();
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool I2CBB::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData,
|
||||
uint16_t Size) {
|
||||
if (!lock())
|
||||
return false;
|
||||
start();
|
||||
bool ack = send(DevAddress);
|
||||
if (!ack) {
|
||||
stop();
|
||||
asm("bkpt");
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
ack = send(MemAddress);
|
||||
if (!ack) {
|
||||
stop();
|
||||
asm("bkpt");
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
while (Size) {
|
||||
@@ -74,40 +97,51 @@ bool I2CBB::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData,
|
||||
bool ack = send(pData[0]);
|
||||
if (!ack) {
|
||||
stop();
|
||||
asm("bkpt");
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
pData++;
|
||||
Size--;
|
||||
}
|
||||
stop();
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
void I2CBB::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
|
||||
if (!lock())
|
||||
return;
|
||||
start();
|
||||
bool ack = send(DevAddress);
|
||||
if (!ack) {
|
||||
stop();
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
while (Size) {
|
||||
bool ack = send(pData[0]);
|
||||
if (!ack) {
|
||||
stop();
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
pData++;
|
||||
Size--;
|
||||
}
|
||||
stop();
|
||||
unlock();
|
||||
|
||||
}
|
||||
|
||||
void I2CBB::Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
|
||||
if (!lock())
|
||||
return;
|
||||
start();
|
||||
bool ack = send(DevAddress | 1);
|
||||
if (!ack) {
|
||||
stop();
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
while (Size) {
|
||||
@@ -116,23 +150,28 @@ void I2CBB::Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
|
||||
Size--;
|
||||
}
|
||||
stop();
|
||||
unlock();
|
||||
}
|
||||
|
||||
void I2CBB::TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx,
|
||||
uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx) {
|
||||
if (Size_tx == 0 && Size_rx == 0)
|
||||
return;
|
||||
if (lock() == false)
|
||||
return;
|
||||
if (Size_tx) {
|
||||
start();
|
||||
bool ack = send(DevAddress);
|
||||
if (!ack) {
|
||||
stop();
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
while (Size_tx) {
|
||||
bool ack = send(pData_tx[0]);
|
||||
if (!ack) {
|
||||
stop();
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
pData_tx++;
|
||||
@@ -144,6 +183,7 @@ void I2CBB::TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx,
|
||||
bool ack = send(DevAddress | 1);
|
||||
if (!ack) {
|
||||
stop();
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
while (Size_rx) {
|
||||
@@ -153,6 +193,7 @@ void I2CBB::TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx,
|
||||
}
|
||||
}
|
||||
stop();
|
||||
unlock();
|
||||
}
|
||||
|
||||
void I2CBB::start() {
|
||||
@@ -220,6 +261,17 @@ uint8_t I2CBB::read_bit() {
|
||||
return b;
|
||||
}
|
||||
|
||||
void I2CBB::unlock() {
|
||||
xSemaphoreGive(I2CSemaphore);
|
||||
}
|
||||
|
||||
bool I2CBB::lock() {
|
||||
if (I2CSemaphore == NULL) {
|
||||
asm("bkpt");
|
||||
}
|
||||
return xSemaphoreTake(I2CSemaphore, (TickType_t) 50) == pdTRUE;
|
||||
}
|
||||
|
||||
void I2CBB::write_bit(uint8_t val) {
|
||||
if (val > 0)
|
||||
SDA_HIGH();
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "BSP.h"
|
||||
#include "Setup.h"
|
||||
#include "Pins.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
/*
|
||||
* Simple static I2C bit-bang class used on the TS80P
|
||||
* SCL = PA5
|
||||
@@ -31,6 +33,10 @@ public:
|
||||
static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx,
|
||||
uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx);
|
||||
private:
|
||||
static SemaphoreHandle_t I2CSemaphore;
|
||||
static StaticSemaphore_t xSemaphoreBuffer;
|
||||
static void unlock();
|
||||
static bool lock();
|
||||
static void start();
|
||||
static void stop();
|
||||
static bool send(uint8_t value);
|
||||
|
||||
Reference in New Issue
Block a user