From e5b795d51690cbca4ecad8c30af36ce14627979f Mon Sep 17 00:00:00 2001 From: Michal Frankiewicz Date: Wed, 5 Feb 2025 08:59:23 +0100 Subject: [PATCH 1/3] drivers: mspi: Reduced IPC structures-drivers Implemented smaller structures and reduced ammount of opcodes in IPC. Added support for multiple target devices. Signed-off-by: Michal Frankiewicz --- drivers/mspi/mspi_nrfe.c | 137 +++++++++++-------------------- include/drivers/mspi/nrfe_mspi.h | 81 ++++++++++-------- 2 files changed, 97 insertions(+), 121 deletions(-) diff --git a/drivers/mspi/mspi_nrfe.c b/drivers/mspi/mspi_nrfe.c index 9e530b00df50..f2f784179968 100644 --- a/drivers/mspi/mspi_nrfe.c +++ b/drivers/mspi/mspi_nrfe.c @@ -65,14 +65,6 @@ static atomic_t ipc_atomic_sem = ATOMIC_INIT(0); .sw_multi_periph = false, \ } -struct mspi_nrfe_data { - struct mspi_xfer xfer; - struct mspi_dev_id dev_id; - struct mspi_dev_cfg dev_cfg; -}; - -static struct mspi_nrfe_data dev_data; - struct mspi_nrfe_config { struct mspi_cfg mspicfg; const struct pinctrl_dev_config *pcfg; @@ -83,7 +75,7 @@ static const struct mspi_nrfe_config dev_config = { .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), }; -static void ipc_recv_clbk(const void *data, size_t len); +static void ep_recv(const void *data, size_t len, void *priv); static void ep_bound(void *priv) { @@ -96,18 +88,8 @@ static void ep_bound(void *priv) LOG_DBG("Ep bounded"); } -static void ep_recv(const void *data, size_t len, void *priv) -{ - (void)priv; - - ipc_recv_clbk(data, len); -} - static struct ipc_ept_cfg ep_cfg = { - .cb = { - .bound = ep_bound, - .received = ep_recv, - }, + .cb = {.bound = ep_bound, .received = ep_recv}, }; /** @@ -120,9 +102,9 @@ static struct ipc_ept_cfg ep_cfg = { * @param data Pointer to the received message. * @param len Length of the received message. */ -static void ipc_recv_clbk(const void *data, size_t len) +static void ep_recv(const void *data, size_t len, void *priv) { - nrfe_mspi_flpr_response_t *response = (nrfe_mspi_flpr_response_t *)data; + nrfe_mspi_flpr_response_msg_t *response = (nrfe_mspi_flpr_response_msg_t *)data; switch (response->opcode) { case NRFE_MSPI_CONFIG_PINS: { @@ -130,14 +112,6 @@ static void ipc_recv_clbk(const void *data, size_t len) k_sem_give(&ipc_sem_cfg); #else atomic_set_bit(&ipc_atomic_sem, NRFE_MSPI_CONFIG_PINS); -#endif - break; - } - case NRFE_MSPI_CONFIG_CTRL: { -#if defined(CONFIG_MULTITHREADING) - k_sem_give(&ipc_sem_cfg); -#else - atomic_set_bit(&ipc_atomic_sem, NRFE_MSPI_CONFIG_CTRL); #endif break; } @@ -167,7 +141,7 @@ static void ipc_recv_clbk(const void *data, size_t len) } case NRFE_MSPI_TXRX: { if (len > 0) { - ipc_received = len - 1; + ipc_received = len - sizeof(nrfe_mspi_opcode_t); ipc_receive_buffer = (uint8_t *)&response->data; } #if defined(CONFIG_MULTITHREADING) @@ -196,7 +170,7 @@ static void ipc_recv_clbk(const void *data, size_t len) * @return 0 on success, -ENOMEM if there is no space in the buffer, * -ETIMEDOUT if the transfer timed out. */ -static int mspi_ipc_data_send(enum nrfe_mspi_opcode opcode, const void *data, size_t len) +static int mspi_ipc_data_send(nrfe_mspi_opcode_t opcode, const void *data, size_t len) { int rc; @@ -233,14 +207,13 @@ static int mspi_ipc_data_send(enum nrfe_mspi_opcode opcode, const void *data, si * * @return 0 on success, -ETIMEDOUT if the operation timed out. */ -static int nrfe_mspi_wait_for_response(enum nrfe_mspi_opcode opcode, uint32_t timeout) +static int nrfe_mspi_wait_for_response(nrfe_mspi_opcode_t opcode, uint32_t timeout) { #if defined(CONFIG_MULTITHREADING) int ret = 0; switch (opcode) { case NRFE_MSPI_CONFIG_PINS: - case NRFE_MSPI_CONFIG_CTRL: case NRFE_MSPI_CONFIG_DEV: case NRFE_MSPI_CONFIG_XFER: { ret = k_sem_take(&ipc_sem_cfg, K_MSEC(timeout)); @@ -280,28 +253,6 @@ static int nrfe_mspi_wait_for_response(enum nrfe_mspi_opcode opcode, uint32_t ti return 0; } -/** - * @brief Send a data struct to the FLPR core using the IPC service. - * - * The function sends a data structure to the FLPR core, - * inserting a byte at the beginning responsible for the opcode. - * - * @param opcode The NRFE MSPI opcode. - * @param data The data to send. - * @param len The length of the data to send. - * - * @return 0 on success, negative errno code on failure. - */ -static int send_with_opcode(enum nrfe_mspi_opcode opcode, const void *data, size_t len) -{ - uint8_t buffer[len + 1]; - - buffer[0] = (uint8_t)opcode; - memcpy(&buffer[1], data, len); - - return mspi_ipc_data_send(opcode, buffer, sizeof(buffer)); -} - /** * @brief Send a configuration struct to the FLPR core using the IPC service. * @@ -311,11 +262,11 @@ static int send_with_opcode(enum nrfe_mspi_opcode opcode, const void *data, size * * @return 0 on success, negative errno code on failure. */ -static int send_config(enum nrfe_mspi_opcode opcode, const void *config, size_t len) +static int send_config(nrfe_mspi_opcode_t opcode, const void *config, size_t len) { int rc; + rc = mspi_ipc_data_send(opcode, config, len); - rc = send_with_opcode(opcode, config, len); if (rc < 0) { LOG_ERR("Configuration send failed: %d", rc); return rc; @@ -342,9 +293,9 @@ static int send_config(enum nrfe_mspi_opcode opcode, const void *config, size_t */ static int api_config(const struct mspi_dt_spec *spec) { - int ret; const struct mspi_cfg *config = &spec->config; const struct mspi_nrfe_config *drv_cfg = spec->bus->config; + nrfe_mspi_pinctrl_soc_pin_msg_t mspi_pin_config; if (config->op_mode != MSPI_OP_MODE_CONTROLLER) { LOG_ERR("Only MSPI controller mode is supported."); @@ -363,7 +314,6 @@ static int api_config(const struct mspi_dt_spec *spec) /* Create pinout configuration */ uint8_t state_id; - nrfe_mspi_pinctrl_soc_pin_t pins_cfg; for (state_id = 0; state_id < drv_cfg->pcfg->state_cnt; state_id++) { if (drv_cfg->pcfg->states[state_id].id == PINCTRL_STATE_DEFAULT) { @@ -382,17 +332,13 @@ static int api_config(const struct mspi_dt_spec *spec) } for (uint8_t i = 0; i < drv_cfg->pcfg->states[state_id].pin_cnt; i++) { - pins_cfg.pin[i] = drv_cfg->pcfg->states[state_id].pins[i]; + mspi_pin_config.pin[i] = drv_cfg->pcfg->states[state_id].pins[i]; } + mspi_pin_config.opcode = NRFE_MSPI_CONFIG_PINS; /* Send pinout configuration to FLPR */ - 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_PINS, (const void *)&mspi_pin_config, + sizeof(nrfe_mspi_pinctrl_soc_pin_msg_t)); } static int check_io_mode(enum mspi_io_mode io_mode) @@ -425,8 +371,8 @@ static int api_dev_config(const struct device *dev, const struct mspi_dev_id *de const enum mspi_dev_cfg_mask param_mask, const struct mspi_dev_cfg *cfg) { const struct mspi_nrfe_config *drv_cfg = dev->config; - struct mspi_nrfe_data *drv_data = dev->data; int rc; + nrfe_mspi_dev_config_msg_t mspi_dev_config_msg; if (param_mask & MSPI_DEVICE_CONFIG_MEM_BOUND) { if (cfg->mem_boundary) { @@ -471,10 +417,16 @@ static int api_dev_config(const struct device *dev, const struct mspi_dev_id *de } } - memcpy((void *)&drv_data->dev_cfg, (void *)cfg, sizeof(drv_data->dev_cfg)); - drv_data->dev_id = *dev_id; + mspi_dev_config_msg.opcode = NRFE_MSPI_CONFIG_DEV; + mspi_dev_config_msg.device_index = dev_id->dev_idx; + mspi_dev_config_msg.dev_config.io_mode = cfg->io_mode; + mspi_dev_config_msg.dev_config.cpp = cfg->cpp; + mspi_dev_config_msg.dev_config.ce_polarity = cfg->ce_polarity; + mspi_dev_config_msg.dev_config.freq = cfg->freq; + mspi_dev_config_msg.dev_config.ce_index = cfg->ce_num; - return send_config(NRFE_MSPI_CONFIG_DEV, (void *)cfg, sizeof(struct mspi_dev_cfg)); + return send_config(NRFE_MSPI_CONFIG_DEV, (void *)&mspi_dev_config_msg, + sizeof(nrfe_mspi_dev_config_msg_t)); } static int api_get_channel_status(const struct device *dev, uint8_t ch) @@ -497,21 +449,23 @@ static int api_get_channel_status(const struct device *dev, uint8_t ch) static int xfer_packet(struct mspi_xfer_packet *packet, uint32_t timeout) { int rc; - uint32_t struct_size = sizeof(struct mspi_xfer_packet); - uint32_t len = struct_size + packet->num_bytes + 1; + uint32_t len = sizeof(nrfe_mspi_xfer_packet_msg_t) + packet->num_bytes; uint8_t buffer[len]; - enum nrfe_mspi_opcode opcode = (packet->dir == MSPI_RX) ? NRFE_MSPI_TXRX : NRFE_MSPI_TX; + nrfe_mspi_xfer_packet_msg_t *xfer_packet = (nrfe_mspi_xfer_packet_msg_t *)buffer; + + xfer_packet->opcode = (packet->dir == MSPI_RX) ? NRFE_MSPI_TXRX : NRFE_MSPI_TX; + xfer_packet->command = packet->cmd; + xfer_packet->address = packet->address; + xfer_packet->num_bytes = packet->num_bytes; - buffer[0] = (uint8_t)opcode; - memcpy((void *)&buffer[1], (void *)packet, struct_size); - memcpy((void *)(&buffer[1] + struct_size), (void *)packet->data_buf, packet->num_bytes); + memcpy((void *)xfer_packet->data, (void *)packet->data_buf, packet->num_bytes); - rc = mspi_ipc_data_send(opcode, buffer, len); + rc = mspi_ipc_data_send(xfer_packet->opcode, buffer, len); if (rc < 0) { LOG_ERR("Packet transfer error: %d", rc); } - rc = nrfe_mspi_wait_for_response(opcode, timeout); + rc = nrfe_mspi_wait_for_response(xfer_packet->opcode, timeout); if (rc < 0) { LOG_ERR("FLPR Xfer response timeout: %d", rc); return rc; @@ -573,10 +527,10 @@ static int start_next_packet(struct mspi_xfer *xfer, uint32_t packets_done) static int api_transceive(const struct device *dev, const struct mspi_dev_id *dev_id, const struct mspi_xfer *req) { - (void)dev_id; - struct mspi_nrfe_data *drv_data = dev->data; + (void)dev; uint32_t packets_done = 0; int rc; + nrfe_mspi_xfer_config_msg_t mspi_xfer_config_msg; /* TODO: add support for asynchronous transfers */ if (req->async) { @@ -588,16 +542,23 @@ static int api_transceive(const struct device *dev, const struct mspi_dev_id *de return -EFAULT; } - drv_data->xfer = *req; + mspi_xfer_config_msg.opcode = NRFE_MSPI_CONFIG_XFER; + mspi_xfer_config_msg.xfer_config.device_index = dev_id->dev_idx; + mspi_xfer_config_msg.xfer_config.command_length = req->cmd_length; + mspi_xfer_config_msg.xfer_config.address_length = req->addr_length; + mspi_xfer_config_msg.xfer_config.hold_ce = req->hold_ce; + mspi_xfer_config_msg.xfer_config.tx_dummy = req->tx_dummy; + mspi_xfer_config_msg.xfer_config.rx_dummy = req->rx_dummy; - rc = send_config(NRFE_MSPI_CONFIG_XFER, (void *)&drv_data->xfer, sizeof(struct mspi_xfer)); + rc = send_config(NRFE_MSPI_CONFIG_XFER, (void *)&mspi_xfer_config_msg, + sizeof(nrfe_mspi_xfer_config_msg_t)); if (rc < 0) { LOG_ERR("Send xfer config error: %d", rc); return rc; } - while (packets_done < drv_data->xfer.num_packet) { - rc = start_next_packet(&drv_data->xfer, packets_done); + while (packets_done < req->num_packet) { + rc = start_next_packet((struct mspi_xfer *)req, packets_done); if (rc < 0) { LOG_ERR("Start next packet error: %d", rc); return rc; @@ -710,5 +671,5 @@ static const struct mspi_driver_api drv_api = { PM_DEVICE_DT_INST_DEFINE(0, dev_pm_action_cb); -DEVICE_DT_INST_DEFINE(0, nrfe_mspi_init, PM_DEVICE_DT_INST_GET(0), &dev_data, &dev_config, - POST_KERNEL, CONFIG_MSPI_NRFE_INIT_PRIORITY, &drv_api); +DEVICE_DT_INST_DEFINE(0, nrfe_mspi_init, PM_DEVICE_DT_INST_GET(0), NULL, &dev_config, POST_KERNEL, + CONFIG_MSPI_NRFE_INIT_PRIORITY, &drv_api); diff --git a/include/drivers/mspi/nrfe_mspi.h b/include/drivers/mspi/nrfe_mspi.h index f404a42e1d8a..d940482cf204 100644 --- a/include/drivers/mspi/nrfe_mspi.h +++ b/include/drivers/mspi/nrfe_mspi.h @@ -30,47 +30,62 @@ extern "C" { #endif /** @brief eMSPI opcodes. */ -enum nrfe_mspi_opcode { +typedef enum { 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_TX, + NRFE_MSPI_CONFIG_PINS, /* nrfe_mspi_pinctrl_soc_pin_msg_t */ + NRFE_MSPI_CONFIG_DEV, /* nrfe_mspi_dev_config_msg_t */ + NRFE_MSPI_CONFIG_XFER, /* nrfe_mspi_xfer_config_msg_t */ + NRFE_MSPI_TX, /* nrfe_mspi_xfer_packet_msg_t + data buffer at the end */ NRFE_MSPI_TXRX, NRFE_MSPI_WRONG_OPCODE, NRFE_MSPI_ALL_OPCODES = NRFE_MSPI_WRONG_OPCODE, -}; +} nrfe_mspi_opcode_t; -typedef struct __packed { - uint8_t opcode; /* nrfe_mspi_opcode */ +typedef struct { + enum mspi_io_mode io_mode; + enum mspi_cpp_mode cpp; + uint8_t ce_index; + enum mspi_ce_polarity ce_polarity; + uint32_t freq; +} nrfe_mspi_dev_config_t; + +typedef struct { + uint8_t device_index; + uint8_t command_length; + uint8_t address_length; + bool hold_ce; + uint16_t tx_dummy; + uint16_t rx_dummy; +} nrfe_mspi_xfer_config_t; + +typedef struct { + nrfe_mspi_opcode_t opcode; /* NRFE_MSPI_CONFIG_PINS */ pinctrl_soc_pin_t pin[NRFE_MSPI_PINS_MAX]; -} nrfe_mspi_pinctrl_soc_pin_t; +} nrfe_mspi_pinctrl_soc_pin_msg_t; + +typedef struct { + nrfe_mspi_opcode_t opcode; /* NRFE_MSPI_CONFIG_DEV */ + uint8_t device_index; + nrfe_mspi_dev_config_t dev_config; +} nrfe_mspi_dev_config_msg_t; + +typedef struct { + nrfe_mspi_opcode_t opcode; /* NRFE_MSPI_CONFIG_XFER */ + nrfe_mspi_xfer_config_t xfer_config; +} nrfe_mspi_xfer_config_msg_t; + +typedef struct { + nrfe_mspi_opcode_t opcode; /* NRFE_MSPI_TX or NRFE_MSPI_TXRX */ + uint32_t command; + uint32_t address; + uint32_t num_bytes; /* Size of data */ + uint8_t data[]; /* Variable length data field at the end of packet. */ +} nrfe_mspi_xfer_packet_msg_t; -typedef struct __packed { - uint8_t opcode; /* nrfe_mspi_opcode */ +typedef struct { + nrfe_mspi_opcode_t opcode; /* Same as application's request. */ 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; +} nrfe_mspi_flpr_response_msg_t; #ifdef __cplusplus } From 216f212251bd8ef52f77e0fd68cf3e6912271808 Mon Sep 17 00:00:00 2001 From: Michal Frankiewicz Date: Wed, 5 Feb 2025 08:59:23 +0100 Subject: [PATCH 2/3] applications: sdp: mspi: Reduced IPC structures-applications Implemented smaller structures and reduced ammount of opcodes in IPC. Added support for multiple target devices. Signed-off-by: Michal Frankiewicz --- applications/sdp/mspi/src/main.c | 141 ++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 50 deletions(-) diff --git a/applications/sdp/mspi/src/main.c b/applications/sdp/mspi/src/main.c index bc7bc597f1bf..c0503c56c80e 100644 --- a/applications/sdp/mspi/src/main.c +++ b/applications/sdp/mspi/src/main.c @@ -17,11 +17,15 @@ #include -#define CE_PINS_MAX 9 +#define SUPPORTED_IO_MODES_COUNT 7 + +#define DEVICES_MAX 5 #define DATA_PINS_MAX 8 #define VIO_COUNT 11 -#define SUPPORTED_IO_MODES_COUNT 7 +#define MAX_FREQUENCY 64000000 + +#define CE_PIN_UNUSED UINT8_MAX #define HRT_IRQ_PRIORITY 2 #define HRT_VEVIF_IDX_WRITE 18 @@ -29,7 +33,7 @@ #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*/ +/* 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] = { @@ -57,18 +61,28 @@ static const hrt_xfer_bus_widths_t io_modes[SUPPORTED_IO_MODES_COUNT] = { }; static volatile uint8_t ce_vios_count; -static volatile uint8_t ce_vios[CE_PINS_MAX]; +static volatile uint8_t ce_vios[DEVICES_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 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); +NRF_STATIC_INLINE void nrf_vpr_csr_vio_out_or_set(uint16_t value) +{ + nrf_csr_set_bits(VPRCSR_NORDIC_OUT, value); +} + +NRF_STATIC_INLINE void nrf_vpr_csr_vio_out_clear_set(uint16_t value) +{ + nrf_csr_clear_bits(VPRCSR_NORDIC_OUT, value); +} + static void adjust_tail(volatile hrt_xfer_data_t *xfer_data, uint16_t frame_width, uint32_t data_length) { @@ -152,38 +166,39 @@ 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) +static void xfer_execute(nrfe_mspi_xfer_packet_msg_t *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); + volatile nrfe_mspi_dev_config_t *device = + &nrfe_mspi_devices[nrfe_mspi_xfer_config.device_index]; 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]; + 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]; - /* Fix position of command if command length is < BITS_IN_WORD, + /* 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.cmd = xfer_packet.cmd - << (BITS_IN_WORD - nrfe_mspi_xfer.cmd_length * BITS_IN_BYTE); + xfer_packet->command = + xfer_packet->command + << (BITS_IN_WORD - nrfe_mspi_xfer_config.command_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].data = (uint8_t *)&xfer_packet->command; 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); + 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.addr_length; i++) { + /* 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.addr_length - i - 1); + *(((uint8_t *)&xfer_packet->address) + nrfe_mspi_xfer_config.address_length - i - 1); } - for (uint8_t i = nrfe_mspi_xfer.addr_length; i < ADDR_AND_CYCLES_MAX_SIZE; i++) { + for (uint8_t i = nrfe_mspi_xfer_config.address_length; i < ADDR_AND_CYCLES_MAX_SIZE; i++) { address_and_dummy_cycles[i] = 0; } @@ -193,21 +208,21 @@ static void xfer_execute(struct mspi_xfer_packet xfer_packet) 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); + nrfe_mspi_xfer_config.address_length * BITS_IN_BYTE + + nrfe_mspi_xfer_config.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].data = xfer_packet->data; 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); + 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) +static void config_pins(nrfe_mspi_pinctrl_soc_pin_msg_t *pins_cfg) { ce_vios_count = 0; data_vios_count = 0; @@ -249,7 +264,11 @@ static void config_pins(nrfe_mspi_pinctrl_soc_pin_t *pins_cfg) } } 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]); + + /* Set all devices as undefined. */ + for (uint8_t i = 0; i < DEVICES_MAX; i++) { + nrfe_mspi_devices[i].ce_index = CE_PIN_UNUSED; + } } static void ep_bound(void *priv) @@ -261,46 +280,68 @@ static void ep_recv(const void *data, size_t len, void *priv) { (void)priv; (void)len; - nrfe_mspi_flpr_response_t response; + nrfe_mspi_flpr_response_msg_t response; uint8_t opcode = *(uint8_t *)data; response.opcode = opcode; switch (opcode) { case NRFE_MSPI_CONFIG_PINS: { - nrfe_mspi_pinctrl_soc_pin_t *pins_cfg = (nrfe_mspi_pinctrl_soc_pin_t *)data; + nrfe_mspi_pinctrl_soc_pin_msg_t *pins_cfg = (nrfe_mspi_pinctrl_soc_pin_msg_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_config_msg_t *dev_config = (nrfe_mspi_dev_config_msg_t *)data; + + NRFX_ASSERT(dev_config->device_index < DEVICES_MAX); + NRFX_ASSERT(dev_config->dev_config.io_mode < SUPPORTED_IO_MODES_COUNT); + NRFX_ASSERT(dev_config->dev_config.cpp <= MSPI_CPP_MODE_3); + NRFX_ASSERT(dev_config->dev_config.ce_index < ce_vios_count); + NRFX_ASSERT(dev_config->dev_config.ce_polarity <= MSPI_CE_ACTIVE_HIGH); + NRFX_ASSERT(dev_config->dev_config.freq <= MAX_FREQUENCY); + + nrfe_mspi_devices[dev_config->device_index] = dev_config->dev_config; + + /* Configure CE pin. */ + if (nrfe_mspi_devices[dev_config->device_index].ce_polarity == MSPI_CE_ACTIVE_LOW) { + nrf_vpr_csr_vio_out_or_set( + BIT(ce_vios[nrfe_mspi_devices[dev_config->device_index].ce_index])); + } else { + nrf_vpr_csr_vio_out_clear_set( + BIT(ce_vios[nrfe_mspi_devices[dev_config->device_index].ce_index])); + } - 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_config_msg_t *xfer_config = (nrfe_mspi_xfer_config_msg_t *)data; - nrfe_mspi_xfer = xfer->xfer; + NRFX_ASSERT(xfer_config->xfer_config.device_index < DEVICES_MAX); + /* Check if device was configured. */ + NRFX_ASSERT(nrfe_mspi_devices[xfer_config->xfer_config.device_index].ce_index < + ce_vios_count); + NRFX_ASSERT(xfer_config->xfer_config.command_length <= sizeof(uint32_t)); + NRFX_ASSERT(xfer_config->xfer_config.address_length <= sizeof(uint32_t)); + NRFX_ASSERT(xfer_config->xfer_config.tx_dummy == 0 || + xfer_config->xfer_config.command_length != 0 || + xfer_config->xfer_config.address_length != 0); + + nrfe_mspi_xfer_config = xfer_config->xfer_config; + + configure_clock(nrfe_mspi_devices[nrfe_mspi_xfer_config.device_index].cpp); break; } case NRFE_MSPI_TX: + nrfe_mspi_xfer_packet_msg_t *packet = (nrfe_mspi_xfer_packet_msg_t *)data; + + xfer_execute(packet); + break; case NRFE_MSPI_TXRX: { - nrfe_mspi_xfer_packet_t *packet = (nrfe_mspi_xfer_packet_t *)data; + nrfe_mspi_xfer_packet_msg_t *packet = (nrfe_mspi_xfer_packet_msg_t *)data; - if (packet->packet.dir == MSPI_RX) { - /* TODO: Process received data */ - } else if (packet->packet.dir == MSPI_TX) { - xfer_execute(packet->packet); - } + (void)packet; break; } default: @@ -322,7 +363,7 @@ static int backend_init(void) volatile uint32_t delay = 0; #if !defined(CONFIG_SYS_CLOCK_EXISTS) - /* Wait a little bit for IPC service to be ready on APP side */ + /* Wait a little bit for IPC service to be ready on APP side. */ while (delay < 1000) { delay++; } @@ -340,7 +381,7 @@ static int backend_init(void) return ret; } - /* Wait for endpoint to be bound */ + /* Wait for endpoint to be bound. */ while (!atomic_test_and_clear_bit(&ipc_atomic_sem, NRFE_MSPI_EP_BOUNDED)) { } From d51395ecd1b883fe7747dee125b6b370576d48aa Mon Sep 17 00:00:00 2001 From: Michal Frankiewicz Date: Wed, 5 Feb 2025 08:59:23 +0100 Subject: [PATCH 3/3] applications: sdp: mspi: Dummy cycles fix Fixed dummy cycles implementation. Changed dummy cycles limit from 32 to UINT32_MAX. Signed-off-by: Michal Frankiewicz --- applications/sdp/mspi/src/hrt/hrt-nrf54l15.s | 216 ++++++++++--------- applications/sdp/mspi/src/hrt/hrt.c | 10 +- applications/sdp/mspi/src/hrt/hrt.h | 6 +- applications/sdp/mspi/src/main.c | 82 ++++--- 4 files changed, 185 insertions(+), 129 deletions(-) diff --git a/applications/sdp/mspi/src/hrt/hrt-nrf54l15.s b/applications/sdp/mspi/src/hrt/hrt-nrf54l15.s index 6cfc1b95db80..7d1e048aac39 100644 --- a/applications/sdp/mspi/src/hrt/hrt-nrf54l15.s +++ b/applications/sdp/mspi/src/hrt/hrt-nrf54l15.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/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/main.c b/applications/sdp/mspi/src/main.c index c0503c56c80e..1d64d10a03f3 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;