From b6ab25ff8133adc10d07005f439ba8a806842379 Mon Sep 17 00:00:00 2001 From: Michal Frankiewicz Date: Wed, 22 Jan 2025 09:45:18 +0100 Subject: [PATCH 1/4] cmake: Fixed mspi.h include error kobj-types-enum.h was generated after VPR asm_gen, added kobj-types-enum.h as dependence for asm_gen. Signed-off-by: Michal Frankiewicz --- cmake/sdp.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/sdp.cmake b/cmake/sdp.cmake index 573ffe0e1c1e..619a18fb4b3d 100644 --- a/cmake/sdp.cmake +++ b/cmake/sdp.cmake @@ -46,7 +46,7 @@ function(sdp_assembly_generate hrt_srcs) ) endforeach() - add_dependencies(asm_gen syscall_list_h_target) + add_dependencies(asm_gen syscall_list_h_target kobj_types_h_target) endfunction() From 6f5c33e3b2c66c00b0b4f4070e761828e1b2fb17 Mon Sep 17 00:00:00 2001 From: Jakub Zymelka Date: Thu, 23 Jan 2025 16:31:36 +0100 Subject: [PATCH 2/4] drivers: mspi: Mode and structures added mode support for SINGLE,QUAD,QUAD_1_4_4,QUAD_1_1_4 and custom Ipc mspi structures Signed-off-by: Michal Frankiewicz Signed-off-by: Jakub Zymelka --- drivers/mspi/mspi_nrfe.c | 6 ++--- include/drivers/mspi/nrfe_mspi.h | 42 ++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/drivers/mspi/mspi_nrfe.c b/drivers/mspi/mspi_nrfe.c index 96eb895e812d..9e530b00df50 100644 --- a/drivers/mspi/mspi_nrfe.c +++ b/drivers/mspi/mspi_nrfe.c @@ -386,15 +386,13 @@ static int api_config(const struct mspi_dt_spec *spec) } /* Send pinout configuration to FLPR */ - ret = send_config(NRFE_MSPI_CONFIG_PINS, (const void *)pins_cfg.pin, - sizeof(pins_cfg)); + ret = send_config(NRFE_MSPI_CONFIG_PINS, (const void *)pins_cfg.pin, sizeof(pins_cfg)); if (ret < 0) { return ret; } /* Send controller configuration to FLPR */ - return send_config(NRFE_MSPI_CONFIG_CTRL, (const void *)config, - sizeof(struct mspi_cfg)); + return send_config(NRFE_MSPI_CONFIG_CTRL, (const void *)config, sizeof(struct mspi_cfg)); } static int check_io_mode(enum mspi_io_mode io_mode) diff --git a/include/drivers/mspi/nrfe_mspi.h b/include/drivers/mspi/nrfe_mspi.h index 467b6806739c..f404a42e1d8a 100644 --- a/include/drivers/mspi/nrfe_mspi.h +++ b/include/drivers/mspi/nrfe_mspi.h @@ -8,42 +8,34 @@ #define DRIVERS_MSPI_NRFE_MSPI_H #include +#include #ifdef __cplusplus extern "C" { #endif #ifdef CONFIG_SOC_NRF54L15 -#define NRFE_MSPI_PORT_NUMBER 2 /* Physical port number */ + +#define NRFE_MSPI_PORT_NUMBER 2 /* Physical port number */ #define NRFE_MSPI_SCK_PIN_NUMBER 1 /* Physical pins number on port 2 */ #define NRFE_MSPI_DQ0_PIN_NUMBER 2 #define NRFE_MSPI_DQ1_PIN_NUMBER 4 #define NRFE_MSPI_DQ2_PIN_NUMBER 3 #define NRFE_MSPI_DQ3_PIN_NUMBER 0 #define NRFE_MSPI_CS0_PIN_NUMBER 5 -#define NRFE_MSPI_PINS_MAX 6 - -#define NRFE_MSPI_SCK_PIN_NUMBER_VIO 0 /* FLPR VIO SCLK pin number */ -#define NRFE_MSPI_DQ0_PIN_NUMBER_VIO 1 -#define NRFE_MSPI_DQ1_PIN_NUMBER_VIO 2 -#define NRFE_MSPI_DQ2_PIN_NUMBER_VIO 3 -#define NRFE_MSPI_DQ3_PIN_NUMBER_VIO 4 -#define NRFE_MSPI_CS0_PIN_NUMBER_VIO 5 +#define NRFE_MSPI_PINS_MAX 6 -#define VIO(_pin_) _pin_##_VIO #else #error "Unsupported SoC for SDP MSPI" #endif -#define NRFE_MSPI_MAX_CE_PINS_COUNT 5 /* Ex. CE0 CE1 CE2 CE3 CE4 */ - /** @brief eMSPI opcodes. */ enum nrfe_mspi_opcode { NRFE_MSPI_EP_BOUNDED = 0, NRFE_MSPI_CONFIG_PINS, - NRFE_MSPI_CONFIG_CTRL, /* struct mspi_cfg */ - NRFE_MSPI_CONFIG_DEV, /* struct mspi_dev_cfg */ - NRFE_MSPI_CONFIG_XFER, /* struct mspi_xfer */ + NRFE_MSPI_CONFIG_CTRL, /* struct mspi_cfg */ + NRFE_MSPI_CONFIG_DEV, /* struct mspi_dev_cfg */ + NRFE_MSPI_CONFIG_XFER, /* struct mspi_xfer */ NRFE_MSPI_TX, NRFE_MSPI_TXRX, NRFE_MSPI_WRONG_OPCODE, @@ -60,6 +52,26 @@ typedef struct __packed { uint8_t data; } nrfe_mspi_flpr_response_t; +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; + #ifdef __cplusplus } #endif From 5b8af6185b6ea5232f4e9734d7f96d4aa41c4c9a Mon Sep 17 00:00:00 2001 From: Michal Frankiewicz Date: Thu, 23 Jan 2025 16:31:36 +0100 Subject: [PATCH 3/4] applications: sdp: mspi: Ipc communication reaction Added reactions to all mspi Ipc messages but NRFE_MSPI_TXRX and NRFE_MSPI_TX. The data is stored in local structures for later use. Signed-off-by: Michal Frankiewicz --- .../boards/nrf54l15dk_nrf54l15_cpuflpr.conf | 2 + applications/sdp/mspi/src/hrt/hrt.h | 68 +-- applications/sdp/mspi/src/hrt/hrt.s | 421 ++++++++---------- applications/sdp/mspi/src/main.c | 297 ++++++------ 4 files changed, 338 insertions(+), 450 deletions(-) diff --git a/applications/sdp/mspi/boards/nrf54l15dk_nrf54l15_cpuflpr.conf b/applications/sdp/mspi/boards/nrf54l15dk_nrf54l15_cpuflpr.conf index 6c1b7543e212..21b98e3b93ad 100644 --- a/applications/sdp/mspi/boards/nrf54l15dk_nrf54l15_cpuflpr.conf +++ b/applications/sdp/mspi/boards/nrf54l15dk_nrf54l15_cpuflpr.conf @@ -44,3 +44,5 @@ CONFIG_SYS_CLOCK_EXISTS=n CONFIG_OUTPUT_DISASSEMBLY=y CONFIG_COMMON_LIBC_MALLOC=n + +CONFIG_COMPILER_OPT="-fshort-enums" diff --git a/applications/sdp/mspi/src/hrt/hrt.h b/applications/sdp/mspi/src/hrt/hrt.h index 94b88a515796..443a62634371 100644 --- a/applications/sdp/mspi/src/hrt/hrt.h +++ b/applications/sdp/mspi/src/hrt/hrt.h @@ -10,67 +10,39 @@ #include #include #include +#include -/* Max word size. */ -#define MAX_WORD_SIZE NRF_VPR_CSR_VIO_SHIFT_CNT_OUT_BUFFERED_MAX +#define VPRCSR_NORDIC_OUT_HIGH 1 +#define VPRCSR_NORDIC_OUT_LOW 0 -/* Macro for getting direction mask for specified pin and direction. */ -#define PIN_DIR_MASK(PIN_NUM, DIR) \ - (VPRCSR_NORDIC_DIR_PIN##PIN_NUM##_##DIR << VPRCSR_NORDIC_DIR_PIN##PIN_NUM##_Pos) +#define VPRCSR_NORDIC_DIR_OUTPUT 1 +#define VPRCSR_NORDIC_DIR_INPUT 0 -/* Macro for getting output mask for specified pin. */ -#define PIN_DIR_OUT_MASK(PIN_NUM) PIN_DIR_MASK(PIN_NUM, OUTPUT) - -/* Macro for getting input mask for specified pin. */ -#define PIN_DIR_IN_MASK(PIN_NUM) PIN_DIR_MASK(PIN_NUM, INPUT) - -/* Macro for getting state mask for specified pin and state. */ -#define PIN_OUT_MASK(PIN_NUM, STATE) \ - (VPRCSR_NORDIC_OUT_PIN##PIN_NUM##_##STATE << VPRCSR_NORDIC_OUT_PIN##PIN_NUM##_Pos) - -/* Macro for getting high state mask for specified pin. */ -#define PIN_OUT_HIGH_MASK(PIN_NUM) PIN_OUT_MASK(PIN_NUM, HIGH) - -/* Macro for getting low state mask for specified pin. */ -#define PIN_OUT_LOW_MASK(PIN_NUM) PIN_OUT_MASK(PIN_NUM, LOW) +#define BITS_IN_WORD 32 +#define BITS_IN_BYTE 8 /** @brief Low level transfer parameters. */ -struct hrt_ll_xfer { - /** @brief Top value of VTIM. This will determine clock frequency - * (SPI_CLOCK ~= CPU_CLOCK / (2 * TOP)). - */ - volatile uint8_t counter_top; - - /** @brief Word size of passed data, bits. */ - volatile uint8_t word_size; +struct hrt_xfer { - /** @brief Data to send, under each index there is data of length word_size. */ - volatile uint32_t *data_to_send; + /** @brief When true clock signal makes 1 transition less. + * It is required for spi modes 1 and 3 due to hardware issue. + */ + bool eliminate_last_pulse; - /** @brief Data length. */ - volatile uint8_t data_len; + /** @brief Tx mode mask for csr dir register */ + uint16_t tx_direction_mask; - /** @brief If true chip enable pin will be left active after transfer */ - volatile uint8_t ce_hold; + /** @brief Rx mode mask for csr dir register */ + uint16_t rx_direction_mask; - /** @brief Chip enable pin polarity in enabled state. */ - volatile bool ce_enable_state; }; -/** @brief Write on single line. - * - * Function to be used to write data on single data line (SPI). - * - * @param[in] xfer_ll_params Low level transfer parameters. - */ -void write_single_by_word(volatile struct hrt_ll_xfer xfer_ll_params); - -/** @brief Write on four lines. +/** @brief Write. * - * Function to be used to write data on quad data line (SPI). + * Function to be used to write data on SPI. * - * @param[in] xfer_ll_params Low level transfer parameters. + * @param[in] xfer_ll_params Low level transfer parameters and data. */ -void write_quad_by_word(volatile struct hrt_ll_xfer xfer_ll_params); +void hrt_write(struct hrt_xfer *xfer_ll_params); #endif /* _HRT_H__ */ diff --git a/applications/sdp/mspi/src/hrt/hrt.s b/applications/sdp/mspi/src/hrt/hrt.s index 5e9923fce21c..c6358998304f 100644 --- a/applications/sdp/mspi/src/hrt/hrt.s +++ b/applications/sdp/mspi/src/hrt/hrt.s @@ -4,285 +4,236 @@ .attribute unaligned_access, 0 .attribute stack_align, 4 .text - .section .text.write_single_by_word,"ax",@progbits + .section .text.hrt_tx,"ax",@progbits .align 1 - .globl write_single_by_word - .type write_single_by_word, @function -write_single_by_word: - #APP - csrr a5, 3009 - #NO_APP - ori a5,a5,2 - slli a5,a5,16 - srli a5,a5,16 - #APP - csrw 3009, a5 - csrr a5, 3008 - #NO_APP - slli a5,a5,16 - srli a5,a5,16 - #APP - csrw 3008, a5 - #NO_APP - li a5,65536 - addi a5,a5,4 - #APP - csrw 3043, a5 - csrw 3045, 0 - csrr a5, 1996 - #NO_APP - andi a5,a5,17 - #APP - csrw 1996, a5 - #NO_APP - lbu a4,1(a0) - li a5,31 - bleu a4,a5,.L8 -.L5: - #APP - csrw 2000, 2 - #NO_APP - lbu a5,0(a0) - andi a5,a5,0xff - #APP - csrr a4, 2003 - #NO_APP - li a3,-65536 - and a4,a4,a3 - or a5,a5,a4 - #APP - csrw 2003, a5 - #NO_APP - lbu a5,1(a0) - #APP - csrw 3022, a5 - #NO_APP - lbu a5,1(a0) + .type hrt_tx, @function +hrt_tx: + addi sp,sp,-24 + sw ra,20(sp) + sw s0,16(sp) + sw s1,12(sp) + lw a5,4(a0) + sw a2,0(sp) + sw a3,4(sp) + beq a5,zero,.L1 + li a5,32 + div a5,a5,a1 + andi a1,a1,31 + slli a1,a1,12 + mv s0,a0 addi a5,a5,-1 - andi a5,a5,0xff - #APP - csrw 3023, a5 - csrr a5, 3008 - #NO_APP - lbu a4,10(a0) - andi a5,a5,-33 - slli a5,a5,16 - slli a4,a4,5 - srli a5,a5,16 - or a5,a5,a4 + andi a5,a5,63 + ori a5,a5,1024 + or a1,a5,a1 + sw a1,8(sp) #APP - csrw 3008, a5 + csrw 3019, a1 #NO_APP - lbu a5,0(a0) - li a4,3 - mul a5,a5,a4 - #APP - csrw 2005, a5 - #NO_APP - li a5,0 + li s1,0 .L3: - lbu a4,8(a0) - bgtu a4,a5,.L6 - #APP - csrw 3012, 0 - #NO_APP - li a5,65536 - #APP - csrw 3043, a5 - csrw 3045, 0 - #NO_APP - lbu a5,9(a0) - bne a5,zero,.L7 - #APP - csrr a5, 3008 - #NO_APP - lbu a4,10(a0) - andi a5,a5,-34 - slli a5,a5,16 - xori a4,a4,1 - slli a4,a4,5 - srli a5,a5,16 - or a5,a5,a4 - #APP - csrw 3008, a5 - #NO_APP + lw a5,4(s0) + bgtu a5,s1,.L9 +.L1: + lw ra,20(sp) + lw s0,16(sp) + lw s1,12(sp) + addi sp,sp,24 + jr ra +.L9: + sub a5,a5,s1 + li a2,1 + beq a5,a2,.L4 + li a2,2 + beq a5,a2,.L5 +.L6: + lw a5,0(s0) + slli a2,s1,2 + add a5,a5,a2 + lw a0,0(a5) + lw a2,16(s0) + jalr a2 + j .L7 +.L4: + lbu a2,8(s0) + lw a5,8(sp) + addi a2,a2,-1 + andi a2,a2,63 + andi a5,a5,-64 + or a5,a5,a2 + sw a5,8(sp) + #APP + csrw 3019, a5 + #NO_APP + lw a5,16(s0) + lw a0,12(s0) + jalr a5 .L7: + bne s1,zero,.L8 + lw a5,0(sp) + lbu a5,0(a5) + bne a5,zero,.L8 + lw a5,4(sp) #APP - csrw 2000, 0 + csrw 2005, a5 #NO_APP - ret -.L4: - lw a4,4(a0) - slli t1,a5,2 - addi a5,a5,1 - add a4,a4,t1 - lw a3,0(a4) - lbu a2,1(a0) - lw a4,4(a0) - andi a5,a5,0xff - sub a2,a1,a2 - add a4,a4,t1 - sll a3,a3,a2 - sw a3,0(a4) -.L2: - lbu a4,8(a0) - bgtu a4,a5,.L4 - j .L5 + lw a4,0(sp) + li a5,1 + sb a5,0(a4) .L8: - li a5,0 - li a1,32 - j .L2 -.L6: - lw a4,4(a0) - slli a3,a5,2 - add a4,a4,a3 - lw a4,0(a4) - #APP - csrw 3016, a4 - #NO_APP - addi a5,a5,1 - andi a5,a5,0xff + addi s1,s1,1 j .L3 - .size write_single_by_word, .-write_single_by_word - .section .text.write_quad_by_word,"ax",@progbits +.L5: + lbu a2,9(s0) + lw a5,8(sp) + addi a2,a2,-1 + andi a2,a2,63 + andi a5,a5,-64 + or a5,a5,a2 + sw a5,8(sp) + #APP + csrw 3019, a5 + #NO_APP + j .L6 + .size hrt_tx, .-hrt_tx + .section .text.hrt_write,"ax",@progbits .align 1 - .globl write_quad_by_word - .type write_quad_by_word, @function -write_quad_by_word: - #APP - csrr a5, 3009 - #NO_APP - ori a5,a5,30 - slli a5,a5,16 - srli a5,a5,16 + .globl hrt_write + .type hrt_write, @function +hrt_write: + addi sp,sp,-20 + li a5,16384 + sw s0,12(sp) + sw ra,16(sp) + addi a5,a5,1 + sw a5,4(sp) + mv s0,a0 + lhu a5,70(a0) + sb zero,3(sp) #APP csrw 3009, a5 - csrr a5, 3008 - #NO_APP - slli a5,a5,16 - srli a5,a5,16 - #APP - csrw 3008, a5 #NO_APP - li a5,262144 - addi a5,a5,4 - #APP - csrw 3043, a5 - csrw 3045, 0 - csrr a5, 1996 - #NO_APP - andi a5,a5,17 - #APP - csrw 1996, a5 - #NO_APP - lbu a4,1(a0) - li a5,31 - bleu a4,a5,.L16 -.L13: + lw a5,4(a0) + beq a5,zero,.L15 + lbu a3,60(a0) #APP csrw 2000, 2 #NO_APP - lbu a5,0(a0) - andi a5,a5,0xff + lhu a5,64(a0) #APP csrr a4, 2003 #NO_APP - li a3,-65536 - and a4,a4,a3 + li a2,-65536 + and a4,a4,a2 or a5,a5,a4 #APP csrw 2003, a5 + csrw 3011, 0 #NO_APP - lbu a5,1(a0) - srli a5,a5,2 + li a4,2031616 + slli a5,a3,16 + and a5,a5,a4 + ori a5,a5,4 + #APP + csrw 3043, a5 + #NO_APP + lw a5,4(a0) + li a4,1 + beq a5,a4,.L16 + li a4,2 + beq a5,a4,.L17 + li a5,32 + div a5,a5,a3 + j .L35 +.L16: + lbu a5,8(a0) +.L35: #APP csrw 3022, a5 #NO_APP - lbu a5,1(a0) - srli a5,a5,2 - addi a5,a5,-1 - andi a5,a5,0xff +.L15: #APP - csrw 3023, a5 - csrr a5, 3008 + csrr a4, 3008 #NO_APP - lbu a4,10(a0) - andi a5,a5,-33 + lbu a5,68(s0) + lbu a3,66(s0) + bne a5,zero,.L19 + li a5,1 + sll a5,a5,a3 + not a5,a5 + and a5,a5,a4 +.L36: slli a5,a5,16 - slli a4,a4,5 srli a5,a5,16 - or a5,a5,a4 #APP csrw 3008, a5 #NO_APP - lbu a5,0(a0) - li a4,3 - mul a5,a5,a4 - #APP - csrw 2005, a5 + lhu a3,64(s0) + lbu a1,60(s0) + addi a2,sp,3 + mv a0,s0 + call hrt_tx + lhu a3,64(s0) + lbu a1,61(s0) + addi a2,sp,3 + addi a0,s0,20 + call hrt_tx + lhu a3,64(s0) + lbu a1,62(s0) + addi a2,sp,3 + addi a0,s0,40 + call hrt_tx + lbu a5,69(s0) + beq a5,zero,.L21 +.L22: + #APP + csrr a5, 3022 #NO_APP - li a5,0 -.L11: - lbu a4,8(a0) - bgtu a4,a5,.L14 + andi a5,a5,0xff + bne a5,zero,.L22 #APP - csrw 3012, 0 + csrw 2010, 0 #NO_APP - li a5,262144 +.L21: + lw a5,4(sp) #APP - csrw 3043, a5 - csrw 3045, 0 + csrw 3019, a5 + csrw 3017, 0 + csrw 2000, 0 #NO_APP - lbu a5,9(a0) - bne a5,zero,.L15 + lbu a5,67(s0) + bne a5,zero,.L14 #APP - csrr a5, 3008 + csrr a4, 3008 #NO_APP - lbu a4,10(a0) - andi a5,a5,-34 + lbu a5,68(s0) + lbu a3,66(s0) + bne a5,zero,.L24 + li a5,1 + sll a5,a5,a3 + or a5,a5,a4 +.L37: slli a5,a5,16 - xori a4,a4,1 - slli a4,a4,5 srli a5,a5,16 - or a5,a5,a4 #APP csrw 3008, a5 #NO_APP -.L15: - #APP - csrw 2000, 0 - #NO_APP - ret -.L12: - lw a4,4(a0) - slli t1,a5,2 - addi a5,a5,1 - add a4,a4,t1 - lw a3,0(a4) - lbu a2,1(a0) - lw a4,4(a0) - andi a5,a5,0xff - sub a2,a1,a2 - add a4,a4,t1 - sll a3,a3,a2 - sw a3,0(a4) -.L10: - lbu a4,8(a0) - bgtu a4,a5,.L12 - j .L13 -.L16: - li a5,0 - li a1,32 - j .L10 .L14: - lw a4,4(a0) - slli a3,a5,2 - add a4,a4,a3 - lw a4,0(a4) - #APP - csrw 3016, a4 - #NO_APP - addi a5,a5,1 - andi a5,a5,0xff - j .L11 - .size write_quad_by_word, .-write_quad_by_word + lw ra,16(sp) + lw s0,12(sp) + addi sp,sp,20 + jr ra +.L17: + lbu a5,9(a0) + j .L35 +.L19: + li a5,1 + sll a5,a5,a3 + or a5,a5,a4 + j .L36 +.L24: + li a5,1 + sll a5,a5,a3 + not a5,a5 + and a5,a5,a4 + j .L37 + .size hrt_write, .-hrt_write diff --git a/applications/sdp/mspi/src/main.c b/applications/sdp/mspi/src/main.c index 2aa528dae0ab..d494c486a9d8 100644 --- a/applications/sdp/mspi/src/main.c +++ b/applications/sdp/mspi/src/main.c @@ -12,94 +12,136 @@ #include #include +#include #include -#include - -#define MAX_DATA_LEN 256 - -#define XFER_COMMAND_IDX (0) -#define XFER_ADDRESS_IDX (1) -#define XFER_DATA_IDX (2) +#include -#define HRT_IRQ_PRIORITY 2 -#define HRT_VEVIF_IDX_WRITE_SINGLE 17 -#define HRT_VEVIF_IDX_WRITE_QUAD 18 +#define CE_PINS_MAX 9 +#define DATA_PINS_MAX 8 +#define VIO_COUNT 11 -/* How many words are needed for given amount of bytes.*/ -#define WORDS_FOR_BYTES(bytes) ((bytes - 1) / 4 + 1) +#define HRT_IRQ_PRIORITY 2 +#define HRT_VEVIF_IDX_WRITE 18 #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; - uint8_t word_size; +static const uint8_t pin_to_vio_map[VIO_COUNT] = { + 4, /* Physical pin 0 */ + 0, /* Physical pin 1 */ + 1, /* Physical pin 2 */ + 3, /* Physical pin 3 */ + 2, /* Physical pin 4 */ + 5, /* Physical pin 5 */ + 6, /* Physical pin 6 */ + 7, /* Physical pin 7 */ + 8, /* Physical pin 8 */ + 9, /* Physical pin 9 */ + 10, /* Physical pin 10 */ }; -struct mspi_dev_config { - enum mspi_io_mode io_mode; - enum mspi_ce_polarity ce_polarity; - uint32_t read_cmd; - uint32_t write_cmd; - uint8_t cmd_length; /* Command length in bits. */ - uint8_t addr_length; /* Address length in bits. */ -}; - -static struct mspi_dev_config mspi_dev_configs; - -uint32_t data_buffer[MAX_DATA_LEN + 2]; - -volatile struct hrt_ll_xfer xfer_ll_params = { - .counter_top = 4, - .word_size = 4, - .data_to_send = NULL, - .data_len = 0, - .ce_hold = false, - .ce_enable_state = false, -}; +static volatile uint8_t ce_vios_count; +static volatile uint8_t ce_vios[CE_PINS_MAX]; +static volatile uint8_t data_vios_count; +static volatile uint8_t data_vios[DATA_PINS_MAX]; +static volatile struct mspi_cfg nrfe_mspi_cfg; +static volatile struct mspi_dev_cfg nrfe_mspi_dev_cfg; +static volatile struct mspi_xfer nrfe_mspi_xfer; +static struct hrt_xfer xfer_params; 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 configure_clock(enum mspi_cpp_mode cpp_mode) +{ + nrf_vpr_csr_vio_config_t vio_config = { + .input_sel = false, + .stop_cnt = true, + }; + uint16_t out = nrf_vpr_csr_vio_out_get(); -static void ep_bound(void *priv) + switch (cpp_mode) { + case MSPI_CPP_MODE_0: { + vio_config.clk_polarity = 0; + WRITE_BIT(out, pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER], VPRCSR_NORDIC_OUT_LOW); + xfer_params.eliminate_last_pulse = false; + break; + } + case MSPI_CPP_MODE_1: { + vio_config.clk_polarity = 1; + WRITE_BIT(out, pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER], VPRCSR_NORDIC_OUT_LOW); + xfer_params.eliminate_last_pulse = true; + break; + } + case MSPI_CPP_MODE_2: { + vio_config.clk_polarity = 1; + WRITE_BIT(out, pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER], VPRCSR_NORDIC_OUT_HIGH); + xfer_params.eliminate_last_pulse = false; + break; + } + case MSPI_CPP_MODE_3: { + vio_config.clk_polarity = 0; + WRITE_BIT(out, pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER], VPRCSR_NORDIC_OUT_HIGH); + xfer_params.eliminate_last_pulse = true; + break; + } + } + nrf_vpr_csr_vio_out_set(out); + nrf_vpr_csr_vio_config_set(&vio_config); +} + +static void config_pins(nrfe_mspi_pinctrl_soc_pin_t *pins_cfg) { - (void)priv; + ce_vios_count = 0; + data_vios_count = 0; + xfer_params.tx_direction_mask = 0; + xfer_params.rx_direction_mask = 0; + + 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]); + + uint8_t pin_number = NRF_PIN_NUMBER_TO_PIN(psel); + + NRFX_ASSERT(pin_number < VIO_COUNT) + + if ((fun >= NRF_FUN_SDP_MSPI_CS0) && (fun <= NRF_FUN_SDP_MSPI_CS4)) { + + ce_vios[ce_vios_count] = pin_to_vio_map[pin_number]; + WRITE_BIT(xfer_params.tx_direction_mask, ce_vios[ce_vios_count], + VPRCSR_NORDIC_DIR_OUTPUT); + WRITE_BIT(xfer_params.rx_direction_mask, ce_vios[ce_vios_count], + VPRCSR_NORDIC_DIR_OUTPUT); + ce_vios_count++; + + } else if ((fun >= NRF_FUN_SDP_MSPI_DQ0) && (fun <= NRF_FUN_SDP_MSPI_DQ7)) { + + data_vios[data_vios_count] = pin_to_vio_map[pin_number]; + WRITE_BIT(xfer_params.tx_direction_mask, data_vios[data_vios_count], + VPRCSR_NORDIC_DIR_OUTPUT); + WRITE_BIT(xfer_params.rx_direction_mask, data_vios[data_vios_count], + VPRCSR_NORDIC_DIR_INPUT); + data_vios_count++; + } else if (fun == NRF_FUN_SDP_MSPI_SCK) { + WRITE_BIT(xfer_params.tx_direction_mask, + pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER], + VPRCSR_NORDIC_DIR_OUTPUT); + WRITE_BIT(xfer_params.rx_direction_mask, + pin_to_vio_map[NRFE_MSPI_SCK_PIN_NUMBER], + VPRCSR_NORDIC_DIR_OUTPUT); + } + } + nrf_vpr_csr_vio_dir_set(xfer_params.tx_direction_mask); + nrf_vpr_csr_vio_out_set(VPRCSR_NORDIC_OUT_HIGH << pin_to_vio_map[NRFE_MSPI_CS0_PIN_NUMBER]); +} +static void ep_bound(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) +static void ep_recv(const void *data, size_t len, void *priv) { (void)priv; (void)len; @@ -110,45 +152,30 @@ static void process_packet(const void *data, size_t len, void *priv) 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); - * } - */ + nrfe_mspi_pinctrl_soc_pin_t *pins_cfg = (nrfe_mspi_pinctrl_soc_pin_t *)data; + config_pins(pins_cfg); 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; - */ + nrfe_mspi_cfg_t *cfg = (nrfe_mspi_cfg_t *)data; + nrfe_mspi_cfg = cfg->cfg; 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; - */ + nrfe_mspi_dev_cfg_t *cfg = (nrfe_mspi_dev_cfg_t *)data; + nrfe_mspi_dev_cfg = cfg->cfg; + configure_clock(nrfe_mspi_dev_cfg.cpp); 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; - */ + nrfe_mspi_xfer_t *xfer = (nrfe_mspi_xfer_t *)data; + nrfe_mspi_xfer = xfer->xfer; 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) { @@ -164,41 +191,6 @@ static void process_packet(const void *data, size_t len, void *priv) 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 = { - .input_sel = 0, - .stop_cnt = 0, - }; - - 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(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(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(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(VIO(NRFE_MSPI_SCK_PIN_NUMBER))); - break; - } - } - - nrf_vpr_csr_vio_config_set(&vio_config); -} - void prepare_and_send_data(uint8_t *data, uint8_t data_length) { memcpy(&(data_buffer[2]), data, data_length); @@ -242,19 +234,9 @@ void prepare_and_send_data(uint8_t *data, uint8_t data_length) } } -__attribute__((interrupt)) void hrt_handler_write_single(void) -{ - xfer_ll_params.ce_enable_state = (mspi_dev_configs.ce_polarity == MSPI_CE_ACTIVE_HIGH); - - write_single_by_word(xfer_ll_params); -} - -__attribute__((interrupt)) void hrt_handler_write_quad(void) -{ - xfer_ll_params.ce_enable_state = (mspi_dev_configs.ce_polarity == MSPI_CE_ACTIVE_HIGH); - - write_quad_by_word(xfer_ll_params); -} +static const struct ipc_ept_cfg ep_cfg = { + .cb = {.bound = ep_bound, .received = ep_recv}, +}; static int backend_init(void) { @@ -288,43 +270,24 @@ static int backend_init(void) return 0; } +__attribute__((interrupt)) void hrt_handler_write(void) +{ + hrt_write(&xfer_params); +} + int main(void) { - int ret = 0; - uint16_t direction; - uint16_t output; + int ret = backend_init(); - ret = backend_init(); if (ret < 0) { return 0; } - IRQ_DIRECT_CONNECT(HRT_VEVIF_IDX_WRITE_SINGLE, HRT_IRQ_PRIORITY, hrt_handler_write_single, - 0); - nrf_vpr_clic_int_enable_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_WRITE_SINGLE), true); - - IRQ_DIRECT_CONNECT(HRT_VEVIF_IDX_WRITE_QUAD, HRT_IRQ_PRIORITY, hrt_handler_write_quad, 0); - nrf_vpr_clic_int_enable_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_WRITE_QUAD), 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); nrf_vpr_csr_rtperiph_enable_set(true); - configure_clock(MSPI_CPP_MODE_0); - - direction = nrf_vpr_csr_vio_dir_get(); - 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))); - - /* 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; - - data_buffer[XFER_COMMAND_IDX] = 0xe5b326c1; - data_buffer[XFER_ADDRESS_IDX] = 0xaabbccdd; - while (true) { k_cpu_idle(); } From 85a040283aff5bc473e85b2b0e845cd237beccbf Mon Sep 17 00:00:00 2001 From: Michal Frankiewicz Date: Thu, 23 Jan 2025 16:31:36 +0100 Subject: [PATCH 4/4] application: sdp: mspi: Hrt data transfer Added MSPI_TX reaction to NRFE_MSPI_TXRX and NRFE_MSPI_TX. Added HRT mspi TX functionality. Signed-off-by: Michal Frankiewicz --- applications/sdp/mspi/src/hrt/hrt.c | 303 ++++++++++++++-------------- applications/sdp/mspi/src/hrt/hrt.h | 82 +++++++- applications/sdp/mspi/src/hrt/hrt.s | 247 ++++++++++++----------- applications/sdp/mspi/src/main.c | 173 +++++++++++----- 4 files changed, 478 insertions(+), 327 deletions(-) diff --git a/applications/sdp/mspi/src/hrt/hrt.c b/applications/sdp/mspi/src/hrt/hrt.c index b4588856e1e9..ecf16c0f153b 100644 --- a/applications/sdp/mspi/src/hrt/hrt.c +++ b/applications/sdp/mspi/src/hrt/hrt.c @@ -7,182 +7,185 @@ #include #include -#define CLK_FIRST_CYCLE_MULTIPLICATOR (3) +/* Hardware requirement, to get n shifts SHIFTCNTB register has to be set to n-1*/ +#define SHIFTCNTB_VALUE(shift_count) (shift_count - 1) + +/** @brief Shift control configuration. */ +typedef struct { + uint8_t shift_count; + nrf_vpr_csr_vio_shift_t out_mode; + uint8_t frame_width; + nrf_vpr_csr_vio_mode_in_t in_mode; +} nrf_vpr_csr_vio_shift_ctrl_t; + +NRF_STATIC_INLINE void +nrf_vpr_csr_vio_shift_ctrl_buffered_set(nrf_vpr_csr_vio_shift_ctrl_t const *p_shift_ctrl) +{ + uint32_t reg = + ((p_shift_ctrl->shift_count << VPRCSR_NORDIC_SHIFTCTRLB_SHIFTCNTB_VALUE_Pos) & + VPRCSR_NORDIC_SHIFTCTRLB_SHIFTCNTB_VALUE_Msk) | + ((p_shift_ctrl->out_mode << VPRCSR_NORDIC_SHIFTCTRLB_OUTMODEB_MODE_Pos) & + VPRCSR_NORDIC_SHIFTCTRLB_OUTMODEB_MODE_Msk) | + ((p_shift_ctrl->frame_width << VPRCSR_NORDIC_SHIFTCTRLB_OUTMODEB_FRAMEWIDTH_Pos) & + VPRCSR_NORDIC_SHIFTCTRLB_OUTMODEB_FRAMEWIDTH_Msk) | + ((p_shift_ctrl->in_mode << VPRCSR_NORDIC_SHIFTCTRLB_INMODEB_MODE_Pos) & + VPRCSR_NORDIC_SHIFTCTRLB_INMODEB_MODE_Msk); + + nrf_csr_write(VPRCSR_NORDIC_SHIFTCTRLB, reg); +} -void write_single_by_word(volatile struct hrt_ll_xfer xfer_ll_params) +NRF_STATIC_INLINE void nrf_vpr_csr_vio_out_or_set(uint16_t value) { - uint16_t dir; - uint16_t out; - nrf_vpr_csr_vio_config_t config; - nrf_vpr_csr_vio_mode_out_t out_mode = { - .mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE, - .frame_width = 1, - }; + nrf_csr_set_bits(VPRCSR_NORDIC_OUT, value); +} - 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(VIO(NRFE_MSPI_DQ0_PIN_NUMBER))); +NRF_STATIC_INLINE void nrf_vpr_csr_vio_out_clear_set(uint16_t value) +{ + nrf_csr_clear_bits(VPRCSR_NORDIC_OUT, value); +} - out = nrf_vpr_csr_vio_out_get(); - nrf_vpr_csr_vio_out_set(out | PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_DQ0_PIN_NUMBER))); +static const nrf_vpr_csr_vio_shift_ctrl_t write_final_shift_ctrl_cfg = { + .shift_count = 1, + .out_mode = NRF_VPR_CSR_VIO_SHIFT_NONE, + .frame_width = 4, + .in_mode = NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS, +}; - nrf_vpr_csr_vio_mode_out_set(&out_mode); - nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS); - - nrf_vpr_csr_vio_config_get(&config); - config.input_sel = false; - nrf_vpr_csr_vio_config_set(&config); - - /* Fix position of data if word size < MAX_WORD_SIZE, - * so that leading zeros would not be printed instead of data bits. - */ - if (xfer_ll_params.word_size < MAX_WORD_SIZE) { - for (uint8_t i = 0; i < xfer_ll_params.data_len; i++) { - xfer_ll_params.data_to_send[i] = - xfer_ll_params.data_to_send[i] - << (MAX_WORD_SIZE - xfer_ll_params.word_size); - } +static void hrt_tx(volatile hrt_xfer_data_t *xfer_data, uint8_t frame_width, bool *counter_running, + uint16_t counter_value) +{ + if (xfer_data->word_count == 0) { + return; } - /* Counter settings */ - nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_RELOAD); - nrf_vpr_csr_vtim_simple_counter_top_set(0, xfer_ll_params.counter_top); - - /* Set number of shifts before OUTB needs to be updated. - * First shift needs to be increased by 1. - */ - nrf_vpr_csr_vio_shift_cnt_out_set(xfer_ll_params.word_size); - nrf_vpr_csr_vio_shift_cnt_out_buffered_set(xfer_ll_params.word_size - 1); - - /* Enable CS */ - out = nrf_vpr_csr_vio_out_get(); - 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 */ - nrf_vpr_csr_vtim_simple_counter_set(0, CLK_FIRST_CYCLE_MULTIPLICATOR * - xfer_ll_params.counter_top); - - /* Send data */ - for (uint8_t i = 0; i < xfer_ll_params.data_len; i++) { - nrf_vpr_csr_vio_out_buffered_reversed_byte_set(xfer_ll_params.data_to_send[i]); - } + nrf_vpr_csr_vio_shift_ctrl_t xfer_shift_ctrl = { + .shift_count = SHIFTCNTB_VALUE(BITS_IN_WORD / frame_width), + .out_mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE, + .frame_width = frame_width, + .in_mode = NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS, + }; - /* Clear all bits, wait until the last word is sent */ - nrf_vpr_csr_vio_out_buffered_set(0); + nrf_vpr_csr_vio_shift_ctrl_buffered_set(&xfer_shift_ctrl); - /* Final configuration */ - out_mode.mode = NRF_VPR_CSR_VIO_SHIFT_NONE; - nrf_vpr_csr_vio_mode_out_buffered_set(&out_mode); - nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS); - - /* Disable CS */ - if (!xfer_ll_params.ce_hold) { - out = nrf_vpr_csr_vio_out_get(); - 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); - } + for (uint32_t i = 0; i < xfer_data->word_count; i++) { - /* Stop counter */ - nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_STOP); + switch (xfer_data->word_count - i) { + case 1: /* Last transfer */ + xfer_shift_ctrl.shift_count = SHIFTCNTB_VALUE(xfer_data->last_word_clocks); + nrf_vpr_csr_vio_shift_ctrl_buffered_set(&xfer_shift_ctrl); + + xfer_data->vio_out_set(xfer_data->last_word); + break; + case 2: /* Last but one transfer.*/ + xfer_shift_ctrl.shift_count = + SHIFTCNTB_VALUE(xfer_data->penultimate_word_clocks); + nrf_vpr_csr_vio_shift_ctrl_buffered_set(&xfer_shift_ctrl); + default: /* Intentional fallthrough */ + xfer_data->vio_out_set(((uint32_t *)xfer_data->data)[i]); + } + + if ((i == 0) && (!*counter_running)) { + /* Start counter */ + nrf_vpr_csr_vtim_simple_counter_set(0, counter_value); + *counter_running = true; + } + } } -void write_quad_by_word(volatile struct hrt_ll_xfer xfer_ll_params) +void hrt_write(hrt_xfer_t *hrt_xfer_params) { - uint16_t dir; - uint16_t out; - nrf_vpr_csr_vio_config_t config; - nrf_vpr_csr_vio_mode_out_t out_mode = { - .mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE, - .frame_width = 4, - }; - - NRFX_ASSERT(xfer_ll_params.word_size % 4 == 0); - NRFX_ASSERT(xfer_ll_params.word_size <= MAX_WORD_SIZE); - /* Configuration step */ - dir = nrf_vpr_csr_vio_dir_get(); + hrt_frame_element_t first_element = HRT_FE_DATA; + bool counter_running = false; - 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))); + nrf_vpr_csr_vio_mode_out_t out_mode = {.mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE}; - out = nrf_vpr_csr_vio_out_get(); + /* Configure clock and pins */ + nrf_vpr_csr_vio_dir_set(hrt_xfer_params->tx_direction_mask); - 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))); + for (uint8_t i = 0; i < HRT_FE_MAX; i++) { - nrf_vpr_csr_vio_mode_out_set(&out_mode); - nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS); - - nrf_vpr_csr_vio_config_get(&config); - config.input_sel = false; - nrf_vpr_csr_vio_config_set(&config); - - /* Fix position of data if word size < MAX_WORD_SIZE, - * so that leading zeros would not be printed instead of data. - */ - if (xfer_ll_params.word_size < MAX_WORD_SIZE) { - for (uint8_t i = 0; i < xfer_ll_params.data_len; i++) { - xfer_ll_params.data_to_send[i] = - xfer_ll_params.data_to_send[i] - << (MAX_WORD_SIZE - xfer_ll_params.word_size); + if (hrt_xfer_params->xfer_data[i].word_count != 0) { + first_element = i; + break; } } - /* Counter settings */ + switch (first_element) { + case HRT_FE_COMMAND: + out_mode.frame_width = hrt_xfer_params->bus_widths.command; + break; + case HRT_FE_ADDRESS: + out_mode.frame_width = hrt_xfer_params->bus_widths.address; + break; + case HRT_FE_DATA: + out_mode.frame_width = hrt_xfer_params->bus_widths.data; + break; + default: + break; + } + nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_RELOAD); - nrf_vpr_csr_vtim_simple_counter_top_set(0, xfer_ll_params.counter_top); - - /* Set number of shifts before OUTB needs to be updated. - * First shift needs to be increased by 1. - */ - nrf_vpr_csr_vio_shift_cnt_out_set(xfer_ll_params.word_size / 4); - nrf_vpr_csr_vio_shift_cnt_out_buffered_set(xfer_ll_params.word_size / 4 - 1); - - /* Enable CS */ - out = nrf_vpr_csr_vio_out_get(); - 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 */ - nrf_vpr_csr_vtim_simple_counter_set(0, 3 * xfer_ll_params.counter_top); - - /* Send data */ - for (uint8_t i = 0; i < xfer_ll_params.data_len; i++) { - nrf_vpr_csr_vio_out_buffered_reversed_byte_set(xfer_ll_params.data_to_send[i]); + nrf_vpr_csr_vtim_simple_counter_top_set(0, hrt_xfer_params->counter_value); + nrf_vpr_csr_vio_mode_in_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS); + + nrf_vpr_csr_vio_mode_out_set(&out_mode); + + switch (hrt_xfer_params->xfer_data[first_element].word_count) { + case 1: + nrf_vpr_csr_vio_shift_cnt_out_set( + hrt_xfer_params->xfer_data[first_element].last_word_clocks); + break; + case 2: + nrf_vpr_csr_vio_shift_cnt_out_set( + hrt_xfer_params->xfer_data[first_element].penultimate_word_clocks); + break; + default: + nrf_vpr_csr_vio_shift_cnt_out_set(BITS_IN_WORD / out_mode.frame_width); } - /* Clear all bits, wait until the last word is sent */ - nrf_vpr_csr_vio_out_buffered_set(0); + /* Enable CE */ + 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)); + } - /* Final configuration */ - out_mode.mode = NRF_VPR_CSR_VIO_SHIFT_NONE; - nrf_vpr_csr_vio_mode_out_buffered_set(&out_mode); - nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS); - - /* Disable CS */ - if (!xfer_ll_params.ce_hold) { - out = nrf_vpr_csr_vio_out_get(); - 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); + /* Transfer command */ + hrt_tx(&hrt_xfer_params->xfer_data[HRT_FE_COMMAND], hrt_xfer_params->bus_widths.command, + &counter_running, hrt_xfer_params->counter_value); + /* Transfer address */ + hrt_tx(&hrt_xfer_params->xfer_data[HRT_FE_ADDRESS], hrt_xfer_params->bus_widths.address, + &counter_running, hrt_xfer_params->counter_value); + /* Transfer data */ + hrt_tx(&hrt_xfer_params->xfer_data[HRT_FE_DATA], hrt_xfer_params->bus_widths.data, + &counter_running, hrt_xfer_params->counter_value); + + if (hrt_xfer_params->eliminate_last_pulse) { + + /* Wait until the last word is sent */ + while (nrf_vpr_csr_vio_shift_cnt_out_get() != 0) { + } + + /* This is a partial solution to surplus clock edge problem in modes 1 and 3. + * This solution works only for counter values above 20. + */ + nrf_vpr_csr_vtim_simple_wait_set(0, false, 0); } + /* Final configuration */ + nrf_vpr_csr_vio_shift_ctrl_buffered_set(&write_final_shift_ctrl_cfg); + nrf_vpr_csr_vio_out_buffered_reversed_word_set(0x00); + /* Stop counter */ nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_STOP); + + /* Disable CE */ + 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)); + } + } } diff --git a/applications/sdp/mspi/src/hrt/hrt.h b/applications/sdp/mspi/src/hrt/hrt.h index 443a62634371..3a81f15be37a 100644 --- a/applications/sdp/mspi/src/hrt/hrt.h +++ b/applications/sdp/mspi/src/hrt/hrt.h @@ -21,8 +21,78 @@ #define BITS_IN_WORD 32 #define BITS_IN_BYTE 8 -/** @brief Low level transfer parameters. */ -struct hrt_xfer { +typedef enum { + HRT_FE_COMMAND, + HRT_FE_ADDRESS, + HRT_FE_DATA, + HRT_FE_MAX +} hrt_frame_element_t; + +/** @brief Structure for holding bus width of different xfer parts */ +typedef struct { + uint8_t command; + uint8_t address; + uint8_t data; +} hrt_xfer_bus_widths_t; + +typedef struct { + /** @brief Buffer for RX/TX data */ + volatile uint8_t *data; + + /** @brief Data length in 4 byte words, + * calculated as CEIL(buffer_length_bits/32). + */ + uint32_t word_count; + + /** @brief Amount of clock pulses for last word. + * Due to hardware limitation, in case when last word clock pulse count is 1, + * the penultimate word has to share its bits with last word, + * for example: + * buffer length = 36bits, + * bus_width = QUAD, + * last_word_clocks would be:(buffer_length%32)/QUAD = 1 + * so: + * penultimate_word_clocks = 32-BITS_IN_BYTE + * last_word_clocks = (buffer_length%32)/QUAD + BITS_IN_BYTE + * last_word = penultimate_word>>24 | last_word<<8 + */ + uint8_t last_word_clocks; + + /** @brief Amount of clock pulses for penultimate word. + * For more info see last_word_clocks. + */ + uint8_t penultimate_word_clocks; + + /** @brief Value of last word. + * For more info see last_word_clocks. + */ + uint32_t last_word; + + /** @brief Function for writing to buffered out register. */ + void (*vio_out_set)(uint32_t value); +} hrt_xfer_data_t; + +/** @brief Hrt transfer parameters. */ +typedef struct { + + /** @brief Data for all transfer parts */ + hrt_xfer_data_t xfer_data[HRT_FE_MAX]; + + /** @brief Bus widths for different transfer parts (command, address, and data). */ + hrt_xfer_bus_widths_t bus_widths; + + /** @brief Timer value, used for setting clock frequency + */ + uint16_t counter_value; + + /** @brief Index of CE VIO pin */ + uint8_t ce_vio; + + /** @brief If true chip enable pin will be left active after transfer */ + bool ce_hold; + + /** @brief Chip enable pin polarity in enabled state. */ + enum mspi_ce_polarity ce_polarity; /** @brief When true clock signal makes 1 transition less. * It is required for spi modes 1 and 3 due to hardware issue. @@ -35,14 +105,14 @@ struct hrt_xfer { /** @brief Rx mode mask for csr dir register */ uint16_t rx_direction_mask; -}; +} hrt_xfer_t; /** @brief Write. * - * Function to be used to write data on SPI. + * Function to be used to write data on MSPI. * - * @param[in] xfer_ll_params Low level transfer parameters and data. + * @param[in] hrt_xfer_params Hrt transfer parameters and data. */ -void hrt_write(struct hrt_xfer *xfer_ll_params); +void hrt_write(hrt_xfer_t *hrt_xfer_params); #endif /* _HRT_H__ */ diff --git a/applications/sdp/mspi/src/hrt/hrt.s b/applications/sdp/mspi/src/hrt/hrt.s index c6358998304f..6cfc1b95db80 100644 --- a/applications/sdp/mspi/src/hrt/hrt.s +++ b/applications/sdp/mspi/src/hrt/hrt.s @@ -12,27 +12,27 @@ hrt_tx: sw ra,20(sp) sw s0,16(sp) sw s1,12(sp) - lw a5,4(a0) + lw a4,4(a0) sw a2,0(sp) sw a3,4(sp) - beq a5,zero,.L1 - li a5,32 - div a5,a5,a1 - andi a1,a1,31 - slli a1,a1,12 + beq a4,zero,.L1 + slli a3,a1,12 + li a4,126976 + and a3,a3,a4 + li a4,32 + div a4,a4,a1 mv s0,a0 - addi a5,a5,-1 - andi a5,a5,63 - ori a5,a5,1024 - or a1,a5,a1 - sw a1,8(sp) + addi a4,a4,-1 + andi a4,a4,63 + or a4,a4,a3 + ori a4,a4,1024 #APP - csrw 3019, a1 + csrw 3019, a4 #NO_APP li s1,0 .L3: - lw a5,4(s0) - bgtu a5,s1,.L9 + lw a4,4(s0) + bltu s1,a4,.L9 .L1: lw ra,20(sp) lw s0,16(sp) @@ -40,58 +40,58 @@ hrt_tx: addi sp,sp,24 jr ra .L9: - sub a5,a5,s1 - li a2,1 - beq a5,a2,.L4 - li a2,2 - beq a5,a2,.L5 + lw a4,4(s0) + li a1,1 + sub a4,a4,s1 + beq a4,a1,.L4 + li a1,2 + beq a4,a1,.L5 .L6: - lw a5,0(s0) - slli a2,s1,2 - add a5,a5,a2 - lw a0,0(a5) - lw a2,16(s0) - jalr a2 - j .L7 + lw a1,16(s0) + lw a4,0(s0) + slli a0,s1,2 + sw a3,8(sp) + add a4,a4,a0 + lw a0,0(a4) + jalr a1 + j .L12 .L4: - lbu a2,8(s0) - lw a5,8(sp) - addi a2,a2,-1 - andi a2,a2,63 - andi a5,a5,-64 - or a5,a5,a2 - sw a5,8(sp) + lbu a4,8(s0) + sw a3,8(sp) + addi a4,a4,-1 + andi a4,a4,63 + or a4,a4,a3 + ori a4,a4,1024 #APP - csrw 3019, a5 + csrw 3019, a4 #NO_APP - lw a5,16(s0) + lw a4,16(s0) lw a0,12(s0) - jalr a5 -.L7: + jalr a4 +.L12: + lw a3,8(sp) bne s1,zero,.L8 lw a5,0(sp) - lbu a5,0(a5) - bne a5,zero,.L8 + lbu a4,0(a5) + bne a4,zero,.L8 lw a5,4(sp) #APP csrw 2005, a5 #NO_APP - lw a4,0(sp) - li a5,1 - sb a5,0(a4) + lw a5,0(sp) + li a4,1 + sb a4,0(a5) .L8: addi s1,s1,1 j .L3 .L5: - lbu a2,9(s0) - lw a5,8(sp) - addi a2,a2,-1 - andi a2,a2,63 - andi a5,a5,-64 - or a5,a5,a2 - sw a5,8(sp) + lbu a4,9(s0) + addi a4,a4,-1 + andi a4,a4,63 + or a4,a4,a3 + ori a4,a4,1024 #APP - csrw 3019, a5 + csrw 3019, a4 #NO_APP j .L6 .size hrt_tx, .-hrt_tx @@ -100,73 +100,79 @@ hrt_tx: .globl hrt_write .type hrt_write, @function hrt_write: - addi sp,sp,-20 - li a5,16384 - sw s0,12(sp) - sw ra,16(sp) - addi a5,a5,1 - sw a5,4(sp) - mv s0,a0 + addi sp,sp,-16 + sw s0,8(sp) + sw ra,12(sp) lhu a5,70(a0) + mv s0,a0 sb zero,3(sp) #APP csrw 3009, a5 #NO_APP lw a5,4(a0) - beq a5,zero,.L15 + beq a5,zero,.L14 lbu a3,60(a0) + li a5,0 +.L15: #APP csrw 2000, 2 #NO_APP - lhu a5,64(a0) + lhu a4,64(s0) #APP - csrr a4, 2003 + csrr a2, 2003 #NO_APP - li a2,-65536 - and a4,a4,a2 - or a5,a5,a4 + li a1,-65536 + and a2,a2,a1 + or a4,a4,a2 #APP - csrw 2003, a5 + csrw 2003, a4 csrw 3011, 0 #NO_APP - li a4,2031616 - slli a5,a3,16 - and a5,a5,a4 - ori a5,a5,4 + li a2,2031616 + slli a4,a3,16 + and a4,a4,a2 + ori a4,a4,4 #APP - csrw 3043, a5 + csrw 3043, a4 #NO_APP - lw a5,4(a0) - li a4,1 - beq a5,a4,.L16 - li a4,2 - beq a5,a4,.L17 + li a4,20 + mul a5,a5,a4 + li a2,1 + add a5,s0,a5 + lw a4,4(a5) + beq a4,a2,.L17 + li a2,2 + beq a4,a2,.L18 li a5,32 div a5,a5,a3 - j .L35 + j .L33 +.L14: + lw a5,24(a0) + beq a5,zero,.L16 + lbu a3,61(a0) + li a5,1 + j .L15 .L16: - lbu a5,8(a0) -.L35: + lbu a3,62(a0) + li a5,2 + j .L15 +.L17: + lbu a5,8(a5) +.L33: #APP csrw 3022, a5 #NO_APP -.L15: - #APP - csrr a4, 3008 - #NO_APP - lbu a5,68(s0) - lbu a3,66(s0) - bne a5,zero,.L19 + lbu a4,66(s0) li a5,1 - sll a5,a5,a3 - not a5,a5 - and a5,a5,a4 -.L36: + sll a5,a5,a4 + lbu a4,68(s0) slli a5,a5,16 srli a5,a5,16 + bne a4,zero,.L21 #APP - csrw 3008, a5 + csrc 3008, a5 #NO_APP +.L22: lhu a3,64(s0) lbu a1,60(s0) addi a2,sp,3 @@ -183,57 +189,52 @@ hrt_write: addi a0,s0,40 call hrt_tx lbu a5,69(s0) - beq a5,zero,.L21 -.L22: + beq a5,zero,.L23 +.L24: #APP csrr a5, 3022 #NO_APP andi a5,a5,0xff - bne a5,zero,.L22 + bne a5,zero,.L24 #APP csrw 2010, 0 #NO_APP -.L21: - lw a5,4(sp) +.L23: + li a5,16384 + addi a5,a5,1 #APP csrw 3019, a5 csrw 3017, 0 csrw 2000, 0 #NO_APP lbu a5,67(s0) - bne a5,zero,.L14 - #APP - csrr a4, 3008 - #NO_APP - lbu a5,68(s0) - lbu a3,66(s0) - bne a5,zero,.L24 + bne a5,zero,.L13 + lbu a4,66(s0) li a5,1 - sll a5,a5,a3 - or a5,a5,a4 -.L37: + sll a5,a5,a4 + lbu a4,68(s0) slli a5,a5,16 srli a5,a5,16 + bne a4,zero,.L26 #APP - csrw 3008, a5 + csrs 3008, a5 #NO_APP -.L14: - lw ra,16(sp) - lw s0,12(sp) - addi sp,sp,20 +.L13: + lw ra,12(sp) + lw s0,8(sp) + addi sp,sp,16 jr ra -.L17: - lbu a5,9(a0) - j .L35 -.L19: - li a5,1 - sll a5,a5,a3 - or a5,a5,a4 - j .L36 -.L24: - li a5,1 - sll a5,a5,a3 - not a5,a5 - and a5,a5,a4 - j .L37 +.L18: + lbu a5,9(a5) + j .L33 +.L21: + #APP + csrs 3008, a5 + #NO_APP + j .L22 +.L26: + #APP + csrc 3008, a5 + #NO_APP + j .L13 .size hrt_write, .-hrt_write diff --git a/applications/sdp/mspi/src/main.c b/applications/sdp/mspi/src/main.c index d494c486a9d8..bc7bc597f1bf 100644 --- a/applications/sdp/mspi/src/main.c +++ b/applications/sdp/mspi/src/main.c @@ -6,9 +6,9 @@ #include "hrt/hrt.h" -#include -#include #include +#include +#include #include #include @@ -21,12 +21,17 @@ #define DATA_PINS_MAX 8 #define VIO_COUNT 11 +#define SUPPORTED_IO_MODES_COUNT 7 + #define HRT_IRQ_PRIORITY 2 #define HRT_VEVIF_IDX_WRITE 18 #define VEVIF_IRQN(vevif) VEVIF_IRQN_1(vevif) #define VEVIF_IRQN_1(vevif) VPRCLIC_##vevif##_IRQn +/* In OCTAL mode 4 bytes for address + 32 bytes for up to 32 dummy cycles*/ +#define ADDR_AND_CYCLES_MAX_SIZE 36 + static const uint8_t pin_to_vio_map[VIO_COUNT] = { 4, /* Physical pin 0 */ 0, /* Physical pin 1 */ @@ -41,6 +46,16 @@ static const uint8_t pin_to_vio_map[VIO_COUNT] = { 10, /* Physical pin 10 */ }; +static const hrt_xfer_bus_widths_t io_modes[SUPPORTED_IO_MODES_COUNT] = { + {1, 1, 1}, /* MSPI_IO_MODE_SINGLE */ + {2, 2, 2}, /* MSPI_IO_MODE_DUAL */ + {1, 1, 2}, /* MSPI_IO_MODE_DUAL_1_1_2 */ + {1, 2, 2}, /* MSPI_IO_MODE_DUAL_1_2_2 */ + {4, 4, 4}, /* MSPI_IO_MODE_QUAD */ + {1, 1, 4}, /* MSPI_IO_MODE_QUAD_1_1_4 */ + {1, 4, 4}, /* MSPI_IO_MODE_QUAD_1_4_4 */ +}; + static volatile uint8_t ce_vios_count; static volatile uint8_t ce_vios[CE_PINS_MAX]; static volatile uint8_t data_vios_count; @@ -48,11 +63,57 @@ static volatile uint8_t data_vios[DATA_PINS_MAX]; static volatile struct mspi_cfg nrfe_mspi_cfg; static volatile struct mspi_dev_cfg nrfe_mspi_dev_cfg; static volatile struct mspi_xfer nrfe_mspi_xfer; -static struct hrt_xfer xfer_params; +static volatile hrt_xfer_t xfer_params; +static volatile uint8_t address_and_dummy_cycles[ADDR_AND_CYCLES_MAX_SIZE]; static struct ipc_ept ep; static atomic_t ipc_atomic_sem = ATOMIC_INIT(0); +static void adjust_tail(volatile hrt_xfer_data_t *xfer_data, uint16_t frame_width, + uint32_t data_length) +{ + if (data_length == 0) { + return; + } + + /* Due to hardware limitation, it is not possible to send only 1 + * clock pulse. + */ + NRFX_ASSERT(data_length / frame_width >= 1); + NRFX_ASSERT(data_vios_count >= frame_width); + NRFX_ASSERT(data_length % frame_width == 0); + + uint8_t last_word_length = data_length % BITS_IN_WORD; + uint8_t penultimate_word_length = BITS_IN_WORD; + + xfer_data->word_count = NRFX_CEIL_DIV(data_length, BITS_IN_WORD); + xfer_data->last_word = ((uint32_t *)xfer_data->data)[xfer_data->word_count - 1]; + + /* Due to hardware limitations it is not possible to send only 1 + * clock cycle. Therefore when data_length%32==FRAME_WIDTH last + * word is sent shorter (24bits) and the remaining byte and + * FRAME_WIDTH number of bits are bit is sent together. + */ + if (last_word_length == 0) { + + last_word_length = BITS_IN_WORD; + xfer_data->last_word = ((uint32_t *)xfer_data->data)[xfer_data->word_count - 1]; + + } else if ((last_word_length / frame_width == 1) && (xfer_data->word_count > 1)) { + + penultimate_word_length -= BITS_IN_BYTE; + last_word_length += BITS_IN_BYTE; + + xfer_data->last_word = ((uint32_t *)xfer_data->data)[xfer_data->word_count - 2] >> + (BITS_IN_WORD - BITS_IN_BYTE) | + ((uint32_t *)xfer_data->data)[xfer_data->word_count - 1] + << BITS_IN_BYTE; + } + + xfer_data->last_word_clocks = last_word_length / frame_width; + xfer_data->penultimate_word_clocks = penultimate_word_length / frame_width; +} + static void configure_clock(enum mspi_cpp_mode cpp_mode) { nrf_vpr_csr_vio_config_t vio_config = { @@ -91,6 +152,61 @@ static void configure_clock(enum mspi_cpp_mode cpp_mode) nrf_vpr_csr_vio_config_set(&vio_config); } +static void xfer_execute(struct mspi_xfer_packet xfer_packet) +{ + NRFX_ASSERT(nrfe_mspi_dev_cfg.ce_num < ce_vios_count); + NRFX_ASSERT(nrfe_mspi_dev_cfg.io_mode < SUPPORTED_IO_MODES_COUNT); + + xfer_params.counter_value = 4; + xfer_params.ce_vio = ce_vios[nrfe_mspi_dev_cfg.ce_num]; + xfer_params.ce_hold = nrfe_mspi_xfer.hold_ce; + xfer_params.ce_polarity = nrfe_mspi_dev_cfg.ce_polarity; + xfer_params.bus_widths = io_modes[nrfe_mspi_dev_cfg.io_mode]; + + /* Fix position of command if command length is < BITS_IN_WORD, + * so that leading zeros would not be printed instead of data bits. + */ + xfer_packet.cmd = xfer_packet.cmd + << (BITS_IN_WORD - nrfe_mspi_xfer.cmd_length * BITS_IN_BYTE); + + 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.cmd; + xfer_params.xfer_data[HRT_FE_COMMAND].word_count = 0; + + adjust_tail(&xfer_params.xfer_data[HRT_FE_COMMAND], xfer_params.bus_widths.command, + nrfe_mspi_xfer.cmd_length * BITS_IN_BYTE); + + /* Reverse address byte order so that address values are sent instead of zeros */ + for (uint8_t i = 0; i < nrfe_mspi_xfer.addr_length; i++) { + address_and_dummy_cycles[i] = + *(((uint8_t *)&xfer_packet.address) + nrfe_mspi_xfer.addr_length - i - 1); + } + + for (uint8_t i = nrfe_mspi_xfer.addr_length; i < ADDR_AND_CYCLES_MAX_SIZE; i++) { + address_and_dummy_cycles[i] = 0; + } + + xfer_params.xfer_data[HRT_FE_ADDRESS].vio_out_set = + &nrf_vpr_csr_vio_out_buffered_reversed_byte_set; + xfer_params.xfer_data[HRT_FE_ADDRESS].data = address_and_dummy_cycles; + xfer_params.xfer_data[HRT_FE_ADDRESS].word_count = 0; + + adjust_tail(&xfer_params.xfer_data[HRT_FE_ADDRESS], xfer_params.bus_widths.address, + nrfe_mspi_xfer.addr_length * BITS_IN_BYTE + + nrfe_mspi_xfer.tx_dummy * xfer_params.bus_widths.address); + + xfer_params.xfer_data[HRT_FE_DATA].vio_out_set = + &nrf_vpr_csr_vio_out_buffered_reversed_byte_set; + xfer_params.xfer_data[HRT_FE_DATA].data = xfer_packet.data_buf; + xfer_params.xfer_data[HRT_FE_DATA].word_count = 0; + + adjust_tail(&xfer_params.xfer_data[HRT_FE_DATA], xfer_params.bus_widths.data, + xfer_packet.num_bytes * BITS_IN_BYTE); + + nrf_vpr_clic_int_pending_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_WRITE)); +} + static void config_pins(nrfe_mspi_pinctrl_soc_pin_t *pins_cfg) { ce_vios_count = 0; @@ -153,22 +269,26 @@ static void ep_recv(const void *data, size_t len, void *priv) switch (opcode) { case NRFE_MSPI_CONFIG_PINS: { nrfe_mspi_pinctrl_soc_pin_t *pins_cfg = (nrfe_mspi_pinctrl_soc_pin_t *)data; + config_pins(pins_cfg); break; } case NRFE_MSPI_CONFIG_CTRL: { nrfe_mspi_cfg_t *cfg = (nrfe_mspi_cfg_t *)data; + nrfe_mspi_cfg = cfg->cfg; break; } case NRFE_MSPI_CONFIG_DEV: { nrfe_mspi_dev_cfg_t *cfg = (nrfe_mspi_dev_cfg_t *)data; + nrfe_mspi_dev_cfg = cfg->cfg; configure_clock(nrfe_mspi_dev_cfg.cpp); break; } case NRFE_MSPI_CONFIG_XFER: { nrfe_mspi_xfer_t *xfer = (nrfe_mspi_xfer_t *)data; + nrfe_mspi_xfer = xfer->xfer; break; } @@ -179,7 +299,7 @@ static void ep_recv(const void *data, size_t len, void *priv) if (packet->packet.dir == MSPI_RX) { /* TODO: Process received data */ } else if (packet->packet.dir == MSPI_TX) { - /* TODO: Send data */ + xfer_execute(packet->packet); } break; } @@ -191,49 +311,6 @@ static void ep_recv(const void *data, size_t len, void *priv) ipc_service_send(&ep, (const void *)&response.opcode, sizeof(response)); } -void prepare_and_send_data(uint8_t *data, uint8_t data_length) -{ - memcpy(&(data_buffer[2]), data, data_length); - - /* Send command */ - xfer_ll_params.ce_hold = true; - xfer_ll_params.word_size = mspi_dev_configs.cmd_length; - xfer_ll_params.data_len = 1; - xfer_ll_params.data_to_send = data_buffer; - - if (mspi_dev_configs.io_mode == MSPI_IO_MODE_QUAD) { - nrf_vpr_clic_int_pending_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_WRITE_QUAD)); - } else { - nrf_vpr_clic_int_pending_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_WRITE_SINGLE)); - } - - /* Send address */ - xfer_ll_params.word_size = mspi_dev_configs.addr_length; - xfer_ll_params.data_to_send = data_buffer + XFER_ADDRESS_IDX; - - if (mspi_dev_configs.io_mode == MSPI_IO_MODE_SINGLE || - mspi_dev_configs.io_mode == MSPI_IO_MODE_QUAD_1_1_4) { - nrf_vpr_clic_int_pending_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_WRITE_SINGLE)); - } else { - nrf_vpr_clic_int_pending_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_WRITE_QUAD)); - } - - /* Send data */ - xfer_ll_params.ce_hold = false; - xfer_ll_params.word_size = 32; - /* TODO: this system needs to be fixed as for now, - * there are problems when (data_length%4) != 0 - */ - xfer_ll_params.data_len = WORDS_FOR_BYTES(data_length); - xfer_ll_params.data_to_send = data_buffer + XFER_DATA_IDX; - - if (mspi_dev_configs.io_mode == MSPI_IO_MODE_SINGLE) { - nrf_vpr_clic_int_pending_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_WRITE_SINGLE)); - } else { - nrf_vpr_clic_int_pending_set(NRF_VPRCLIC, VEVIF_IRQN(HRT_VEVIF_IDX_WRITE_QUAD)); - } -} - static const struct ipc_ept_cfg ep_cfg = { .cb = {.bound = ep_bound, .received = ep_recv}, }; @@ -272,7 +349,7 @@ static int backend_init(void) __attribute__((interrupt)) void hrt_handler_write(void) { - hrt_write(&xfer_params); + hrt_write((hrt_xfer_t *)&xfer_params); } int main(void)