Skip to content

Commit 9784ae0

Browse files
magp-nordicjaz1-nordic
authored andcommitted
applications: sdp: mspi: Initial implementation
Added initial mspi implementation with hard real time task running on interrupts. Signed-off-by: Michal Frankiewicz <[email protected]> Signed-off-by: Magdalena Pastula <[email protected]>
1 parent de0f3e7 commit 9784ae0

File tree

10 files changed

+901
-0
lines changed

10 files changed

+901
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#
2+
# Copyright (c) 2024 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
cmake_minimum_required(VERSION 3.20.0)
8+
9+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
10+
project(sdp_mspi)
11+
12+
sdp_assembly_generate("${CMAKE_SOURCE_DIR}/src/hrt/hrt.c")
13+
sdp_assembly_check("${CMAKE_SOURCE_DIR}/src/hrt/hrt.c")
14+
sdp_assembly_prepare_install("${CMAKE_SOURCE_DIR}/src/hrt/hrt.c")
15+
16+
target_sources(app PRIVATE src/main.c)
17+
target_sources(app PRIVATE src/hrt/hrt.s)
18+
19+
add_dependencies(app asm_check)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Single-threaded
2+
CONFIG_MULTITHREADING=n
3+
CONFIG_KERNEL_MEM_POOL=n
4+
CONFIG_LOG=n
5+
6+
# Drivers and peripherals
7+
CONFIG_I2C=n
8+
CONFIG_WATCHDOG=n
9+
CONFIG_GPIO=n
10+
CONFIG_PINCTRL=n
11+
CONFIG_SPI=n
12+
CONFIG_SERIAL=n
13+
CONFIG_FLASH=n
14+
15+
# Power management
16+
CONFIG_PM=n
17+
18+
# Interrupts
19+
CONFIG_DYNAMIC_INTERRUPTS=n
20+
CONFIG_IRQ_OFFLOAD=n
21+
CONFIG_GEN_SW_ISR_TABLE=n
22+
23+
# Memory protection
24+
CONFIG_THREAD_STACK_INFO=n
25+
CONFIG_THREAD_CUSTOM_DATA=n
26+
CONFIG_FPU=n
27+
28+
# Boot
29+
CONFIG_BOOT_BANNER=n
30+
CONFIG_NCS_BOOT_BANNER=n
31+
32+
# Console
33+
CONFIG_CONSOLE=n
34+
CONFIG_UART_CONSOLE=n
35+
CONFIG_STDOUT_CONSOLE=n
36+
CONFIG_PRINTK=n
37+
CONFIG_EARLY_CONSOLE=n
38+
39+
# Build
40+
CONFIG_SIZE_OPTIMIZATIONS=y
41+
42+
# No timer support in the kernel
43+
CONFIG_SYS_CLOCK_EXISTS=n
44+
45+
CONFIG_OUTPUT_DISASSEMBLY=y
46+
CONFIG_COMMON_LIBC_MALLOC=n
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
&gpio0 {
8+
status = "disabled";
9+
};
10+
11+
&gpio1 {
12+
status = "disabled";
13+
};
14+
15+
&gpio2 {
16+
status = "disabled";
17+
};
18+
19+
&gpiote20 {
20+
status = "disabled";
21+
};
22+
23+
&gpiote30 {
24+
status = "disabled";
25+
};
26+
27+
&grtc {
28+
status = "disabled";
29+
};
30+
31+
&uart20 {
32+
status = "disabled";
33+
};
34+
35+
&uart30 {
36+
status = "disabled";
37+
};
38+
39+
&pwm20 {
40+
status = "disabled";
41+
};

applications/sdp/mspi/prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CONFIG_MBOX=y

