From 006137c92db8758bbfff08fa87aacdb5325820f6 Mon Sep 17 00:00:00 2001 From: Magdalena Pastula Date: Tue, 28 Jan 2025 18:16:43 +0100 Subject: [PATCH 1/2] drivers: mspi: prepare APP side driver for receiving data Fixed hard fault that occurs when receiving data caused by memory access violation and changed logging so that all received data is printed, not only an opcode. Signed-off-by: Magdalena Pastula --- drivers/mspi/mspi_nrfe.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/mspi/mspi_nrfe.c b/drivers/mspi/mspi_nrfe.c index f2f784179968..086d307ed034 100644 --- a/drivers/mspi/mspi_nrfe.c +++ b/drivers/mspi/mspi_nrfe.c @@ -157,7 +157,7 @@ static void ep_recv(const void *data, size_t len, void *priv) } } - LOG_DBG("Received msg with opcode: %d", response->opcode); + LOG_HEXDUMP_DBG((uint8_t *)data, len, "Received msg:"); } /** @@ -473,8 +473,15 @@ static int xfer_packet(struct mspi_xfer_packet *packet, uint32_t timeout) /* Wait for the transfer to complete and receive data. */ if ((packet->dir == MSPI_RX) && (ipc_receive_buffer != NULL) && (ipc_received > 0)) { - memcpy((void *)packet->data_buf, (void *)ipc_receive_buffer, ipc_received); - packet->num_bytes = ipc_received; + /* + * It is not possible to check whether received data is valid, so packet->num_bytes + * should always be equal to ipc_received. If it is not, then something went wrong. + */ + if (packet->num_bytes != ipc_received) { + rc = -EIO; + } else { + memcpy((void *)packet->data_buf, (void *)ipc_receive_buffer, ipc_received); + } /* Clear the receive buffer pointer and size */ ipc_receive_buffer = NULL; From bf4777d92e9c0eb010a0b715f202cea7f8ab7dc1 Mon Sep 17 00:00:00 2001 From: Magdalena Pastula Date: Wed, 29 Jan 2025 15:02:33 +0100 Subject: [PATCH 2/2] applications: sdp: mspi: add SPI RX path Add path for receiving data on SPI. Signed-off-by: Magdalena Pastula --- applications/sdp/mspi/Kconfig | 5 + applications/sdp/mspi/src/hrt/hrt-nrf54l15.s | 265 ++++++++++++++++--- applications/sdp/mspi/src/hrt/hrt.c | 134 ++++++++++ applications/sdp/mspi/src/hrt/hrt.h | 8 + applications/sdp/mspi/src/main.c | 80 +++++- 5 files changed, 456 insertions(+), 36 deletions(-) create mode 100644 applications/sdp/mspi/Kconfig diff --git a/applications/sdp/mspi/Kconfig b/applications/sdp/mspi/Kconfig new file mode 100644 index 000000000000..7967741f8df1 --- /dev/null +++ b/applications/sdp/mspi/Kconfig @@ -0,0 +1,5 @@ +config SDP_MSPI_MAX_RESPONSE_SIZE + int "Max size of response that can be sent to APP core. In bytes." + default 128 + +source "Kconfig.zephyr" diff --git a/applications/sdp/mspi/src/hrt/hrt-nrf54l15.s b/applications/sdp/mspi/src/hrt/hrt-nrf54l15.s index 7d1e048aac39..4ed84bf29974 100644 --- a/applications/sdp/mspi/src/hrt/hrt-nrf54l15.s +++ b/applications/sdp/mspi/src/hrt/hrt-nrf54l15.s @@ -103,6 +103,67 @@ hrt_tx: jalr a2 j .L13 .size hrt_tx, .-hrt_tx + .section .text.hrt_tx_rx.constprop.0,"ax",@progbits + .align 1 + .type hrt_tx_rx.constprop.0, @function +hrt_tx_rx.constprop.0: + lw a5,0(a0) + lw a4,4(a0) + beq a4,zero,.L26 + li a4,126976 + slli a1,a1,12 + addi sp,sp,-24 + and a1,a1,a4 + li a4,2097152 + sw s0,16(sp) + sw ra,20(sp) + sw s1,12(sp) + addi a4,a4,1031 + mv s0,a0 + lw a5,0(a5) + or a1,a1,a4 + #APP + csrw 3019, a1 + #NO_APP + li s1,0 +.L17: + lw a4,4(s0) + bltu s1,a4,.L20 + lw ra,20(sp) + lw s0,16(sp) + lw s1,12(sp) + addi sp,sp,24 + jr ra +.L20: + lw a4,16(s0) + li a0,-16777216 + and a0,a5,a0 + sw a3,8(sp) + sw a2,4(sp) + sw a5,0(sp) + jalr a4 + lw a5,0(sp) + lw a2,4(sp) + lw a3,8(sp) + slli a5,a5,8 + bne s1,zero,.L18 + beq a2,zero,.L18 + li a4,65536 + add a4,a3,a4 + #APP + csrw 2002, a4 + #NO_APP +.L19: + addi s1,s1,1 + j .L17 +.L18: + #APP + csrr a4, 3018 + #NO_APP + j .L19 +.L26: + ret + .size hrt_tx_rx.constprop.0, .-hrt_tx_rx.constprop.0 .section .text.hrt_write,"ax",@progbits .align 1 .globl hrt_write @@ -120,23 +181,23 @@ hrt_write: li a5,0 addi a4,a0,4 li a3,4 -.L17: +.L31: lw a2,0(a4) - bne a2,zero,.L16 + bne a2,zero,.L30 addi a5,a5,1 andi a5,a5,0xff addi a4,a4,20 - bne a5,a3,.L17 + bne a5,a3,.L31 li a5,3 -.L16: +.L30: li a4,1 - beq a5,a4,.L18 + beq a5,a4,.L32 li a4,3 - beq a5,a4,.L19 + beq a5,a4,.L33 li a4,0 - bne a5,zero,.L20 + bne a5,zero,.L34 lbu a4,80(s0) -.L20: +.L34: #APP csrw 2000, 2 #NO_APP @@ -163,21 +224,21 @@ hrt_write: li a2,1 add a5,s0,a5 lw a3,4(a5) - beq a3,a2,.L21 + beq a3,a2,.L35 li a2,2 - beq a3,a2,.L22 + beq a3,a2,.L36 li a5,32 div a5,a5,a4 - j .L39 -.L18: + j .L53 +.L32: lbu a4,81(s0) - j .L20 -.L19: + j .L34 +.L33: lbu a4,83(s0) - j .L20 -.L21: + j .L34 +.L35: lbu a5,8(a5) -.L39: +.L53: #APP csrw 3022, a5 #NO_APP @@ -187,11 +248,11 @@ hrt_write: lbu a4,88(s0) slli a5,a5,16 srli a5,a5,16 - bne a4,zero,.L25 + bne a4,zero,.L39 #APP csrc 3008, a5 #NO_APP -.L26: +.L40: lhu a3,84(s0) lbu a1,80(s0) addi a2,sp,3 @@ -213,17 +274,17 @@ hrt_write: addi a0,s0,60 call hrt_tx lbu a5,89(s0) - beq a5,zero,.L27 -.L28: + beq a5,zero,.L41 +.L42: #APP csrr a5, 3022 #NO_APP andi a5,a5,0xff - bne a5,zero,.L28 + bne a5,zero,.L42 #APP csrw 2010, 0 #NO_APP -.L27: +.L41: li a5,16384 addi a5,a5,1 #APP @@ -232,33 +293,173 @@ hrt_write: csrw 2000, 0 #NO_APP lbu a5,87(s0) - bne a5,zero,.L15 + bne a5,zero,.L29 lbu a4,86(s0) li a5,1 sll a5,a5,a4 lbu a4,88(s0) slli a5,a5,16 srli a5,a5,16 - bne a4,zero,.L30 + bne a4,zero,.L44 #APP csrs 3008, a5 #NO_APP -.L15: +.L29: lw ra,12(sp) lw s0,8(sp) addi sp,sp,16 jr ra -.L22: +.L36: lbu a5,9(a5) - j .L39 -.L25: + j .L53 +.L39: #APP csrs 3008, a5 #NO_APP - j .L26 -.L30: + j .L40 +.L44: #APP csrc 3008, a5 #NO_APP - j .L15 + j .L29 .size hrt_write, .-hrt_write + .section .text.hrt_read,"ax",@progbits + .align 1 + .globl hrt_read + .type hrt_read, @function +hrt_read: + addi sp,sp,-12 + sw s0,4(sp) + sw ra,8(sp) + lbu a5,88(a0) + lbu a4,86(a0) + mv s0,a0 + bne a5,zero,.L55 + li a5,1 + sll a5,a5,a4 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrc 3008, a5 + #NO_APP +.L56: + lhu a5,90(s0) + slli a5,a5,16 + srli a5,a5,16 + andi a5,a5,-5 + slli a5,a5,16 + srli a5,a5,16 + sh a5,90(s0) + lhu a5,90(s0) + #APP + csrw 3009, a5 + csrw 3011, 2 + #NO_APP + li a5,65536 + addi a5,a5,4 + #APP + csrw 3043, a5 + csrw 3022, 8 + csrw 2000, 2 + csrw 2001, 2 + #NO_APP + lhu a5,84(s0) + slli a5,a5,16 + srli a5,a5,16 + #APP + csrr a4, 2003 + #NO_APP + li a3,-65536 + and a4,a4,a3 + or a5,a5,a4 + #APP + csrw 2003, a5 + #NO_APP + lhu a5,84(s0) + slli a5,a5,16 + srli a5,a5,16 + #APP + csrr a4, 2003 + #NO_APP + slli a5,a5,1 + slli a4,a4,16 + addi a5,a5,1 + srli a4,a4,16 + slli a5,a5,16 + or a5,a5,a4 + #APP + csrw 2003, a5 + #NO_APP + lbu a1,80(s0) + lhu a3,84(s0) + li a2,1 + mv a0,s0 + call hrt_tx_rx.constprop.0 + lbu a1,81(s0) + lhu a3,84(s0) + li a2,0 + addi a0,s0,20 + call hrt_tx_rx.constprop.0 + li a5,0 +.L57: + lw a4,64(s0) + bltu a5,a4,.L58 + #APP + csrw 2000, 0 + csrw 2001, 0 + csrw 3019, 0 + #NO_APP + lbu a5,87(s0) + bne a5,zero,.L59 + lbu a5,88(s0) + lbu a4,86(s0) + bne a5,zero,.L60 + li a5,1 + sll a5,a5,a4 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrs 3008, a5 + #NO_APP +.L59: + lhu a5,90(s0) + ori a5,a5,4 + sh a5,90(s0) + lhu a5,90(s0) + #APP + csrw 3009, a5 + #NO_APP + lw ra,8(sp) + lw s0,4(sp) + addi sp,sp,12 + jr ra +.L55: + li a5,1 + sll a5,a5,a4 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrs 3008, a5 + #NO_APP + j .L56 +.L58: + #APP + csrr a3, 3018 + #NO_APP + lw a4,60(s0) + srli a3,a3,24 + add a4,a4,a5 + addi a5,a5,1 + sb a3,0(a4) + andi a5,a5,0xff + j .L57 +.L60: + li a5,1 + sll a5,a5,a4 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrc 3008, a5 + #NO_APP + j .L59 + .size hrt_read, .-hrt_read diff --git a/applications/sdp/mspi/src/hrt/hrt.c b/applications/sdp/mspi/src/hrt/hrt.c index abc699990da2..642ecc7c28c5 100644 --- a/applications/sdp/mspi/src/hrt/hrt.c +++ b/applications/sdp/mspi/src/hrt/hrt.c @@ -10,6 +10,22 @@ /* Hardware requirement, to get n shifts SHIFTCNTB register has to be set to n-1*/ #define SHIFTCNTB_VALUE(shift_count) (shift_count - 1) +#define SPI_INPUT_PIN_NUM 2 +#define CNT1_INIT_VALUE 1 +#define MSB_MASK (0xff000000) + +#define INPUT_SHIFT_COUNT (BITS_IN_WORD - BITS_IN_BYTE) + +/* + * Macro for calculating TOP value of CNT1. It should be twice as TOP value of CNT0 + * so that input was sampled on the other clock edge than sending. + * Subtraction of 1 is needed, because value written to the register should be + * equal to N - 1, where N is the desired value. For the same reason value of + * cnt0_top needs to be increased by 1 first - it is already in form that should + * be written to a CNT0 TOP register. + */ +#define CNT1_TOP_CALCULATE(cnt0_top) (2 * ((cnt0_top) + 1) - 1) + /** @brief Shift control configuration. */ typedef struct { uint8_t shift_count; @@ -34,6 +50,12 @@ nrf_vpr_csr_vio_shift_ctrl_buffered_set(nrf_vpr_csr_vio_shift_ctrl_t const *p_sh nrf_csr_write(VPRCSR_NORDIC_SHIFTCTRLB, reg); } +/* Temporary function definition until the one from nrfx has its return type fixed. */ +NRF_STATIC_INLINE uint32_t vpr_csr_vio_in_buffered_reversed_byte_get(void) +{ + return nrf_csr_read(VPRCSR_NORDIC_INBRB); +} + NRF_STATIC_INLINE void nrf_vpr_csr_vio_out_or_set(uint16_t value) { nrf_csr_set_bits(VPRCSR_NORDIC_OUT, value); @@ -197,3 +219,115 @@ void hrt_write(hrt_xfer_t *hrt_xfer_params) } } } + +static void hrt_tx_rx(volatile hrt_xfer_data_t *xfer_data, uint8_t frame_width, bool start_counter, + uint16_t cnt0_val, uint16_t cnt1_val) +{ + nrf_vpr_csr_vio_shift_ctrl_t shift_ctrl = { + .shift_count = BITS_IN_BYTE - 1, + .out_mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE, + .frame_width = frame_width, + .in_mode = NRF_VPR_CSR_VIO_MODE_IN_SHIFT, + }; + + uint32_t to_send = *((uint32_t *)xfer_data->data); + + if (xfer_data->word_count == 0) { + return; + } + + nrf_vpr_csr_vio_shift_ctrl_buffered_set(&shift_ctrl); + + for (uint32_t i = 0; i < xfer_data->word_count; i++) { + xfer_data->vio_out_set(to_send & MSB_MASK); + + to_send = to_send << BITS_IN_BYTE; + + if ((i == 0) && start_counter) { + /* Start both counters */ + nrf_vpr_csr_vtim_combined_counter_set( + (cnt0_val << VPRCSR_NORDIC_CNT_CNT0_Pos) + + (cnt1_val << VPRCSR_NORDIC_CNT_CNT1_Pos)); + } else { + /* + * Since we start reading right after the transmission is started, + * we need to read from INB register in the meantime, even if stop_cnt + * from nrf_vpr_csr_vio_config_t is set to false. Otherwise clock is + * not generated when the actual data is sent by a peripheral device. + */ + nrf_vpr_csr_vio_in_buffered_reversed_byte_get(); + } + } +} + +void hrt_read(volatile hrt_xfer_t *hrt_xfer_params) +{ + static const nrf_vpr_csr_vio_shift_ctrl_t shift_ctrl = { + .out_mode = NRF_VPR_CSR_VIO_SHIFT_NONE, + .in_mode = NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS, + }; + static const nrf_vpr_csr_vio_mode_out_t out_mode = { + .mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE, + .frame_width = 1, + }; + + /* Enable CS */ + if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) { + nrf_vpr_csr_vio_out_clear_set(BIT(hrt_xfer_params->ce_vio)); + } else { + nrf_vpr_csr_vio_out_or_set(BIT(hrt_xfer_params->ce_vio)); + } + + /* Configure clock and pins */ + /* Set DQ1 as input */ + WRITE_BIT(hrt_xfer_params->tx_direction_mask, SPI_INPUT_PIN_NUM, VPRCSR_NORDIC_DIR_INPUT); + nrf_vpr_csr_vio_dir_set(hrt_xfer_params->tx_direction_mask); + + /* Initial configuration */ + nrf_vpr_csr_vio_mode_in_set(NRF_VPR_CSR_VIO_MODE_IN_SHIFT); + nrf_vpr_csr_vio_mode_out_set(&out_mode); + nrf_vpr_csr_vio_shift_cnt_out_set(BITS_IN_BYTE); + + /* Counter settings */ + nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_RELOAD); + nrf_vpr_csr_vtim_count_mode_set(1, NRF_VPR_CSR_VTIM_COUNT_RELOAD); + + /* Set top counters value. Trigger data capture every two clock cycles */ + nrf_vpr_csr_vtim_simple_counter_top_set(0, hrt_xfer_params->counter_value); + nrf_vpr_csr_vtim_simple_counter_top_set(1, + CNT1_TOP_CALCULATE(hrt_xfer_params->counter_value)); + + /* Transfer command */ + hrt_tx_rx(&hrt_xfer_params->xfer_data[HRT_FE_COMMAND], hrt_xfer_params->bus_widths.command, + true, hrt_xfer_params->counter_value, CNT1_INIT_VALUE); + + /* Transfer address */ + hrt_tx_rx(&hrt_xfer_params->xfer_data[HRT_FE_ADDRESS], hrt_xfer_params->bus_widths.address, + false, hrt_xfer_params->counter_value, CNT1_INIT_VALUE); + + for (uint8_t i = 0; i < hrt_xfer_params->xfer_data[HRT_FE_DATA].word_count; i++) { + hrt_xfer_params->xfer_data[HRT_FE_DATA].data[i] = + vpr_csr_vio_in_buffered_reversed_byte_get() >> INPUT_SHIFT_COUNT; + } + + /* Stop counters */ + nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_STOP); + nrf_vpr_csr_vtim_count_mode_set(1, NRF_VPR_CSR_VTIM_COUNT_STOP); + + /* Final configuration */ + nrf_vpr_csr_vio_shift_ctrl_buffered_set(&shift_ctrl); + + /* Disable CS */ + if (!hrt_xfer_params->ce_hold) { + + if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) { + nrf_vpr_csr_vio_out_or_set(BIT(hrt_xfer_params->ce_vio)); + } else { + nrf_vpr_csr_vio_out_clear_set(BIT(hrt_xfer_params->ce_vio)); + } + } + + /* Set DQ1 back as output. */ + WRITE_BIT(hrt_xfer_params->tx_direction_mask, SPI_INPUT_PIN_NUM, VPRCSR_NORDIC_DIR_OUTPUT); + nrf_vpr_csr_vio_dir_set(hrt_xfer_params->tx_direction_mask); +} diff --git a/applications/sdp/mspi/src/hrt/hrt.h b/applications/sdp/mspi/src/hrt/hrt.h index e5a576da8dd2..aa9db4368f98 100644 --- a/applications/sdp/mspi/src/hrt/hrt.h +++ b/applications/sdp/mspi/src/hrt/hrt.h @@ -119,4 +119,12 @@ typedef struct { */ void hrt_write(hrt_xfer_t *hrt_xfer_params); +/** @brief Read. + * + * Function to be used to read data from MSPI. + * + * @param[in] hrt_xfer_params Hrt transfer parameters and data. + */ +void hrt_read(volatile hrt_xfer_t *hrt_xfer_params); + #endif /* _HRT_H__ */ diff --git a/applications/sdp/mspi/src/main.c b/applications/sdp/mspi/src/main.c index 1d64d10a03f3..10127468b9d8 100644 --- a/applications/sdp/mspi/src/main.c +++ b/applications/sdp/mspi/src/main.c @@ -30,11 +30,14 @@ #define CE_PIN_UNUSED UINT8_MAX #define HRT_IRQ_PRIORITY 2 +#define HRT_VEVIF_IDX_READ 17 #define HRT_VEVIF_IDX_WRITE 18 #define VEVIF_IRQN(vevif) VEVIF_IRQN_1(vevif) #define VEVIF_IRQN_1(vevif) VPRCLIC_##vevif##_IRQn +BUILD_ASSERT(CONFIG_SDP_MSPI_MAX_RESPONSE_SIZE > 0, "Response max size should be greater that 0"); + static const uint8_t pin_to_vio_map[VIO_COUNT] = { 4, /* Physical pin 0 */ 0, /* Physical pin 1 */ @@ -68,6 +71,8 @@ static volatile nrfe_mspi_dev_config_t nrfe_mspi_devices[DEVICES_MAX]; static volatile hrt_xfer_t xfer_params; +static volatile uint8_t response_buffer[CONFIG_SDP_MSPI_MAX_RESPONSE_SIZE]; + static struct ipc_ept ep; static atomic_t ipc_atomic_sem = ATOMIC_INIT(0); @@ -169,6 +174,10 @@ static void configure_clock(enum mspi_cpp_mode cpp_mode) break; } } + + WRITE_BIT(out, 3, VPRCSR_NORDIC_OUT_HIGH); + WRITE_BIT(out, 4, VPRCSR_NORDIC_OUT_HIGH); + nrf_vpr_csr_vio_out_set(out); nrf_vpr_csr_vio_config_set(&vio_config); } @@ -228,7 +237,7 @@ static void xfer_execute(nrfe_mspi_xfer_packet_msg_t *xfer_packet) } else { adjust_tail(&xfer_params.xfer_data[HRT_FE_DUMMY_CYCLES], xfer_params.bus_widths.dummy_cycles, - nrfe_mspi_xfer_config.tx_dummy*xfer_params.bus_widths.dummy_cycles); + nrfe_mspi_xfer_config.tx_dummy * xfer_params.bus_widths.dummy_cycles); } xfer_params.xfer_data[HRT_FE_DATA].vio_out_set = @@ -242,6 +251,56 @@ static void xfer_execute(nrfe_mspi_xfer_packet_msg_t *xfer_packet) nrf_vpr_clic_int_pending_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_WRITE)); } +void prepare_and_read_data(nrfe_mspi_xfer_packet_msg_t *xfer_packet, volatile uint8_t *buffer) +{ + volatile nrfe_mspi_dev_config_t *device = + &nrfe_mspi_devices[nrfe_mspi_xfer_config.device_index]; + nrf_vpr_csr_vio_config_t config; + + xfer_params.counter_value = 4; + xfer_params.ce_vio = ce_vios[device->ce_index]; + xfer_params.ce_hold = nrfe_mspi_xfer_config.hold_ce; + xfer_params.ce_polarity = device->ce_polarity; + xfer_params.bus_widths = io_modes[device->io_mode]; + xfer_params.xfer_data[HRT_FE_DATA].data = buffer; + + nrf_vpr_csr_vio_config_get(&config); + config.input_sel = true; + nrf_vpr_csr_vio_config_set(&config); + + /* + * Fix position of command and address if command/address length is < BITS_IN_WORD, + * so that leading zeros would not be printed instead of data bits. + */ + xfer_packet->command = + xfer_packet->command + << (BITS_IN_WORD - nrfe_mspi_xfer_config.command_length * BITS_IN_BYTE); + xfer_packet->address = + xfer_packet->address + << (BITS_IN_WORD - nrfe_mspi_xfer_config.address_length * BITS_IN_BYTE); + + /* Configure command phase. */ + xfer_params.xfer_data[HRT_FE_COMMAND].vio_out_set = + nrf_vpr_csr_vio_out_buffered_reversed_word_set; + xfer_params.xfer_data[HRT_FE_COMMAND].data = (uint8_t *)&xfer_packet->command; + xfer_params.xfer_data[HRT_FE_COMMAND].word_count = nrfe_mspi_xfer_config.command_length; + + /* Configure address phase. */ + xfer_params.xfer_data[HRT_FE_ADDRESS].vio_out_set = + nrf_vpr_csr_vio_out_buffered_reversed_word_set; + xfer_params.xfer_data[HRT_FE_ADDRESS].data = (uint8_t *)&xfer_packet->address; + xfer_params.xfer_data[HRT_FE_ADDRESS].word_count = nrfe_mspi_xfer_config.address_length; + + /* Configure data phase. */ + xfer_params.xfer_data[HRT_FE_DATA].word_count = xfer_packet->num_bytes; + + /* Read/write barrier to make sure that all configuration is done before jumping to HRT. */ + nrf_barrier_rw(); + + /* Read data */ + nrf_vpr_clic_int_pending_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_READ)); +} + static void config_pins(nrfe_mspi_pinctrl_soc_pin_msg_t *pins_cfg) { ce_vios_count = 0; @@ -302,6 +361,7 @@ static void ep_recv(const void *data, size_t len, void *priv) (void)len; nrfe_mspi_flpr_response_msg_t response; uint8_t opcode = *(uint8_t *)data; + uint32_t num_bytes = 0; response.opcode = opcode; @@ -360,16 +420,20 @@ static void ep_recv(const void *data, size_t len, void *priv) break; case NRFE_MSPI_TXRX: { nrfe_mspi_xfer_packet_msg_t *packet = (nrfe_mspi_xfer_packet_msg_t *)data; + num_bytes = packet->num_bytes; - (void)packet; + if (num_bytes > 0) { + prepare_and_read_data(packet, response_buffer + 1); + } break; } default: - response.opcode = NRFE_MSPI_WRONG_OPCODE; + opcode = NRFE_MSPI_WRONG_OPCODE; break; } - ipc_service_send(&ep, (const void *)&response.opcode, sizeof(response)); + response_buffer[0] = opcode; + ipc_service_send(&ep, (const void *)response_buffer, sizeof(opcode) + num_bytes); } static const struct ipc_ept_cfg ep_cfg = { @@ -408,6 +472,11 @@ static int backend_init(void) return 0; } +__attribute__((interrupt)) void hrt_handler_read(void) +{ + hrt_read(&xfer_params); +} + __attribute__((interrupt)) void hrt_handler_write(void) { hrt_write((hrt_xfer_t *)&xfer_params); @@ -421,6 +490,9 @@ int main(void) return 0; } + IRQ_DIRECT_CONNECT(HRT_VEVIF_IDX_READ, HRT_IRQ_PRIORITY, hrt_handler_read, 0); + nrf_vpr_clic_int_enable_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_READ), true); + IRQ_DIRECT_CONNECT(HRT_VEVIF_IDX_WRITE, HRT_IRQ_PRIORITY, hrt_handler_write, 0); nrf_vpr_clic_int_enable_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_WRITE), true);