diff --git a/CMakeLists.txt b/CMakeLists.txt index eadadf3..df19c14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,14 +28,13 @@ if(CONFIG_IOLINK) ${STACK_SRC}/iolink_pde.c ${STACK_SRC}/iolink_pl.c ${STACK_SRC}/iolink_sm.c - src/iol_osal/osal_spi.c - src/iol_osal/osal_irq.c src/osal/osal.c - src/osal/osal_log.c) + src/osal/osal_log.c + src/transciever.c) #zephyr_library_sources_ifdef(CONFIG_XX xx) #target_compile_definitions(${lib_name} PUBLIC MY_DEF="123") - #target_include_directories(${lib_name} PRIVATE lib/etl/include) + target_include_directories(${lib_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/dts/bindingS/iolm) target_compile_options(${lib_name} PRIVATE -Wfatal-errors) endif() \ No newline at end of file diff --git a/README.md b/README.md index 51debd9..0f4cf52 100644 --- a/README.md +++ b/README.md @@ -4,26 +4,41 @@ This repository integrates a [forked](https://github.com/vChavezB/i-link/tree/ze ## Supported PHYS -The RT-Labs stack only supports the MAX14189 PHY. This requires only from the Zephyr board side an SPI interface and an IRQ pin. +The RT-Labs stack only supports the MAX14189 PHY. This requires a Zephyr board that has an SPI interface and GPIOs for the Chip select and IRQ. ## License The IO-Link stack (i.e., backend) is provided by RT-Labs as GPLv3.0. Hence This Zephyr port is also licensed as GPLv3.0. +## Tested boards + +- ESP32 Devkit C +- NRF52833 DK + +Zephyr version v3.6.99 commit `34c84eccec0508b16f5001b20fa369f387d856df` + +## Testing + +Build and flash the sample located in `samples/demo` and follow the Readme.md ## Current Status -This repository is under development and will not provide a stable API/Documentation until the first release version. +This project is in pre-alpha version and will not provide a stable API/Documentation until the first release. + +## Issues + +- Legacy devices (V.1.0) do not go to operate. Some tests have been done and it seems +that the RT-Labs stack cannot process events for legacy devices. The device goes to operate +but the System Managemen (SM) and SMI Configuration Management (CM) do not report back this change. +This happens as it seems that the OD Handler for the event state machine gets stuck. + ### TODOS -- Device Tree bindings for Drivers - Friendly API to initialize stack -- Test with different boards -- Stability -- Samples - Documentation (Usage, Caveats) + diff --git a/dts/bindings/iolm/iol,maxim14819.yaml b/dts/bindings/iolm/iol,maxim14819.yaml new file mode 100644 index 0000000..3678a2b --- /dev/null +++ b/dts/bindings/iolm/iol,maxim14819.yaml @@ -0,0 +1,69 @@ +# Copyright (c) 2024 Victor Chavez +# SPDX-License-Identifier: GPL-3.0-or-later + +description: > + Binding for the MAXIM14819 IOLM Transciever + +compatible: "iolm,maxim14819" + +include: [ spi-device.yaml ] + +properties: + irq-gpios: + type: phandle-array + required: true + description: GPIO pin used for irq + + + chip-address: + description: SPI address of the transceiver + type: int + required: true + + IntE: + description: Initial value of the InterruptEn register + type: int + + CQCtrlA: + description: Initial value of the CQCtrlA register + type: int + + CQCtrlB: + description: Initial value of the CQCtrlB register + type: int + + LEDCtrl: + description: Initial value of the LEDCtrl register + type: int + + CQCfgA: + description: Initial value of the CQCfgA register + type: int + + CQCfgB: + description: Initial value of the CQCfgB register + type: int + + LPCnfgA: + description: Initial value of the LPCnfgA register + type: int + + LPCnfgB: + description: Initial value of the LPCnfgB register + type: int + + IOStCfgA: + description: Initial value of the IOStCfgA register + type: int + + IOStCfgB: + description: Initial value of the IOStCfgB register + type: int + + DrvCurrLim: + description: Initial value of the DrvCurrLim register + type: int + + Clock: + description: Initial value of the Clock register + type: int \ No newline at end of file diff --git a/dts/bindings/iolm/maxim14819.h b/dts/bindings/iolm/maxim14819.h new file mode 100644 index 0000000..aef3954 --- /dev/null +++ b/dts/bindings/iolm/maxim14819.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2024 Victor Chavez + SPDX-License-Identifier: GPL-3.0-or-later +*/ +#define CQCFG_CQFILTEREN BIT(0) +#define CQCFG_DRVDIS BIT(1) +#define CQCFG_PUSHPUL BIT(2) +#define CQCFG_NPN BIT(3) +#define CQCFG_SINKSEL(x) (((x) & 0x03) << 4) +#define CQCFG_SINKSEL_MASK CQCFG_SINKSEL (0x3) +#define CQCFG_SOURCESINK BIT(6) +#define CQCFG_IEC3TH BIT(7) + +#define CLOCK_XTALEN BIT (0) +#define CLOCK_EXTCLKEN BIT (1) +#define CLOCK_CLKDIV(x) (((x) & 0x03) << 2) +#define CLOCK_CLKDIV_MASK CLOCK_CLKDIV (0x03) +#define CLOCK_CLKOEN BIT (4) +#define CLOCK_EXTCLKMIS BIT (5) +#define CLOCK_TXTXENDIS BIT (6) +#define CLOCK_VCCWARNEN BIT (7) + +#define IOSTCFG_DICSINK BIT (0) +#define IOSTCFG_DICSOURCE BIT (1) +#define IOSTCFG_DIEC3TH BIT (2) +#define IOSTCFG_DIFILTEREN BIT (3) +#define IOSTCFG_TX BIT (4) +#define IOSTCFG_TXEN BIT (5) +#define IOSTCFG_CQLEVEL BIT (6) +#define IOSTCFG_DILEVEL BIT (7) + +#define LPCNFG_LPEN BIT (0) +#define LPCNFG_LPCLIMDIS BIT (1) +#define LPCNFG_LPCL2X BIT (2) +#define LPCNFG_LPBL(x) (((x) & 0x03) << 3) +#define LPCNFG_LPBL_MASK LPCNFG_BLA (0x03) +#define LPCNFG_LPDYNBL BIT (5) +#define LPCNFG_LPRT(x) (((x) & 0x03) << 6) +#define LPCNFG_LPRT_MASK LPCNFG_BLA (0x03) + +#define CURR_100MA 0x00 +#define CURR_200MA 0x01 +#define CURR_300MA 0x02 +#define CURR_500MA 0x03 +#define DRVRCURRLIM_CLDIS BIT(5) + +#define CURR_OFF 0x06 + +#define CL_CONF(x) ((x) << CURR_OFF) \ No newline at end of file diff --git a/i-link b/i-link index 25c6a2a..be5bf99 160000 --- a/i-link +++ b/i-link @@ -1 +1 @@ -Subproject commit 25c6a2a518ebcf29aea808385b2d98f3080c9214 +Subproject commit be5bf991eabba9db935cb68ad15a1705ed38205d diff --git a/include/iolm/transciever.h b/include/iolm/transciever.h new file mode 100644 index 0000000..c0f8715 --- /dev/null +++ b/include/iolm/transciever.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2024 Victor Chavez + SPDX-License-Identifier: GPL-3.0-or-later +*/ +#pragma once +#include +#include + +#define TRANSCIEVER_MAX_PORTS 2 + +/** + * @brief Get the Maxim14819 Driver object initialized in src/transciever.c + * + * @param port The IO-Link port number associated to the maxim driver. + * The value should be 0 to CONFIG_IOLINK_NUM_PORTS-1 + * @return driver object if found, NULL otherwise + */ +iolink_hw_drv_t * get_drv(uint8_t port); \ No newline at end of file diff --git a/include/iolm/zephyr.h b/include/iolm/zephyr.h deleted file mode 100644 index cf6c62b..0000000 --- a/include/iolm/zephyr.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright (c) 2024 Victor Chavez - SPDX-License-Identifier: GPL-3.0-or-later -*/ - -#pragma once -#include -#include - -/** - * A function that creates an interrupt handler thread, which will call the - * isr_func when a falling edge is detected on the GPIO pin. - * - * @note In USB mode, the GPIO pin value does not matter, instead the interrupt - * handler is setup to poll a pre defined pin on the FT2232H chip. - * @note In USB mode, state of the GPIO pin is polled and isr_func is called - * when GPIO pin is detected as low. - * @param port In: The GPIO port that is connected to the IRQ pin - * @param gpio_pin In: The GPIO pin that is connected to the IRQ pin - * @param isr_func In: The function that will be called when the interrupt gets - * triggered - * @param irq_arg In: Pointer to the iolink_hw_drv_t structure containing - * thread parameter - */ -int _iolink_setup_int_zephyr (const struct device * port, gpio_pin_t pin, isr_func_t isr_func, void * irq_arg); \ No newline at end of file diff --git a/samples/ifm_sample_app/CMakeLists.txt b/samples/demo/CMakeLists.txt similarity index 79% rename from samples/ifm_sample_app/CMakeLists.txt rename to samples/demo/CMakeLists.txt index a5ebeeb..5520232 100644 --- a/samples/ifm_sample_app/CMakeLists.txt +++ b/samples/demo/CMakeLists.txt @@ -5,9 +5,9 @@ cmake_minimum_required(VERSION 3.20.0) set(IOLINK_MODULE ${CMAKE_CURRENT_SOURCE_DIR}/../..) set(ZEPHYR_EXTRA_MODULES ${IOLINK_MODULE}) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(ifm_sample_app) +project(iolm_demo) target_sources(app PRIVATE src/iolink_smi.c src/iolink_handler.c - src/iol_master_sample_app.c + src/demo.c ) diff --git a/samples/demo/README.md b/samples/demo/README.md new file mode 100644 index 0000000..cfc2fcb --- /dev/null +++ b/samples/demo/README.md @@ -0,0 +1,55 @@ +# Zephyr IO-Link Master Demo + +A sample application running the Zephyr IO-Link Master module with the i-link rt-lab stack. + +## Tested Boards + +- NRF52833DK +- ESP32 + +## Build and Flash + +``` +git clone --recursive https://github.com/vChavezB/zephyr-iolm/ +cd YOUR_ZEPHYR_WEST_WORKSPACE +west build zephyr-iolm/samples/demo -b YOUR_BOARD +west flash +``` + +Where: + +- YOUR_ZEPHYR_WEST_WORKSPACE: Is the installation of your Zephyr SDK (i.e. `west init ..`). + Note: This has only been tested with Zephyr revision v3.6.99 commit `34c84eccec0508b16f5001b20fa369f387d856df` +- `YOUR_BOARD`: `esp32`, `nrf52833dk_nrf52833` + +## Expected Output + +``` +*** Booting Zephyr OS build *** +[00:00:00.252,868] iol_master: IOLM Demo +[00:00:00.252,868] iol_master: Total port cfg 2 +[00:00:00.252,929] iol_master: thread created iolink_handler_thread, prio 4 +[00:00:00.252,960] iol_master: Thread entry iolink_handler_thread +[00:00:00.252,990] iol_master: os_event_create addr 2000a550 +[00:00:00.255,493] iol_master: Thread entry iolink_m_thread +[00:00:00.255,584] iol_master: thread created iolink_m_thread, prio 3 +[00:00:00.255,737] iol_master: os_event_create addr 2000cd40 +[00:00:00.255,859] iol_master: Thread entry iolport1 +[00:00:00.255,920] iol_master: thread created iolport1, prio 2 +[00:00:00.255,981] iol_master: os_event_create addr 2000ced0 +[00:00:00.257,843] iol_master: os_event_create addr 2000cf68 +[00:00:00.257,965] iol_master: Thread entry iolport2 +[00:00:00.258,026] iol_master: thread created iolport2, prio 2 +[00:00:00.258,056] iol_master: os_event_create addr 2000d0f8 +[00:00:00.259,765] iol_master: iolink_handler started +[00:00:00.386,138] iol_master: handle_smi_portevent (1): type = 0, event_code = 0xFF26, count = 0 +[00:00:00.386,169] iol_master: Port status changed +[00:00:00.386,505] iol_master: iolink_start_port: Port 0: iolink device 0x0002b1 for VID 0x0136 +[00:00:00.386,535] iol_master: iolink_start_port: Port 0: Start done! +[00:00:00.950,927] iol_master: handle_smi_portevent (2): type = 0, event_code = 0xFF26, count = 0 +[00:00:00.950,927] iol_master: Port status changed +[00:00:00.951,263] iol_master: iolink_start_port: Port 1: iolink device 0x000243 for VID 0x0136 +[00:00:00.951,293] iol_master: iolink_start_port: Port 1: Start done! +[00:00:01.006,591] iol_master: Port [2] PDIN Cnf 0b61 +[00:00:01.017,425] iol_master: Port [1] PDIN Cnf 00aa +``` \ No newline at end of file diff --git a/samples/demo/boards/esp32_devkitc_wrover_procpu.overlay b/samples/demo/boards/esp32_devkitc_wrover_procpu.overlay new file mode 100644 index 0000000..8b2e6f3 --- /dev/null +++ b/samples/demo/boards/esp32_devkitc_wrover_procpu.overlay @@ -0,0 +1,16 @@ +&uart0 { + current-speed = <460800>; +}; + +&spi2 { + status = "okay"; + cs-gpios = <&gpio0 19 GPIO_ACTIVE_LOW>; + max:maxim14819@0 { + spi-max-frequency = <8000000>; + status = "okay"; + irq-gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + compatible = "iolm,maxim14819"; + reg = <0x00>; + chip-address = <0x00>; + }; +}; diff --git a/samples/demo/boards/nrf52833dk_nrf52833.overlay b/samples/demo/boards/nrf52833dk_nrf52833.overlay new file mode 100644 index 0000000..c505f6d --- /dev/null +++ b/samples/demo/boards/nrf52833dk_nrf52833.overlay @@ -0,0 +1,39 @@ +&uart0 { + current-speed = <460800>; +}; + +&pinctrl { + + spi1_default: spi1_default { + group1 { + psels = , + , + ; + }; + }; + + spi1_sleep: spi1_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; + +//#include + +&spi1 { + status = "okay"; + pinctrl-names = "default", "sleep"; + cs-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + max:maxim14819@0 { + spi-max-frequency = <10000000>; + status = "okay"; + irq-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + compatible = "iolm,maxim14819"; + reg = <0x00>; + chip-address = <0x00>; + }; +}; diff --git a/samples/demo/prj.conf b/samples/demo/prj.conf new file mode 100644 index 0000000..7ddd4ee --- /dev/null +++ b/samples/demo/prj.conf @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Victor Chavez +# SPDX-License-Identifier: GPL-3.0-or-later + +CONFIG_THREAD_NAME=y +CONFIG_LOG=y +CONFIG_IOLINK_LOG_LEVEL_DBG=y +CONFIG_ASSERT=y +CONFIG_MINIMAL_LIBC=y +#CONFIG_LOG_BUFFER_SIZE=16384 +CONFIG_IOLINK=y +CONFIG_IOLINK_MAIN_STACK_SIZE=1024 +CONFIG_IOLINK_DL_STACK_SIZE=1024 +CONFIG_IOLINK_NUM_PORTS=2 \ No newline at end of file diff --git a/samples/demo/src/demo.c b/samples/demo/src/demo.c new file mode 100644 index 0000000..dc9820b --- /dev/null +++ b/samples/demo/src/demo.c @@ -0,0 +1,70 @@ +/* Copyright (c) 2024 Victor Chavez + SPDX-License-Identifier: GPL-3.0-or-later +*/ +#include +#include "osal.h" +#include "osal_irq.h" +#include "osal_log.h" +#include "iolink.h" +#include "iolink_max14819.h" +#include "iolink_handler.h" +#include + +#define IOLINK_HANDLER_THREAD_STACK_SIZE (1024) +#define IOLINK_HANDLER_THREAD_PRIO CONFIG_IOLINK_MASTER_PRIO+1 +static K_THREAD_STACK_DEFINE(iolm_handler_stack, IOLINK_HANDLER_THREAD_STACK_SIZE); + +void main_handler_thread (void * ctx) +{ + const iolink_m_cfg_t * cfg = (const iolink_m_cfg_t *)ctx; + iolink_handler (*cfg); +} + +static iolink_m_cfg_t iolink_cfg = { + .cb_arg = NULL, + .cb_smi = NULL, + .cb_pd = NULL, +}; + +os_thread_t * iolink_handler_thread; + + +iolink_port_cfg_t port_cfgs[CONFIG_IOLINK_NUM_PORTS]; +static iolink_pl_mode_t init_mode[] = +{ + iolink_mode_SDCI, + iolink_mode_INACTIVE, +}; + + +int main(void) +{ + LOG_INF("IOLM Demo"); + uint8_t transciever_cnt = 0; + for (int i = 0; i < CONFIG_IOLINK_NUM_PORTS; i++) { + iolink_hw_drv_t * drv = get_drv(i); + if (drv == NULL) { + LOG_ERR("No driver found for port %d", i); + return -ENODEV; + } + port_cfgs[i].drv = drv; + port_cfgs[i].name = "dummy"; // not used in stack at all + port_cfgs[i].mode = &init_mode[0]; + const uint8_t ch_no = i%TRANSCIEVER_MAX_PORTS; + port_cfgs[i].arg = (void*)(ch_no); + } + + iolink_cfg.port_cnt = CONFIG_IOLINK_NUM_PORTS; + iolink_cfg.port_cfgs = port_cfgs; + LOG_INF("Total port cfg %d", iolink_cfg.port_cnt); + + iolink_handler_thread = os_thread_create ( + "iolink_handler_thread", + IOLINK_HANDLER_THREAD_PRIO, + iolm_handler_stack, + K_THREAD_STACK_SIZEOF(iolm_handler_stack), + main_handler_thread, + (void*)&iolink_cfg); + CC_ASSERT (iolink_handler_thread != NULL); + return 0; +} diff --git a/samples/ifm_sample_app/src/iolink_handler.c b/samples/demo/src/iolink_handler.c similarity index 97% rename from samples/ifm_sample_app/src/iolink_handler.c rename to samples/demo/src/iolink_handler.c index a2f461a..8cc90d1 100644 --- a/samples/ifm_sample_app/src/iolink_handler.c +++ b/samples/demo/src/iolink_handler.c @@ -12,6 +12,9 @@ * license. See the file LICENSE.md distributed with this software for * full license information. ********************************************************************/ +/* Copyright (c) 2024 Victor Chavez + SPDX-License-Identifier: GPL-3.0-or-later +*/ #include #include #include @@ -263,39 +266,21 @@ static uint8_t iolink_start_port (iolink_app_port_ctx_t * app_port) return 1; } - //if (port_status->vendorid == IFM_VENDOR_ID) - { - switch (port_status->deviceid) - { - default: - app_port->type = UNKNOWN; - app_port->app_port_state = IOL_STATE_RUNNING; - app_port->run_function = generic_app; - LOG_INFO ( - LOG_STATE_ON, - "%s: Port %u: iolink device 0x%06x for VID 0x%04x\n", - __func__, - portnumber, - (int)port_status->deviceid, - port_status->vendorid); - break; - } - } - /* - else - { - app_port->type = UNKNOWN; - LOG_WARNING ( + + switch (port_status->deviceid) { + default: + app_port->type = UNKNOWN; + app_port->app_port_state = IOL_STATE_RUNNING; + app_port->run_function = generic_app; + LOG_INFO ( LOG_STATE_ON, - "%s: Port %u: Unknown device: Vendor ID = 0x%04X, Device ID = " - "0x%06X\n", + "%s: Port %u: iolink device 0x%06x for VID 0x%04x\n", __func__, portnumber, - port_status->vendorid, - (int)port_status->deviceid); + (int)port_status->deviceid, + port_status->vendorid); + break; } - */ - LOG_INFO (LOG_STATE_ON, "%s: Port %u: Start done!\n", __func__, portnumber); os_mutex_unlock (app_port->status_mtx); diff --git a/samples/ifm_sample_app/src/iolink_handler.h b/samples/demo/src/iolink_handler.h similarity index 93% rename from samples/ifm_sample_app/src/iolink_handler.h rename to samples/demo/src/iolink_handler.h index ef2f975..1b4be4c 100644 --- a/samples/ifm_sample_app/src/iolink_handler.h +++ b/samples/demo/src/iolink_handler.h @@ -12,7 +12,9 @@ * license. See the file LICENSE.md distributed with this software for * full license information. ********************************************************************/ - +/* Copyright (c) 2024 Victor Chavez + SPDX-License-Identifier: GPL-3.0-or-later +*/ #ifndef IOLINK_HANDLER_H #define IOLINK_HANDLER_H diff --git a/samples/ifm_sample_app/src/iolink_smi.c b/samples/demo/src/iolink_smi.c similarity index 95% rename from samples/ifm_sample_app/src/iolink_smi.c rename to samples/demo/src/iolink_smi.c index ba3bc14..cb8d1de 100644 --- a/samples/ifm_sample_app/src/iolink_smi.c +++ b/samples/demo/src/iolink_smi.c @@ -12,7 +12,9 @@ * license. See the file LICENSE.md distributed with this software for * full license information. ********************************************************************/ - +/* Copyright (c) 2024 Victor Chavez + SPDX-License-Identifier: GPL-3.0-or-later +*/ #include #include "osal.h" #include "osal_log.h" diff --git a/samples/ifm_sample_app/src/iolink_smi.h b/samples/demo/src/iolink_smi.h similarity index 90% rename from samples/ifm_sample_app/src/iolink_smi.h rename to samples/demo/src/iolink_smi.h index 0bdd784..5512798 100644 --- a/samples/ifm_sample_app/src/iolink_smi.h +++ b/samples/demo/src/iolink_smi.h @@ -12,7 +12,9 @@ * license. See the file LICENSE.md distributed with this software for * full license information. ********************************************************************/ - +/* Copyright (c) 2024 Victor Chavez + SPDX-License-Identifier: GPL-3.0-or-later +*/ #ifndef IOLINK_SMI_H #define IOLINK_SMI_H diff --git a/samples/demo/west.yml b/samples/demo/west.yml new file mode 100644 index 0000000..e69de29 diff --git a/samples/ifm_sample_app/README.md b/samples/ifm_sample_app/README.md deleted file mode 100644 index 6c41c17..0000000 --- a/samples/ifm_sample_app/README.md +++ /dev/null @@ -1,16 +0,0 @@ -i-link Sample Application -------------------------- - -A sample application running a single port in SDCI / IO-Link mode with -SMI (Standardised Master Interface) and HMI (Human Machine Interface) support -for controlling a RFID tag reader as well as a display unit. - - -Supported devices ------------------ - -The sample application currently supports two different devices from IFM -(with vendor ID = 0x0136): - -* Display IFM E30391 (device ID = 0x02A9): https://www.ifm.com/se/sv/product/E30391 -* RFID Reader IFM DTI515 (device ID = 0x03C7): https://www.ifm.com/se/sv/product/DTI515 diff --git a/samples/ifm_sample_app/boards/esp32_devkitc_wrover_procpu.overlay b/samples/ifm_sample_app/boards/esp32_devkitc_wrover_procpu.overlay deleted file mode 100644 index 00bf551..0000000 --- a/samples/ifm_sample_app/boards/esp32_devkitc_wrover_procpu.overlay +++ /dev/null @@ -1,27 +0,0 @@ -/ { - - iolm_gpios: iolm_gpios { - compatible = "gpio-leds"; - iolm_irq: iolm_irq { - status = "okay"; - gpios = <&gpio0 18 (GPIO_ACTIVE_LOW)>; - label = "iolm_irq"; - }; - iolm_cs: iolm_cs { - status = "okay"; - gpios = <&gpio0 19 (GPIO_ACTIVE_LOW)>; - label = "iolm_cs"; - }; - }; - - aliases { - iolm-spi= &spi2; - iolm-cs = &iolm_cs; - iolm-irq = &iolm_irq; - }; - -}; - -&uart0 { - current-speed = <460800>; -}; \ No newline at end of file diff --git a/samples/ifm_sample_app/boards/native_posix_64.conf b/samples/ifm_sample_app/boards/native_posix_64.conf deleted file mode 100644 index 77c5be9..0000000 --- a/samples/ifm_sample_app/boards/native_posix_64.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_SPI_EMUL=y -CONFIG_EMUL=y -CONFIG_GPIO_EMUL=y \ No newline at end of file diff --git a/samples/ifm_sample_app/boards/nrf52833dk_nrf52833.overlay b/samples/ifm_sample_app/boards/nrf52833dk_nrf52833.overlay deleted file mode 100644 index e74ead1..0000000 --- a/samples/ifm_sample_app/boards/nrf52833dk_nrf52833.overlay +++ /dev/null @@ -1,47 +0,0 @@ -/ { - - iolm_gpios: iolm_gpios { - compatible = "gpio-leds"; - iolm_irq: iolm_irq { - status = "okay"; - gpios = <&gpio0 28 (GPIO_ACTIVE_LOW)>; - label = "iolm_irq"; - }; - iolm_cs: iolm_cs { - status = "okay"; - gpios = <&gpio1 9 (GPIO_ACTIVE_LOW)>; - label = "iolm_cs"; - }; - }; - - aliases { - iolm-spi= &spi1; - iolm-cs = &iolm_cs; - iolm-irq = &iolm_irq; - }; - -}; - -&uart0 { - current-speed = <460800>; -}; - -&pinctrl { - - spi1_default: spi1_default { - group1 { - psels = , - , - ; - }; - }; - - spi1_sleep: spi1_sleep { - group1 { - psels = , - , - ; - low-power-enable; - }; - }; -}; diff --git a/samples/ifm_sample_app/prj.conf b/samples/ifm_sample_app/prj.conf deleted file mode 100644 index 14c065b..0000000 --- a/samples/ifm_sample_app/prj.conf +++ /dev/null @@ -1,10 +0,0 @@ -CONFIG_CPP=y -CONFIG_STD_CPP17=y -CONFIG_THREAD_NAME=y -CONFIG_LOG=y -CONFIG_IOLINK=y -CONFIG_IOLINK_LOG_LEVEL_DBG=y -CONFIG_ASSERT=y -CONFIG_MINIMAL_LIBC=y -CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE=32768 -CONFIG_LOG_BUFFER_SIZE=16384 \ No newline at end of file diff --git a/samples/ifm_sample_app/src/iol_master_sample_app.c b/samples/ifm_sample_app/src/iol_master_sample_app.c deleted file mode 100644 index 398b301..0000000 --- a/samples/ifm_sample_app/src/iol_master_sample_app.c +++ /dev/null @@ -1,183 +0,0 @@ -/********************************************************************* - * _ _ _ - * _ __ | |_ _ | | __ _ | |__ ___ - * | '__|| __|(_)| | / _` || '_ \ / __| - * | | | |_ _ | || (_| || |_) |\__ \ - * |_| \__|(_)|_| \__,_||_.__/ |___/ - * - * www.rt-labs.com - * Copyright 2021 rt-labs AB, Sweden. - * - * This software is dual-licensed under GPLv3 and a commercial - * license. See the file LICENSE.md distributed with this software for - * full license information. - ********************************************************************/ - -#include -#include "osal.h" -#include "osal_irq.h" -#include "osal_log.h" -#include "iolink.h" -#include "iolink_max14819.h" -#include "iolink_handler.h" -#include - -static const struct device *const spi_dev = DEVICE_DT_GET(DT_ALIAS(iolm_spi)); -static const struct gpio_dt_spec irq_dev = GPIO_DT_SPEC_GET(DT_ALIAS(iolm_irq), gpios); - -#define IOLINK_HANDLER_THREAD_STACK_SIZE (8192) -#define IOLINK_HANDLER_THREAD_PRIO 5 -static K_THREAD_STACK_DEFINE(iolm_handler_stack, IOLINK_HANDLER_THREAD_STACK_SIZE); - - -#define IOLINK_APP_CHIP0_IRQ 25 - -#define IOLINK_APP_CHIP0_ADDRESS 0x0 - -#ifndef IOLINK_APP_CHIP1_ADDRESS -#define IOLINK_APP_CHIP1_ADDRESS 0x0 -#endif - - -static iolink_pl_mode_t mode_ch[] = -{ - iolink_mode_SDCI, - iolink_mode_INACTIVE, -#ifdef IOLINK_APP_CHIP1_SPI - iolink_mode_SDCI, - iolink_mode_INACTIVE, -#endif -}; - -void main_handler_thread (void * ctx) -{ - const iolink_m_cfg_t * cfg = (const iolink_m_cfg_t *)ctx; - iolink_handler (*cfg); -} - -static iolink_hw_drv_t * main_14819_init(const char* name, const iolink_14819_cfg_t * cfg, - const struct device * gpio_port,int irq_pin) -{ - iolink_hw_drv_t * drv; - drv = iolink_14819_init (cfg); - if (drv == NULL) - { - LOG_ERR ("APP: Failed to open SPI %s\n", name); - return NULL; - } - if (_iolink_setup_int_zephyr (gpio_port, irq_pin, iolink_14819_isr, drv) < 0) - { - LOG_ERR ("APP: Failed to setup interrupt %s\n", name); - return NULL; - } - return drv; -} - -static iolink_m_cfg_t iolink_cfg = { - .cb_arg = NULL, - .cb_smi = NULL, - .cb_pd = NULL, - /* Not needed, statically set with Kconfig*/ - .master_thread_prio = 0, - .master_thread_stack_size = 0, - .dl_thread_prio = 0, - .dl_thread_stack_size = 0, -}; - -os_thread_t * iolink_handler_thread; -iolink_hw_drv_t * hw[2]; -#define CURR_100MA 0x00 -#define CURR_200MA 0x01 -#define CURR_300MA 0x02 -#define CURR_500MA 0x03 -#define DRVRCURRLIM_CLDIS BIT(5) - -#define CURR_OFF 0x06 - -#define CL_CONF(x) ((x) << CURR_OFF) -static const iolink_14819_cfg_t iol_14819_0_cfg = { - .chip_address = IOLINK_APP_CHIP0_ADDRESS, - .spi_slave_name = spi_dev, - .CQCfgA = MAX14819_CQCFG_DRVDIS | MAX14819_CQCFG_SINKSEL(0x2), - .CQCfgB = MAX14819_CQCFG_DRVDIS | MAX14819_CQCFG_SINKSEL(0x2), - .LPCnfgA = MAX14819_LPCNFG_LPEN, - .LPCnfgB = MAX14819_LPCNFG_LPEN, - .IOStCfgA = MAX14819_IOSTCFG_DICSINK | MAX14819_IOSTCFG_DIEC3TH, - .IOStCfgB = MAX14819_IOSTCFG_DICSINK | MAX14819_IOSTCFG_DIEC3TH, - .DrvCurrLim = CL_CONF(CURR_300MA), - .Clock = MAX14819_CLOCK_XTALEN | MAX14819_CLOCK_TXTXENDIS, -}; - -#ifdef IOLINK_APP_CHIP1_SPI - -static const iolink_14819_cfg_t iol_14819_1_cfg = { - .chip_address = IOLINK_APP_CHIP1_ADDRESS, - .spi_slave_name = IOLINK_APP_CHIP1_SPI, - .CQCfgA = MAX14819_CQCFG_DRVDIS | MAX14819_CQCFG_SINKSEL(0x2), - .LPCnfgA = MAX14819_LPCNFG_LPEN, - .IOStCfgA = MAX14819_IOSTCFG_DICSINK | MAX14819_IOSTCFG_DIEC3TH, - .DrvCurrLim = 0x00, - .Clock = MAX14819_CLOCK_XTALEN | MAX14819_CLOCK_TXTXENDIS, -}; -#endif - -iolink_port_cfg_t port_cfgs[] = { - { - .name = "/iolink0/0", - .mode = &mode_ch[0], - .arg = (void*)0, - }, - { - .name = "/iolink0/1", - .mode = &mode_ch[0], - .arg = (void*)1, - }, -#ifdef IOLINK_APP_CHIP1_SPI - { - .name = "/iolink1/0", - .mode = &mode_ch[2], - .drv = hw[1], - .arg = (void*)0, - }, - { - .name = "/iolink1/1", - .mode = &mode_ch[3], - .drv = hw[1], - .arg = (void*)1, - }, -#endif - }; - -int main(void) -{ - - - LOG_INF("Starting app"); - hw[0] = main_14819_init("/iolink0", &iol_14819_0_cfg, irq_dev.port, irq_dev.pin); - if (hw[0] == NULL) { - return 0; - } -#ifdef IOLINK_APP_CHIP1_SPI - hw[1] = main_14819_init("/iolink1", &iol_14819_1_cfg, irq_dev.port, irq_dev.pin); -#endif - port_cfgs[0].drv = hw[0]; - port_cfgs[1].drv = hw[0]; - - - iolink_cfg.port_cnt = NELEMENTS (port_cfgs); - iolink_cfg.port_cfgs = port_cfgs; - LOG_INF("Total port cfg %d",iolink_cfg.port_cnt); - - k_sleep(K_MSEC(200)); - - - iolink_handler_thread = os_thread_create ( - "iolink_handler_thread", - IOLINK_HANDLER_THREAD_PRIO, - iolm_handler_stack, - K_THREAD_STACK_SIZEOF(iolm_handler_stack), - main_handler_thread, - (void*)&iolink_cfg); - CC_ASSERT (iolink_handler_thread != NULL); - return 0; -} diff --git a/src/iol_osal/osal_irq.c b/src/iol_osal/osal_irq.c deleted file mode 100644 index df59184..0000000 --- a/src/iol_osal/osal_irq.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 2024 Victor Chavez - SPDX-License-Identifier: GPL-3.0-or-later -*/ - -#include -#include -#include -#include - -struct gpio_cb_data { - struct gpio_callback zephyr_data; - isr_func_t isr_func; - void * arg; -}; - -void gpio_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins){ - const struct gpio_cb_data * cb_data = CONTAINER_OF(cb, struct gpio_cb_data, zephyr_data); - if (cb_data->isr_func) { - cb_data->isr_func(cb_data->arg); - } -} - -int _iolink_setup_int_zephyr (const struct device * port, gpio_pin_t pin, isr_func_t isr_func, void* irq_arg) -{ - if (!device_is_ready(port)) { - return -ENODEV; - } - int rc = gpio_pin_configure(port, pin, GPIO_ACTIVE_LOW | GPIO_INPUT | GPIO_PULL_UP ); - struct gpio_cb_data * cb_data = (struct gpio_cb_data *)malloc(sizeof(struct gpio_cb_data)); - cb_data->arg = irq_arg; - cb_data->isr_func = isr_func; - gpio_init_callback(&cb_data->zephyr_data, gpio_cb, BIT(pin)); - gpio_add_callback(port, &cb_data->zephyr_data); - rc = gpio_pin_interrupt_configure(port,pin,GPIO_INT_EDGE_TO_ACTIVE); - return rc == 0; -} \ No newline at end of file diff --git a/src/iol_osal/osal_spi.c b/src/iol_osal/osal_spi.c deleted file mode 100644 index 69ac520..0000000 --- a/src/iol_osal/osal_spi.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2024 Victor Chavez - SPDX-License-Identifier: GPL-3.0-or-later -*/ - -#include -#include -#include -#include - -static const struct gpio_dt_spec cs_pin = GPIO_DT_SPEC_GET(DT_ALIAS(iolm_cs), gpios); - -static const struct spi_cs_control iolm_cs_pin={ - cs_pin,0 -}; - -// TODO check SPI cfg required for MAX14819 -static struct spi_config spi_cfg = { - .frequency = 20000000U, - .operation = {{SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_OP_MODE_MASTER}}, - .slave = 0U, - .cs = NULL -}; - -void * _iolink_pl_hw_spi_init (const char * device) -{ - gpio_pin_configure_dt(&cs_pin,GPIO_OUTPUT); - gpio_pin_set_dt(&cs_pin,0); - const struct device * spi_dev = (struct device *) device; - if(device_is_ready(spi_dev)!=true) { - return NULL; - } - return (void *)spi_dev; -} - -void _iolink_pl_hw_spi_close (void * fd) -{ - // Nothing to do, driver is initialized by zephyr in kernel -} - -void _iolink_pl_hw_spi_transfer ( - void * fd, - void * data_read, - const void * data_written, - size_t n_bytes_to_transfer) -{ - const struct device * spi_dev = (struct device *) fd; - const struct spi_buf tx_buf = {.buf=(uint8_t*)(data_written), .len=n_bytes_to_transfer}; - const struct spi_buf rx_buf = {.buf=data_read, .len=n_bytes_to_transfer}; - struct spi_buf_set tx_set = {.buffers=&tx_buf, .count=1}; - struct spi_buf_set rx_set = {.buffers=&rx_buf, .count=1}; - gpio_pin_set_dt(&cs_pin,1); - const int spi_res = spi_transceive(spi_dev, - &spi_cfg, - &tx_set, - &rx_set); - gpio_pin_set_dt(&cs_pin,0); - // TODO log error, check how to deal with LOG_DBG -} \ No newline at end of file diff --git a/src/osal/osal.c b/src/osal/osal.c index 2866ec1..8d24b35 100644 --- a/src/osal/osal.c +++ b/src/osal/osal.c @@ -8,15 +8,28 @@ #include #include -void * os_malloc (size_t size) -{ - return malloc (size); -} +#define TIMERS_PER_PORT 3 +#define MUTEX_PER_PORT 6 +#define EVT_PER_PORT 2 +#define THREAD_PER_PORT 1 +#define MBOX_PER_PORT 2 +#define TOTAL_TIMERS (TIMERS_PER_PORT * CONFIG_IOLINK_NUM_PORTS) +#define TOTAL_MUTEX (MUTEX_PER_PORT*CONFIG_IOLINK_NUM_PORTS) +#define TOTAL_EVT (EVT_PER_PORT*CONFIG_IOLINK_NUM_PORTS+20) +#define TOTAL_THREADS (CONFIG_IOLINK_NUM_PORTS*THREAD_PER_PORT+5) +#define TOTAL_MBOX (MBOX_PER_PORT*CONFIG_IOLINK_NUM_PORTS) + +static uint8_t timer_cnt; +static uint8_t mutex_cnt; +static uint8_t evt_cnt; +static uint8_t thread_cnt; +static uint8_t mbox_cnt; +os_timer_t timer_inst[TOTAL_TIMERS]; +struct k_mutex mutex_inst[TOTAL_MUTEX]; +struct k_event evt_inst[TOTAL_EVT]; +struct k_thread thread_inst[TOTAL_THREADS]; +os_mbox_t mbox_inst[TOTAL_MBOX]; -void os_free (void * ptr) -{ - free (ptr); -} static k_timeout_t get_timeout(uint32_t osal_time) { if (osal_time == OS_WAIT_FOREVER) { @@ -27,10 +40,8 @@ static k_timeout_t get_timeout(uint32_t osal_time) { } void os_thread_entry(void *entry, void *arg, void *name) { - LOG_INF("Thread entry %s\n",name); void (*entry_func)(void * arg) = (void (*)(void * arg))entry; entry_func(arg); - //free(thread); // TODO do we need to free the thread or iol-stack thread does not exit? } os_thread_t * os_thread_create ( @@ -41,10 +52,10 @@ os_thread_t * os_thread_create ( void (*entry) (void * arg), void * arg) { - struct k_thread * thread = (struct k_thread *)malloc (sizeof(struct k_thread)); - if (thread == NULL) { + if (thread_cnt >= TOTAL_THREADS) { return NULL; } + struct k_thread * thread = &thread_inst[thread_cnt++]; const k_tid_t tid = k_thread_create(thread, (k_thread_stack_t *)(stkSto), (size_t)stkSize, @@ -58,14 +69,15 @@ os_thread_t * os_thread_create ( if (name != NULL) { k_thread_name_set(thread, name); } - LOG_INF("thread created %s, prio %d",name,priority); return thread; } os_mutex_t * os_mutex_create (void) { - struct k_mutex * mutex = (struct k_mutex *)malloc (sizeof(struct k_mutex)); - CC_ASSERT (mutex != NULL); + if(mutex_cnt >= TOTAL_MUTEX) { + return NULL; + } + struct k_mutex * mutex = &mutex_inst[mutex_cnt++]; k_mutex_init(mutex); return (os_mutex_t *)mutex; } @@ -75,7 +87,6 @@ void os_mutex_lock (os_mutex_t * mutex) k_mutex_lock(mutex, K_FOREVER); } - void os_mutex_unlock (os_mutex_t * mutex) { k_mutex_unlock(mutex); @@ -83,7 +94,7 @@ void os_mutex_unlock (os_mutex_t * mutex) void os_mutex_destroy (os_mutex_t * mutex) { - free(mutex); + mutex_cnt--; } void os_usleep (uint32_t us) @@ -96,37 +107,13 @@ uint32_t os_get_current_time_us (void) return k_uptime_get_32()*1000; } -os_sem_t * os_sem_create (size_t count) -{ - struct k_sem * sem = (struct k_sem *)malloc (sizeof(struct k_sem)); - CC_ASSERT (sem != NULL); - int rc = k_sem_init(sem, count, count); - if (rc!=0) { - free(sem); - return NULL; - } - return sem; -} - -bool os_sem_wait (os_sem_t * sem, uint32_t time) -{ - return k_sem_take(sem, get_timeout(time)) == 0; -} - -void os_sem_signal (os_sem_t * sem) -{ - k_sem_give(sem); -} - -void os_sem_destroy (os_sem_t * sem) -{ - k_sem_reset(sem); - free(sem); -} os_event_t * os_event_create (void) { - struct k_event * event = (struct k_event *)malloc (sizeof(struct k_event)); + if (evt_cnt >= TOTAL_EVT) { + return NULL; + } + struct k_event * event = &evt_inst[evt_cnt++]; CC_ASSERT (event != NULL); k_event_init(event); LOG_INF("os_event_create addr %x\n",event); @@ -155,18 +142,19 @@ void os_event_clr (os_event_t * event, uint32_t value) void os_event_destroy (os_event_t * event) { - free(event); + evt_cnt--; } + os_mbox_t * os_mbox_create (size_t size) { os_mbox_t * mbox; - mbox = (os_mbox_t *)malloc (sizeof (*mbox) + size * sizeof (void *)); - if (mbox == NULL) - { + + if (mbox_cnt >= TOTAL_MBOX || size > MAX_MAILBOX_MSGS) { return NULL; } + mbox = &mbox_inst[mbox_cnt++]; k_mutex_init(&mbox->mutex); k_event_init(&mbox->evt); @@ -175,7 +163,6 @@ os_mbox_t * os_mbox_create (size_t size) mbox->count = 0; mbox->size = size; return mbox; - } size_t get_mbox_cnt(os_mbox_t * mbox){ @@ -236,7 +223,7 @@ bool os_mbox_post (os_mbox_t * mbox, void * msg, uint32_t time) void os_mbox_destroy (os_mbox_t * mbox) { - free (mbox); + mbox_cnt--; } static void timer_internal_cb(struct k_timer * timer) @@ -253,19 +240,15 @@ os_timer_t * os_timer_create ( void * arg, bool oneshot) { - struct k_timer * handle = (struct k_timer *)malloc (sizeof(struct k_timer)); - if (handle == NULL) { - return NULL; - } - os_timer_t * os_timer = (os_timer_t *)malloc (sizeof(os_timer_t)); - if (os_timer == NULL) { - free(handle); + + if (timer_cnt > TOTAL_TIMERS) { return NULL; } - k_timer_init(handle, timer_internal_cb, NULL); - handle->user_data = os_timer; + + os_timer_t * os_timer = &timer_inst[timer_cnt++]; + k_timer_init(&os_timer->handle, timer_internal_cb, NULL); + os_timer->handle.user_data = os_timer; os_timer->one_shot = oneshot; - os_timer->handle = handle; os_timer->fn = fn; os_timer->arg = arg; return os_timer; @@ -278,20 +261,17 @@ void os_timer_set (os_timer_t * timer, uint32_t us) void os_timer_start (os_timer_t * timer) { + k_timeout_t period; if (timer->one_shot) { - k_timer_start(timer->handle, K_USEC(timer->us), K_NO_WAIT); + period = K_NO_WAIT; + } else { - k_timer_start(timer->handle, K_USEC(timer->us), K_USEC(timer->us)); + period = K_USEC(timer->us); } + k_timer_start(&timer->handle, K_USEC(timer->us), period); } void os_timer_stop (os_timer_t * timer) { - k_timer_stop(timer->handle); + k_timer_stop(&timer->handle); } - -void os_timer_destroy (os_timer_t * timer) -{ - free(timer->handle); - free(timer); -} \ No newline at end of file diff --git a/src/osal/sys/osal_sys.h b/src/osal/sys/osal_sys.h index 9a99eba..b3a3012 100644 --- a/src/osal/sys/osal_sys.h +++ b/src/osal/sys/osal_sys.h @@ -25,10 +25,11 @@ typedef struct k_mutex os_mutex_t; typedef struct k_sem os_sem_t; typedef struct k_event os_event_t; typedef uint32_t os_tick_t; +#define MAX_MAILBOX_MSGS 50 typedef struct os_timer { - struct k_timer * handle; + struct k_timer handle; void(*fn) (struct os_timer *, void * arg); void * arg; uint32_t us; @@ -44,7 +45,7 @@ typedef struct os_mbox size_t w; size_t count; size_t size; - void * msg[]; + void * msg[MAX_MAILBOX_MSGS]; } os_mbox_t; #ifdef __cplusplus diff --git a/src/transciever.c b/src/transciever.c new file mode 100644 index 0000000..ed79fa5 --- /dev/null +++ b/src/transciever.c @@ -0,0 +1,172 @@ +/* Copyright (c) 2024 Victor Chavez + SPDX-License-Identifier: GPL-3.0-or-later +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(maxim14819, LOG_LEVEL_DBG); +#define DT_DRV_COMPAT iolm_maxim14819 + +#define DEFAULT_CHIP_ADDRESS 0x00 +#define DEFAULT_INT_E 0x00 +#define DEFAULT_LED_CTRL 0x00 +#define DEFAULT_CQC_CFG (CQCFG_DRVDIS | CQCFG_SINKSEL(0x2)) +#define DEFAULT_CQ_CTRL 0x00 +#define DEFAULT_LPCNFG LPCNFG_LPEN +#define DEFAULT_IOST_CFG (IOSTCFG_DICSINK | IOSTCFG_DIEC3TH) +#define DEFAULT_DRV_CURR_LIMIT (CL_CONF(CURR_300MA)) +#define DEFAULT_CLOCK (CLOCK_XTALEN | CLOCK_TXTXENDIS) + +struct gpio_cb_data { + struct gpio_callback cb; + void * arg; +}; + +struct maxim_14819_cfg { + struct spi_dt_spec spi; + struct gpio_dt_spec irq; + iolink_14819_cfg_t drv; + uint8_t id; +}; + +struct maxim_14819_data { + struct gpio_cb_data irq_data; + iolink_hw_drv_t * hw; +}; + +void irq_cb(const struct device *dev, struct gpio_callback *gpio_cb, uint32_t pins){ + const struct gpio_cb_data * cb_data = CONTAINER_OF(gpio_cb, struct gpio_cb_data, cb); + iolink_14819_isr(cb_data->arg); +} + +static int maxim_init(const struct device *dev){ + const struct maxim_14819_cfg *cfg = dev->config; + struct maxim_14819_data *data = dev->data; + iolink_hw_drv_t * iol_drv = iolink_14819_init(&cfg->drv); + int rc; + do { + if (iol_drv == NULL) { + LOG_ERR("Failed to initialize Maxim 14819 %d", cfg->id); + rc = -ENODEV; + break; + } + data->hw = iol_drv; + rc = gpio_pin_configure_dt(&cfg->irq, GPIO_INPUT); + if (rc != 0) { + LOG_ERR("Failed to configure IRQ pin %d", cfg->irq.pin); + break; + } + data->irq_data.arg = iol_drv; + gpio_init_callback(&data->irq_data.cb, irq_cb, BIT(cfg->irq.pin)); + rc = gpio_add_callback(cfg->irq.port, &data->irq_data.cb); + if (rc != 0) { + LOG_ERR("Failed to add IRQ callback %d", cfg->irq.pin); + break; + } + rc = gpio_pin_interrupt_configure(cfg->irq.port,cfg->irq.pin,GPIO_INT_EDGE_TO_ACTIVE); + if (rc != 0) { + LOG_ERR("Failed to configure IRQ interrupt %d", cfg->irq.pin); + } + }while(0); + return rc; +} + + +#define MAXIM14819_DEFINE(inst) \ + static struct maxim_14819_data maxim_14819_data_##inst ={ \ + .hw = NULL, \ + .irq_data = {.cb = {0}, .arg = NULL} \ + }; \ + static const struct maxim_14819_cfg maxim_14819_cfg_##inst = { \ + .id = inst, \ + .spi = SPI_DT_SPEC_GET(DT_DRV_INST(inst), SPI_WORD_SET(8) | SPI_TRANSFER_MSB, 0), \ + .irq = GPIO_DT_SPEC_GET(DT_DRV_INST(inst), irq_gpios), \ + .drv={.chip_address = DT_INST_PROP(inst, chip_address), \ + .IntE = DT_INST_PROP_OR(inst, IntE,DEFAULT_INT_E), \ + .CQCtrlA = DT_INST_PROP_OR(inst, CQCtrlA,DEFAULT_CQ_CTRL), \ + .spi_slave_name = &maxim_14819_cfg_##inst, \ + .CQCtrlB = DT_INST_PROP_OR(inst, CQCtrlB,DEFAULT_CQ_CTRL), \ + .LEDCtrl = DT_INST_PROP_OR(inst, LEDCtrl,DEFAULT_LED_CTRL), \ + .CQCfgA = DT_INST_PROP_OR(inst, CQCfgA,DEFAULT_CQC_CFG), \ + .CQCfgB = DT_INST_PROP_OR(inst, CQCfgB,DEFAULT_CQC_CFG), \ + .LPCnfgA = DT_INST_PROP_OR(inst, LPCnfgA,DEFAULT_LPCNFG), \ + .LPCnfgB = DT_INST_PROP_OR(inst, LPCnfgB,DEFAULT_LPCNFG), \ + .IOStCfgA = DT_INST_PROP_OR(inst, IOStCfgA,DEFAULT_IOST_CFG), \ + .IOStCfgB = DT_INST_PROP_OR(inst, IOStCfgB,DEFAULT_IOST_CFG), \ + .DrvCurrLim = DT_INST_PROP_OR(inst, DrvCurrLim,DEFAULT_DRV_CURR_LIMIT), \ + .Clock = DT_INST_PROP_OR(inst, Clock,DEFAULT_CLOCK)} \ + }; \ + DEVICE_DT_INST_DEFINE(inst, \ + maxim_init, \ + NULL, \ + &maxim_14819_data_##inst, \ + &maxim_14819_cfg_##inst, \ + POST_KERNEL, \ + CONFIG_TRANSCIEVER_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(MAXIM14819_DEFINE) + + +static const struct device *maxim14819_devices[] = { + DT_INST_FOREACH_STATUS_OKAY(DEVICE_DT_INST_GET), +}; + +iolink_hw_drv_t * get_drv(uint8_t port){ + if (port >= CONFIG_IOLINK_NUM_PORTS ) { + return NULL; + } + const uint8_t drv_idx = port/ TRANSCIEVER_MAX_PORTS; + if (drv_idx > DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)) { + return NULL; + } + if (!device_is_ready(maxim14819_devices[port])) { + return NULL; + } + struct maxim_14819_data *data = maxim14819_devices[drv_idx]->data; + return data->hw; +} + +/*----------------------------------------- + RT Labs Required PL implementation methods +------------------------------------------ */ +void _iolink_pl_hw_spi_transfer ( + void * device, + void * data_read, + const void * data_written, + size_t n_bytes_to_transfer) +{ + const struct spi_buf tx_buf = {.buf=(uint8_t*)(data_written), .len=n_bytes_to_transfer}; + const struct spi_buf rx_buf = {.buf=data_read, .len=n_bytes_to_transfer}; + struct spi_buf_set tx_set = {.buffers=&tx_buf, .count=1}; + struct spi_buf_set rx_set = {.buffers=&rx_buf, .count=1}; + const int spi_res = spi_transceive_dt(device, + &tx_set, + &rx_set); +} + +void * _iolink_pl_hw_spi_init (const char * device) +{ + struct maxim_14819_cfg* cfg = (struct maxim_14819_cfg*) device; + if (!device_is_ready(cfg->spi.bus)) { + return NULL; + } + return &cfg->spi; +} + +void _iolink_pl_hw_spi_close (void * fd) +{ + // Nothing to do +} diff --git a/zephyr/KConfig b/zephyr/KConfig index a6d99b1..4c96f9c 100644 --- a/zephyr/KConfig +++ b/zephyr/KConfig @@ -57,6 +57,13 @@ config IOLINK_MAX_EVENTS help Maximum number of io-link events +config TRANSCIEVER_INIT_PRIORITY + int "Maxim 14819 init priority" + default 90 + help + Priority of the Maxim 14819 transceiver initialization, should be + greater than CONFIG_SPI_INIT_PRIORITY + choice "$(module)_LOG_LEVEL_CHOICE" prompt "Max compiled-in log level for $(module-str)" default $(module)_LOG_LEVEL_DEFAULT diff --git a/zephyr/module.yaml b/zephyr/module.yaml index 01c0ec0..92b3e90 100644 --- a/zephyr/module.yaml +++ b/zephyr/module.yaml @@ -5,3 +5,5 @@ name: iolink build: cmake: . kconfig: zephyr/KConfig + settings: + dts_root: .