Skip to content

Commit 750080b

Browse files
committed
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 <[email protected]>
1 parent c0a523b commit 750080b

File tree

4 files changed

+478
-327
lines changed

4 files changed

+478
-327
lines changed

applications/sdp/mspi/src/hrt/hrt.c

Lines changed: 153 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -7,182 +7,185 @@
77
#include <hal/nrf_vpr_csr_vio.h>
88
#include <hal/nrf_vpr_csr_vtim.h>
99

10-
#define CLK_FIRST_CYCLE_MULTIPLICATOR (3)
10+
/* Hardware requirement, to get n shifts SHIFTCNTB register has to be set to n-1*/
11+
#define SHIFTCNTB_VALUE(shift_count) (shift_count - 1)
12+
13+
/** @brief Shift control configuration. */
14+
typedef struct {
15+
uint8_t shift_count;
16+
nrf_vpr_csr_vio_shift_t out_mode;
17+
uint8_t frame_width;
18+
nrf_vpr_csr_vio_mode_in_t in_mode;
19+
} nrf_vpr_csr_vio_shift_ctrl_t;
20+
21+
NRF_STATIC_INLINE void
22+
nrf_vpr_csr_vio_shift_ctrl_buffered_set(nrf_vpr_csr_vio_shift_ctrl_t const *p_shift_ctrl)
23+
{
24+
uint32_t reg =
25+
((p_shift_ctrl->shift_count << VPRCSR_NORDIC_SHIFTCTRLB_SHIFTCNTB_VALUE_Pos) &
26+
VPRCSR_NORDIC_SHIFTCTRLB_SHIFTCNTB_VALUE_Msk) |
27+
((p_shift_ctrl->out_mode << VPRCSR_NORDIC_SHIFTCTRLB_OUTMODEB_MODE_Pos) &
28+
VPRCSR_NORDIC_SHIFTCTRLB_OUTMODEB_MODE_Msk) |
29+
((p_shift_ctrl->frame_width << VPRCSR_NORDIC_SHIFTCTRLB_OUTMODEB_FRAMEWIDTH_Pos) &
30+
VPRCSR_NORDIC_SHIFTCTRLB_OUTMODEB_FRAMEWIDTH_Msk) |
31+
((p_shift_ctrl->in_mode << VPRCSR_NORDIC_SHIFTCTRLB_INMODEB_MODE_Pos) &
32+
VPRCSR_NORDIC_SHIFTCTRLB_INMODEB_MODE_Msk);
33+
34+
nrf_csr_write(VPRCSR_NORDIC_SHIFTCTRLB, reg);
35+
}
1136

12-
void write_single_by_word(volatile struct hrt_ll_xfer xfer_ll_params)
37+
NRF_STATIC_INLINE void nrf_vpr_csr_vio_out_or_set(uint16_t value)
1338
{
14-
uint16_t dir;
15-
uint16_t out;
16-
nrf_vpr_csr_vio_config_t config;
17-
nrf_vpr_csr_vio_mode_out_t out_mode = {
18-
.mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE,
19-
.frame_width = 1,
20-
};
39+
nrf_csr_set_bits(VPRCSR_NORDIC_OUT, value);
40+
}
2141

22-
NRFX_ASSERT(xfer_ll_params.word_size <= MAX_WORD_SIZE);
23-
/* Configuration step */
24-
dir = nrf_vpr_csr_vio_dir_get();
25-
nrf_vpr_csr_vio_dir_set(dir | PIN_DIR_OUT_MASK(VIO(NRFE_MSPI_DQ0_PIN_NUMBER)));
42+
NRF_STATIC_INLINE void nrf_vpr_csr_vio_out_clear_set(uint16_t value)
43+
{
44+
nrf_csr_clear_bits(VPRCSR_NORDIC_OUT, value);
45+
}
2646

27-
out = nrf_vpr_csr_vio_out_get();
28-
nrf_vpr_csr_vio_out_set(out | PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_DQ0_PIN_NUMBER)));
47+
static const nrf_vpr_csr_vio_shift_ctrl_t write_final_shift_ctrl_cfg = {
48+
.shift_count = 1,
49+
.out_mode = NRF_VPR_CSR_VIO_SHIFT_NONE,
50+
.frame_width = 4,
51+
.in_mode = NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS,
52+
};
2953

