From 1d80154c1c182df2238a2616c70d57d1e316fa5f Mon Sep 17 00:00:00 2001 From: Jacek Maksymowicz Date: Tue, 9 Jul 2024 11:32:36 +0200 Subject: [PATCH] imxrt-multi: add PCT2075 I2C temperature sensor Export functions from i2c.c to allow access to I2C busses from other multidriver files. Change some error codes returned from I2C driver. JIRA: NIL-586 --- multi/imxrt-multi/Makefile | 2 +- multi/imxrt-multi/config.h | 12 +++++ multi/imxrt-multi/i2c.c | 52 ++++++++++++++++++--- multi/imxrt-multi/i2c.h | 13 +++++- multi/imxrt-multi/imxrt-multi.c | 16 +++++++ multi/imxrt-multi/imxrt-multi.h | 2 +- multi/imxrt-multi/pct2075.c | 83 +++++++++++++++++++++++++++++++++ multi/imxrt-multi/pct2075.h | 25 ++++++++++ 8 files changed, 195 insertions(+), 10 deletions(-) create mode 100644 multi/imxrt-multi/pct2075.c create mode 100644 multi/imxrt-multi/pct2075.h diff --git a/multi/imxrt-multi/Makefile b/multi/imxrt-multi/Makefile index b286613b..f970cdc2 100644 --- a/multi/imxrt-multi/Makefile +++ b/multi/imxrt-multi/Makefile @@ -8,7 +8,7 @@ NAME := imxrt-multi LOCAL_PATH := $(call my-dir) -LOCAL_SRCS = imxrt-multi.c common.c uart.c gpio.c spi.c i2c.c fs.c posixsrv.c +LOCAL_SRCS = imxrt-multi.c common.c uart.c gpio.c spi.c i2c.c fs.c posixsrv.c pct2075.c ifneq ($(TARGET_SUBFAMILY), imxrt117x) LOCAL_SRCS += trng.c else diff --git a/multi/imxrt-multi/config.h b/multi/imxrt-multi/config.h index 45d19225..26b06c6e 100644 --- a/multi/imxrt-multi/config.h +++ b/multi/imxrt-multi/config.h @@ -1223,6 +1223,18 @@ #endif /* #ifndef __CPU_IMXRT117X */ +/* Temperature */ + +#ifndef PCT2075 +#define PCT2075 0 +#elif !ISBOOLEAN(PCT2075) +#error "PCT2075 must have a value of 0, 1, or be undefined" +#elif !defined(PCT2075_BUS_NUM) +#error "PCT2075_BUS_NUM must be defined" +#elif !defined(PCT2075_DEV_ADDR) +#error "PCT2075_DEV_ADDR must be defined" +#endif + /* libdummyfs */ #ifndef BUILTIN_DUMMYFS #define BUILTIN_DUMMYFS 0 diff --git a/multi/imxrt-multi/i2c.c b/multi/imxrt-multi/i2c.c index d898650f..b04a8b7b 100644 --- a/multi/imxrt-multi/i2c.c +++ b/multi/imxrt-multi/i2c.c @@ -18,9 +18,7 @@ #include #include -#include #include "common.h" -#include "config.h" #include "trace.h" @@ -232,7 +230,7 @@ static inline int _i2c_getAndClearStatus(volatile uint32_t *base) *(base + msr) = status; if ((status & STATUS_PIN_LOW_TIMEOUT) != 0) { - return -ETIME; + return -ETIMEDOUT; } else if ((status & STATUS_FIFO_ERROR) != 0) { return -EIO; @@ -241,7 +239,7 @@ static inline int _i2c_getAndClearStatus(volatile uint32_t *base) return -EIO; } else if ((status & STATUS_NACK) != 0) { - return -ENOENT; + return -ENXIO; } else if ((status & STATUS_STOP) != 0) { return RET_STOP; @@ -266,7 +264,7 @@ static int _i2c_waitForInterrupt(int pos, uint32_t bitWait) *(base + mier) = 0; /* More cleanup will be done by _i2c_finishTransaction */ mutexUnlock(i2c_common[pos].irqMutex); - return -ETIME; + return -ETIMEDOUT; } } while (i2c_common[pos].state != i2c_stateReady); @@ -375,7 +373,7 @@ static int _i2c_finishTransaction(int pos, int ret) ret = -EIO; } - if (ret == -ETIME) { + if (ret == -ETIMEDOUT) { mutexLock(i2c_common[pos].irqMutex); i2c_common[pos].state = i2c_stateReady; /* cond may have been signalled before we turned off IRQ - try to take it to ensure it's @@ -491,6 +489,48 @@ void i2c_handleMsg(msg_t *msg, int dev) } +int multi_i2c_busWrite(unsigned bus, uint8_t dev_addr, const uint8_t *data, uint32_t len) +{ + if (bus >= N_PERIPHERALS) { + return -EINVAL; + } + + unsigned pos = i2cPreConfig[bus].pos; + mutexLock(i2c_common[pos].mutex); + int ret = _i2c_busWrite(pos, dev_addr, data, len); + mutexUnlock(i2c_common[pos].mutex); + return ret; +} + + +int multi_i2c_busRead(unsigned bus, uint8_t dev_addr, uint8_t *data_out, uint32_t len) +{ + if (bus >= N_PERIPHERALS) { + return -EINVAL; + } + + unsigned pos = i2cPreConfig[bus].pos; + mutexLock(i2c_common[pos].mutex); + int ret = _i2c_busRead(pos, dev_addr, data_out, len); + mutexUnlock(i2c_common[pos].mutex); + return ret; +} + + +int multi_i2c_regRead(unsigned bus, uint8_t dev_addr, uint8_t reg_addr, uint8_t *data_out, uint32_t len) +{ + if (bus >= N_PERIPHERALS) { + return -EINVAL; + } + + unsigned pos = i2cPreConfig[bus].pos; + mutexLock(i2c_common[pos].mutex); + int ret = _i2c_regRead(pos, dev_addr, reg_addr, data_out, len); + mutexUnlock(i2c_common[pos].mutex); + return ret; +} + + static int i2c_getMuxData(int mux, int *mode, int *isel, int *daisy) { switch (mux) { diff --git a/multi/imxrt-multi/i2c.h b/multi/imxrt-multi/i2c.h index 6aad9adb..2446be5a 100644 --- a/multi/imxrt-multi/i2c.h +++ b/multi/imxrt-multi/i2c.h @@ -3,8 +3,8 @@ * * i.MX RT i2c driver * - * Copyright 2019 Phoenix Systems - * Author: Andrzej Glowinski + * Copyright 2019, 2024 Phoenix Systems + * Author: Andrzej Glowinski, Jacek Maksymowicz * * This file is part of Phoenix-RTOS. * @@ -23,4 +23,13 @@ void i2c_handleMsg(msg_t *msg, int dev); int i2c_init(void); +int multi_i2c_busWrite(unsigned bus, uint8_t dev_addr, const uint8_t *data, uint32_t len); + + +int multi_i2c_busRead(unsigned bus, uint8_t dev_addr, uint8_t *data_out, uint32_t len); + + +int multi_i2c_regRead(unsigned bus, uint8_t dev_addr, uint8_t reg_addr, uint8_t *data_out, uint32_t len); + + #endif diff --git a/multi/imxrt-multi/imxrt-multi.c b/multi/imxrt-multi/imxrt-multi.c index 8fa68bc4..39c126a3 100644 --- a/multi/imxrt-multi/imxrt-multi.c +++ b/multi/imxrt-multi/imxrt-multi.c @@ -43,6 +43,10 @@ #include #endif +#if PCT2075 +#include "pct2075.h" +#endif + #define MULTI_THREADS_NO 2 #define UART_THREADS_NO 2 @@ -145,6 +149,12 @@ static void multi_dispatchMsg(msg_t *msg) break; #endif +#if PCT2075 + case id_temp1: + pct2075_handleMsg(msg); + break; +#endif + default: msg->o.err = -ENODEV; break; @@ -443,6 +453,12 @@ static int createDevFiles(void) } #endif +#endif + +#if PCT2075 + if (mkFile(&dir, id_temp1, "temp1", multi_port) < 0) { + return -1; + } #endif return 0; diff --git a/multi/imxrt-multi/imxrt-multi.h b/multi/imxrt-multi/imxrt-multi.h index 13256301..13f768d2 100644 --- a/multi/imxrt-multi/imxrt-multi.h +++ b/multi/imxrt-multi/imxrt-multi.h @@ -31,7 +31,7 @@ enum { id_console = 0, id_uart1, id_uart2, id_uart3, id_uart4, id_uart5, id_uart id_i2c5, id_i2c6, id_cm4_0, id_cm4_1, id_cm4_2, id_cm4_3, #endif - id_trng, id_pseudoNull, id_pseudoZero, id_pseudoFull, id_pseudoRandom, id_kmsgctrl, + id_trng, id_pseudoNull, id_pseudoZero, id_pseudoFull, id_pseudoRandom, id_kmsgctrl, id_temp1 }; /* clang-format on */ diff --git a/multi/imxrt-multi/pct2075.c b/multi/imxrt-multi/pct2075.c new file mode 100644 index 00000000..65b9af91 --- /dev/null +++ b/multi/imxrt-multi/pct2075.c @@ -0,0 +1,83 @@ +/* + * Phoenix-RTOS + * + * i.MX RT integrated PCT2075 driver + * + * Copyright 2021, 2024 Phoenix Systems + * Author: Marek Bialowas, Jacek Maksymowicz + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + +#include +#include +#include +#include +#include + +#include "common.h" +#include "i2c.h" +#if PCT2075 + + +static const uint8_t TEMP_REG_ADDR = 0x00u; /* stored temperature value - 16bit */ + + +/* Get temperature in miliCelsius */ +static int pct2075_getTemp(int32_t *tempOut) +{ + uint8_t tempBytes[2]; + int busNum = PCT2075_BUS_NUM; + if (busNum <= 0) { + return -EINVAL; + } + + int ret = multi_i2c_regRead(busNum - 1, PCT2075_DEV_ADDR, TEMP_REG_ADDR, tempBytes, sizeof(tempBytes)); + if (ret < 0) { + return ret; + } + + int16_t tempRaw = ((int16_t)tempBytes[0] << 8) | tempBytes[1]; + *tempOut = (tempRaw >> 5) * 125; + return EOK; +} + + +void pct2075_handleMsg(msg_t *msg) +{ + switch (msg->type) { + case mtOpen: + case mtClose: + msg->o.err = EOK; + break; + case mtWrite: + msg->o.err = -EINVAL; + break; + case mtRead: + /* don't support partial reads, signal EOF */ + if (msg->i.io.offs > 0) { + msg->o.err = 0; /* EOF */ + } + else { + int32_t temp; + int ret = pct2075_getTemp(&temp); + if (ret == EOK) { + ret = snprintf(msg->o.data, msg->o.size, "%d\n", temp); + if ((ret > 0) && ((size_t)ret > msg->o.size)) { + ret = msg->o.size; + } + } + + msg->o.err = ret; + } + break; + default: + msg->o.err = -ENOSYS; + break; + } +} + +#endif /* PCT2075 */ diff --git a/multi/imxrt-multi/pct2075.h b/multi/imxrt-multi/pct2075.h new file mode 100644 index 00000000..b0a56057 --- /dev/null +++ b/multi/imxrt-multi/pct2075.h @@ -0,0 +1,25 @@ +/* + * Phoenix-RTOS + * + * i.MX RT integrated PCT2075 driver + * + * Copyright 2024 Phoenix Systems + * Author: Jacek Maksymowicz + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _PCT2075_H_ +#define _PCT2075_H_ + +#include +#include +#include + + +void pct2075_handleMsg(msg_t *msg); + + +#endif /* _PCT2075_H_ */