281 lines
7.8 KiB
C
281 lines
7.8 KiB
C
//
|
|
// Created by xemon on 13.10.22.
|
|
//
|
|
|
|
#include "I2cPortNation.h"
|
|
#include "SystemDelayInterface.h"
|
|
|
|
|
|
bool vI2cPortNationWaitBusy(tI2cPortNation *env, uint32_t endTimeout) {
|
|
while (I2C_GetFlag(env->I2Cx, I2C_FLAG_BUSY)) {
|
|
if (SystemGetMs() > endTimeout)return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool vI2cPortNationWaitMasterMode(tI2cPortNation *env, uint32_t endTimeout) {
|
|
while (!I2C_CheckEvent(env->I2Cx, I2C_EVT_MASTER_MODE_FLAG)) {
|
|
if (SystemGetMs() > endTimeout)return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool vI2cPortNationWaitTxAllow(tI2cPortNation *env, uint32_t endTimeout) {
|
|
|
|
while (!I2C_CheckEvent(env->I2Cx, I2C_EVT_MASTER_TXMODE_FLAG)) {
|
|
if (SystemGetMs() > endTimeout)return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool vI2cPortNationWaitRxAllow(tI2cPortNation *env, uint32_t endTimeout) {
|
|
|
|
while (!I2C_CheckEvent(env->I2Cx, I2C_EVT_MASTER_DATA_RECVD_FLAG)) {
|
|
if (SystemGetMs() > endTimeout)return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool vI2cPortNationWaitByteFull(tI2cPortNation *env, uint32_t endTimeout) {
|
|
|
|
while (!I2C_GetFlag(env->I2Cx, I2C_FLAG_BYTEF)) {
|
|
if (SystemGetMs() > endTimeout)return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool vI2cPortNationWaitDataSend(tI2cPortNation *env, uint32_t endTimeout) {
|
|
while (!I2C_CheckEvent(env->I2Cx, I2C_EVT_MASTER_DATA_SENDED)) {
|
|
if (SystemGetMs() > endTimeout)return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void vI2cPortNationSendAddr(tI2cPortNation *env, uint16_t devAddress, uint8_t direction) {
|
|
if (env->initStruct.AddrMode == I2C_ADDR_MODE_7BIT) {
|
|
I2C_SendAddr7bit(env->I2Cx, devAddress, direction);
|
|
} else {
|
|
assert_param(env->initStruct.AddrMode == I2C_ADDR_MODE_7BIT);
|
|
}
|
|
}
|
|
|
|
///?????
|
|
bool vI2cPortNationWaitAddrf(tI2cPortNation *env, uint32_t endTimeout) {
|
|
while (!I2C_GetFlag(env->I2Cx, I2C_FLAG_ADDRF)) {
|
|
if (SystemGetMs() > endTimeout)return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#define I2C_NATION_RETURN_SEND() return dataByte - data;
|
|
|
|
//Return if error
|
|
#define I2C_NATION_RIFE(FUNC) if(FUNC){ I2C_GenerateStop(env->I2Cx, ENABLE); return dataByte - data;}
|
|
|
|
uint16_t vI2cPortNationWrite(tI2cPortNation *env, uint16_t devAddress, uint8_t *data, uint16_t size, uint32_t timeout) {
|
|
uint32_t endTimeout = SystemGetMs() + timeout;
|
|
uint8_t *dataByte = data;
|
|
uint8_t *dataEnd = data + size;
|
|
|
|
|
|
I2C_NATION_RIFE(vI2cPortNationWaitBusy(env, endTimeout))
|
|
I2C_GenerateStart(env->I2Cx, ENABLE);
|
|
|
|
|
|
if (env->initStruct.AckEnable == I2C_ACKEN) {
|
|
I2C_NATION_RIFE(vI2cPortNationWaitMasterMode(env, endTimeout))
|
|
}
|
|
|
|
vI2cPortNationSendAddr(env, devAddress, I2C_DIRECTION_SEND);
|
|
|
|
I2C_NATION_RIFE(vI2cPortNationWaitTxAllow(env, endTimeout))
|
|
|
|
while ((SystemGetMs() < endTimeout) && (dataByte < dataEnd)) {
|
|
I2C_SendData(env->I2Cx, *dataByte);
|
|
I2C_NATION_RIFE(vI2cPortNationWaitDataSend(env, endTimeout))
|
|
++dataByte;
|
|
}
|
|
I2C_GenerateStop(env->I2Cx, ENABLE);
|
|
|
|
I2C_NATION_RETURN_SEND();
|
|
}
|
|
|
|
#define I2C_NATION_READ_ONE_DATA_BYTE() *dataByte = I2C_RecvData(env->I2Cx); ++dataByte; --left
|
|
|
|
uint16_t vI2cPortNationRead(tI2cPortNation *env, uint16_t devAddress, uint8_t *data, uint16_t size, uint32_t timeout) {
|
|
uint32_t endTimeout = SystemGetMs() + timeout;
|
|
uint8_t *dataByte = data;
|
|
uint8_t *dataEnd = data + size;
|
|
|
|
I2C_NATION_RIFE(vI2cPortNationWaitBusy(env, endTimeout))
|
|
|
|
I2C_GenerateStart(env->I2Cx, ENABLE);
|
|
|
|
I2C_NATION_RIFE(vI2cPortNationWaitMasterMode(env, endTimeout))
|
|
|
|
vI2cPortNationSendAddr(env, devAddress, I2C_DIRECTION_RECV);
|
|
|
|
I2C_NATION_RIFE(vI2cPortNationWaitAddrf(env, endTimeout))
|
|
|
|
|
|
|
|
/** While there is data to be read */
|
|
if (size == 1) {
|
|
/** Disable Acknowledgement */
|
|
I2C_ConfigAck(env->I2Cx, DISABLE);
|
|
(void) (env->I2Cx->STS1); /// clear ADDR
|
|
(void) (env->I2Cx->STS2);
|
|
I2C_GenerateStop(env->I2Cx, ENABLE);
|
|
} else if (size == 2) {
|
|
env->I2Cx->CTRL1 |= 0x0800; /// set POSEN
|
|
(void) (env->I2Cx->STS1);
|
|
(void) (env->I2Cx->STS2);
|
|
I2C_ConfigAck(env->I2Cx, DISABLE);
|
|
} else {
|
|
I2C_ConfigAck(env->I2Cx, ENABLE);
|
|
(void) (env->I2Cx->STS1);
|
|
(void) (env->I2Cx->STS2);
|
|
}
|
|
|
|
uint16_t left = size;
|
|
while ((SystemGetMs() < endTimeout) && (dataByte < dataEnd)) {
|
|
|
|
if (size <= 3) {
|
|
/** One byte */
|
|
if (left == 1) {
|
|
|
|
I2C_NATION_RIFE(vI2cPortNationWaitRxAllow(env, endTimeout))
|
|
|
|
I2C_NATION_READ_ONE_DATA_BYTE();
|
|
}
|
|
/** Two bytes */
|
|
else if (left == 2) {
|
|
|
|
I2C_NATION_RIFE(vI2cPortNationWaitByteFull(env, endTimeout))
|
|
|
|
I2C_GenerateStop(env->I2Cx, ENABLE);
|
|
|
|
I2C_NATION_READ_ONE_DATA_BYTE();
|
|
I2C_NATION_READ_ONE_DATA_BYTE();
|
|
|
|
}
|
|
/** 3 Last bytes */
|
|
else {
|
|
I2C_NATION_RIFE(vI2cPortNationWaitByteFull(env, endTimeout))
|
|
|
|
I2C_ConfigAck(env->I2Cx, DISABLE);
|
|
|
|
I2C_NATION_READ_ONE_DATA_BYTE();
|
|
|
|
|
|
I2C_NATION_RIFE(vI2cPortNationWaitByteFull(env, endTimeout))
|
|
|
|
I2C_GenerateStop(env->I2Cx, ENABLE);
|
|
|
|
|
|
I2C_NATION_READ_ONE_DATA_BYTE();
|
|
I2C_NATION_READ_ONE_DATA_BYTE();
|
|
|
|
}
|
|
} else {
|
|
|
|
|
|
I2C_NATION_RIFE(vI2cPortNationWaitRxAllow(env, endTimeout))
|
|
|
|
I2C_NATION_READ_ONE_DATA_BYTE();
|
|
|
|
|
|
if (I2C_GetFlag(env->I2Cx, I2C_FLAG_BYTEF)) {
|
|
|
|
I2C_NATION_READ_ONE_DATA_BYTE();
|
|
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
I2C_NATION_RETURN_SEND()
|
|
}
|
|
|
|
|
|
|
|
//void dfad() {
|
|
// /** GPIO configuration and clock enable */
|
|
// GPIO_InitType GPIO_InitStructure;
|
|
//
|
|
//
|
|
// /** enable peripheral clk*/
|
|
// RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_I2C1, ENABLE);
|
|
//
|
|
// RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
|
|
// RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
|
|
//
|
|
// RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
|
|
// GPIO_ConfigPinRemap(GPIO_RMP_I2C1, ENABLE);
|
|
//
|
|
//
|
|
// GPIO_InitStructure.Pin = I2Cx_SCL_PIN | I2Cx_SDA_PIN;
|
|
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
|
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
|
|
// GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure);
|
|
//
|
|
//}
|
|
|
|
|
|
//void initNvic() {
|
|
//#if PROCESS_MODE == 1 /* interrupt */
|
|
// /** I2C NVIC configuration */
|
|
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
|
|
// NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
|
|
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
|
|
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
|
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
|
// NVIC_Init(&NVIC_InitStructure);
|
|
// NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;
|
|
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
|
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
|
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
|
// NVIC_Init(&NVIC_InitStructure);
|
|
//#elif PROCESS_MODE == 2 /* DMA */
|
|
// RCC_EnableAHBPeriphClk(RCC_AHBPERIPH_DMA1, ENABLE);
|
|
//#endif
|
|
//}
|
|
|
|
void vI2cPortNationInit7bit(tI2cPortNation *env, I2C_Module *I2Cx, uint32_t I2C_Speed) {
|
|
|
|
|
|
I2C_InitType I2C_InitStructure;
|
|
|
|
/** I2C periphral configuration */
|
|
I2C_DeInit(I2Cx);
|
|
|
|
I2C_InitStructure.BusMode = I2C_BUSMODE_I2C;
|
|
I2C_InitStructure.FmDutyCycle = I2C_FMDUTYCYCLE_2;
|
|
I2C_InitStructure.OwnAddr1 = 0xff;
|
|
I2C_InitStructure.AckEnable = I2C_ACKEN;
|
|
I2C_InitStructure.AddrMode = I2C_ADDR_MODE_7BIT;
|
|
I2C_InitStructure.ClkSpeed = I2C_Speed;
|
|
|
|
|
|
I2C_Init(I2Cx, &I2C_InitStructure);
|
|
|
|
env->initStruct = I2C_InitStructure;
|
|
env->I2Cx = I2Cx;
|
|
}
|
|
|
|
tI2cIO I2cPortNation_GetIO(tI2cPortNation *env) {
|
|
|
|
return (tI2cIO) {
|
|
.env = env,
|
|
.read = (I2C_IO_Operation) vI2cPortNationRead,
|
|
.write = (I2C_IO_Operation) vI2cPortNationWrite,
|
|
};
|
|
} |