From e0a0e0d736b6826dd1caad2898c438c42e3a8a83 Mon Sep 17 00:00:00 2001 From: Jakub Zymelka Date: Wed, 27 Nov 2024 09:41:27 +0100 Subject: [PATCH] applications: sdp: mspi: Add IPC solution to SDP MSPI application Add IPC solution based on icmsg to application for FLPR core to communicate with SDP MSPI driver. Signed-off-by: Jakub Zymelka --- .../nrf54l15dk_nrf54l15_cpuflpr.overlay | 52 +++++ applications/sdp/mspi/prj.conf | 6 +- applications/sdp/mspi/sample.yaml | 2 +- applications/sdp/mspi/src/hrt/hrt.c | 46 ++-- applications/sdp/mspi/src/hrt/hrt.h | 8 +- applications/sdp/mspi/src/main.c | 200 ++++++++++++++---- 6 files changed, 236 insertions(+), 78 deletions(-) diff --git a/applications/sdp/mspi/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay b/applications/sdp/mspi/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay index 4afa34f53f35..c3c8081a6be0 100644 --- a/applications/sdp/mspi/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay +++ b/applications/sdp/mspi/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay @@ -4,6 +4,58 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ +/ { + soc { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + + sram_tx: memory@2003c000 { + reg = <0x2003c000 0x0800>; + }; + + sram_rx: memory@2003c800 { + reg = <0x2003c800 0x0800>; + }; + }; + }; + + ipc { + ipc0: ipc0 { + compatible = "zephyr,ipc-icmsg"; + tx-region = <&sram_tx>; + rx-region = <&sram_rx>; + mboxes = <&cpuflpr_vevif_rx 16>, <&cpuflpr_vevif_tx 20>; + mbox-names = "rx", "tx"; + status = "okay"; + }; + }; +}; + +&cpuflpr_rram { + reg = <0x17a000 DT_SIZE_K(12)>; +}; + +&cpuflpr_code_partition { + reg = <0x0 DT_SIZE_K(12)>; +}; + +&cpuflpr_sram { + reg = <0x2003d000 DT_SIZE_K(12)>; + ranges = <0x0 0x2003d000 0x3000>; +}; + +&cpuflpr_vevif_rx { + status = "okay"; + interrupts = <16 NRF_DEFAULT_IRQ_PRIORITY>; + nordic,tasks = <1>; + nordic,tasks-mask = <0x00010000>; +}; + +&cpuflpr_vevif_tx { + status = "okay"; +}; + &gpio0 { status = "disabled"; }; diff --git a/applications/sdp/mspi/prj.conf b/applications/sdp/mspi/prj.conf index 33d849aaadd3..5db8be05d329 100644 --- a/applications/sdp/mspi/prj.conf +++ b/applications/sdp/mspi/prj.conf @@ -1,3 +1,3 @@ -CONFIG_MBOX=n -CONFIG_IPC_SERVICE=n -CONFIG_IPC_SERVICE_BACKEND_ICMSG=n +CONFIG_MBOX=y +CONFIG_IPC_SERVICE=y +CONFIG_IPC_SERVICE_BACKEND_ICMSG=y diff --git a/applications/sdp/mspi/sample.yaml b/applications/sdp/mspi/sample.yaml index 5baf87658636..9eba8063d713 100644 --- a/applications/sdp/mspi/sample.yaml +++ b/applications/sdp/mspi/sample.yaml @@ -5,7 +5,7 @@ common: integration_platforms: - nrf54l15dk/nrf54l15/cpuflpr tests: - applications.sdp.mspi.icmsg: + applications.sdp.mspi: build_only: true sysbuild: true platform_allow: nrf54l15dk/nrf54l15/cpuflpr diff --git a/applications/sdp/mspi/src/hrt/hrt.c b/applications/sdp/mspi/src/hrt/hrt.c index 35e8bd3ff8bb..b4588856e1e9 100644 --- a/applications/sdp/mspi/src/hrt/hrt.c +++ b/applications/sdp/mspi/src/hrt/hrt.c @@ -22,12 +22,10 @@ void write_single_by_word(volatile struct hrt_ll_xfer xfer_ll_params) NRFX_ASSERT(xfer_ll_params.word_size <= MAX_WORD_SIZE); /* Configuration step */ dir = nrf_vpr_csr_vio_dir_get(); - - nrf_vpr_csr_vio_dir_set(dir | PIN_DIR_OUT_MASK(D0_PIN)); + nrf_vpr_csr_vio_dir_set(dir | PIN_DIR_OUT_MASK(VIO(NRFE_MSPI_DQ0_PIN_NUMBER))); out = nrf_vpr_csr_vio_out_get(); - - nrf_vpr_csr_vio_out_set(out | PIN_OUT_LOW_MASK(D0_PIN)); + nrf_vpr_csr_vio_out_set(out | PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_DQ0_PIN_NUMBER))); nrf_vpr_csr_vio_mode_out_set(&out_mode); nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS); @@ -59,9 +57,9 @@ void write_single_by_word(volatile struct hrt_ll_xfer xfer_ll_params) /* Enable CS */ out = nrf_vpr_csr_vio_out_get(); - out &= ~PIN_OUT_HIGH_MASK(CS_PIN); - out |= xfer_ll_params.ce_enable_state ? PIN_OUT_HIGH_MASK(CS_PIN) - : PIN_OUT_LOW_MASK(CS_PIN); + out &= ~PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)); + out |= xfer_ll_params.ce_enable_state ? PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)) + : PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)); nrf_vpr_csr_vio_out_set(out); /* Start counter */ @@ -84,9 +82,11 @@ void write_single_by_word(volatile struct hrt_ll_xfer xfer_ll_params) /* Disable CS */ if (!xfer_ll_params.ce_hold) { out = nrf_vpr_csr_vio_out_get(); - out &= ~(PIN_OUT_HIGH_MASK(CS_PIN) | PIN_OUT_HIGH_MASK(SCLK_PIN)); - out |= xfer_ll_params.ce_enable_state ? PIN_OUT_LOW_MASK(CS_PIN) - : PIN_OUT_HIGH_MASK(CS_PIN); + out &= ~(PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)) | + PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_SCK_PIN_NUMBER))); + out |= xfer_ll_params.ce_enable_state + ? PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)) + : PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)); nrf_vpr_csr_vio_out_set(out); } @@ -109,13 +109,17 @@ void write_quad_by_word(volatile struct hrt_ll_xfer xfer_ll_params) /* Configuration step */ dir = nrf_vpr_csr_vio_dir_get(); - nrf_vpr_csr_vio_dir_set(dir | PIN_DIR_OUT_MASK(D0_PIN) | PIN_DIR_OUT_MASK(D1_PIN) | - PIN_DIR_OUT_MASK(D2_PIN) | PIN_DIR_OUT_MASK(D3_PIN)); + nrf_vpr_csr_vio_dir_set(dir | PIN_DIR_OUT_MASK(VIO(NRFE_MSPI_DQ0_PIN_NUMBER)) | + PIN_DIR_OUT_MASK(VIO(NRFE_MSPI_DQ1_PIN_NUMBER)) | + PIN_DIR_OUT_MASK(VIO(NRFE_MSPI_DQ2_PIN_NUMBER)) | + PIN_DIR_OUT_MASK(VIO(NRFE_MSPI_DQ3_PIN_NUMBER))); out = nrf_vpr_csr_vio_out_get(); - nrf_vpr_csr_vio_out_set(out | PIN_OUT_LOW_MASK(D0_PIN) | PIN_OUT_LOW_MASK(D1_PIN) | - PIN_OUT_LOW_MASK(D2_PIN) | PIN_OUT_LOW_MASK(D3_PIN)); + nrf_vpr_csr_vio_out_set(out | PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_DQ0_PIN_NUMBER)) | + PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_DQ1_PIN_NUMBER)) | + PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_DQ2_PIN_NUMBER)) | + PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_DQ3_PIN_NUMBER))); nrf_vpr_csr_vio_mode_out_set(&out_mode); nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS); @@ -147,9 +151,9 @@ void write_quad_by_word(volatile struct hrt_ll_xfer xfer_ll_params) /* Enable CS */ out = nrf_vpr_csr_vio_out_get(); - out &= ~PIN_OUT_HIGH_MASK(CS_PIN); - out |= xfer_ll_params.ce_enable_state ? PIN_OUT_HIGH_MASK(CS_PIN) - : PIN_OUT_LOW_MASK(CS_PIN); + out &= ~PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)); + out |= xfer_ll_params.ce_enable_state ? PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)) + : PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)); nrf_vpr_csr_vio_out_set(out); /* Start counter */ @@ -171,9 +175,11 @@ void write_quad_by_word(volatile struct hrt_ll_xfer xfer_ll_params) /* Disable CS */ if (!xfer_ll_params.ce_hold) { out = nrf_vpr_csr_vio_out_get(); - out &= ~(PIN_OUT_HIGH_MASK(CS_PIN) | PIN_OUT_HIGH_MASK(SCLK_PIN)); - out |= xfer_ll_params.ce_enable_state ? PIN_OUT_LOW_MASK(CS_PIN) - : PIN_OUT_HIGH_MASK(CS_PIN); + out &= ~(PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)) | + PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_SCK_PIN_NUMBER))); + out |= xfer_ll_params.ce_enable_state + ? PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)) + : PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)); nrf_vpr_csr_vio_out_set(out); } diff --git a/applications/sdp/mspi/src/hrt/hrt.h b/applications/sdp/mspi/src/hrt/hrt.h index c5e47618720d..94b88a515796 100644 --- a/applications/sdp/mspi/src/hrt/hrt.h +++ b/applications/sdp/mspi/src/hrt/hrt.h @@ -9,13 +9,7 @@ #include #include - -#define SCLK_PIN 0 -#define D0_PIN 1 -#define D1_PIN 2 -#define D2_PIN 3 -#define D3_PIN 4 -#define CS_PIN 5 +#include /* Max word size. */ #define MAX_WORD_SIZE NRF_VPR_CSR_VIO_SHIFT_CNT_OUT_BUFFERED_MAX diff --git a/applications/sdp/mspi/src/main.c b/applications/sdp/mspi/src/main.c index 69a85649a489..2aa528dae0ab 100644 --- a/applications/sdp/mspi/src/main.c +++ b/applications/sdp/mspi/src/main.c @@ -4,10 +4,12 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ -#include "./hrt/hrt.h" +#include "hrt/hrt.h" -#include #include +#include +#include + #include #include #include @@ -30,6 +32,26 @@ #define VEVIF_IRQN(vevif) VEVIF_IRQN_1(vevif) #define VEVIF_IRQN_1(vevif) VPRCLIC_##vevif##_IRQn +typedef struct __packed { + uint8_t opcode; + struct mspi_cfg cfg; +} nrfe_mspi_cfg_t; + +typedef struct __packed { + uint8_t opcode; + struct mspi_dev_cfg cfg; +} nrfe_mspi_dev_cfg_t; + +typedef struct __packed { + uint8_t opcode; + struct mspi_xfer xfer; +} nrfe_mspi_xfer_t; + +typedef struct __packed { + uint8_t opcode; + struct mspi_xfer_packet packet; +} nrfe_mspi_xfer_packet_t; + struct mspi_config { uint8_t *data; uint8_t data_len; @@ -58,6 +80,90 @@ volatile struct hrt_ll_xfer xfer_ll_params = { .ce_enable_state = false, }; +static struct ipc_ept ep; +static atomic_t ipc_atomic_sem = ATOMIC_INIT(0); + +static void process_packet(const void *data, size_t len, void *priv); + +static void ep_bound(void *priv) +{ + (void)priv; + + atomic_set_bit(&ipc_atomic_sem, NRFE_MSPI_EP_BOUNDED); +} + +static struct ipc_ept_cfg ep_cfg = { + .cb = { + .bound = ep_bound, + .received = process_packet, + }, +}; + +static void process_packet(const void *data, size_t len, void *priv) +{ + (void)priv; + (void)len; + nrfe_mspi_flpr_response_t response; + uint8_t opcode = *(uint8_t *)data; + + response.opcode = opcode; + + switch (opcode) { + case NRFE_MSPI_CONFIG_PINS: { + /* TODO: Process pinctrl config data + * nrfe_mspi_pinctrl_soc_pin_t *pins_cfg = (nrfe_mspi_pinctrl_soc_pin_t *)data; + * response.opcode = pins_cfg->opcode; + * + * for (uint8_t i = 0; i < NRFE_MSPI_PINS_MAX; i++) { + * uint32_t psel = NRF_GET_PIN(pins_cfg->pin[i]); + * uint32_t fun = NRF_GET_FUN(pins_cfg->pin[i]); + * NRF_GPIO_Type *reg = nrf_gpio_pin_port_decode(&psel); + * } + */ + break; + } + case NRFE_MSPI_CONFIG_CTRL: { + /* TODO: Process controller config data + * nrfe_mspi_cfg_t *cfg = (nrfe_mspi_cfg_t *)data; + * response.opcode = cfg->opcode; + */ + break; + } + case NRFE_MSPI_CONFIG_DEV: { + /* TODO: Process device config data + * nrfe_mspi_dev_cfg_t *cfg = (nrfe_mspi_dev_cfg_t *)data; + * response.opcode = cfg->opcode; + */ + break; + } + case NRFE_MSPI_CONFIG_XFER: { + /* TODO: Process xfer config data + * nrfe_mspi_xfer_t *xfer = (nrfe_mspi_xfer_t *)data; + * response.opcode = xfer->opcode; + */ + break; + } + case NRFE_MSPI_TX: + case NRFE_MSPI_TXRX: { + nrfe_mspi_xfer_packet_t *packet = (nrfe_mspi_xfer_packet_t *)data; + + response.opcode = packet->opcode; + + if (packet->packet.dir == MSPI_RX) { + /* TODO: Process received data */ + } else if (packet->packet.dir == MSPI_TX) { + /* TODO: Send data */ + } + break; + } + default: + response.opcode = NRFE_MSPI_WRONG_OPCODE; + break; + } + + ipc_service_send(&ep, (const void *)&response.opcode, sizeof(response)); +} + void configure_clock(enum mspi_cpp_mode cpp_mode) { nrf_vpr_csr_vio_config_t vio_config = { @@ -65,27 +171,27 @@ void configure_clock(enum mspi_cpp_mode cpp_mode) .stop_cnt = 0, }; - nrf_vpr_csr_vio_dir_set(PIN_DIR_OUT_MASK(SCLK_PIN)); + nrf_vpr_csr_vio_dir_set(PIN_DIR_OUT_MASK(VIO(NRFE_MSPI_SCK_PIN_NUMBER))); switch (cpp_mode) { case MSPI_CPP_MODE_0: { vio_config.clk_polarity = 0; - nrf_vpr_csr_vio_out_set(PIN_OUT_LOW_MASK(SCLK_PIN)); + nrf_vpr_csr_vio_out_set(PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_SCK_PIN_NUMBER))); break; } case MSPI_CPP_MODE_1: { vio_config.clk_polarity = 1; - nrf_vpr_csr_vio_out_set(PIN_OUT_LOW_MASK(SCLK_PIN)); + nrf_vpr_csr_vio_out_set(PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_SCK_PIN_NUMBER))); break; } case MSPI_CPP_MODE_2: { vio_config.clk_polarity = 1; - nrf_vpr_csr_vio_out_set(PIN_OUT_HIGH_MASK(SCLK_PIN)); + nrf_vpr_csr_vio_out_set(PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_SCK_PIN_NUMBER))); break; } case MSPI_CPP_MODE_3: { vio_config.clk_polarity = 0; - nrf_vpr_csr_vio_out_set(PIN_OUT_HIGH_MASK(SCLK_PIN)); + nrf_vpr_csr_vio_out_set(PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_SCK_PIN_NUMBER))); break; } } @@ -150,23 +256,48 @@ __attribute__((interrupt)) void hrt_handler_write_quad(void) write_quad_by_word(xfer_ll_params); } +static int backend_init(void) +{ + int ret = 0; + const struct device *ipc0_instance; + volatile uint32_t delay = 0; + +#if !defined(CONFIG_SYS_CLOCK_EXISTS) + /* Wait a little bit for IPC service to be ready on APP side */ + while (delay < 1000) { + delay++; + } +#endif + + ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0)); + + ret = ipc_service_open_instance(ipc0_instance); + if ((ret < 0) && (ret != -EALREADY)) { + return ret; + } + + ret = ipc_service_register_endpoint(ipc0_instance, &ep, &ep_cfg); + if (ret < 0) { + return ret; + } + + /* Wait for endpoint to be bound */ + while (!atomic_test_and_clear_bit(&ipc_atomic_sem, NRFE_MSPI_EP_BOUNDED)) { + } + + return 0; +} + int main(void) { + int ret = 0; uint16_t direction; uint16_t output; - /* This is temporary sample data. */ - uint8_t data[30] = {0xa3, 0x21, 0x54, 0x3a, 0x55, 0xa5, 0x45, 0x35, 0x34, 0x23, - 0xa3, 0xad, 0x97, 0xb2, 0x56, 0x54, 0x38, 0x88, 0x0, 0x5, - 0x33, 0x6, 0x34, 0x6, 0x57, 0x7, 0xbb, 0xba, 0xa3, 0xf6}; - - /* This pin initialization is temporary until code is merged with app with GPIO - * initialization - */ - nrf_gpio_pin_dir_t dir = NRF_GPIO_PIN_DIR_OUTPUT; - nrf_gpio_pin_input_t input = NRF_GPIO_PIN_INPUT_DISCONNECT; - nrf_gpio_pin_pull_t pull = NRF_GPIO_PIN_NOPULL; - nrf_gpio_pin_drive_t drive = NRF_GPIO_PIN_E0E1; + ret = backend_init(); + if (ret < 0) { + return 0; + } IRQ_DIRECT_CONNECT(HRT_VEVIF_IDX_WRITE_SINGLE, HRT_IRQ_PRIORITY, hrt_handler_write_single, 0); @@ -177,48 +308,23 @@ int main(void) nrf_vpr_csr_rtperiph_enable_set(true); - /* This pin initialization is temporary until code is merged with app with GPIO - * initialization - */ - nrfy_gpio_reconfigure(NRF_GPIO_PIN_MAP(2, SCLK_PIN), &dir, &input, &pull, &drive, NULL); - nrfy_gpio_reconfigure(NRF_GPIO_PIN_MAP(2, D0_PIN), &dir, &input, &pull, &drive, NULL); - nrfy_gpio_reconfigure(NRF_GPIO_PIN_MAP(2, D1_PIN), &dir, &input, &pull, &drive, NULL); - nrfy_gpio_reconfigure(NRF_GPIO_PIN_MAP(2, D2_PIN), &dir, &input, &pull, &drive, NULL); - nrfy_gpio_reconfigure(NRF_GPIO_PIN_MAP(2, D3_PIN), &dir, &input, &pull, &drive, NULL); - nrfy_gpio_reconfigure(NRF_GPIO_PIN_MAP(2, CS_PIN), &dir, &input, &pull, &drive, NULL); - - nrfy_gpio_pin_control_select(NRF_GPIO_PIN_MAP(2, SCLK_PIN), NRF_GPIO_PIN_SEL_VPR); - nrfy_gpio_pin_control_select(NRF_GPIO_PIN_MAP(2, D0_PIN), NRF_GPIO_PIN_SEL_VPR); - nrfy_gpio_pin_control_select(NRF_GPIO_PIN_MAP(2, D1_PIN), NRF_GPIO_PIN_SEL_VPR); - nrfy_gpio_pin_control_select(NRF_GPIO_PIN_MAP(2, D2_PIN), NRF_GPIO_PIN_SEL_VPR); - nrfy_gpio_pin_control_select(NRF_GPIO_PIN_MAP(2, D3_PIN), NRF_GPIO_PIN_SEL_VPR); - nrfy_gpio_pin_control_select(NRF_GPIO_PIN_MAP(2, CS_PIN), NRF_GPIO_PIN_SEL_VPR); - configure_clock(MSPI_CPP_MODE_0); direction = nrf_vpr_csr_vio_dir_get(); - - nrf_vpr_csr_vio_dir_set(direction | PIN_DIR_OUT_MASK(CS_PIN)); + nrf_vpr_csr_vio_dir_set(direction | PIN_DIR_OUT_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER))); output = nrf_vpr_csr_vio_out_get(); + nrf_vpr_csr_vio_out_set(output | PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER))); - nrf_vpr_csr_vio_out_set(output | PIN_OUT_HIGH_MASK(CS_PIN)); - + /* This initialization is temporary until code is merged with APP core part */ mspi_dev_configs.ce_polarity = MSPI_CE_ACTIVE_LOW; mspi_dev_configs.io_mode = MSPI_IO_MODE_SINGLE; mspi_dev_configs.cmd_length = 32; mspi_dev_configs.addr_length = 32; - /* This is here only temporarly to set command and address parameters. */ data_buffer[XFER_COMMAND_IDX] = 0xe5b326c1; data_buffer[XFER_ADDRESS_IDX] = 0xaabbccdd; - prepare_and_send_data(data, 30); - - mspi_dev_configs.io_mode = MSPI_IO_MODE_QUAD; - - prepare_and_send_data(data, 30); - while (true) { k_cpu_idle(); }