samples: boards: stm32: pm: s2ram: add spi
Add SPI transfer in the suspend to ram samples to test SPI PM. Signed-off-by: Guillaume Gautier <guillaume.gautier-ext@st.com>
This commit is contained in:
parent
b567a7db83
commit
97177ba01a
5 changed files with 146 additions and 12 deletions
|
@ -9,6 +9,8 @@ Overview
|
||||||
This sample is a minimum application to demonstrate basic power management
|
This sample is a minimum application to demonstrate basic power management
|
||||||
behavior in a basic blinking LED set up using the :ref:`GPIO API <gpio_api>` in
|
behavior in a basic blinking LED set up using the :ref:`GPIO API <gpio_api>` in
|
||||||
low power context + ADC measurements and entropy.
|
low power context + ADC measurements and entropy.
|
||||||
|
SPI loopback is also available but not yet implemented for Suspend To RAM PM
|
||||||
|
mode.
|
||||||
|
|
||||||
.. _stm32-pm-suspend-to-ram-sample-requirements:
|
.. _stm32-pm-suspend-to-ram-sample-requirements:
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,18 @@
|
||||||
/* adjust channel number according to pinmux in board.dts */
|
/* adjust channel number according to pinmux in board.dts */
|
||||||
io-channels = <&adc4 8>;
|
io-channels = <&adc4 8>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
leds: leds {
|
||||||
|
compatible = "gpio-leds";
|
||||||
|
red_led_3: led_3 {
|
||||||
|
gpios = <&gpiob 8 GPIO_ACTIVE_LOW>;
|
||||||
|
label = "User LD2";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
aliases {
|
||||||
|
led2 = &red_led_3;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&lptim1 {
|
&lptim1 {
|
||||||
|
@ -50,3 +62,18 @@
|
||||||
zephyr,resolution = <12>;
|
zephyr,resolution = <12>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&spi1 {
|
||||||
|
dmas = <&gpdma1 0 2 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH)
|
||||||
|
&gpdma1 1 1 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH)>;
|
||||||
|
dma-names = "tx", "rx";
|
||||||
|
fast@0 {
|
||||||
|
compatible = "test-spi-loopback";
|
||||||
|
reg = <0>;
|
||||||
|
spi-max-frequency = <500000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&gpdma1 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2024 STMicroelectronics
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
description: |
|
||||||
|
This binding provides resources required to build and run an SPI
|
||||||
|
loopback test under power management conditions
|
||||||
|
|
||||||
|
compatible: "test-spi-loopback"
|
||||||
|
|
||||||
|
include: [spi-device.yaml]
|
|
@ -5,4 +5,7 @@ CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n
|
||||||
CONFIG_PM_S2RAM=y
|
CONFIG_PM_S2RAM=y
|
||||||
CONFIG_ADC=y
|
CONFIG_ADC=y
|
||||||
CONFIG_ENTROPY_GENERATOR=y
|
CONFIG_ENTROPY_GENERATOR=y
|
||||||
#CONFIG_DEBUG=y
|
CONFIG_SPI=y
|
||||||
|
CONFIG_SPI_STM32_DMA=y
|
||||||
|
CONFIG_SPI_STM32_INTERRUPT=n
|
||||||
|
CONFIG_SPI_ASYNC=n
|
||||||
|
|
|
@ -13,7 +13,10 @@
|
||||||
#include <zephyr/pm/device_runtime.h>
|
#include <zephyr/pm/device_runtime.h>
|
||||||
#include <zephyr/drivers/adc.h>
|
#include <zephyr/drivers/adc.h>
|
||||||
#include <zephyr/drivers/entropy.h>
|
#include <zephyr/drivers/entropy.h>
|
||||||
|
#include <zephyr/drivers/spi.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#define SLEEP_TIME_STOP0_MS 800
|
#define SLEEP_TIME_STOP0_MS 800
|
||||||
#define SLEEP_TIME_STOP1_MS 1500
|
#define SLEEP_TIME_STOP1_MS 1500
|
||||||
|
@ -21,7 +24,7 @@
|
||||||
#define SLEEP_TIME_BUSY_MS 2000
|
#define SLEEP_TIME_BUSY_MS 2000
|
||||||
|
|
||||||
static const struct gpio_dt_spec led =
|
static const struct gpio_dt_spec led =
|
||||||
GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
|
GPIO_DT_SPEC_GET(DT_ALIAS(led2), gpios);
|
||||||
|
|
||||||
#if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || \
|
#if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || \
|
||||||
!DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
|
!DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
|
||||||
|
@ -43,6 +46,86 @@ const struct device *rng_dev;
|
||||||
|
|
||||||
static uint8_t entropy_buffer[BUFFER_LENGTH] = {0};
|
static uint8_t entropy_buffer[BUFFER_LENGTH] = {0};
|
||||||
|
|
||||||
|
#define SPI_TEST_DEV DT_COMPAT_GET_ANY_STATUS_OKAY(test_spi_loopback)
|
||||||
|
|
||||||
|
#define FRAME_SIZE (8)
|
||||||
|
|
||||||
|
#define SPI_OP(frame_size) SPI_OP_MODE_MASTER | SPI_MODE_CPOL | \
|
||||||
|
SPI_MODE_CPHA | SPI_WORD_SET(frame_size) | SPI_LINES_SINGLE
|
||||||
|
|
||||||
|
static struct spi_dt_spec spi_test_dev = SPI_DT_SPEC_GET(SPI_TEST_DEV, SPI_OP(FRAME_SIZE), 0);
|
||||||
|
|
||||||
|
#define SPI_BUF_SIZE 18
|
||||||
|
|
||||||
|
static const char spi_tx_data[SPI_BUF_SIZE] = "0123456789abcdef-\0";
|
||||||
|
static __aligned(32) char spi_buffer_tx[SPI_BUF_SIZE] __used;
|
||||||
|
static __aligned(32) char spi_buffer_rx[SPI_BUF_SIZE] __used;
|
||||||
|
|
||||||
|
static uint8_t spi_buffer_print_tx[SPI_BUF_SIZE * 5 + 1];
|
||||||
|
static uint8_t spi_buffer_print_rx[SPI_BUF_SIZE * 5 + 1];
|
||||||
|
|
||||||
|
static void to_display_format(const uint8_t *src, size_t size, char *dst)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
sprintf(dst + 5 * i, "0x%02x,", src[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int spi_test(void)
|
||||||
|
{
|
||||||
|
const struct spi_buf tx_bufs[] = {
|
||||||
|
{
|
||||||
|
.buf = spi_buffer_tx,
|
||||||
|
.len = SPI_BUF_SIZE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const struct spi_buf rx_bufs[] = {
|
||||||
|
{
|
||||||
|
.buf = spi_buffer_rx,
|
||||||
|
.len = SPI_BUF_SIZE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const struct spi_buf_set tx = {
|
||||||
|
.buffers = tx_bufs,
|
||||||
|
.count = ARRAY_SIZE(tx_bufs)
|
||||||
|
};
|
||||||
|
const struct spi_buf_set rx = {
|
||||||
|
.buffers = rx_bufs,
|
||||||
|
.count = ARRAY_SIZE(rx_bufs)
|
||||||
|
};
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = spi_transceive_dt(&spi_test_dev, &tx, &rx);
|
||||||
|
if (ret) {
|
||||||
|
printk("SPI transceive failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(spi_buffer_tx, spi_buffer_rx, SPI_BUF_SIZE)) {
|
||||||
|
to_display_format(spi_buffer_tx, SPI_BUF_SIZE, spi_buffer_print_tx);
|
||||||
|
to_display_format(spi_buffer_rx, SPI_BUF_SIZE, spi_buffer_print_rx);
|
||||||
|
printk("Buffer contents are different\n");
|
||||||
|
printk("tx: %s\n", spi_buffer_print_tx);
|
||||||
|
printk("rx: %s\n", spi_buffer_print_rx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spi_setup(void)
|
||||||
|
{
|
||||||
|
memset(spi_buffer_tx, 0, sizeof(spi_buffer_tx));
|
||||||
|
memcpy(spi_buffer_tx, spi_tx_data, sizeof(spi_tx_data));
|
||||||
|
|
||||||
|
if (!spi_is_ready_dt(&spi_test_dev)) {
|
||||||
|
printk("Fast spi lookback device is not ready\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int adc_test(void)
|
static int adc_test(void)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
@ -122,6 +205,17 @@ void print_buf(uint8_t *buffer)
|
||||||
printk("\n");
|
printk("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void loop(void)
|
||||||
|
{
|
||||||
|
gpio_pin_set_dt(&led, 1);
|
||||||
|
adc_test();
|
||||||
|
if (!IS_ENABLED(CONFIG_PM_S2RAM)) {
|
||||||
|
spi_test();
|
||||||
|
}
|
||||||
|
k_busy_wait(SLEEP_TIME_BUSY_MS*1000);
|
||||||
|
gpio_pin_set_dt(&led, 0);
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
__ASSERT_NO_MSG(gpio_is_ready_dt(&led));
|
__ASSERT_NO_MSG(gpio_is_ready_dt(&led));
|
||||||
|
@ -131,20 +225,17 @@ int main(void)
|
||||||
printk("error: random device not ready");
|
printk("error: random device not ready");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spi_setup();
|
||||||
|
|
||||||
printk("Device ready\n");
|
printk("Device ready\n");
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
|
gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
|
||||||
adc_test();
|
loop();
|
||||||
k_busy_wait(SLEEP_TIME_BUSY_MS*1000);
|
|
||||||
gpio_pin_set_dt(&led, 0);
|
|
||||||
k_msleep(SLEEP_TIME_STOP0_MS);
|
k_msleep(SLEEP_TIME_STOP0_MS);
|
||||||
printk("Exit Stop0\n");
|
printk("Exit Stop0\n");
|
||||||
|
|
||||||
gpio_pin_set_dt(&led, 1);
|
loop();
|
||||||
adc_test();
|
|
||||||
k_busy_wait(SLEEP_TIME_BUSY_MS*1000);
|
|
||||||
gpio_pin_set_dt(&led, 0);
|
|
||||||
k_msleep(SLEEP_TIME_STOP1_MS);
|
k_msleep(SLEEP_TIME_STOP1_MS);
|
||||||
printk("Exit Stop1\n");
|
printk("Exit Stop1\n");
|
||||||
|
|
||||||
|
@ -153,9 +244,7 @@ int main(void)
|
||||||
printk("Sync entropy: ");
|
printk("Sync entropy: ");
|
||||||
print_buf(entropy_buffer);
|
print_buf(entropy_buffer);
|
||||||
|
|
||||||
gpio_pin_set_dt(&led, 1);
|
loop();
|
||||||
adc_test();
|
|
||||||
k_busy_wait(SLEEP_TIME_BUSY_MS*1000);
|
|
||||||
gpio_pin_configure_dt(&led, GPIO_DISCONNECTED);
|
gpio_pin_configure_dt(&led, GPIO_DISCONNECTED);
|
||||||
k_msleep(SLEEP_TIME_STANDBY_MS);
|
k_msleep(SLEEP_TIME_STANDBY_MS);
|
||||||
printk("Exit Standby\n");
|
printk("Exit Standby\n");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue