Skip to content

Commit

Permalink
applications: sdp: mspi: Initial implementation
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
magp-nordic authored and mif1-nordic committed Nov 27, 2024
1 parent 9598724 commit 89779ab
Show file tree
Hide file tree
Showing 10 changed files with 944 additions and 0 deletions.
19 changes: 19 additions & 0 deletions applications/sdp/mspi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(sdp_mspi)

sdp_assembly_generate("${CMAKE_SOURCE_DIR}/src/hrt/hrt.c")
sdp_assembly_check("${CMAKE_SOURCE_DIR}/src/hrt/hrt.c")
sdp_assembly_prepare_install("${CMAKE_SOURCE_DIR}/src/hrt/hrt.c")

target_sources(app PRIVATE src/main.c)
target_sources(app PRIVATE src/hrt/hrt.s)

add_dependencies(app asm_check)
46 changes: 46 additions & 0 deletions applications/sdp/mspi/boards/nrf54l15dk_nrf54l15_cpuflpr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Single-threaded
CONFIG_MULTITHREADING=n
CONFIG_KERNEL_MEM_POOL=n
CONFIG_LOG=n

# Drivers and peripherals
CONFIG_I2C=n
CONFIG_WATCHDOG=n
CONFIG_GPIO=n
CONFIG_PINCTRL=n
CONFIG_SPI=n
CONFIG_SERIAL=n
CONFIG_FLASH=n

# Power management
CONFIG_PM=n

# Interrupts
CONFIG_DYNAMIC_INTERRUPTS=n
CONFIG_IRQ_OFFLOAD=n
CONFIG_GEN_SW_ISR_TABLE=n

# Memory protection
CONFIG_THREAD_STACK_INFO=n
CONFIG_THREAD_CUSTOM_DATA=n
CONFIG_FPU=n

# Boot
CONFIG_BOOT_BANNER=n
CONFIG_NCS_BOOT_BANNER=n

# Console
CONFIG_CONSOLE=n
CONFIG_UART_CONSOLE=n
CONFIG_STDOUT_CONSOLE=n
CONFIG_PRINTK=n
CONFIG_EARLY_CONSOLE=n

# Build
CONFIG_SIZE_OPTIMIZATIONS=y

# No timer support in the kernel
CONFIG_SYS_CLOCK_EXISTS=n

CONFIG_OUTPUT_DISASSEMBLY=y
CONFIG_COMMON_LIBC_MALLOC=n
41 changes: 41 additions & 0 deletions applications/sdp/mspi/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

&gpio0 {
status = "disabled";
};

&gpio1 {
status = "disabled";
};

&gpio2 {
status = "disabled";
};

&gpiote20 {
status = "disabled";
};

&gpiote30 {
status = "disabled";
};

&grtc {
status = "disabled";
};

&uart20 {
status = "disabled";
};

&uart30 {
status = "disabled";
};

&pwm20 {
status = "disabled";
};
1 change: 1 addition & 0 deletions applications/sdp/mspi/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_MBOX=y
15 changes: 15 additions & 0 deletions applications/sdp/mspi/sample.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
sample:
name: SDP mSPI application
description: SDP mSPI application
common:
integration_platforms:
- nrf54l15dk/nrf54l15/cpuflpr
tests:
applications.sdp.mspi.icmsg:
build_only: true
sysbuild: true
platform_allow: nrf54l15dk/nrf54l15/cpuflpr
tags: ci_build sysbuild mspi
extra_configs:
- CONFIG_IPC_SERVICE=y
- CONFIG_IPC_SERVICE_BACKEND_ICMSG=y
195 changes: 195 additions & 0 deletions applications/sdp/mspi/src/hrt/hrt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include "hrt.h"
#include <hal/nrf_vpr_csr_vio.h>
#include <hal/nrf_vpr_csr_vtim.h>

#define TOP 4

