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); 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;