Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

samples: Introduce "simple_txrx" #42

Merged
merged 6 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ jobs:
run: |
pip3 install crc

- name: Fetch blobs
run: |
west blobs fetch hal_silabs

- name: Build hello world
working-directory: zephyr-silabs
shell: bash
Expand All @@ -46,3 +50,4 @@ jobs:
west twister --test sample.basic.helloworld -p siwx917_rb4338a -v --inline-logs $EXTRA_TWISTER_FLAGS
west twister --test sample.net.wifi -p siwx917_rb4338a -v --inline-logs -K $EXTRA_TWISTER_FLAGS
west twister --test sample.bluetooth.peripheral_hr -p siwx917_rb4338a -v --inline-logs -K $EXTRA_TWISTER_FLAGS
west twister --test sample.rail.simple_txrx -T samples -v --inline-logs $EXTRA_TWISTER_FLAGS
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sort of unrelated to this PR, but I think we should work on cleaning up the ever growing list of west twister ... commands. It should be possible to pass multiple --test parameters to a single twister invocation. Maybe we need to declare arrays or a matrix of platforms + tests in some single place and then pass those to a single twister command. We might also benefit from the "matrix" feature of GitHub workflows, e.g. have a dedicated workflow invocation per platform, or similar: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow#using-a-matrix-strategy

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have already started a patch for that, but since this work was not related to the current PR, I have not included it.

1 change: 1 addition & 0 deletions .github/workflows/upstream-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,4 @@ jobs:
west twister -T ../zephyr/samples -s sample.basic.helloworld -p siwx917_rb4338a -v --inline-logs $EXTRA_TWISTER_FLAGS
west twister -T ../zephyr/samples -s sample.net.wifi -p siwx917_rb4338a -v --inline-logs -K $EXTRA_TWISTER_FLAGS
west twister -T ../zephyr/samples -s sample.bluetooth.peripheral_hr -p siwx917_rb4338a -v --inline-logs -K $EXTRA_TWISTER_FLAGS
west twister -T samples -s sample.rail.simple_txrx -v --inline-logs $EXTRA_TWISTER_FLAGS
14 changes: 14 additions & 0 deletions samples/simple_txrx/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (c) 2023 Silicon Laboratories Inc.
# SPDX-License-Identifier: Zlib

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(simple_txrx)

target_include_directories(app PRIVATE
src/rail-configs/${CONFIG_BOARD}
)
target_sources(app PRIVATE
src/main.c
src/rail-configs/${CONFIG_BOARD}/rail_config.c
)
8 changes: 8 additions & 0 deletions samples/simple_txrx/boards/sltb010a.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright (c) 2023 Silicon Laboratories Inc.
* SPDX-License-Identifier: Zlib
*/

&cpu0 {
cpu-power-states = <&pstate_em1>;
};
8 changes: 8 additions & 0 deletions samples/simple_txrx/boards/xg24_dk2601b.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright (c) 2023 Silicon Laboratories Inc.
* SPDX-License-Identifier: Zlib
*/

&cpu0 {
cpu-power-states = <&pstate_em1>;
};
8 changes: 8 additions & 0 deletions samples/simple_txrx/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CONFIG_SOC_GECKO_CUSTOM_RADIO_PHY=y
CONFIG_SHELL=y
CONFIG_PM=y
CONFIG_EVENTS=y
CONFIG_LOG=y

