Advanced Distributed Systems module at HSLU
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
ADIS_Projects/McuLib/src/McuI2cLib.c

173 lines
5.0 KiB

/*
* Copyright (c) 2019-2022, Erich Styger
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "McuI2cLibconfig.h"
#if McuLib_CONFIG_MCUI2CLIB_ENABLED
#include "McuLib.h"
#include "McuI2cLib.h"
#include "fsl_i2c.h"
#include "McuGPIO.h"
#include "McuWait.h"
#if McuLib_CONFIG_CPU_IS_KINETIS
#include "fsl_port.h"
#elif McuLib_CONFIG_CPU_IS_LPC
#include "pin_mux.h"
#include "fsl_iocon.h"
#endif
#if McuLib_CONFIG_CPU_VARIANT==McuLib_CONFIG_CPU_VARIANT_NXP_LPC845
#include "fsl_swm.h"
#endif
static uint8_t i2cSlaveDeviceAddr; /* used to store the current I2C device address used */
uint8_t McuI2cLib_SendBlock(void *Ptr, uint16_t Siz, uint16_t *Snt) {
status_t status;
#if McuLib_CONFIG_CPU_IS_KINETIS
I2C_MasterClearStatusFlags(MCUI2CLIB_CONFIG_I2C_MASTER_BASEADDR, kI2C_ArbitrationLostFlag | kI2C_IntPendingFlag | kI2C_StartDetectFlag | kI2C_StopDetectFlag);
#elif McuLib_CONFIG_CPU_IS_LPC
I2C_MasterClearStatusFlags(MCUI2CLIB_CONFIG_I2C_MASTER_BASEADDR, kI2C_MasterPendingFlag | kI2C_MasterArbitrationLostFlag | kI2C_MasterStartStopErrorFlag);
#endif
status = I2C_MasterStart(MCUI2CLIB_CONFIG_I2C_MASTER_BASEADDR, i2cSlaveDeviceAddr, kI2C_Write);
if (status!=kStatus_Success) {
return ERR_FAILED;
}
#if MCUI2CLIB_CONFIG_ADD_DELAY
McuWait_Waitus(MCUI2CLIB_CONFIG_ADD_DELAY_US);
#endif
status = I2C_MasterWriteBlocking(MCUI2CLIB_CONFIG_I2C_MASTER_BASEADDR, Ptr, Siz, kI2C_TransferNoStartFlag|kI2C_TransferNoStopFlag);
if (status!=kStatus_Success) {
return ERR_FAILED;
}
*Snt = Siz;
return ERR_OK;
}
uint8_t McuI2cLib_RecvBlock(void *Ptr, uint16_t Siz, uint16_t *Rcv) {
status_t status;
status = I2C_MasterRepeatedStart(MCUI2CLIB_CONFIG_I2C_MASTER_BASEADDR, i2cSlaveDeviceAddr, kI2C_Read);
if (status!=kStatus_Success) {
return ERR_FAILED;
}
#if MCUI2CLIB_CONFIG_ADD_DELAY
McuWait_Waitus(MCUI2CLIB_CONFIG_ADD_DELAY_US);
#endif
status = I2C_MasterReadBlocking(MCUI2CLIB_CONFIG_I2C_MASTER_BASEADDR, Ptr, Siz, kI2C_TransferDefaultFlag);
if (status!=kStatus_Success) {
return ERR_FAILED;
}
*Rcv = Siz;
return ERR_OK;
}
uint8_t McuI2cLib_SendStop(void) {
status_t status;
status = I2C_MasterStop(MCUI2CLIB_CONFIG_I2C_MASTER_BASEADDR);
if (status!=kStatus_Success) {
return ERR_FAILED;
}
return ERR_OK;
}
uint8_t McuI2cLib_SelectSlave(uint8_t Slv) {
i2cSlaveDeviceAddr = Slv;
return ERR_OK;
}
static void McuI2cLib_ReleaseBus(void) {
McuGPIO_Handle_t sdaPin, sclPin;
McuGPIO_Config_t config;
uint8_t i = 0;
McuGPIO_GetDefaultConfig(&config);
config.isInput = false;
config.isHighOnInit = true;
config.hw.gpio = MCUI2CLIB_CONFIG_SDA_GPIO;
config.hw.pin = MCUI2CLIB_CONFIG_SDA_GPIO_PIN;
config.hw.port = MCUI2CLIB_CONFIG_SDA_GPIO_PORT;
sdaPin = McuGPIO_InitGPIO(&config);
config.hw.gpio = MCUI2CLIB_CONFIG_SCL_GPIO;
config.hw.pin = MCUI2CLIB_CONFIG_SCL_GPIO_PIN;
config.hw.port = MCUI2CLIB_CONFIG_SCL_GPIO_PORT;
sclPin = McuGPIO_InitGPIO(&config);
/* Drive SDA low first to simulate a start */
McuGPIO_SetLow(sdaPin);
McuWait_Waitus(10);
/* Send 9 pulses on SCL and keep SDA high */
for (i = 0; i < 9; i++) {
McuGPIO_SetLow(sclPin);
McuWait_Waitus(10);
McuGPIO_SetHigh(sdaPin);
McuWait_Waitus(10);
McuGPIO_SetHigh(sclPin);
McuWait_Waitus(20);
}
/* Send stop */
McuGPIO_SetLow(sclPin);
McuWait_Waitus(10);
McuGPIO_SetLow(sdaPin);
McuWait_Waitus(10);
McuGPIO_SetLow(sclPin);
McuWait_Waitus(10);
McuGPIO_SetHigh(sdaPin);
McuWait_Waitus(10);
/* cleanup */
sdaPin = McuGPIO_DeinitGPIO(sdaPin);
sclPin = McuGPIO_DeinitGPIO(sclPin);
}
/* mux as I2C pins */
static void McuI2cLib_ConfigureI2cPins(void) {
#if McuLib_CONFIG_CPU_IS_KINETIS \
|| McuLib_CONFIG_CPU_VARIANT==McuLib_CONFIG_CPU_VARIANT_NXP_LPC55S16 \
|| McuLib_CONFIG_CPU_VARIANT==McuLib_CONFIG_CPU_VARIANT_NXP_LPC55S69 \
|| McuLib_CONFIG_CPU_VARIANT==McuLib_CONFIG_CPU_VARIANT_NXP_LPC845
MCUI2CLIB_CONFIG_MUX_I2C_PINS();
#else
#error "unknown configuration and MCU"
#endif
}
void McuI2cLib_Deinit(void) {
}
void McuI2cLib_Init(void) {
McuI2cLib_ReleaseBus();
#if McuLib_CONFIG_CPU_IS_KINETIS \
|| McuLib_CONFIG_CPU_IS_LPC55xx && McuLib_CONFIG_CPU_VARIANT==McuLib_CONFIG_CPU_VARIANT_NXP_LPC55S16 \
|| McuLib_CONFIG_CPU_IS_LPC55xx && McuLib_CONFIG_CPU_VARIANT==McuLib_CONFIG_CPU_VARIANT_NXP_LPC55S69 \
|| McuLib_CONFIG_CPU_IS_LPC && McuLib_CONFIG_CPU_VARIANT==McuLib_CONFIG_CPU_VARIANT_NXP_LPC845
MCUI2CLIB_CONFIG_CLOCK_SELECT();
#else
#error "unknown configuration and MCU"
#endif
McuI2cLib_ConfigureI2cPins();
i2c_master_config_t masterConfig;
uint32_t sourceClock;
/*
* masterConfig->baudRate_Bps = 100000U;
* masterConfig->enableStopHold = false;
* masterConfig->glitchFilterWidth = 0U;
* masterConfig->enableMaster = true;
*/
I2C_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate_Bps = MCUI2CLIB_CONFIG_I2C_BAUDRATE;
sourceClock = MCUI2CLIB_CONFIG_I2C_MASTER_CLK_FREQ;
I2C_MasterInit(MCUI2CLIB_CONFIG_I2C_MASTER_BASEADDR, &masterConfig, sourceClock);
}
#endif /* McuGenericI2C_CONFIG_INTERFACE_HEADER_FILE */