30-
nrf_vpr_csr_vio_mode_out_set(&out_mode);
31-
nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS);
32-
33-
nrf_vpr_csr_vio_config_get(&config);
34-
config.input_sel = false;
35-
nrf_vpr_csr_vio_config_set(&config);
36-
37-
/* Fix position of data if word size < MAX_WORD_SIZE,
38-
* so that leading zeros would not be printed instead of data bits.
39-
*/
40-
if (xfer_ll_params.word_size < MAX_WORD_SIZE) {
41-
for (uint8_t i = 0; i < xfer_ll_params.data_len; i++) {
42-
xfer_ll_params.data_to_send[i] =
43-
xfer_ll_params.data_to_send[i]
44-
<< (MAX_WORD_SIZE - xfer_ll_params.word_size);
45-
}
54+
static void hrt_tx(volatile hrt_xfer_data_t *xfer_data, uint8_t frame_width, bool *counter_running,
55+
uint16_t counter_value)
56+
{
57+
if (xfer_data->word_count == 0) {
58+
return;
4659
}
4760

48-
/* Counter settings */
49-
nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_RELOAD);
50-
nrf_vpr_csr_vtim_simple_counter_top_set(0, xfer_ll_params.counter_top);
51-
52-
/* Set number of shifts before OUTB needs to be updated.
53-
* First shift needs to be increased by 1.
54-
*/
55-
nrf_vpr_csr_vio_shift_cnt_out_set(xfer_ll_params.word_size);
56-
nrf_vpr_csr_vio_shift_cnt_out_buffered_set(xfer_ll_params.word_size - 1);
57-
58-
/* Enable CS */
59-
out = nrf_vpr_csr_vio_out_get();
60-
out &= ~PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER));
61-
out |= xfer_ll_params.ce_enable_state ? PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER))
62-
: PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER));
63-
nrf_vpr_csr_vio_out_set(out);
64-
65-
/* Start counter */
66-
nrf_vpr_csr_vtim_simple_counter_set(0, CLK_FIRST_CYCLE_MULTIPLICATOR *
67-
xfer_ll_params.counter_top);
68-
69-
/* Send data */
70-
for (uint8_t i = 0; i < xfer_ll_params.data_len; i++) {
71-
nrf_vpr_csr_vio_out_buffered_reversed_byte_set(xfer_ll_params.data_to_send[i]);
72-
}
61+
nrf_vpr_csr_vio_shift_ctrl_t xfer_shift_ctrl = {
62+
.shift_count = SHIFTCNTB_VALUE(BITS_IN_WORD / frame_width),
63+
.out_mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE,
64+
.frame_width = frame_width,
65+
.in_mode = NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS,
66+
};
7367

74-
/* Clear all bits, wait until the last word is sent */
75-
nrf_vpr_csr_vio_out_buffered_set(0);
68+
nrf_vpr_csr_vio_shift_ctrl_buffered_set(&xfer_shift_ctrl);
7669

77-
/* Final configuration */
78-
out_mode.mode = NRF_VPR_CSR_VIO_SHIFT_NONE;
79-
nrf_vpr_csr_vio_mode_out_buffered_set(&out_mode);
80-
nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS);
81-
82-
/* Disable CS */
83-
if (!xfer_ll_params.ce_hold) {
84-
out = nrf_vpr_csr_vio_out_get();
85-
out &= ~(PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)) |
86-
PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_SCK_PIN_NUMBER)));
87-
out |= xfer_ll_params.ce_enable_state
88-
? PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER))
89-
: PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER));
90-
nrf_vpr_csr_vio_out_set(out);
91-
}
70+
for (uint32_t i = 0; i < xfer_data->word_count; i++) {
9271

93-
/* Stop counter */
94-
nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_STOP);
72+
switch (xfer_data->word_count - i) {
73+
case 1: /* Last transfer */
74+
xfer_shift_ctrl.shift_count = SHIFTCNTB_VALUE(xfer_data->last_word_clocks);
75+
nrf_vpr_csr_vio_shift_ctrl_buffered_set(&xfer_shift_ctrl);
76+
77+
xfer_data->vio_out_set(xfer_data->last_word);
78+
break;
79+
case 2: /* Last but one transfer.*/
80+
xfer_shift_ctrl.shift_count =
81+
SHIFTCNTB_VALUE(xfer_data->penultimate_word_clocks);
82+
nrf_vpr_csr_vio_shift_ctrl_buffered_set(&xfer_shift_ctrl);
83+
default: /* Intentional fallthrough */
84+
xfer_data->vio_out_set(((uint32_t *)xfer_data->data)[i]);
85+
}
86+
87+
if ((i == 0) && (!*counter_running)) {
88+
/* Start counter */
89+
nrf_vpr_csr_vtim_simple_counter_set(0, counter_value);
90+
*counter_running = true;
91+
}
92+
}
9593
}
9694