CONFIG_DEBUG_THREAD_INFO=y
CONFIG_DEBUG=y
8 changes: 8 additions & 0 deletions samples/simple_txrx/sample.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
sample:
description: Present basic features of the Silicon Labs Radio Library (RAIL).
name: Silabs Rail sample app
tests:
sample.rail.simple_txrx:
platform_allow:
- sltb010a@2
- xg24_dk2601b
301 changes: 301 additions & 0 deletions samples/simple_txrx/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
/*
* Copyright (c) 2024 Silicon Laboratories Inc.
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/gpio.h>
#include <zephyr/shell/shell.h>
#include <zephyr/logging/log.h>
#include <zephyr/kernel.h>

#include "rail.h"
#include "rail_config.h"
#include "pa_conversions_efr32.h"

LOG_MODULE_REGISTER(app);

#ifdef RAIL0_CHANNEL_GROUP_1_PROFILE_WISUN_OFDM
# if !defined(HARDWARE_BOARD_HAS_EFF)
BUILD_ASSERT(SL_RAIL_UTIL_PA_SELECTION_SUBGHZ == RAIL_TX_POWER_MODE_OFDM_PA,
"Please use the OFDM PA settings in the sl_rail_util_pa_config.h "
"for OFDM phys");
# endif
# if defined(HARDWARE_BOARD_HAS_EFF) && RAIL_SUPPORTS_EFF
BUILD_ASSERT(SL_RAIL_UTIL_PA_SELECTION_SUBGHZ >= RAIL_TX_POWER_MODE_OFDM_PA_EFF_30DBM,
"Please use the OFDM PA for EFF settings in the sl_rail_util_pa_config.h "
"for OFDM phys");
# endif
#endif

Check notice on line 27 in samples/simple_txrx/src/main.c

View workflow job for this annotation

GitHub Actions / build

You may want to run clang-format on this change

samples/simple_txrx/src/main.c:27 -# if !defined(HARDWARE_BOARD_HAS_EFF) - BUILD_ASSERT(SL_RAIL_UTIL_PA_SELECTION_SUBGHZ == RAIL_TX_POWER_MODE_OFDM_PA, - "Please use the OFDM PA settings in the sl_rail_util_pa_config.h " - "for OFDM phys"); -# endif -# if defined(HARDWARE_BOARD_HAS_EFF) && RAIL_SUPPORTS_EFF - BUILD_ASSERT(SL_RAIL_UTIL_PA_SELECTION_SUBGHZ >= RAIL_TX_POWER_MODE_OFDM_PA_EFF_30DBM, - "Please use the OFDM PA for EFF settings in the sl_rail_util_pa_config.h " - "for OFDM phys"); -# endif +#if !defined(HARDWARE_BOARD_HAS_EFF) +BUILD_ASSERT(SL_RAIL_UTIL_PA_SELECTION_SUBGHZ == RAIL_TX_POWER_MODE_OFDM_PA, + "Please use the OFDM PA settings in the sl_rail_util_pa_config.h " + "for OFDM phys"); +#endif +#if defined(HARDWARE_BOARD_HAS_EFF) && RAIL_SUPPORTS_EFF +BUILD_ASSERT(SL_RAIL_UTIL_PA_SELECTION_SUBGHZ >= RAIL_TX_POWER_MODE_OFDM_PA_EFF_30DBM, + "Please use the OFDM PA for EFF settings in the sl_rail_util_pa_config.h " + "for OFDM phys"); +#endif

static const struct gpio_dt_spec sw0 = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios);
static const struct gpio_dt_spec led_rx = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
#if DT_NODE_EXISTS(DT_ALIAS(led1))
static const struct gpio_dt_spec led_tx = GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios);
#else
static const struct gpio_dt_spec led_tx = led_rx;
#endif

enum {
EV_RAIL_RX = BIT(0),
EV_BTN_PRESSED = BIT(1),

Check notice on line 39 in samples/simple_txrx/src/main.c

View workflow job for this annotation

GitHub Actions / build

You may want to run clang-format on this change

samples/simple_txrx/src/main.c:39 - EV_RAIL_RX = BIT(0), + EV_RAIL_RX = BIT(0),
};

struct {
RAIL_Handle_t rail_handle;
struct k_event events;
struct k_mutex tx_lock;
int channel;
const uint8_t *payload;
int payload_len;
} app_ctx;

void rx_packets(RAIL_Handle_t rail_handle)
{
uint8_t rx_frame[32];
RAIL_RxPacketHandle_t handle;
RAIL_RxPacketInfo_t info;
RAIL_Status_t status;

for (;;) {
handle = RAIL_GetRxPacketInfo(rail_handle, RAIL_RX_PACKET_HANDLE_OLDEST_COMPLETE,
&info);
if (handle == RAIL_RX_PACKET_HANDLE_INVALID) {
return;
}
if (info.packetBytes < sizeof(rx_frame)) {
RAIL_CopyRxPacket(rx_frame, &info);
}
status = RAIL_ReleaseRxPacket(rail_handle, handle);
if (status) {
LOG_ERR("RAIL_ReleaseRxPacket(): %d", status);
}
if (info.packetBytes < sizeof(rx_frame)) {
LOG_HEXDUMP_INF(rx_frame, info.packetBytes, "rx data:");
} else {
LOG_INF("rx: skip large packet");
}
gpio_pin_set_dt(&led_rx, 0);
}
}

void tx_packet(RAIL_Handle_t rail_handle, int channel, const uint8_t *payload, int len)
{
RAIL_Status_t status;
int ret;

ret = RAIL_WriteTxFifo(rail_handle, payload, len, true);
if (ret != len) {
LOG_ERR("RAIL_WriteTxFifo(): %d", ret);
return;
}
gpio_pin_set_dt(&led_tx, 1);
status = RAIL_StartTx(rail_handle, channel, RAIL_TX_OPTIONS_DEFAULT, NULL);
if (status) {
LOG_ERR("RAIL_StartTx(): %d ", status);
}
LOG_HEXDUMP_INF(payload, len, "tx data:");
}

void btn_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
/* This function is called from an ISR context. So, transfer the real
* processing to the main loop.
*/
k_event_post(&app_ctx.events, EV_BTN_PRESSED);
}