void write_single_by_word(volatile uint32_t *data,
uint8_t data_len,
uint32_t counter_top,
uint8_t word_size,
bool ce_enable_state,
bool hold_ce)
{
NRFX_ASSERT(word_size > MAX_WORD_SIZE);

/* Configuration step */
uint16_t dir = nrf_vpr_csr_vio_dir_get();

nrf_vpr_csr_vio_dir_set(dir |
PIN_DIR_OUT_MASK(D0_PIN) |
PIN_DIR_OUT_MASK(CS_PIN) |
PIN_DIR_OUT_MASK(SCLK_PIN));

uint16_t out = nrf_vpr_csr_vio_out_get();

nrf_vpr_csr_vio_out_set(out |
PIN_OUT_LOW_MASK(D0_PIN) |
PIN_OUT_HIGH_MASK(CS_PIN) |
PIN_OUT_LOW_MASK(SCLK_PIN));

nrf_vpr_csr_vio_mode_out_t out_mode = {
.mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE,
.frame_width = 1,
};

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_t config;

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 (word_size < MAX_WORD_SIZE) {
for (uint8_t i = 0; i < data_len; i++) {
data[i] = data[i] << (MAX_WORD_SIZE - word_size);
}
}

/* 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, 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(word_size);
nrf_vpr_csr_vio_shift_cnt_out_buffered_set(word_size - 1);

/* Enable CS */
out = nrf_vpr_csr_vio_out_get();
out &= ~PIN_OUT_HIGH_MASK(CS_PIN);
out |= ce_enable_state ? PIN_OUT_HIGH_MASK(CS_PIN) : PIN_OUT_LOW_MASK(CS_PIN);
nrf_vpr_csr_vio_out_set(out);

/* Start counter */
nrf_vpr_csr_vtim_simple_counter_set(0, 3 * counter_top);

/* Send data */
for (uint8_t i = 0; i < data_len; i++) {
nrf_vpr_csr_vio_out_buffered_reversed_byte_set(data[i]);
}

/* Clear all bits, wait until the last word is sent */
nrf_vpr_csr_vio_out_buffered_set(0);

/* 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);

/* Deselect slave */
if (!hold_ce) {
out = nrf_vpr_csr_vio_out_get();
out &= ~(PIN_OUT_HIGH_MASK(CS_PIN) | PIN_OUT_HIGH_MASK(SCLK_PIN));
out |= ce_enable_state ? PIN_OUT_LOW_MASK(CS_PIN) : PIN_OUT_HIGH_MASK(CS_PIN);
out |= PIN_OUT_LOW_MASK(SCLK_PIN);
nrf_vpr_csr_vio_out_set(out);
}

/* Stop counter */
nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_STOP);
}

void write_quad_by_word(volatile uint32_t *data,
uint8_t data_len,
uint32_t counter_top,
uint8_t word_size,
bool ce_enable_state,
bool hold_ce)
{
NRFX_ASSERT(word_size > MAX_WORD_SIZE);
NRFX_ASSERT(word_size % 4 == 0);

/* Configuration step */
uint16_t dir = nrf_vpr_csr_vio_dir_get();

nrf_vpr_csr_vio_dir_set(dir |
PIN_DIR_OUT_MASK(D0_PIN) | PIN_DIR_OUT_MASK(D1_PIN) |
PIN_DIR_OUT_MASK(D2_PIN) | PIN_DIR_OUT_MASK(D3_PIN) |
PIN_DIR_OUT_MASK(CS_PIN) | PIN_DIR_OUT_MASK(SCLK_PIN));

uint16_t out = nrf_vpr_csr_vio_out_get();

nrf_vpr_csr_vio_out_set(out |
PIN_OUT_LOW_MASK(D0_PIN) | PIN_OUT_LOW_MASK(D1_PIN) |
PIN_OUT_LOW_MASK(D2_PIN) | PIN_OUT_LOW_MASK(D3_PIN) |
PIN_OUT_HIGH_MASK(CS_PIN) | PIN_OUT_LOW_MASK(SCLK_PIN));

nrf_vpr_csr_vio_mode_out_t out_mode = {
.mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE,
.frame_width = 4,
};

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_t config;

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 (word_size < MAX_WORD_SIZE) {
for (uint8_t i = 0; i < data_len; i++) {
data[i] = data[i] << (MAX_WORD_SIZE - word_size);
}
}

/* 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, 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(word_size / 4);
nrf_vpr_csr_vio_shift_cnt_out_buffered_set(word_size / 4 - 1);

/* Enable CS */
out = nrf_vpr_csr_vio_out_get();
out &= ~PIN_OUT_HIGH_MASK(CS_PIN);
out |= ce_enable_state ? PIN_OUT_HIGH_MASK(CS_PIN) : PIN_OUT_LOW_MASK(CS_PIN);
nrf_vpr_csr_vio_out_set(out);

/* Start counter */
nrf_vpr_csr_vtim_simple_counter_set(0, 3 * counter_top);

/* Send data */
for (uint8_t i = 0; i < data_len; i++) {
nrf_vpr_csr_vio_out_buffered_reversed_byte_set(data[i]);
}

/* Clear all bits, wait until the last word is sent */
nrf_vpr_csr_vio_out_buffered_set(0);

/* 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);

/* Deselect slave */
if (!hold_ce) {
out = nrf_vpr_csr_vio_out_get();
out &= ~(PIN_OUT_HIGH_MASK(CS_PIN) | PIN_OUT_HIGH_MASK(SCLK_PIN));
out |= ce_enable_state ? PIN_OUT_LOW_MASK(CS_PIN) : PIN_OUT_HIGH_MASK(CS_PIN);
out |= PIN_OUT_LOW_MASK(SCLK_PIN);
nrf_vpr_csr_vio_out_set(out);
}

/* Stop counter */
nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_STOP);
}
Loading

0 comments on commit 89779ab

Please sign in to comment.