97-
void write_quad_by_word(volatile struct hrt_ll_xfer xfer_ll_params)
95+
void hrt_write(hrt_xfer_t *hrt_xfer_params)
9896
{
99-
uint16_t dir;
100-
uint16_t out;
101-
nrf_vpr_csr_vio_config_t config;
102-
nrf_vpr_csr_vio_mode_out_t out_mode = {
103-
.mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE,
104-
.frame_width = 4,
105-
};
106-
107-
NRFX_ASSERT(xfer_ll_params.word_size % 4 == 0);
108-
NRFX_ASSERT(xfer_ll_params.word_size <= MAX_WORD_SIZE);
109-
/* Configuration step */
110-
dir = nrf_vpr_csr_vio_dir_get();
97+
hrt_frame_element_t first_element = HRT_FE_DATA;
98+
bool counter_running = false;
11199

112-
nrf_vpr_csr_vio_dir_set(dir | PIN_DIR_OUT_MASK(VIO(NRFE_MSPI_DQ0_PIN_NUMBER)) |
113-
PIN_DIR_OUT_MASK(VIO(NRFE_MSPI_DQ1_PIN_NUMBER)) |
114-
PIN_DIR_OUT_MASK(VIO(NRFE_MSPI_DQ2_PIN_NUMBER)) |
115-
PIN_DIR_OUT_MASK(VIO(NRFE_MSPI_DQ3_PIN_NUMBER)));
100+
nrf_vpr_csr_vio_mode_out_t out_mode = {.mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE};
116101

117-
out = nrf_vpr_csr_vio_out_get();
102+
/* Configure clock and pins */
103+
nrf_vpr_csr_vio_dir_set(hrt_xfer_params->tx_direction_mask);
118104

119-
nrf_vpr_csr_vio_out_set(out | PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_DQ0_PIN_NUMBER)) |
120-
PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_DQ1_PIN_NUMBER)) |
121-
PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_DQ2_PIN_NUMBER)) |
122-
PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_DQ3_PIN_NUMBER)));
105+
for (uint8_t i = 0; i < HRT_FE_MAX; i++) {
123106

124-
nrf_vpr_csr_vio_mode_out_set(&out_mode);
125-
nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS);
126-
127-
nrf_vpr_csr_vio_config_get(&config);
128-
config.input_sel = false;
129-
nrf_vpr_csr_vio_config_set(&config);
130-
131-
/* Fix position of data if word size < MAX_WORD_SIZE,
132-
* so that leading zeros would not be printed instead of data.
133-
*/
134-
if (xfer_ll_params.word_size < MAX_WORD_SIZE) {
135-
for (uint8_t i = 0; i < xfer_ll_params.data_len; i++) {
136-
xfer_ll_params.data_to_send[i] =
137-
xfer_ll_params.data_to_send[i]
138-
<< (MAX_WORD_SIZE - xfer_ll_params.word_size);
107+
if (hrt_xfer_params->xfer_data[i].word_count != 0) {
108+
first_element = i;
109+
break;
139110
}
140111
}
141112

142-
/* Counter settings */
113+
switch (first_element) {
114+
case HRT_FE_COMMAND:
115+
out_mode.frame_width = hrt_xfer_params->bus_widths.command;
116+
break;
117+
case HRT_FE_ADDRESS:
118+
out_mode.frame_width = hrt_xfer_params->bus_widths.address;
119+
break;
120+
case HRT_FE_DATA:
121+
out_mode.frame_width = hrt_xfer_params->bus_widths.data;
122+
break;
123+
default:
124+
break;
125+
}
126+
143127
nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_RELOAD);
144-
nrf_vpr_csr_vtim_simple_counter_top_set(0, xfer_ll_params.counter_top);
145-
146-
/* Set number of shifts before OUTB needs to be updated.
147-
* First shift needs to be increased by 1.
148-
*/
149-
nrf_vpr_csr_vio_shift_cnt_out_set(xfer_ll_params.word_size / 4);
150-
nrf_vpr_csr_vio_shift_cnt_out_buffered_set(xfer_ll_params.word_size / 4 - 1);
151-
152-
/* Enable CS */
153-
out = nrf_vpr_csr_vio_out_get();
154-
out &= ~PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER));
155-
out |= xfer_ll_params.ce_enable_state ? PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER))
156-
: PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER));
157-
nrf_vpr_csr_vio_out_set(out);
158-
159-
/* Start counter */
160-
nrf_vpr_csr_vtim_simple_counter_set(0, 3 * xfer_ll_params.counter_top);
161-
162-
/* Send data */
163-
for (uint8_t i = 0; i < xfer_ll_params.data_len; i++) {
164-
nrf_vpr_csr_vio_out_buffered_reversed_byte_set(xfer_ll_params.data_to_send[i]);
128+
nrf_vpr_csr_vtim_simple_counter_top_set(0, hrt_xfer_params->counter_value);
129+
nrf_vpr_csr_vio_mode_in_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS);
130+
131+
nrf_vpr_csr_vio_mode_out_set(&out_mode);
132+
133+
switch (hrt_xfer_params->xfer_data[first_element].word_count) {
134+
case 1:
135+
nrf_vpr_csr_vio_shift_cnt_out_set(
136+
hrt_xfer_params->xfer_data[first_element].last_word_clocks);
137+
break;
138+
case 2:
139+
nrf_vpr_csr_vio_shift_cnt_out_set(
140+
hrt_xfer_params->xfer_data[first_element].penultimate_word_clocks);
141+
break;
142+
default:
143+
nrf_vpr_csr_vio_shift_cnt_out_set(BITS_IN_WORD / out_mode.frame_width);
165144
}
166145