void cli_send(const struct shell *sh, size_t argc, char **argv)
{
k_mutex_lock(&app_ctx.tx_lock, K_FOREVER);
tx_packet(app_ctx.rail_handle, app_ctx.channel, app_ctx.payload, app_ctx.payload_len);
zohavas marked this conversation as resolved.
Show resolved Hide resolved
k_mutex_unlock(&app_ctx.tx_lock);
}

void rail_on_event(RAIL_Handle_t rail_handle, RAIL_Events_t events)
{
RAIL_Status_t status;

if (events & RAIL_EVENTS_RX_COMPLETION) {
if (events & RAIL_EVENT_RX_PACKET_RECEIVED) {
gpio_pin_set_dt(&led_rx, 1);
RAIL_HoldRxPacket(rail_handle);
k_event_post(&app_ctx.events, EV_RAIL_RX);
} else {
LOG_ERR("radio rx error: %08llx", events);
}
}

if (events & RAIL_EVENTS_TX_COMPLETION) {
if (!(events & RAIL_EVENT_TX_PACKET_SENT)) {
LOG_ERR("radio tx error: %08llx", events);
}
gpio_pin_set_dt(&led_tx, 0);
}

if (events & RAIL_EVENTS_TXACK_COMPLETION) {
/* We do not configure Tx ack. Catch the event anyway */
LOG_INF("received ack completion");
}

if (events & RAIL_EVENT_CAL_NEEDED) {
status = RAIL_Calibrate(rail_handle, NULL, RAIL_CAL_ALL_PENDING);
if (status) {
LOG_ERR("RAIL_Calibrate(): %d", status);
}
}
}

static void rail_on_rf_ready(RAIL_Handle_t rail_handle)
{
LOG_INF("radio is ready");
}

static void rail_on_channel_config(RAIL_Handle_t rail_handle,
const RAIL_ChannelConfigEntry_t *entry)
{
sl_rail_util_pa_on_channel_config_change(rail_handle, entry);
}

