Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

application: sdp: mspi: Ipc Hrt Connection #19449

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,5 @@ CONFIG_SYS_CLOCK_EXISTS=n

CONFIG_OUTPUT_DISASSEMBLY=y
CONFIG_COMMON_LIBC_MALLOC=n

CONFIG_COMPILER_OPT="-fshort-enums"
303 changes: 153 additions & 150 deletions applications/sdp/mspi/src/hrt/hrt.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,182 +7,185 @@
#include <hal/nrf_vpr_csr_vio.h>
#include <hal/nrf_vpr_csr_vtim.h>

#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);
}
mif1-nordic marked this conversation as resolved.
Show resolved Hide resolved

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,
};

magp-nordic marked this conversation as resolved.
Show resolved Hide resolved
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));
}
}
}
Loading