167-
/* Clear all bits, wait until the last word is sent */
168-
nrf_vpr_csr_vio_out_buffered_set(0);
146+
/* Enable CE */
147+
if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) {
148+
nrf_vpr_csr_vio_out_clear_set(BIT(hrt_xfer_params->ce_vio));
149+
} else {
150+
nrf_vpr_csr_vio_out_or_set(BIT(hrt_xfer_params->ce_vio));
151+
}
169152

170-
/* Final configuration */
171-
out_mode.mode = NRF_VPR_CSR_VIO_SHIFT_NONE;
172-
nrf_vpr_csr_vio_mode_out_buffered_set(&out_mode);
173-
nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS);
174-
175-
/* Disable CS */
176-
if (!xfer_ll_params.ce_hold) {
177-
out = nrf_vpr_csr_vio_out_get();
178-
out &= ~(PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER)) |
179-
PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_SCK_PIN_NUMBER)));
180-
out |= xfer_ll_params.ce_enable_state
181-
? PIN_OUT_LOW_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER))
182-
: PIN_OUT_HIGH_MASK(VIO(NRFE_MSPI_CS0_PIN_NUMBER));
183-
nrf_vpr_csr_vio_out_set(out);
153+
/* Transfer command */
154+
hrt_tx(&hrt_xfer_params->xfer_data[HRT_FE_COMMAND], hrt_xfer_params->bus_widths.command,
155+
&counter_running, hrt_xfer_params->counter_value);
156+
/* Transfer address */
157+
hrt_tx(&hrt_xfer_params->xfer_data[HRT_FE_ADDRESS], hrt_xfer_params->bus_widths.address,
158+
&counter_running, hrt_xfer_params->counter_value);
159+
/* Transfer data */
160+
hrt_tx(&hrt_xfer_params->xfer_data[HRT_FE_DATA], hrt_xfer_params->bus_widths.data,
161+
&counter_running, hrt_xfer_params->counter_value);
162+
163+
if (hrt_xfer_params->eliminate_last_pulse) {
164+
165+
/* Wait until the last word is sent */
166+
while (nrf_vpr_csr_vio_shift_cnt_out_get() != 0) {
167+
}
168+
169+
/* This is a partial solution to surplus clock edge problem in modes 1 and 3.
170+
* This solution works only for counter values above 20.
171+
*/
172+
nrf_vpr_csr_vtim_simple_wait_set(0, false, 0);
184173
}
185174

175+
/* Final configuration */
176+
nrf_vpr_csr_vio_shift_ctrl_buffered_set(&write_final_shift_ctrl_cfg);
177+
nrf_vpr_csr_vio_out_buffered_reversed_word_set(0x00);
178+
186179
/* Stop counter */
187180
nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_STOP);
181+
182+
/* Disable CE */
183+
if (!hrt_xfer_params->ce_hold) {
184+
185+
if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) {
186+
nrf_vpr_csr_vio_out_or_set(BIT(hrt_xfer_params->ce_vio));
187+
} else {
188+
nrf_vpr_csr_vio_out_clear_set(BIT(hrt_xfer_params->ce_vio));
189+
}
190+
}
188191
}

0 commit comments

Comments
 (0)