static RAIL_Handle_t rail_init(void)
{
static uint8_t tx_fifo[256] __aligned(4);
RAIL_Config_t rail_config = {
.eventsCallback = &rail_on_event,
};
RAIL_DataConfig_t data_config = {
.txSource = TX_PACKET_DATA,
.rxSource = RX_PACKET_DATA,
.txMethod = PACKET_MODE,
.rxMethod = PACKET_MODE,
};
RAIL_StateTransitions_t transitions = {
.success = RAIL_RF_STATE_RX,
.error = RAIL_RF_STATE_RX,
};

Check notice on line 173 in samples/simple_txrx/src/main.c

View workflow job for this annotation

GitHub Actions / build

You may want to run clang-format on this change

samples/simple_txrx/src/main.c:173 - .error = RAIL_RF_STATE_RX, + .error = RAIL_RF_STATE_RX,
RAIL_Handle_t rail_handle;
RAIL_Status_t status;
int ret;

rail_handle = RAIL_Init(&rail_config, &rail_on_rf_ready);
if (!rail_handle) {
LOG_ERR("RAIL_Init() failed");
}
status = RAIL_ConfigData(rail_handle, &data_config);
if (status) {
LOG_ERR("RAIL_ConfigData(): %d", status);
}
status = RAIL_ConfigChannels(rail_handle, channelConfigs[0], &rail_on_channel_config);
if (status) {
LOG_ERR("RAIL_ConfigChannels(): %d", status);
}
status = RAIL_SetPtiProtocol(rail_handle, RAIL_PTI_PROTOCOL_CUSTOM);
if (status) {
LOG_ERR("RAIL_SetPtiProtocol(): %d", status);
}
status = RAIL_ConfigCal(rail_handle, RAIL_CAL_TEMP | RAIL_CAL_ONETIME);
if (status) {
LOG_ERR("RAIL_ConfigCal(): %d", status);
}
status = RAIL_ConfigEvents(rail_handle, RAIL_EVENTS_ALL,
RAIL_EVENTS_RX_COMPLETION |
RAIL_EVENTS_TX_COMPLETION |
RAIL_EVENTS_TXACK_COMPLETION |
RAIL_EVENT_CAL_NEEDED);
if (status) {

Check notice on line 203 in samples/simple_txrx/src/main.c

View workflow job for this annotation

GitHub Actions / build

You may want to run clang-format on this change

samples/simple_txrx/src/main.c:203 - RAIL_EVENTS_RX_COMPLETION | - RAIL_EVENTS_TX_COMPLETION | - RAIL_EVENTS_TXACK_COMPLETION | - RAIL_EVENT_CAL_NEEDED); + RAIL_EVENTS_RX_COMPLETION | RAIL_EVENTS_TX_COMPLETION | + RAIL_EVENTS_TXACK_COMPLETION | RAIL_EVENT_CAL_NEEDED);
LOG_ERR("RAIL_ConfigEvents(): %d", status);
}
status = RAIL_SetTxTransitions(rail_handle, &transitions);
if (status) {
LOG_ERR("RAIL_SetTxTransitions(): %d", status);
}
status = RAIL_SetRxTransitions(rail_handle, &transitions);
if (status) {
LOG_ERR("RAIL_SetRxTransitions(): %d", status);
}
ret = RAIL_SetTxFifo(rail_handle, tx_fifo, 0, sizeof(tx_fifo));
if (ret != sizeof(tx_fifo)) {
LOG_ERR("RAIL_SetTxFifo(): %d != %d", ret, sizeof(tx_fifo));
}

return rail_handle;
}

static void rail_isr_installer(void)
{
#ifdef CONFIG_SOC_SERIES_EFR32MG24
IRQ_CONNECT(SYNTH_IRQn, 0, SYNTH_IRQHandler, NULL, 0);
#else
IRQ_CONNECT(RDMAILBOX_IRQn, 0, RDMAILBOX_IRQHandler, NULL, 0);
#endif
IRQ_CONNECT(RAC_SEQ_IRQn, 0, RAC_SEQ_IRQHandler, NULL, 0);
IRQ_CONNECT(RAC_RSM_IRQn, 0, RAC_RSM_IRQHandler, NULL, 0);
IRQ_CONNECT(PROTIMER_IRQn, 0, PROTIMER_IRQHandler, NULL, 0);
IRQ_CONNECT(MODEM_IRQn, 0, MODEM_IRQHandler, NULL, 0);
IRQ_CONNECT(FRC_IRQn, 0, FRC_IRQHandler, NULL, 0);
IRQ_CONNECT(BUFC_IRQn, 0, BUFC_IRQHandler, NULL, 0);
IRQ_CONNECT(AGC_IRQn, 0, AGC_IRQHandler, NULL, 0);
}

