12
12
13
13
#define SPI_INPUT_PIN_NUM 2
14
14
#define CNT1_INIT_VALUE 1
15
- #define MSB_MASK (0xff000000)
15
+ #define MSB_MASK (0xff000000)
16
16
17
- #define INPUT_SHIFT_COUNT (BITS_IN_WORD - BITS_IN_BYTE)
17
+ #define FOURTH_BYTE_SHIFT_CNT 24
18
+ #define THIRD_BYTE_SHIFT_CNT 16
19
+ #define SECOND_BYTE_SHIFT_CNT 8
18
20
19
21
/*
20
22
* Macro for calculating TOP value of CNT1. It should be twice as TOP value of CNT0
@@ -224,7 +226,7 @@ static void hrt_tx_rx(volatile hrt_xfer_data_t *xfer_data, uint8_t frame_width,
224
226
uint16_t cnt0_val , uint16_t cnt1_val )
225
227
{
226
228
nrf_vpr_csr_vio_shift_ctrl_t shift_ctrl = {
227
- .shift_count = BITS_IN_BYTE - 1 ,
229
+ .shift_count = SHIFTCNTB_VALUE ( BITS_IN_BYTE / frame_width ) ,
228
230
.out_mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE ,
229
231
.frame_width = frame_width ,
230
232
.in_mode = NRF_VPR_CSR_VIO_MODE_IN_SHIFT ,
@@ -279,6 +281,13 @@ void hrt_read(volatile hrt_xfer_t *hrt_xfer_params)
279
281
.mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE ,
280
282
.frame_width = 1 ,
281
283
};
284
+ nrf_vpr_csr_vio_mode_out_t out_mode_in = {
285
+ .mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE ,
286
+ .frame_width = hrt_xfer_params -> bus_widths .data ,
287
+ };
288
+
289
+ uint32_t rec_data = 0 ;
290
+ uint32_t iter = 0 ;
282
291
283
292
/* Enable CS */
284
293
if (hrt_xfer_params -> ce_polarity == MSPI_CE_ACTIVE_LOW ) {
@@ -288,9 +297,12 @@ void hrt_read(volatile hrt_xfer_t *hrt_xfer_params)
288
297
}
289
298
290
299
/* Configure clock and pins */
291
- /* Set DQ1 as input */
292
- WRITE_BIT (hrt_xfer_params -> tx_direction_mask , SPI_INPUT_PIN_NUM , VPRCSR_NORDIC_DIR_INPUT );
293
- nrf_vpr_csr_vio_dir_set (hrt_xfer_params -> tx_direction_mask );
300
+ /* Set DQ1 as input in SPI case. */
301
+ if (hrt_xfer_params -> bus_widths .data == 1 ) {
302
+ WRITE_BIT (hrt_xfer_params -> tx_direction_mask , SPI_INPUT_PIN_NUM ,
303
+ VPRCSR_NORDIC_DIR_INPUT );
304
+ nrf_vpr_csr_vio_dir_set (hrt_xfer_params -> tx_direction_mask );
305
+ }
294
306
295
307
/* Initial configuration */
296
308
nrf_vpr_csr_vio_mode_in_set (NRF_VPR_CSR_VIO_MODE_IN_SHIFT );
@@ -314,9 +326,36 @@ void hrt_read(volatile hrt_xfer_t *hrt_xfer_params)
314
326
hrt_tx_rx (& hrt_xfer_params -> xfer_data [HRT_FE_ADDRESS ], hrt_xfer_params -> bus_widths .address ,
315
327
false, hrt_xfer_params -> counter_value , CNT1_INIT_VALUE );
316
328
317
- for (uint8_t i = 0 ; i < hrt_xfer_params -> xfer_data [HRT_FE_DATA ].word_count ; i ++ ) {
318
- hrt_xfer_params -> xfer_data [HRT_FE_DATA ].data [i ] =
319
- nrf_vpr_csr_vio_in_buffered_reversed_byte_get () >> INPUT_SHIFT_COUNT ;
329
+ /* Set pins as input for cases other than SINGLE mode. */
330
+ if (hrt_xfer_params -> bus_widths .data != 1 ) {
331
+ nrf_vpr_csr_vio_dir_set (hrt_xfer_params -> rx_direction_mask );
332
+ }
333
+
334
+ if (hrt_xfer_params -> bus_widths .address != hrt_xfer_params -> bus_widths .data ) {
335
+ /*
336
+ * When writing to SHIFTCTRLB, reception of data starts 6 clock cycles (3 bytes) too
337
+ * late. When writing to OUTMODEB and SHIFTCNTB separately, the problem disappears.
338
+ */
339
+ nrf_vpr_csr_vio_mode_out_buffered_set (& out_mode_in );
340
+ nrf_vpr_csr_vio_shift_cnt_out_buffered_set (
341
+ SHIFTCNTB_VALUE (BITS_IN_BYTE / hrt_xfer_params -> bus_widths .data ));
342
+
343
+ /*
344
+ * When calling `vpr_csr_vio_in_buffered_reversed_byte_get` for the first time in
345
+ * 1_1_4 mode, CPU stalls for 8 clock cycles instead of 2 (so there are 4 bytes in
346
+ * the register, not 1). It is probably due to HW issue causing SHIFT_CNT_IN to be
347
+ * updated one word too late. For this reason, read all four bytes at once, save
348
+ * them in a temporary variable, and put them in buffer later to not perform not
349
+ * needed operations during receive.
350
+ */
351
+ rec_data = nrf_vpr_csr_vio_in_buffered_reversed_byte_get ();
352
+ iter = 4 ;
353
+ }
354
+
355
+ /* Receive data. For QUAD_1_1_4 mode this starts later due to HW issue described above. */
356
+ for (; iter < hrt_xfer_params -> xfer_data [HRT_FE_DATA ].word_count ; iter ++ ) {
357
+ hrt_xfer_params -> xfer_data [HRT_FE_DATA ].data [iter ] =
358
+ nrf_vpr_csr_vio_in_buffered_reversed_byte_get () >> FOURTH_BYTE_SHIFT_CNT ;
320
359
}
321
360
322
361
/* Stop counters */
@@ -336,7 +375,18 @@ void hrt_read(volatile hrt_xfer_t *hrt_xfer_params)
336
375
}
337
376
}
338
377
339
- /* Set DQ1 back as output. */
340
- WRITE_BIT (hrt_xfer_params -> tx_direction_mask , SPI_INPUT_PIN_NUM , VPRCSR_NORDIC_DIR_OUTPUT );
341
- nrf_vpr_csr_vio_dir_set (hrt_xfer_params -> tx_direction_mask );
378
+ /* Copy the first 4 bytes of data to buffer. */
379
+ if (hrt_xfer_params -> bus_widths .address != hrt_xfer_params -> bus_widths .data ) {
380
+ hrt_xfer_params -> xfer_data [HRT_FE_DATA ].data [0 ] = rec_data ;
381
+ hrt_xfer_params -> xfer_data [HRT_FE_DATA ].data [1 ] = rec_data >> SECOND_BYTE_SHIFT_CNT ;
382
+ hrt_xfer_params -> xfer_data [HRT_FE_DATA ].data [2 ] = rec_data >> THIRD_BYTE_SHIFT_CNT ;
383
+ hrt_xfer_params -> xfer_data [HRT_FE_DATA ].data [3 ] = rec_data >> FOURTH_BYTE_SHIFT_CNT ;
384
+ }
385
+
386
+ /* Set DQ1 back as output in SINGLE mode. */
387
+ if (hrt_xfer_params -> bus_widths .data == 1 ) {
388
+ WRITE_BIT (hrt_xfer_params -> tx_direction_mask , SPI_INPUT_PIN_NUM ,
389
+ VPRCSR_NORDIC_DIR_OUTPUT );
390
+ nrf_vpr_csr_vio_dir_set (hrt_xfer_params -> tx_direction_mask );
391
+ }
342
392
}
0 commit comments