applications/sdp/mspi/sample.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
sample:
2+
name: SDP mSPI application
3+
description: SDP mSPI application
4+
common:
5+
integration_platforms:
6+
- nrf54l15dk/nrf54l15/cpuflpr
7+
tests:
8+
applications.sdp.mspi.icmsg:
9+
build_only: true
10+
sysbuild: true
11+
platform_allow: nrf54l15dk/nrf54l15/cpuflpr
12+
tags: ci_build sysbuild mspi
13+
extra_configs:
14+
- CONFIG_IPC_SERVICE=y
15+
- CONFIG_IPC_SERVICE_BACKEND_ICMSG=y
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
#include "hrt.h"
7+
#include <hal/nrf_vpr_csr_vio.h>
8+
#include <hal/nrf_vpr_csr_vtim.h>
9+
10+
#define TOP 4
11+
12+
void write_single_by_word(volatile uint32_t *data, uint8_t data_len, uint32_t counter_top,
13+
uint8_t word_size, bool ce_enable_state, bool hold_ce)
14+
{
15+
NRFX_ASSERT(word_size > MAX_WORD_SIZE);
16+
17+
/* Configuration step */
18+
uint16_t dir = nrf_vpr_csr_vio_dir_get();
19+
20+
nrf_vpr_csr_vio_dir_set(dir | PIN_DIR_OUT_MASK(D0_PIN) | PIN_DIR_OUT_MASK(CS_PIN) |
21+
PIN_DIR_OUT_MASK(SCLK_PIN));
22+
23+
uint16_t out = nrf_vpr_csr_vio_out_get();
24+
25+
nrf_vpr_csr_vio_out_set(out | PIN_OUT_LOW_MASK(D0_PIN) | PIN_OUT_HIGH_MASK(CS_PIN) |
26+
PIN_OUT_LOW_MASK(SCLK_PIN));
27+
28+
nrf_vpr_csr_vio_mode_out_t out_mode = {
29+
.mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE,
30+
.frame_width = 1,
31+
};
32+
33+
nrf_vpr_csr_vio_mode_out_set(&out_mode);
34+
nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS);
35+
36+
nrf_vpr_csr_vio_config_t config;
37+
38+
nrf_vpr_csr_vio_config_get(&config);
39+
config.input_sel = false;
40+
nrf_vpr_csr_vio_config_set(&config);
41+
42+
/* Fix position of data if word size < MAX_WORD_SIZE,
43+
* so that leading zeros would not be printed instead of data bits.
44+
*/
45+
if (word_size < MAX_WORD_SIZE) {
46+
for (uint8_t i = 0; i < data_len; i++) {
47+
data[i] = data[i] << (MAX_WORD_SIZE - word_size);
48+
}
49+
}
50+
51+
/* Counter settings */
52+
nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_RELOAD);
53+
nrf_vpr_csr_vtim_simple_counter_top_set(0, counter_top);
54+
55+
/* Set number of shifts before OUTB needs to be updated.
56+
* First shift needs to be increased by 1.
57+
*/
58+
nrf_vpr_csr_vio_shift_cnt_out_set(word_size);
59+
nrf_vpr_csr_vio_shift_cnt_out_buffered_set(word_size - 1);
60+
61+
/* Enable CS */
62+
out = nrf_vpr_csr_vio_out_get();
63+
out &= ~PIN_OUT_HIGH_MASK(CS_PIN);
64+
out |= ce_enable_state ? PIN_OUT_HIGH_MASK(CS_PIN) : PIN_OUT_LOW_MASK(CS_PIN);
65+
nrf_vpr_csr_vio_out_set(out);
66+
67+
/* Start counter */
68+
nrf_vpr_csr_vtim_simple_counter_set(0, 3 * counter_top);
69+
70+
/* Send data */
71+
for (uint8_t i = 0; i < data_len; i++) {
72+
nrf_vpr_csr_vio_out_buffered_reversed_byte_set(data[i]);
73+
}
74+
75+
/* Clear all bits, wait until the last word is sent */
76+
nrf_vpr_csr_vio_out_buffered_set(0);
77+
78+
/* Final configuration */
79+
out_mode.mode = NRF_VPR_CSR_VIO_SHIFT_NONE;
80+
nrf_vpr_csr_vio_mode_out_buffered_set(&out_mode);
81+
nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS);
82+
83+
/* Deselect slave */
84+
if (!hold_ce) {
85+
out = nrf_vpr_csr_vio_out_get();
86+
out &= ~(PIN_OUT_HIGH_MASK(CS_PIN) | PIN_OUT_HIGH_MASK(SCLK_PIN));
87+
out |= ce_enable_state ? PIN_OUT_LOW_MASK(CS_PIN) : PIN_OUT_HIGH_MASK(CS_PIN);
88+
out |= PIN_OUT_LOW_MASK(SCLK_PIN);
89+
nrf_vpr_csr_vio_out_set(out);
90+
}
91+
92+
/* Stop counter */
93+
nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_STOP);
94+
}
95+
96+
void write_quad_by_word(volatile uint32_t *data, uint8_t data_len, uint32_t counter_top,
97+
uint8_t word_size, bool ce_enable_state, bool hold_ce)
98+
{
99+
NRFX_ASSERT(word_size > MAX_WORD_SIZE);
100+
NRFX_ASSERT(word_size % 4 == 0);
101+
102+
/* Configuration step */
103+
uint16_t dir = nrf_vpr_csr_vio_dir_get();
104+
105+
nrf_vpr_csr_vio_dir_set(dir | PIN_DIR_OUT_MASK(D0_PIN) | PIN_DIR_OUT_MASK(D1_PIN) |
106+
PIN_DIR_OUT_MASK(D2_PIN) | PIN_DIR_OUT_MASK(D3_PIN) |
107+
PIN_DIR_OUT_MASK(CS_PIN) | PIN_DIR_OUT_MASK(SCLK_PIN));
108+
109+
uint16_t out = nrf_vpr_csr_vio_out_get();
110+
111+
nrf_vpr_csr_vio_out_set(out | PIN_OUT_LOW_MASK(D0_PIN) | PIN_OUT_LOW_MASK(D1_PIN) |
112+
PIN_OUT_LOW_MASK(D2_PIN) | PIN_OUT_LOW_MASK(D3_PIN) |
113+
PIN_OUT_HIGH_MASK(CS_PIN) | PIN_OUT_LOW_MASK(SCLK_PIN));
114+
115+
nrf_vpr_csr_vio_mode_out_t out_mode = {
116+
.mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE,
117+
.frame_width = 4,
118+
};
119+
120+
nrf_vpr_csr_vio_mode_out_set(&out_mode);
121+
nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS);
122+
123+
nrf_vpr_csr_vio_config_t config;
124+
125+
nrf_vpr_csr_vio_config_get(&config);
126+
config.input_sel = false;
127+
nrf_vpr_csr_vio_config_set(&config);
128+
129+
/* Fix position of data if word size < MAX_WORD_SIZE,
130+
* so that leading zeros would not be printed instead of data.
131+
*/
132+
if (word_size < MAX_WORD_SIZE) {
133+
for (uint8_t i = 0; i < data_len; i++) {
134+
data[i] = data[i] << (MAX_WORD_SIZE - word_size);
135+
}
136+
}
137+
138+
/* Counter settings */
139+
nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_RELOAD);
140+
nrf_vpr_csr_vtim_simple_counter_top_set(0, counter_top);
141+
142+
/* Set number of shifts before OUTB needs to be updated.
143+
* First shift needs to be increased by 1.
144+
*/
145+
nrf_vpr_csr_vio_shift_cnt_out_set(word_size / 4);
146+
nrf_vpr_csr_vio_shift_cnt_out_buffered_set(word_size / 4 - 1);
147+
148+
/* Enable CS */
149+
out = nrf_vpr_csr_vio_out_get();
150+
out &= ~PIN_OUT_HIGH_MASK(CS_PIN);
151+
out |= ce_enable_state ? PIN_OUT_HIGH_MASK(CS_PIN) : PIN_OUT_LOW_MASK(CS_PIN);
152+
nrf_vpr_csr_vio_out_set(out);
153+
154+
/* Start counter */
155+
nrf_vpr_csr_vtim_simple_counter_set(0, 3 * counter_top);
156+
157+
/* Send data */
158+
for (uint8_t i = 0; i < data_len; i++) {
159+
nrf_vpr_csr_vio_out_buffered_reversed_byte_set(data[i]);
160+
}
161+
162+
/* Clear all bits, wait until the last word is sent */
163+
nrf_vpr_csr_vio_out_buffered_set(0);
164+
165+
/* Final configuration */
166+
out_mode.mode = NRF_VPR_CSR_VIO_SHIFT_NONE;
167+
nrf_vpr_csr_vio_mode_out_buffered_set(&out_mode);
168+
nrf_vpr_csr_vio_mode_in_buffered_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS);
169+
170+
/* Deselect slave */
171+
if (!hold_ce) {
172+
out = nrf_vpr_csr_vio_out_get();
173+
out &= ~(PIN_OUT_HIGH_MASK(CS_PIN) | PIN_OUT_HIGH_MASK(SCLK_PIN));
174+
out |= ce_enable_state ? PIN_OUT_LOW_MASK(CS_PIN) : PIN_OUT_HIGH_MASK(CS_PIN);
175+
out |= PIN_OUT_LOW_MASK(SCLK_PIN);
176+
nrf_vpr_csr_vio_out_set(out);
177+
}
178+
179+
/* Stop counter */
180+
nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_STOP);
181+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#ifndef _HRT_H__
8+
#define _HRT_H__
9+
10+
#include <stdint.h>
11+
#include <stdbool.h>
12+
13+
#define SCLK_PIN 0
14+
#define D0_PIN 1
15+
#define D1_PIN 2
16+
#define D2_PIN 3
17+
#define D3_PIN 4
18+
#define CS_PIN 5
19+
20+
/* Max word size. */
21+
#define MAX_WORD_SIZE NRF_VPR_CSR_VIO_SHIFT_CNT_OUT_BUFFERED_MAX
22+
23+
/* Macro for getting direction mask for specified pin and direction. */
24+
#define PIN_DIR_MASK(PIN_NUM, DIR) \
25+
(VPRCSR_NORDIC_DIR_PIN##PIN_NUM##_##DIR << VPRCSR_NORDIC_DIR_PIN##PIN_NUM##_Pos)
26+
27+
/* Macro for getting output mask for specified pin. */
28+
#define PIN_DIR_OUT_MASK(PIN_NUM) PIN_DIR_MASK(PIN_NUM, OUTPUT)
29+
30+
/* Macro for getting input mask for specified pin. */
31+
#define PIN_DIR_IN_MASK(PIN_NUM) PIN_DIR_MASK(PIN_NUM, INPUT)
32+
33+
/* Macro for getting state mask for specified pin and state. */
34+
#define PIN_OUT_MASK(PIN_NUM, STATE) \
35+
(VPRCSR_NORDIC_OUT_PIN##PIN_NUM##_##STATE << VPRCSR_NORDIC_OUT_PIN##PIN_NUM##_Pos)
36+
37+
/* Macro for getting high state mask for specified pin. */
38+
#define PIN_OUT_HIGH_MASK(PIN_NUM) PIN_OUT_MASK(PIN_NUM, HIGH)
39+
40+
/* Macro for getting low state mask for specified pin. */
41+
#define PIN_OUT_LOW_MASK(PIN_NUM) PIN_OUT_MASK(PIN_NUM, LOW)
42+
43+
/** @brief Write on single line.
44+
*
45+
* Function to be used to write data on single data line (SPI).
46+
*
47+
* @param[in] data Data to be sent.
48+
* @param[in] data_len Length of data in words.
49+
* @param[in] counter_top Top value of VTIM. This will determine clock frequency
50+
* (SPI_CLOCK ~= CPU_CLOCK / (2 * TOP)).
51+
* @param[in] word_size Size of a word in bits.
52+
* @param[in] ce_enable_state Chip enable pin polarity in enabled state
53+
* @param[in] hold_ce If true CE pin will be left enabled after transfer
54+
*/
55+
void write_single_by_word(volatile uint32_t *data, uint8_t data_len, uint32_t counter_top,
56+
uint8_t word_size, bool ce_enable_state, bool hold_ce);
57+
58+
/** @brief Write on four lines.
59+
*
60+
* Function to be used to write data on quad data line (SPI).
61+
*
62+
* @param[in] data Data to be sent.
63+
* @param[in] data_len Length of data in words.
64+
* @param[in] counter_top Top value of VTIM. This will determine clock frequency
65+
* (SPI_CLOCK ~= CPU_CLOCK / (2 * TOP)).
66+
* @param[in] word_size Size of a word in bits.
67+
* @param[in] ce_enable_state Chip enable pin polarity in enabled state
68+
* @param[in] hold_ce If true CE pin will be left enabled after transfer
69+
*/
70+
void write_quad_by_word(volatile uint32_t *data, uint8_t data_len, uint32_t counter_top,
71+
uint8_t word_size, bool ce_enable_state, bool hold_ce);
72+
73+
#endif /* _HRT_H__ */

0 commit comments

Comments
 (0)