int main(void)
{
static const uint8_t default_payload[] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
struct gpio_callback sw0_cb;

Check notice on line 244 in samples/simple_txrx/src/main.c

View workflow job for this annotation

GitHub Actions / build

You may want to run clang-format on this change

samples/simple_txrx/src/main.c:244 - static const uint8_t default_payload[] = { - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF - }; + static const uint8_t default_payload[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
RAIL_Status_t status;
uint32_t events;
int ret;

k_event_init(&app_ctx.events);
k_mutex_init(&app_ctx.tx_lock);
gpio_pin_configure_dt(&led_tx, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&led_rx, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&sw0, GPIO_INPUT);
gpio_pin_interrupt_configure_dt(&sw0, GPIO_INT_EDGE_TO_ACTIVE);
gpio_init_callback(&sw0_cb, btn_pressed, BIT(sw0.pin));
gpio_add_callback(sw0.port, &sw0_cb);

rail_isr_installer();
sl_rail_util_pa_init();
app_ctx.rail_handle = rail_init();
app_ctx.channel = 0;
app_ctx.payload = default_payload;
app_ctx.payload_len = sizeof(default_payload);

ret = RAIL_SetFixedLength(app_ctx.rail_handle, app_ctx.payload_len);
if (ret != app_ctx.payload_len) {
LOG_ERR("RAIL_SetFixedLength(): %d ", ret);
}
status = RAIL_StartRx(app_ctx.rail_handle, app_ctx.channel, NULL);
if (status) {
LOG_ERR("RAIL_StartRx(): %d ", status);
}

#ifdef CONFIG_PM
status = RAIL_InitPowerManager();
if (status) {
LOG_ERR("RAIL_InitPowerManager(): %d", status);
}
#endif

for (;;) {
events = k_event_wait(&app_ctx.events, 0xFFFFFFFF, true, K_FOREVER);
if (events & EV_RAIL_RX) {
rx_packets(app_ctx.rail_handle);
}
if (events & EV_BTN_PRESSED) {
k_mutex_lock(&app_ctx.tx_lock, K_FOREVER);
tx_packet(app_ctx.rail_handle, app_ctx.channel,
app_ctx.payload, app_ctx.payload_len);
k_mutex_unlock(&app_ctx.tx_lock);

Check notice on line 290 in samples/simple_txrx/src/main.c

View workflow job for this annotation

GitHub Actions / build

You may want to run clang-format on this change

samples/simple_txrx/src/main.c:290 - tx_packet(app_ctx.rail_handle, app_ctx.channel, - app_ctx.payload, app_ctx.payload_len); + tx_packet(app_ctx.rail_handle, app_ctx.channel, app_ctx.payload, + app_ctx.payload_len);
}
}

return 0;
}

SHELL_STATIC_SUBCMD_SET_CREATE(radio_cmds,
SHELL_CMD_ARG(send, NULL, "Send a packet", cli_send, 1, 0),
SHELL_SUBCMD_SET_END
);
SHELL_CMD_ARG_REGISTER(radio, &radio_cmds, "Radio control", NULL, 2, 0);

Check notice on line 301 in samples/simple_txrx/src/main.c

View workflow job for this annotation

GitHub Actions / build

You may want to run clang-format on this change

samples/simple_txrx/src/main.c:301 - SHELL_CMD_ARG(send, NULL, "Send a packet", cli_send, 1, 0), - SHELL_SUBCMD_SET_END -); + SHELL_CMD_ARG(send, NULL, "Send a packet", cli_send, 1, 0), + SHELL_SUBCMD_SET_END);
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<multi_phy_configuration part_family="lynx" part_revision="A0" rail_adapter_version="rail_api_2.x" status_code="0" xsd_version="0.0.20">
<base_channel_configurations>
<base_channel_configuration name="Protocol Configuration" profile="Base">
<channel_config_entries>
<channel_config_entry name="Channel Group 1">
<channel_number_start>0</channel_number_start>
<channel_number_end>20</channel_number_end>
<physical_channel_offset>SAME_AS_FIRST_CHANNEL</physical_channel_offset>
<max_power>RAIL_TX_POWER_MAX</max_power>
<metadata>{"selectedPhy":"PHY_Datasheet_2450M_2GFSK_1Mbps_500K"}</metadata>
</channel_config_entry>
</channel_config_entries>
<metadata>{"selectedPhy":"PHY_Datasheet_2450M_2GFSK_1Mbps_500K"}</metadata>
<phy name="PHY_Datasheet_2450M_2GFSK_1Mbps_500K"/>
</base_channel_configuration>
</base_channel_configurations>
</multi_phy_configuration>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub seems to complain of a missing newline character at the end of the file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe GitHub does not complain, it just notifies.

Since this file is generated by a tool, I hesitate to edit it. That's I have already applied (too) many changes to rail-config.[ch].

Loading
Loading