diff --git a/applications/sdp/mspi/src/hrt/hrt.c b/applications/sdp/mspi/src/hrt/hrt.c index ecf16c0f153b..abc699990da2 100644 --- a/applications/sdp/mspi/src/hrt/hrt.c +++ b/applications/sdp/mspi/src/hrt/hrt.c @@ -81,7 +81,11 @@ static void hrt_tx(volatile hrt_xfer_data_t *xfer_data, uint8_t frame_width, boo 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 (xfer_data->data == NULL) { + xfer_data->vio_out_set(0); + } else { + xfer_data->vio_out_set(((uint32_t *)xfer_data->data)[i]); + } } if ((i == 0) && (!*counter_running)) { @@ -156,6 +160,10 @@ void hrt_write(hrt_xfer_t *hrt_xfer_params) /* 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 dummy cycles */ + hrt_tx(&hrt_xfer_params->xfer_data[HRT_FE_DUMMY_CYCLES], + hrt_xfer_params->bus_widths.dummy_cycles, &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); diff --git a/applications/sdp/mspi/src/hrt/hrt.h b/applications/sdp/mspi/src/hrt/hrt.h index 3a81f15be37a..e5a576da8dd2 100644 --- a/applications/sdp/mspi/src/hrt/hrt.h +++ b/applications/sdp/mspi/src/hrt/hrt.h @@ -24,6 +24,7 @@ typedef enum { HRT_FE_COMMAND, HRT_FE_ADDRESS, + HRT_FE_DUMMY_CYCLES, HRT_FE_DATA, HRT_FE_MAX } hrt_frame_element_t; @@ -32,6 +33,7 @@ typedef enum { typedef struct { uint8_t command; uint8_t address; + uint8_t dummy_cycles; uint8_t data; } hrt_xfer_bus_widths_t; @@ -78,7 +80,9 @@ 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). */ + /** @brief Bus widths for different transfer parts (command, address, dummy_cycles, and + * data). + */ hrt_xfer_bus_widths_t bus_widths; /** @brief Timer value, used for setting clock frequency diff --git a/applications/sdp/mspi/src/hrt/hrt.s b/applications/sdp/mspi/src/hrt/hrt.s index 6cfc1b95db80..7d1e048aac39 100644 --- a/applications/sdp/mspi/src/hrt/hrt.s +++ b/applications/sdp/mspi/src/hrt/hrt.s @@ -16,84 +16,92 @@ hrt_tx: sw a2,0(sp) sw a3,4(sp) beq a4,zero,.L1 - slli a3,a1,12 + slli s0,a1,12 li a4,126976 - and a3,a3,a4 + and s0,s0,a4 li a4,32 div a4,a4,a1 - mv s0,a0 + mv a5,a0 addi a4,a4,-1 andi a4,a4,63 - or a4,a4,a3 + or a4,a4,s0 ori a4,a4,1024 #APP csrw 3019, a4 #NO_APP li s1,0 .L3: - lw a4,4(s0) - bltu s1,a4,.L9 + lw a4,4(a5) + bltu s1,a4,.L10 .L1: lw ra,20(sp) lw s0,16(sp) lw s1,12(sp) addi sp,sp,24 jr ra -.L9: - lw a4,4(s0) - li a1,1 +.L10: + lw a4,4(a5) + li a2,1 sub a4,a4,s1 - beq a4,a1,.L4 - li a1,2 - beq a4,a1,.L5 + beq a4,a2,.L4 + li a2,2 + beq a4,a2,.L5 .L6: - 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 + lw a4,0(a5) + bne a4,zero,.L8 + lw a4,16(a5) + sw a5,8(sp) + li a0,0 + j .L14 .L4: - lbu a4,8(s0) - sw a3,8(sp) + lbu a4,8(a5) addi a4,a4,-1 andi a4,a4,63 - or a4,a4,a3 + or a4,a4,s0 ori a4,a4,1024 #APP csrw 3019, a4 #NO_APP - lw a4,16(s0) - lw a0,12(s0) + lw a4,16(a5) + lw a0,12(a5) + sw a5,8(sp) +.L14: jalr a4 -.L12: - lw a3,8(sp) - bne s1,zero,.L8 - lw a5,0(sp) - lbu a4,0(a5) - bne a4,zero,.L8 - lw a5,4(sp) +.L13: + lw a5,8(sp) + bne s1,zero,.L9 + lw a4,0(sp) + lbu a4,0(a4) + bne a4,zero,.L9 + lw a4,4(sp) #APP - csrw 2005, a5 + csrw 2005, a4 #NO_APP - lw a5,0(sp) + lw a3,0(sp) li a4,1 - sb a4,0(a5) -.L8: + sb a4,0(a3) +.L9: addi s1,s1,1 j .L3 .L5: - lbu a4,9(s0) + lbu a4,9(a5) addi a4,a4,-1 andi a4,a4,63 - or a4,a4,a3 + or a4,a4,s0 ori a4,a4,1024 #APP csrw 3019, a4 #NO_APP j .L6 +.L8: + lw a2,16(a5) + lw a4,0(a5) + slli a1,s1,2 + sw a5,8(sp) + add a4,a4,a1 + lw a0,0(a4) + jalr a2 + j .L13 .size hrt_tx, .-hrt_tx .section .text.hrt_write,"ax",@progbits .align 1 @@ -103,103 +111,119 @@ hrt_write: addi sp,sp,-16 sw s0,8(sp) sw ra,12(sp) - lhu a5,70(a0) mv s0,a0 sb zero,3(sp) + lhu a5,90(a0) #APP csrw 3009, a5 #NO_APP - lw a5,4(a0) - beq a5,zero,.L14 - lbu a3,60(a0) li a5,0 -.L15: + addi a4,a0,4 + li a3,4 +.L17: + lw a2,0(a4) + bne a2,zero,.L16 + addi a5,a5,1 + andi a5,a5,0xff + addi a4,a4,20 + bne a5,a3,.L17 + li a5,3 +.L16: + li a4,1 + beq a5,a4,.L18 + li a4,3 + beq a5,a4,.L19 + li a4,0 + bne a5,zero,.L20 + lbu a4,80(s0) +.L20: #APP csrw 2000, 2 #NO_APP - lhu a4,64(s0) + lhu a3,84(s0) #APP csrr a2, 2003 #NO_APP li a1,-65536 and a2,a2,a1 - or a4,a4,a2 + or a3,a3,a2 #APP - csrw 2003, a4 + csrw 2003, a3 csrw 3011, 0 #NO_APP li a2,2031616 - slli a4,a3,16 - and a4,a4,a2 - ori a4,a4,4 + slli a3,a4,16 + and a3,a3,a2 + ori a3,a3,4 #APP - csrw 3043, a4 + csrw 3043, a3 #NO_APP - li a4,20 - mul a5,a5,a4 + li a3,20 + mul a5,a5,a3 li a2,1 add a5,s0,a5 - lw a4,4(a5) - beq a4,a2,.L17 + lw a3,4(a5) + beq a3,a2,.L21 li a2,2 - beq a4,a2,.L18 + beq a3,a2,.L22 li a5,32 - div a5,a5,a3 - j .L33 -.L14: - lw a5,24(a0) - beq a5,zero,.L16 - lbu a3,61(a0) - li a5,1 - j .L15 -.L16: - lbu a3,62(a0) - li a5,2 - j .L15 -.L17: + div a5,a5,a4 + j .L39 +.L18: + lbu a4,81(s0) + j .L20 +.L19: + lbu a4,83(s0) + j .L20 +.L21: lbu a5,8(a5) -.L33: +.L39: #APP csrw 3022, a5 #NO_APP - lbu a4,66(s0) + lbu a4,86(s0) li a5,1 sll a5,a5,a4 - lbu a4,68(s0) + lbu a4,88(s0) slli a5,a5,16 srli a5,a5,16 - bne a4,zero,.L21 + bne a4,zero,.L25 #APP csrc 3008, a5 #NO_APP -.L22: - lhu a3,64(s0) - lbu a1,60(s0) +.L26: + lhu a3,84(s0) + lbu a1,80(s0) addi a2,sp,3 mv a0,s0 call hrt_tx - lhu a3,64(s0) - lbu a1,61(s0) + lhu a3,84(s0) + lbu a1,81(s0) addi a2,sp,3 addi a0,s0,20 call hrt_tx - lhu a3,64(s0) - lbu a1,62(s0) + lhu a3,84(s0) + lbu a1,82(s0) addi a2,sp,3 addi a0,s0,40 call hrt_tx - lbu a5,69(s0) - beq a5,zero,.L23 -.L24: + lhu a3,84(s0) + lbu a1,83(s0) + addi a2,sp,3 + addi a0,s0,60 + call hrt_tx + lbu a5,89(s0) + beq a5,zero,.L27 +.L28: #APP csrr a5, 3022 #NO_APP andi a5,a5,0xff - bne a5,zero,.L24 + bne a5,zero,.L28 #APP csrw 2010, 0 #NO_APP -.L23: +.L27: li a5,16384 addi a5,a5,1 #APP @@ -207,34 +231,34 @@ hrt_write: csrw 3017, 0 csrw 2000, 0 #NO_APP - lbu a5,67(s0) - bne a5,zero,.L13 - lbu a4,66(s0) + lbu a5,87(s0) + bne a5,zero,.L15 + lbu a4,86(s0) li a5,1 sll a5,a5,a4 - lbu a4,68(s0) + lbu a4,88(s0) slli a5,a5,16 srli a5,a5,16 - bne a4,zero,.L26 + bne a4,zero,.L30 #APP csrs 3008, a5 #NO_APP -.L13: +.L15: lw ra,12(sp) lw s0,8(sp) addi sp,sp,16 jr ra -.L18: +.L22: lbu a5,9(a5) - j .L33 -.L21: + j .L39 +.L25: #APP csrs 3008, a5 #NO_APP - j .L22 -.L26: + j .L26 +.L30: #APP csrc 3008, a5 #NO_APP - j .L13 + j .L15 .size hrt_write, .-hrt_write diff --git a/applications/sdp/mspi/src/main.c b/applications/sdp/mspi/src/main.c index 465cf423b1f7..f6808bcd8c13 100644 --- a/applications/sdp/mspi/src/main.c +++ b/applications/sdp/mspi/src/main.c @@ -25,6 +25,8 @@ #define MAX_FREQUENCY 64000000 +#define MAX_SHIFT_COUNT 63 + #define CE_PIN_UNUSED UINT8_MAX #define HRT_IRQ_PRIORITY 2 @@ -33,9 +35,6 @@ #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 */ @@ -51,13 +50,13 @@ static const uint8_t pin_to_vio_map[VIO_COUNT] = { }; 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 */ + {1, 1, 1, 1}, /* MSPI_IO_MODE_SINGLE */ + {2, 2, 2, 2}, /* MSPI_IO_MODE_DUAL */ + {1, 1, 1, 2}, /* MSPI_IO_MODE_DUAL_1_1_2 */ + {1, 2, 2, 2}, /* MSPI_IO_MODE_DUAL_1_2_2 */ + {4, 4, 4, 4}, /* MSPI_IO_MODE_QUAD */ + {1, 1, 1, 4}, /* MSPI_IO_MODE_QUAD_1_1_4 */ + {1, 4, 4, 4}, /* MSPI_IO_MODE_QUAD_1_4_4 */ }; static volatile uint8_t ce_vios_count; @@ -68,7 +67,6 @@ static volatile nrfe_mspi_xfer_config_t nrfe_mspi_xfer_config; static volatile nrfe_mspi_dev_config_t nrfe_mspi_devices[DEVICES_MAX]; 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); @@ -101,7 +99,6 @@ static void adjust_tail(volatile hrt_xfer_data_t *xfer_data, uint16_t frame_widt 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 @@ -111,17 +108,27 @@ static void adjust_tail(volatile hrt_xfer_data_t *xfer_data, uint16_t frame_widt 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]; + if (xfer_data->data != NULL) { + 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; + if (xfer_data->data != NULL) { + 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; + } + } else if (xfer_data->data == NULL) { + xfer_data->last_word = 0; + } else { + xfer_data->last_word = ((uint32_t *)xfer_data->data)[xfer_data->word_count - 1]; } xfer_data->last_word_clocks = last_word_length / frame_width; @@ -183,6 +190,9 @@ static void xfer_execute(nrfe_mspi_xfer_packet_msg_t *xfer_packet) 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); xfer_params.xfer_data[HRT_FE_COMMAND].vio_out_set = &nrf_vpr_csr_vio_out_buffered_reversed_word_set; @@ -192,24 +202,34 @@ static void xfer_execute(nrfe_mspi_xfer_packet_msg_t *xfer_packet) adjust_tail(&xfer_params.xfer_data[HRT_FE_COMMAND], xfer_params.bus_widths.command, nrfe_mspi_xfer_config.command_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_config.address_length; i++) { - address_and_dummy_cycles[i] = - *(((uint8_t *)&xfer_packet->address) + nrfe_mspi_xfer_config.address_length - i - 1); - } - - for (uint8_t i = nrfe_mspi_xfer_config.address_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; + &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 = 0; adjust_tail(&xfer_params.xfer_data[HRT_FE_ADDRESS], xfer_params.bus_widths.address, - nrfe_mspi_xfer_config.address_length * BITS_IN_BYTE + - nrfe_mspi_xfer_config.tx_dummy * xfer_params.bus_widths.address); + nrfe_mspi_xfer_config.address_length * BITS_IN_BYTE); + + xfer_params.xfer_data[HRT_FE_DUMMY_CYCLES].vio_out_set = + &nrf_vpr_csr_vio_out_buffered_reversed_word_set; + xfer_params.xfer_data[HRT_FE_DUMMY_CYCLES].data = NULL; + xfer_params.xfer_data[HRT_FE_DUMMY_CYCLES].word_count = 0; + + hrt_frame_element_t elem = + nrfe_mspi_xfer_config.address_length != 0 ? HRT_FE_ADDRESS : HRT_FE_COMMAND; + + /* Up to 63 clock pulses (including data from previous part) can be sent by simply + * increasing shift count of last word in the previous part. + * Beyond that, dummy cycles have to be treated af different transfer part. + */ + if (xfer_params.xfer_data[elem].last_word_clocks + nrfe_mspi_xfer_config.tx_dummy <= + MAX_SHIFT_COUNT) { + xfer_params.xfer_data[elem].last_word_clocks += nrfe_mspi_xfer_config.tx_dummy; + } 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); + } xfer_params.xfer_data[HRT_FE_DATA].vio_out_set = &nrf_vpr_csr_vio_out_buffered_reversed_byte_set;