Merge branch 'uart-comm'
This commit is contained in:
@@ -6,6 +6,9 @@
|
||||
|
||||
#include "platform.h"
|
||||
#include "task_main.h"
|
||||
#include "comm/messages.h"
|
||||
#include "comm/interfaces.h"
|
||||
#include "framework/system_settings.h"
|
||||
|
||||
#include "USB/usbd_cdc_if.h"
|
||||
#include "USB/usb_device.h"
|
||||
@@ -14,13 +17,20 @@
|
||||
extern osSemaphoreId semVcomTxReadyHandle;
|
||||
extern osMutexId mutTinyFrameTxHandle;
|
||||
|
||||
void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, uint32_t len)
|
||||
/**
|
||||
* USB transmit implementation
|
||||
*
|
||||
* @param tf - TF
|
||||
* @param buff - buffer to send (can be longer than the buffers)
|
||||
* @param len - buffer size
|
||||
*/
|
||||
static inline void _USB_WriteImpl(TinyFrame *tf, const uint8_t *buff, uint32_t len)
|
||||
{
|
||||
#if 1
|
||||
const uint32_t real_size = len;
|
||||
|
||||
// Padding to a multiple of 64 bytes - this is supposed to maximize the bulk transfer speed
|
||||
if (len&0x3F) {
|
||||
if ((len&0x3F) && !SystemSettings.visible_vcom) { // this corrupts VCOM on Linux for some reason
|
||||
uint32_t pad = (64 - (len&0x3F));
|
||||
memset((void *) (buff + len), 0, pad);
|
||||
len += pad; // padding to a multiple of 64 (size of the endpoint)
|
||||
@@ -32,8 +42,9 @@ void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, uint32_t len)
|
||||
// The buffer is the TF transmit buffer, we can't leave it to work asynchronously because
|
||||
// the next call could modify it before it's been transmitted (in the case of a chunked / multi-part frame)
|
||||
|
||||
// the assumption here is that all until the last chunk use the full buffer capacity
|
||||
// If this is not the last chunk (assuming all but the last use full 512 bytes of the TF buffer), wait now for completion
|
||||
if (real_size == TF_SENDBUF_LEN) {
|
||||
// TODO this seems wrong - investigate
|
||||
if (pdTRUE != xSemaphoreTake(semVcomTxReadyHandle, 100)) {
|
||||
TF_Error("Tx stalled in WriteImpl");
|
||||
return;
|
||||
@@ -41,7 +52,7 @@ void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, uint32_t len)
|
||||
}
|
||||
#else
|
||||
(void) tf;
|
||||
#define CHUNK 64 // same as TF_SENDBUF_LEN, so we should always have only one run of the loop
|
||||
#define CHUNK 64 // size of the USB packet
|
||||
int32_t total = (int32_t) len;
|
||||
while (total > 0) {
|
||||
const int32_t mxStatus = osSemaphoreWait(semVcomTxReadyHandle, 100);
|
||||
@@ -64,11 +75,31 @@ void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, uint32_t len)
|
||||
#endif
|
||||
}
|
||||
|
||||
void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, uint32_t len)
|
||||
{
|
||||
if (gActiveComport == COMPORT_USB) {
|
||||
_USB_WriteImpl(tf, buff, len);
|
||||
}
|
||||
else if (gActiveComport == COMPORT_USART) {
|
||||
// TODO rewrite this to use DMA, then wait for the DMA
|
||||
for(uint32_t i=0;i<len;i++) {
|
||||
while(!LL_USART_IsActiveFlag_TXE(USART2));
|
||||
LL_USART_TransmitData8(USART2, buff[i]);
|
||||
}
|
||||
xSemaphoreGive(semVcomTxReadyHandle); // act as if we just finished it and this is perhaps the DMA irq
|
||||
}
|
||||
else {
|
||||
// TODO other transports
|
||||
trap("not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
/** Claim the TX interface before composing and sending a frame */
|
||||
bool TF_ClaimTx(TinyFrame *tf)
|
||||
{
|
||||
(void) tf;
|
||||
// assert_param(!inIRQ()); // useless delay
|
||||
assert_param(!inIRQ());
|
||||
|
||||
assert_param(pdTRUE == xSemaphoreTake(mutTinyFrameTxHandle, 5000)); // trips the wd
|
||||
|
||||
// The last chunk from some previous frame may still be being transmitted,
|
||||
|
||||
@@ -17,3 +17,15 @@ and processed by the message queue thread. This makes it possible to query hardw
|
||||
also makes it possible to wait on a binary semaphore when sending data back to host. The
|
||||
semaphore is set from the CDC TxComplete callback and taken by the TinyFrame write
|
||||
function, serving as a form of flow control.
|
||||
|
||||
--------------------------------------------
|
||||
|
||||
COMM API:
|
||||
|
||||
GEX supports alternate command interfaces.
|
||||
|
||||
The active interface is set in the global variable gActiveComport
|
||||
Due to special init procedures, the com_switch_transfer() function must be called to change it.
|
||||
|
||||
The TX function is defined in TF_Integration.c and any RX'd data is sent through rxQuePostMsg()
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
|
||||
int8_t STORAGE_Init_FS (uint8_t lun)
|
||||
{
|
||||
/* USER CODE BEGIN 2 */
|
||||
dbg("Plug In");
|
||||
dbg("MSC init request");
|
||||
vfs_mngr_fs_enable(1);
|
||||
return (USBD_OK);
|
||||
/* USER CODE END 2 */
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
//
|
||||
// Created by MightyPork on 2018/03/23.
|
||||
//
|
||||
|
||||
#include <stm32f072xb.h>
|
||||
#include "platform.h"
|
||||
#include "usbd_core.h"
|
||||
#include "USB/usb_device.h"
|
||||
#include "interfaces.h"
|
||||
#include "framework/system_settings.h"
|
||||
#include "framework/unit.h"
|
||||
#include "framework/resources.h"
|
||||
#include "platform/hw_utils.h"
|
||||
#include "framework/unit_base.h"
|
||||
|
||||
enum ComportSelection gActiveComport = COMPORT_USB; // start with USB so the handlers work correctly initially
|
||||
|
||||
static uint32_t last_switch_time = 0; // started with USB
|
||||
static bool xfer_verify_done = false;
|
||||
|
||||
static void configure_interface(enum ComportSelection iface);
|
||||
|
||||
/** Switch com transfer if the current one doesnt seem to work */
|
||||
void com_switch_transfer_if_needed(void)
|
||||
{
|
||||
if (xfer_verify_done) return;
|
||||
|
||||
const uint32_t now = HAL_GetTick();
|
||||
const uint32_t elapsed = now - last_switch_time;
|
||||
|
||||
if (gActiveComport == COMPORT_USB) {
|
||||
if (elapsed > 1000) {
|
||||
// USB may or may not work, depending on whether the module is plugged -
|
||||
// in or running from a battery/external supply remotely.
|
||||
|
||||
// Check if USB is enumerated
|
||||
|
||||
const uint32_t uadr = (USB->DADDR & USB_DADDR_ADD);
|
||||
if (0 == uadr) {
|
||||
dbg("Not enumerated, assuming USB is dead");
|
||||
|
||||
// Fallback to bare USART
|
||||
if (SystemSettings.use_comm_uart) {
|
||||
configure_interface(COMPORT_USART);
|
||||
}
|
||||
else if (SystemSettings.use_comm_nordic) {
|
||||
configure_interface(COMPORT_NORDIC); // this fallbacks to LoRa if LoRa enabled
|
||||
}
|
||||
else if (SystemSettings.use_comm_lora) {
|
||||
configure_interface(COMPORT_LORA);
|
||||
}
|
||||
else {
|
||||
dbg("No alternate com interface configured, leaving USB enabled.");
|
||||
}
|
||||
} else {
|
||||
dbg("USB got address 0x%02x - OK", (int)uadr);
|
||||
}
|
||||
|
||||
xfer_verify_done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Claim resources that may be needed for alternate transfers */
|
||||
void com_claim_resources_for_alt_transfers(void)
|
||||
{
|
||||
if (SystemSettings.use_comm_uart) {
|
||||
do {
|
||||
if (E_SUCCESS != rsc_claim(&UNIT_SYSTEM, R_USART2)) {
|
||||
SystemSettings.use_comm_uart = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (E_SUCCESS != rsc_claim(&UNIT_SYSTEM, R_PA2)) {
|
||||
SystemSettings.use_comm_uart = false;
|
||||
rsc_free(&UNIT_SYSTEM, R_USART2);
|
||||
break;
|
||||
}
|
||||
if (E_SUCCESS != rsc_claim(&UNIT_SYSTEM, R_PA3)) {
|
||||
SystemSettings.use_comm_uart = false;
|
||||
rsc_free(&UNIT_SYSTEM, R_USART2);
|
||||
rsc_free(&UNIT_SYSTEM, R_PA2);
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
}
|
||||
|
||||
/** Release resources allocated for alternate transfers */
|
||||
void com_release_resources_for_alt_transfers(void)
|
||||
{
|
||||
if (SystemSettings.use_comm_uart) {
|
||||
rsc_free(&UNIT_SYSTEM, R_USART2);
|
||||
rsc_free(&UNIT_SYSTEM, R_PA2);
|
||||
rsc_free(&UNIT_SYSTEM, R_PA3);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t usart_rxi = 0;
|
||||
static uint8_t usart_rx_buffer[MSG_QUE_SLOT_SIZE];
|
||||
static uint32_t last_rx_time = 0;
|
||||
|
||||
/** Handler for the USART transport */
|
||||
static void com_UsartIrqHandler(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
if (LL_USART_IsActiveFlag_RXNE(USART2)) {
|
||||
vPortEnterCritical();
|
||||
{
|
||||
usart_rx_buffer[usart_rxi++] = LL_USART_ReceiveData8(USART2);
|
||||
if (usart_rxi == MSG_QUE_SLOT_SIZE) {
|
||||
rxQuePostMsg(usart_rx_buffer, MSG_QUE_SLOT_SIZE); // avoid it happening in the irq
|
||||
usart_rxi = 0;
|
||||
}
|
||||
last_rx_time = HAL_GetTick();
|
||||
}
|
||||
vPortExitCritical();
|
||||
}
|
||||
}
|
||||
|
||||
/** this is called from the hal tick irq */
|
||||
void com_iface_flush_buffer(void)
|
||||
{
|
||||
if (usart_rxi > 0 && (HAL_GetTick()-last_rx_time)>=2) {
|
||||
vPortEnterCritical();
|
||||
{
|
||||
rxQuePostMsg(usart_rx_buffer, usart_rxi);
|
||||
usart_rxi = 0;
|
||||
}
|
||||
vPortExitCritical();
|
||||
}
|
||||
}
|
||||
|
||||
static void configure_interface(enum ComportSelection iface)
|
||||
{
|
||||
// Teardown
|
||||
if (gActiveComport == COMPORT_USB) {
|
||||
// simplest USB disabling (XXX needs porting)
|
||||
HAL_PCD_DeInit(&hpcd_USB_FS);
|
||||
__HAL_RCC_USB_CLK_DISABLE();
|
||||
}
|
||||
else if (gActiveComport == COMPORT_USART) {
|
||||
// this doesn't normally happen
|
||||
hw_deinit_pin_rsc(R_PA2);
|
||||
hw_deinit_pin_rsc(R_PA3);
|
||||
__HAL_RCC_USART2_CLK_DISABLE();
|
||||
irqd_detach(USART2, com_UsartIrqHandler);
|
||||
}
|
||||
gActiveComport = COMPORT_NONE;
|
||||
|
||||
// Init
|
||||
if (iface == COMPORT_USB) {
|
||||
trap("illegal"); // this never happens
|
||||
}
|
||||
else if (iface == COMPORT_USART) {
|
||||
dbg("Setting up UART transfer");
|
||||
assert_param(E_SUCCESS == hw_configure_gpiorsc_af(R_PA2, LL_GPIO_AF_1));
|
||||
assert_param(E_SUCCESS == hw_configure_gpiorsc_af(R_PA3, LL_GPIO_AF_1));
|
||||
|
||||
__HAL_RCC_USART2_CLK_ENABLE();
|
||||
__HAL_RCC_USART2_FORCE_RESET();
|
||||
__HAL_RCC_USART2_RELEASE_RESET();
|
||||
|
||||
LL_USART_Disable(USART2);
|
||||
|
||||
LL_USART_SetBaudRate(USART2, PLAT_APB1_HZ, LL_USART_OVERSAMPLING_16, SystemSettings.comm_uart_baud);
|
||||
dbg("baud = %d", (int)SystemSettings.comm_uart_baud);
|
||||
|
||||
irqd_attach(USART2, com_UsartIrqHandler, NULL);
|
||||
LL_USART_EnableIT_RXNE(USART2);
|
||||
LL_USART_SetTransferDirection(USART2, LL_USART_DIRECTION_TX_RX);
|
||||
|
||||
LL_USART_Enable(USART2);
|
||||
}
|
||||
else {
|
||||
if (iface == COMPORT_NORDIC) {
|
||||
// Try to configure nordic
|
||||
dbg("Setting up nRF transfer");
|
||||
|
||||
// TODO set up and check nRF transport
|
||||
|
||||
// On failure, try setting up LoRa
|
||||
dbg("nRF failed to init");
|
||||
if (SystemSettings.use_comm_lora) {
|
||||
iface = COMPORT_LORA;
|
||||
} else {
|
||||
iface = COMPORT_NONE; // fail
|
||||
}
|
||||
}
|
||||
|
||||
if (iface == COMPORT_LORA) {
|
||||
// Try to configure nordic
|
||||
dbg("Setting up LoRa transfer");
|
||||
|
||||
// TODO set up and check LoRa transport
|
||||
|
||||
dbg("LoRa failed to init");
|
||||
iface = COMPORT_NONE; // fail
|
||||
}
|
||||
}
|
||||
|
||||
if (iface == COMPORT_NONE) {
|
||||
dbg("NO COM PORT AVAILABLE!");
|
||||
}
|
||||
|
||||
gActiveComport = iface;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Created by MightyPork on 2018/03/23.
|
||||
//
|
||||
|
||||
#ifndef GEX_F072_COM_INTERFACES_H
|
||||
#define GEX_F072_COM_INTERFACES_H
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
enum ComportSelection {
|
||||
COMPORT_NONE = 0,
|
||||
COMPORT_USB = 1,
|
||||
COMPORT_USART = 2,
|
||||
COMPORT_NORDIC = 3,
|
||||
COMPORT_LORA = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* The currently active communication port
|
||||
*/
|
||||
extern enum ComportSelection gActiveComport;
|
||||
|
||||
/** Switch com transfer if the current one doesnt seem to work */
|
||||
void com_switch_transfer_if_needed(void);
|
||||
|
||||
/** Claim resources that may be needed for alternate transfers */
|
||||
void com_claim_resources_for_alt_transfers(void);
|
||||
|
||||
/** Release resources allocated for alternate transfers */
|
||||
void com_release_resources_for_alt_transfers(void);
|
||||
|
||||
/** Flush the rx buffer */
|
||||
void com_iface_flush_buffer(void);
|
||||
|
||||
#endif //GEX_F072_COM_INTERFACES_H
|
||||
+1
-1
@@ -2,7 +2,6 @@
|
||||
// Created by MightyPork on 2017/11/21.
|
||||
//
|
||||
|
||||
#include <platform/status_led.h>
|
||||
#include "platform.h"
|
||||
#include "framework/settings.h"
|
||||
#include "utils/ini_parser.h"
|
||||
@@ -11,6 +10,7 @@
|
||||
#include "comm/messages.h"
|
||||
#include "framework/system_settings.h"
|
||||
#include "utils/malloc_safe.h"
|
||||
#include "platform/status_led.h"
|
||||
|
||||
static TinyFrame tf_;
|
||||
TinyFrame *comm = &tf_;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Created by MightyPork on 2017/11/26.
|
||||
//
|
||||
|
||||
#include <comm/interfaces.h>
|
||||
#include "platform.h"
|
||||
#include "utils/hexdump.h"
|
||||
#include "settings.h"
|
||||
@@ -9,6 +10,7 @@
|
||||
#include "system_settings.h"
|
||||
#include "utils/str_utils.h"
|
||||
#include "unit_base.h"
|
||||
#include "platform/debug_uart.h"
|
||||
#include "utils/avrlibc.h"
|
||||
|
||||
// pre-declarations
|
||||
@@ -311,7 +313,7 @@ void settings_load_ini_key(const char *restrict section, const char *restrict ke
|
||||
if (streq(section, "SYSTEM")) {
|
||||
if (SystemSettings.loading_inifile == 0) {
|
||||
SystemSettings.loading_inifile = 'S';
|
||||
systemsettings_mco_teardown();
|
||||
systemsettings_begin_load();
|
||||
systemsettings_loadDefaults();
|
||||
}
|
||||
|
||||
@@ -358,6 +360,6 @@ void settings_load_ini_end(void)
|
||||
}
|
||||
|
||||
if (SystemSettings.loading_inifile == 'S') {
|
||||
systemsettings_mco_init();
|
||||
systemsettings_finalize_load();
|
||||
}
|
||||
}
|
||||
|
||||
+106
-4
@@ -2,6 +2,8 @@
|
||||
// Created by MightyPork on 2017/12/02.
|
||||
//
|
||||
|
||||
#include <platform/debug_uart.h>
|
||||
#include <comm/interfaces.h>
|
||||
#include "platform.h"
|
||||
#include "system_settings.h"
|
||||
#include "utils/str_utils.h"
|
||||
@@ -10,6 +12,11 @@
|
||||
#include "resources.h"
|
||||
#include "unit_base.h"
|
||||
|
||||
static void systemsettings_mco_teardown(void);
|
||||
static void systemsettings_mco_init(void);
|
||||
/** Init/deinit debug uart */
|
||||
static void systemsettings_debug_uart_init_deinit(void);
|
||||
|
||||
struct system_settings SystemSettings;
|
||||
|
||||
/** Load defaults only */
|
||||
@@ -19,6 +26,13 @@ void systemsettings_loadDefaults(void)
|
||||
SystemSettings.ini_comments = true;
|
||||
SystemSettings.enable_mco = false;
|
||||
SystemSettings.mco_prediv = 7;
|
||||
|
||||
SystemSettings.use_comm_uart = false; // TODO configure those based on compile flags for a particular platform
|
||||
SystemSettings.use_comm_lora = false;
|
||||
SystemSettings.use_comm_nordic = false;
|
||||
SystemSettings.comm_uart_baud = 115200; // TODO
|
||||
|
||||
SystemSettings.enable_debug_uart = true;
|
||||
}
|
||||
|
||||
/** Load defaults and init flags */
|
||||
@@ -35,14 +49,20 @@ void systemsettings_init(void)
|
||||
void systemsettings_save(PayloadBuilder *pb)
|
||||
{
|
||||
pb_char(pb, 'S');
|
||||
pb_u8(pb, 1); // settings format version
|
||||
pb_u8(pb, 2); // settings format version
|
||||
|
||||
{ // system settings
|
||||
pb_bool(pb, SystemSettings.visible_vcom);
|
||||
pb_bool(pb, SystemSettings.ini_comments);
|
||||
|
||||
// 1
|
||||
pb_bool(pb, SystemSettings.enable_mco);
|
||||
pb_u8(pb, SystemSettings.mco_prediv);
|
||||
// 2
|
||||
pb_bool(pb, SystemSettings.use_comm_uart);
|
||||
pb_bool(pb, SystemSettings.use_comm_nordic);
|
||||
pb_bool(pb, SystemSettings.use_comm_lora);
|
||||
pb_u32(pb, SystemSettings.comm_uart_baud);
|
||||
pb_bool(pb, SystemSettings.enable_debug_uart);
|
||||
} // end system settings
|
||||
}
|
||||
|
||||
@@ -67,12 +87,40 @@ void systemsettings_mco_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
void systemsettings_debug_uart_init_deinit(void)
|
||||
{
|
||||
if (SystemSettings.enable_debug_uart) {
|
||||
DebugUart_Init();
|
||||
} else {
|
||||
DebugUart_Teardown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin load of system settings, releasing resources etc
|
||||
*/
|
||||
void systemsettings_begin_load(void)
|
||||
{
|
||||
systemsettings_mco_teardown();
|
||||
com_release_resources_for_alt_transfers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim resources and set up system components based on the loaded settings
|
||||
*/
|
||||
void systemsettings_finalize_load(void)
|
||||
{
|
||||
systemsettings_mco_init();
|
||||
systemsettings_debug_uart_init_deinit();
|
||||
com_claim_resources_for_alt_transfers();
|
||||
}
|
||||
|
||||
// from binary
|
||||
bool systemsettings_load(PayloadParser *pp)
|
||||
{
|
||||
if (pp_char(pp) != 'S') return false;
|
||||
|
||||
systemsettings_mco_teardown();
|
||||
systemsettings_begin_load();
|
||||
|
||||
uint8_t version = pp_u8(pp);
|
||||
|
||||
@@ -85,9 +133,16 @@ bool systemsettings_load(PayloadParser *pp)
|
||||
SystemSettings.enable_mco = pp_bool(pp);
|
||||
SystemSettings.mco_prediv = pp_u8(pp);
|
||||
}
|
||||
if (version >= 2) {
|
||||
SystemSettings.use_comm_uart = pp_bool(pp);
|
||||
SystemSettings.use_comm_nordic = pp_bool(pp);
|
||||
SystemSettings.use_comm_lora = pp_bool(pp);
|
||||
SystemSettings.comm_uart_baud = pp_u32(pp);
|
||||
SystemSettings.enable_debug_uart = pp_bool(pp);
|
||||
}
|
||||
} // end system settings
|
||||
|
||||
systemsettings_mco_init();
|
||||
systemsettings_finalize_load();
|
||||
|
||||
return pp->ok;
|
||||
}
|
||||
@@ -106,11 +161,31 @@ void systemsettings_build_ini(IniWriter *iw)
|
||||
iw_comment(iw, "Show comments in INI files (Y, N)");
|
||||
iw_entry_s(iw, "ini-comments", str_yn(SystemSettings.ini_comments));
|
||||
|
||||
iw_comment(iw, "Enable debug UART-Tx on PA9 (Y, N)"); // TODO update if moved to a different pin
|
||||
iw_entry_s(iw, "debug-uart", str_yn(SystemSettings.enable_debug_uart));
|
||||
|
||||
iw_cmt_newline(iw);
|
||||
iw_comment(iw, "Output core clock on PA8 (Y, N)");
|
||||
iw_entry_s(iw, "mco-enable", str_yn(SystemSettings.enable_mco));
|
||||
iw_comment(iw, "Output clock prediv (1,2,...,128)");
|
||||
iw_entry_d(iw, "mco-prediv", (1<<SystemSettings.mco_prediv));
|
||||
|
||||
iw_cmt_newline(iw);
|
||||
iw_comment(iw, "Allowed fallback communication ports");
|
||||
|
||||
iw_comment(iw, "UART Tx:PA2, Rx:PA2");
|
||||
iw_entry_s(iw, "com-uart", str_yn(SystemSettings.use_comm_uart));
|
||||
iw_entry_d(iw, "com-uart-baud", SystemSettings.comm_uart_baud);
|
||||
|
||||
// those aren't implement yet, don't tease the user
|
||||
// TODO show pin-out, extra settings if applicable
|
||||
#if 0
|
||||
iw_comment(iw, "nRF24L01+");
|
||||
iw_entry_s(iw, "com-nordic", str_yn(SystemSettings.use_comm_nrf24l01p));
|
||||
|
||||
iw_comment(iw, "LoRa/GFSK sx127x");
|
||||
iw_entry_s(iw, "com-lora", str_yn(SystemSettings.use_comm_sx127x));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,5 +226,32 @@ bool systemsettings_load_ini(const char *restrict key, const char *restrict valu
|
||||
}
|
||||
}
|
||||
|
||||
if (streq(key, "debug-uart")) {
|
||||
bool yn = cfg_bool_parse(value, &suc);
|
||||
if (suc) SystemSettings.enable_debug_uart = yn;
|
||||
}
|
||||
|
||||
if (streq(key, "com-uart")) {
|
||||
bool yn = cfg_bool_parse(value, &suc);
|
||||
if (suc) SystemSettings.use_comm_uart = yn;
|
||||
}
|
||||
|
||||
if (streq(key, "com-uart-baud")) {
|
||||
uint32_t baud = cfg_u32_parse(value, &suc);
|
||||
if (suc) SystemSettings.comm_uart_baud = baud;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (streq(key, "com-nordic")) {
|
||||
bool yn = cfg_bool_parse(value, &suc);
|
||||
if (suc) SystemSettings.use_comm_nordic = yn;
|
||||
}
|
||||
|
||||
if (streq(key, "com-lora")) {
|
||||
bool yn = cfg_bool_parse(value, &suc);
|
||||
if (suc) SystemSettings.use_comm_lora = yn;
|
||||
}
|
||||
#endif
|
||||
|
||||
return suc;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,13 @@ struct system_settings {
|
||||
bool ini_comments;
|
||||
bool enable_mco;
|
||||
uint8_t mco_prediv;
|
||||
bool enable_debug_uart;
|
||||
|
||||
// enable alternate communication ports if USB doesn't enumerate (e.g. running from battery / solar cell remotely)
|
||||
bool use_comm_uart;
|
||||
uint32_t comm_uart_baud; // baud rate for the uart transport
|
||||
bool use_comm_lora; // SX1276/8
|
||||
bool use_comm_nordic; // nRF24L01+
|
||||
|
||||
// Support flags put here for scoping, but not atcually part of the persistent settings
|
||||
volatile bool editable; //!< True if we booted with the LOCK jumper removed
|
||||
@@ -62,7 +69,9 @@ void systemsettings_build_ini(IniWriter *iw);
|
||||
*/
|
||||
bool systemsettings_load_ini(const char *restrict key, const char *restrict value);
|
||||
|
||||
void systemsettings_mco_teardown(void);
|
||||
void systemsettings_mco_init(void);
|
||||
/** Release system resources before system settings init */
|
||||
void systemsettings_begin_load(void);
|
||||
/** Claim system resources and apply system settings */
|
||||
void systemsettings_finalize_load(void);
|
||||
|
||||
#endif //GEX_SYSTEM_SETTINGS_H
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
#include "platform/debug_uart.h"
|
||||
#include "gex_hooks.h"
|
||||
#include "unit_registry.h"
|
||||
#include "comm/interfaces.h"
|
||||
|
||||
/**
|
||||
* This is a systick callback for GEX application logic
|
||||
*/
|
||||
void GEX_MsTick(void)
|
||||
{
|
||||
com_iface_flush_buffer();
|
||||
TF_Tick(comm);
|
||||
Indicator_Tick();
|
||||
ureg_tick_units();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "debug_uart.h"
|
||||
#include "plat_compat.h"
|
||||
#include "hw_utils.h"
|
||||
#include "framework/system_settings.h"
|
||||
|
||||
#if USE_DEBUG_UART
|
||||
|
||||
@@ -52,18 +53,26 @@
|
||||
#endif
|
||||
|
||||
|
||||
static bool debug_uart_inited = false;
|
||||
static bool debug_uart_preinited = false;
|
||||
|
||||
/** Init the submodule. */
|
||||
void DebugUart_Init(void)
|
||||
{
|
||||
if (debug_uart_inited) return;
|
||||
if (!debug_uart_preinited) DebugUart_PreInit();
|
||||
// Debug UART
|
||||
assert_param(E_SUCCESS == rsc_claim(&UNIT_SYSTEM, DEBUG_USART_RSC));
|
||||
assert_param(E_SUCCESS == rsc_claim_pin(&UNIT_SYSTEM, DEBUG_USART_PORT, DEBUG_USART_PIN));
|
||||
|
||||
debug_uart_inited = true;
|
||||
}
|
||||
|
||||
/** Init the hardware peripheral - this is called early in the boot process */
|
||||
void DebugUart_PreInit(void)
|
||||
{
|
||||
debug_uart_preinited = true;
|
||||
|
||||
// configure AF only if platform uses AF numbers
|
||||
#if !PLAT_NO_AFNUM
|
||||
#pragma GCC diagnostic push
|
||||
@@ -89,8 +98,35 @@ void DebugUart_PreInit(void)
|
||||
LL_USART_Enable(DEBUG_USART);
|
||||
}
|
||||
|
||||
void DebugUart_Teardown(void)
|
||||
{
|
||||
if (!debug_uart_inited) return;
|
||||
|
||||
dbg("Disabling debug UART!");
|
||||
|
||||
// TODO wait for Tx (after debug print DMA is implemented)
|
||||
|
||||
LL_USART_Disable(DEBUG_USART);
|
||||
rsc_free(&UNIT_SYSTEM, DEBUG_USART_RSC);
|
||||
hw_periph_clock_disable(DEBUG_USART);
|
||||
|
||||
bool suc = true;
|
||||
Resource r = rsc_portpin2rsc(DEBUG_USART_PORT, DEBUG_USART_PIN, &suc);
|
||||
rsc_free(&UNIT_SYSTEM, r);
|
||||
hw_deinit_pin_rsc(r);
|
||||
|
||||
debug_uart_preinited = false;
|
||||
debug_uart_inited = false;
|
||||
|
||||
assert_param(suc);
|
||||
}
|
||||
|
||||
void debug_write(const char *buf, uint16_t len)
|
||||
{
|
||||
if (!SystemSettings.enable_debug_uart) return;
|
||||
|
||||
// TODO wait for DMA complete
|
||||
// TODO use DMA
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
while (!LL_USART_IsActiveFlag_TC(DEBUG_USART));
|
||||
LL_USART_TransmitData8(DEBUG_USART, (uint8_t) *buf++);
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#ifndef GEX_DEBUG_UART_H
|
||||
#define GEX_DEBUG_UART_H
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
/**
|
||||
* Pre-init the debug uart
|
||||
*
|
||||
@@ -17,7 +19,13 @@
|
||||
void DebugUart_PreInit(void);
|
||||
|
||||
/**
|
||||
* Finalize the init (claim resources)
|
||||
* Release the peripheral and deinit pin
|
||||
*/
|
||||
void DebugUart_Teardown(void);
|
||||
|
||||
/**
|
||||
* Finalize the init (claim resources).
|
||||
* If not pre-inited (i.e. Teardown was called before), also pre-init.
|
||||
*/
|
||||
void DebugUart_Init(void);
|
||||
|
||||
|
||||
+9
-4
@@ -99,14 +99,19 @@ void hw_deinit_unit_pins(Unit *unit)
|
||||
{
|
||||
for (uint32_t rsc = R_PA0; rsc <= R_PF15; rsc++) {
|
||||
if (RSC_IS_HELD(unit->resources, (Resource)rsc)) {
|
||||
rsc_dbg("Freeing pin %s", rsc_get_name((Resource)rsc));
|
||||
GPIO_TypeDef *port = GPIO_PERIPHS[(rsc-R_PA0) / 16];
|
||||
uint32_t ll_pin = LL_GPIO_PINS[(rsc-R_PA0)%16];
|
||||
LL_GPIO_SetPinMode(port, ll_pin, LL_GPIO_MODE_ANALOG);
|
||||
hw_deinit_pin_rsc((Resource)rsc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hw_deinit_pin_rsc(Resource rsc)
|
||||
{
|
||||
rsc_dbg("Freeing pin %s", rsc_get_name((Resource)rsc));
|
||||
GPIO_TypeDef *port = GPIO_PERIPHS[(rsc-R_PA0) / 16];
|
||||
uint32_t ll_pin = LL_GPIO_PINS[(rsc-R_PA0)%16];
|
||||
LL_GPIO_SetPinMode(port, ll_pin, LL_GPIO_MODE_ANALOG);
|
||||
}
|
||||
|
||||
/** Configure a pin to alternate function */
|
||||
error_t hw_configure_gpio_af(char port_name, uint8_t pin_num, uint32_t ll_af)
|
||||
{
|
||||
|
||||
@@ -40,6 +40,8 @@ GPIO_TypeDef *hw_port2periph(char port_name, bool *suc);
|
||||
*/
|
||||
bool hw_pinrsc2ll(Resource rsc, GPIO_TypeDef **port, uint32_t *llpin) __attribute__((warn_unused_result));
|
||||
|
||||
void hw_deinit_pin_rsc(Resource rsc);
|
||||
|
||||
/**
|
||||
* Spread packed port pins using a mask
|
||||
*
|
||||
|
||||
@@ -56,9 +56,9 @@
|
||||
#define IWBUFFER_LEN 80 // Ini writer buffer for sprintf
|
||||
|
||||
// -------- Timeouts ------------
|
||||
#define TF_PARSER_TIMEOUT_TICKS 300 // Timeout for receiving & parsing a frame
|
||||
#define BULK_LST_TIMEOUT_MS 500 // timeout for the bulk transaction to expire
|
||||
#define MSG_QUE_POST_TIMEOUT 100 // Time to post to the messages / jobs queue
|
||||
#define TF_PARSER_TIMEOUT_TICKS 100 // Timeout for receiving & parsing a frame
|
||||
#define BULK_LST_TIMEOUT_MS 2000 // timeout for the bulk transaction to expire
|
||||
#define MSG_QUE_POST_TIMEOUT 200 // Time to post to the messages / jobs queue
|
||||
|
||||
// -------- Platform specific includes and defines ---------
|
||||
|
||||
|
||||
+4
-1
@@ -2,7 +2,6 @@
|
||||
// Created by MightyPork on 2017/11/26.
|
||||
//
|
||||
|
||||
#include <units/dac/unit_dac.h>
|
||||
#include "platform.h"
|
||||
#include "usbd_core.h"
|
||||
#include "USB/usb_device.h"
|
||||
@@ -22,6 +21,8 @@
|
||||
#include "units/fcap/unit_fcap.h"
|
||||
#include "units/touch/unit_touch.h"
|
||||
#include "units/simple_pwm/unit_pwmdim.h"
|
||||
#include "units/dac/unit_dac.h"
|
||||
#include "comm/interfaces.h"
|
||||
#include "hw_utils.h"
|
||||
|
||||
void plat_init_resources(void)
|
||||
@@ -258,6 +259,8 @@ void plat_init_resources(void)
|
||||
*/
|
||||
void plat_usb_reconnect(void)
|
||||
{
|
||||
if (gActiveComport != COMPORT_USB) return;
|
||||
|
||||
// TODO add better reset methods available on different chips
|
||||
|
||||
USBD_LL_Reset(&hUsbDeviceFS);
|
||||
|
||||
+35
-25
@@ -12,6 +12,7 @@
|
||||
#include "usb_device.h"
|
||||
#include "usbd_msc.h"
|
||||
#include "task_main.h"
|
||||
#include "comm/interfaces.h"
|
||||
|
||||
/* TaskUsbEvent function */
|
||||
void TaskMain(void const * argument)
|
||||
@@ -25,14 +26,16 @@ void TaskMain(void const * argument)
|
||||
|
||||
Indicator_Effect(STATUS_WELCOME);
|
||||
|
||||
uint32_t startTime = xTaskGetTickCount();
|
||||
const uint32_t bootTime = HAL_GetTick();
|
||||
uint32_t startTime = bootTime;
|
||||
uint32_t cnt = 1;
|
||||
bool waiting_for_usb = true;
|
||||
while(1) {
|
||||
uint32_t msg;
|
||||
xTaskNotifyWait(0, UINT32_MAX, &msg, 100); // time out if nothing happened
|
||||
|
||||
// periodic updates to the VFS driver
|
||||
uint32_t now = xTaskGetTickCount();
|
||||
uint32_t now = HAL_GetTick();
|
||||
uint32_t elapsed = now - startTime;
|
||||
if (elapsed >= 100) {
|
||||
// interval 100ms or more - slow periodic
|
||||
@@ -48,6 +51,9 @@ void TaskMain(void const * argument)
|
||||
Indicator_Heartbeat();
|
||||
|
||||
wd_restart();
|
||||
|
||||
// If USB has no signal, set up alternate communication interface
|
||||
com_switch_transfer_if_needed();
|
||||
}
|
||||
|
||||
// if no message and it just timed out, go wait some more...
|
||||
@@ -61,35 +67,39 @@ void TaskMain(void const * argument)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Endpoint 0 - control messages for the different classes
|
||||
if (msg & USBEVT_FLAG_EP0_RX_RDY) {
|
||||
USBD_CDC_EP0_RxReady(&hUsbDeviceFS);
|
||||
}
|
||||
if (gActiveComport == COMPORT_USB) {
|
||||
// Endpoint 0 - control messages for the different classes
|
||||
if (msg & USBEVT_FLAG_EP0_RX_RDY) {
|
||||
USBD_CDC_EP0_RxReady(&hUsbDeviceFS);
|
||||
}
|
||||
|
||||
if (msg & USBEVT_FLAG_EP0_TX_SENT) {
|
||||
//
|
||||
}
|
||||
if (msg & USBEVT_FLAG_EP0_TX_SENT) {
|
||||
//
|
||||
}
|
||||
|
||||
#ifndef DISABLE_MSC
|
||||
// MSC - read/write etc
|
||||
if (msg & (USBEVT_FLAG_EPx_IN(MSC_EPIN_ADDR))) {
|
||||
USBD_MSC_DataIn(&hUsbDeviceFS, MSC_EPIN_ADDR);
|
||||
}
|
||||
// MSC - read/write etc
|
||||
if (msg & (USBEVT_FLAG_EPx_IN(MSC_EPIN_ADDR))) {
|
||||
USBD_MSC_DataIn(&hUsbDeviceFS, MSC_EPIN_ADDR);
|
||||
}
|
||||
|
||||
if (msg & (USBEVT_FLAG_EPx_OUT(MSC_EPOUT_ADDR))) {
|
||||
USBD_MSC_DataOut(&hUsbDeviceFS, MSC_EPOUT_ADDR);
|
||||
}
|
||||
if (msg & (USBEVT_FLAG_EPx_OUT(MSC_EPOUT_ADDR))) {
|
||||
USBD_MSC_DataOut(&hUsbDeviceFS, MSC_EPOUT_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
// CDC - config packets and data in/out
|
||||
// if (msg & (USBEVT_FLAG_EPx_IN(CDC_IN_EP))) {
|
||||
// USBD_CDC_DataIn(&hUsbDeviceFS, CDC_IN_EP);
|
||||
// }
|
||||
if (msg & (USBEVT_FLAG_EPx_IN(CDC_CMD_EP))) {
|
||||
USBD_CDC_DataIn(&hUsbDeviceFS, CDC_CMD_EP);
|
||||
}
|
||||
if (msg & (USBEVT_FLAG_EPx_OUT(CDC_OUT_EP))) {
|
||||
USBD_CDC_DataOut(&hUsbDeviceFS, CDC_OUT_EP);
|
||||
// CDC - config packets and data in/out
|
||||
// if (msg & (USBEVT_FLAG_EPx_IN(CDC_IN_EP))) {
|
||||
// USBD_CDC_DataIn(&hUsbDeviceFS, CDC_IN_EP);
|
||||
// }
|
||||
|
||||
if (msg & (USBEVT_FLAG_EPx_IN(CDC_CMD_EP))) {
|
||||
USBD_CDC_DataIn(&hUsbDeviceFS, CDC_CMD_EP);
|
||||
}
|
||||
|
||||
if (msg & (USBEVT_FLAG_EPx_OUT(CDC_OUT_EP))) {
|
||||
USBD_CDC_DataOut(&hUsbDeviceFS, CDC_OUT_EP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user