ref: ad1df2d2a01bd064e643287ff305673dfede3ce3
dir: /src/bsp.c/
/*============================================================================ * QP/C Real-Time Embedded Framework (RTEF) * Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. * * SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial * * This software is dual-licensed under the terms of the open source GNU * General Public License version 3 (or any later version), or alternatively, * under the terms of one of the closed source Quantum Leaps commercial * licenses. * * The terms of the open source GNU General Public License version 3 * can be found at: <www.gnu.org/licenses/gpl-3.0> * * The terms of the closed source Quantum Leaps commercial licenses * can be found at: <www.state-machine.com/licensing> * * Redistributions in source code must retain this top-level comment block. * Plagiarizing this software to sidestep the license obligations is illegal. * * Contact information: * <www.state-machine.com> * <[email protected]> ============================================================================*/ /*! * @date Last updated on: 2022-08-24 * @version Last updated for: Zephyr 3.1.99 and @ref qpc_7_1_0 * * @file * @brief BSP for Zephyr, DPP example */ #include "qpc.h" #include "dpp.h" #include "bsp.h" #include <zephyr/device.h> #include <zephyr/drivers/display.h> #include <zephyr/drivers/gpio.h> #include <zephyr/display/cfb.h> #include <zephyr/sys/reboot.h> #include <zephyr/drivers/lora.h> #include <zephyr/logging/log.h> /* other drivers, if necessary ... */ Q_DEFINE_THIS_FILE LOG_MODULE_REGISTER(bsp); /* The devicetree node identifier for the "led0" alias. */ #define LED0_NODE DT_ALIAS(led0) static const struct device *const display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display)); static const struct device *const lora_dev = DEVICE_DT_GET(DT_NODELABEL(lora0)); /* Local-scope objects -----------------------------------------------------*/ static struct gpio_dt_spec const l_led0 = GPIO_DT_SPEC_GET(LED0_NODE, gpios); static struct k_timer QF_tick_timer; static uint32_t l_rnd; /* random seed */ #ifdef Q_SPY /* QSpy source IDs */ static QSpyId const timerID = { 0U }; enum AppRecords { /* application-specific trace records */ PHILO_STAT = QS_USER, PAUSED_STAT, COMMAND_STAT, TEST_MSG }; #endif int conf_radio(const struct device *dev, bool transmit) { int ret; struct lora_modem_config config; config.frequency = 903080000; config.bandwidth = BW_125_KHZ; config.datarate = SF_10; config.preamble_len = 8; config.coding_rate = CR_4_5; config.tx_power = 4; config.iq_inverted = false; config.public_network = false; config.tx = transmit; return lora_config(dev, &config); } /*..........................................................................*/ static void QF_tick_function(struct k_timer *tid) { (void)tid; /* unused parameter */ QTIMEEVT_TICK_X(0U, &timerID); } /*..........................................................................*/ void BSP_init(void) { int ret = gpio_pin_configure_dt(&l_led0, GPIO_OUTPUT_ACTIVE); Q_ASSERT(ret >= 0); k_timer_init(&QF_tick_timer, &QF_tick_function, NULL); //... BSP_randomSeed(1234U); if (QS_INIT((void *)0) == 0) { /* initialize the QS software tracing */ Q_ERROR(); } /* object dictionaries... */ QS_OBJ_DICTIONARY(AO_Table); for (int n = 0; n < N_PHILO; ++n) { QS_OBJ_ARR_DICTIONARY(AO_Philo[n], n); } QS_OBJ_DICTIONARY(&timerID); QS_USR_DICTIONARY(PHILO_STAT); QS_USR_DICTIONARY(PAUSED_STAT); QS_USR_DICTIONARY(COMMAND_STAT); QS_USR_DICTIONARY(TEST_MSG); /* setup the QS filters... */ QS_GLB_FILTER(QS_SM_RECORDS); /* state machine records */ QS_GLB_FILTER(QS_AO_RECORDS); /* active object records */ QS_GLB_FILTER(QS_UA_RECORDS); /* all user records */ QS_GLB_FILTER(TEST_MSG); struct display_capabilities capabilities; if (display_dev == NULL) { Q_PRINTK("Display device not found."); } else { if (!device_is_ready(display_dev)) { Q_PRINTK("display not ready"); } } display_get_capabilities(display_dev, &capabilities); ret = cfb_framebuffer_init(display_dev); if (ret != 0) { Q_PRINTK("Could not init fb"); } ret = cfb_print(display_dev, "Hello world!", 0, 0); if (ret != 0) { Q_PRINTK("Could not print to fb"); } ret = cfb_framebuffer_finalize(display_dev); if (ret != 0) { Q_PRINTK("Could not finalize to fb"); } // LoRa: if (lora_dev != NULL) { Q_PRINTK("Found lora_dev: %s", lora_dev->name); } /* if (!device_is_ready(lora_dev)) { Q_PRINTK("LoRa dev not ready."); } else { ret = conf_radio(lora_dev, true); if (ret != 0) { Q_PRINTK("Failed to conf_radio()"); } else { Q_PRINTK("LoRa radio configured successfully."); } } */ } // end of BSP_init() /*..........................................................................*/ void BSP_ledOn(void) { gpio_pin_set_dt(&l_led0, true); } /*..........................................................................*/ void BSP_ledOff(void) { gpio_pin_set_dt(&l_led0, false); } /*..........................................................................*/ void BSP_displayPhilStat(uint8_t n, char const *stat) { if (stat[0] == 'e') { BSP_ledOn(); } else { BSP_ledOff(); } Q_PRINTK("Philo[%d]->%s\n", n, stat); char buf[20]; int ret = snprintf(buf, sizeof(buf), "Ph[%d]->%s", n, stat); //printk("Philo[%d]->%s\n", n, stat); printk(buf, n, stat); ret = cfb_print(display_dev, buf, 0, 0); if (ret != 0) { Q_PRINTK("Could not print to fb"); } ret = cfb_framebuffer_finalize(display_dev); if (ret != 0) { Q_PRINTK("Could not finalize to fb"); } QS_BEGIN_ID(PHILO_STAT, AO_Philo[n]->prio) /* app-specific record */ QS_U8(1, n); /* Philosopher number */ QS_STR(stat); /* Philosopher status */ QS_END() /* application-specific record end */ } /*..........................................................................*/ void BSP_displayPaused(uint8_t paused) { if (paused != 0U) { //BSP_LED_On(LED2); } else { //BSP_LED_Off(LED2); } } /*..........................................................................*/ uint32_t BSP_random(void) { /* a very cheap pseudo-random-number generator */ uint32_t rnd; /* Some flating point code is to exercise the VFP... */ float volatile x = 3.1415926F; x = x + 2.7182818F; /* "Super-Duper" Linear Congruential Generator (LCG) * LCG(2^32, 3*7*11*13*23, 0, seed) */ rnd = l_rnd * (3U*7U*11U*13U*23U); l_rnd = rnd; /* set for the next time */ return (rnd >> 8); } /*..........................................................................*/ void BSP_randomSeed(uint32_t seed) { l_rnd = seed; } /*..........................................................................*/ void BSP_terminate(int16_t result) { (void)result; } /* QF callbacks ============================================================*/ void QF_onStartup(void) { k_timer_start(&QF_tick_timer, K_MSEC(1), K_MSEC(1)); Q_PRINTK("QF_onStartup\n"); } /*..........................................................................*/ void QF_onCleanup(void) { Q_PRINTK("QF_onCleanup\n"); } /*..........................................................................*/ Q_NORETURN Q_onAssert(char const * const module, int_t const loc) { /* * NOTE: add here your application-specific error handling */ printk("\nASSERTION in %s:%d\n", module, loc); QS_ASSERTION(module, loc, 10000U); /* report assertion to QS */ #ifndef NDEBUG k_panic(); /* debug build: halt the system for error search... */ #else sys_reboot(SYS_REBOOT_COLD); /* release build: reboot the system */ #endif } /* QS callbacks ============================================================*/ #ifdef Q_SPY #include <zephyr/drivers/uart.h> /* select the Zephyr shell UART * NOTE: you can change this to other UART peripheral if desired */ static struct device const *uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_shell_uart)); /*..........................................................................*/ static void uart_cb(const struct device *dev, void *user_data) { if (!uart_irq_update(uart_dev)) { return; } if (uart_irq_rx_ready(uart_dev)) { uint8_t buf[32]; int n = uart_fifo_read(uart_dev, buf, sizeof(buf)); for (uint8_t const *p = buf; n > 0; --n, ++p) { QS_RX_PUT(*p); } } } /*..........................................................................*/ uint8_t QS_onStartup(void const *arg) { static uint8_t qsTxBuf[1024]; /* buffer for QS-TX channel */ static uint8_t qsRxBuf[256]; /* buffer for QS-RX channel */ Q_REQUIRE(uart_dev != (struct device *)0); QS_initBuf (qsTxBuf, sizeof(qsTxBuf)); QS_rxInitBuf(qsRxBuf, sizeof(qsRxBuf)); // configure interrupt and callback to receive data uart_irq_callback_user_data_set(uart_dev, &uart_cb, (void *)0); uart_irq_rx_enable(uart_dev); return 1U; /* return success */ } /*..........................................................................*/ void QS_onCleanup(void) { } /*..........................................................................*/ QSTimeCtr QS_onGetTime(void) { /* NOTE: invoked with interrupts DISABLED */ return k_cycle_get_32(); } /*..........................................................................*/ void QS_onFlush(void) { uint16_t len = 0xFFFFU; /* to get as many bytes as available */ uint8_t const *buf; while ((buf = QS_getBlock(&len)) != (uint8_t*)0) { for (; len != 0U; --len, ++buf) { uart_poll_out(uart_dev, *buf); } len = 0xFFFFU; /* to get as many bytes as available */ } } /*..........................................................................*/ void QS_doOutput(void) { uint16_t len = 0xFFFFU; /* big number to get all available bytes */ QS_CRIT_STAT_ QS_CRIT_E_(); uint8_t const *buf = QS_getBlock(&len); QS_CRIT_X_(); /* transmit the bytes via the UART... */ for (; len != 0U; --len, ++buf) { uart_poll_out(uart_dev, *buf); } } /*..........................................................................*/ /*! callback function to reset the target (to be implemented in the BSP) */ void QS_onReset(void) { sys_reboot(SYS_REBOOT_COLD); } /*..........................................................................*/ /*! callback function to execute a user command (to be implemented in BSP) */ void QS_onCommand(uint8_t cmdId, uint32_t param1, uint32_t param2, uint32_t param3) { (void)cmdId; (void)param1; (void)param2; (void)param3; } #endif /* Q_SPY */