implemented fallback to physical usart and basis for wireless support in the future

remotes/github/master
Ondřej Hruška 6 years ago
parent 1797f179b4
commit 102d5f5a4c
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 41
      TinyFrame/TF_Integration.c
  2. 12
      USB/README.TXT
  3. 2
      USB/usbd_storage_if.c
  4. 207
      comm/interfaces.c
  5. 35
      comm/interfaces.h
  6. 2
      comm/messages.c
  7. 6
      framework/settings.c
  8. 110
      framework/system_settings.c
  9. 13
      framework/system_settings.h
  10. 2
      gex_hooks.c
  11. 36
      platform/debug_uart.c
  12. 10
      platform/debug_uart.h
  13. 13
      platform/hw_utils.c
  14. 2
      platform/hw_utils.h
  15. 6
      platform/plat_compat.h
  16. 5
      platform/platform.c
  17. 62
      tasks/task_main.c

@ -6,6 +6,9 @@
#include "platform.h" #include "platform.h"
#include "task_main.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/usbd_cdc_if.h"
#include "USB/usb_device.h" #include "USB/usb_device.h"
@ -14,13 +17,20 @@
extern osSemaphoreId semVcomTxReadyHandle; extern osSemaphoreId semVcomTxReadyHandle;
extern osMutexId mutTinyFrameTxHandle; 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 #if 1
const uint32_t real_size = len; const uint32_t real_size = len;
// Padding to a multiple of 64 bytes - this is supposed to maximize the bulk transfer speed // 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)); uint32_t pad = (64 - (len&0x3F));
memset((void *) (buff + len), 0, pad); memset((void *) (buff + len), 0, pad);
len += pad; // padding to a multiple of 64 (size of the endpoint) 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 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 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) { if (real_size == TF_SENDBUF_LEN) {
// TODO this seems wrong - investigate
if (pdTRUE != xSemaphoreTake(semVcomTxReadyHandle, 100)) { if (pdTRUE != xSemaphoreTake(semVcomTxReadyHandle, 100)) {
TF_Error("Tx stalled in WriteImpl"); TF_Error("Tx stalled in WriteImpl");
return; return;
@ -41,7 +52,7 @@ void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, uint32_t len)
} }
#else #else
(void) tf; (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; int32_t total = (int32_t) len;
while (total > 0) { while (total > 0) {
const int32_t mxStatus = osSemaphoreWait(semVcomTxReadyHandle, 100); const int32_t mxStatus = osSemaphoreWait(semVcomTxReadyHandle, 100);
@ -64,11 +75,31 @@ void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, uint32_t len)
#endif #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 */ /** Claim the TX interface before composing and sending a frame */
bool TF_ClaimTx(TinyFrame *tf) bool TF_ClaimTx(TinyFrame *tf)
{ {
(void) tf; (void) tf;
// assert_param(!inIRQ()); // useless delay assert_param(!inIRQ());
assert_param(pdTRUE == xSemaphoreTake(mutTinyFrameTxHandle, 5000)); // trips the wd assert_param(pdTRUE == xSemaphoreTake(mutTinyFrameTxHandle, 5000)); // trips the wd
// The last chunk from some previous frame may still be being transmitted, // 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 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 semaphore is set from the CDC TxComplete callback and taken by the TinyFrame write
function, serving as a form of flow control. 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) int8_t STORAGE_Init_FS (uint8_t lun)
{ {
/* USER CODE BEGIN 2 */ /* USER CODE BEGIN 2 */
dbg("Plug In"); dbg("MSC init request");
vfs_mngr_fs_enable(1); vfs_mngr_fs_enable(1);
return (USBD_OK); return (USBD_OK);
/* USER CODE END 2 */ /* 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

@ -2,7 +2,6 @@
// Created by MightyPork on 2017/11/21. // Created by MightyPork on 2017/11/21.
// //
#include <platform/status_led.h>
#include "platform.h" #include "platform.h"
#include "framework/settings.h" #include "framework/settings.h"
#include "utils/ini_parser.h" #include "utils/ini_parser.h"
@ -11,6 +10,7 @@
#include "comm/messages.h" #include "comm/messages.h"
#include "framework/system_settings.h" #include "framework/system_settings.h"
#include "utils/malloc_safe.h" #include "utils/malloc_safe.h"
#include "platform/status_led.h"
static TinyFrame tf_; static TinyFrame tf_;
TinyFrame *comm = &tf_; TinyFrame *comm = &tf_;

@ -2,6 +2,7 @@
// Created by MightyPork on 2017/11/26. // Created by MightyPork on 2017/11/26.
// //
#include <comm/interfaces.h>
#include "platform.h" #include "platform.h"
#include "utils/hexdump.h" #include "utils/hexdump.h"
#include "settings.h" #include "settings.h"
@ -9,6 +10,7 @@
#include "system_settings.h" #include "system_settings.h"
#include "utils/str_utils.h" #include "utils/str_utils.h"
#include "unit_base.h" #include "unit_base.h"
#include "platform/debug_uart.h"
#include "utils/avrlibc.h" #include "utils/avrlibc.h"
// pre-declarations // pre-declarations
@ -311,7 +313,7 @@ void settings_load_ini_key(const char *restrict section, const char *restrict ke
if (streq(section, "SYSTEM")) { if (streq(section, "SYSTEM")) {
if (SystemSettings.loading_inifile == 0) { if (SystemSettings.loading_inifile == 0) {
SystemSettings.loading_inifile = 'S'; SystemSettings.loading_inifile = 'S';
systemsettings_mco_teardown(); systemsettings_begin_load();
systemsettings_loadDefaults(); systemsettings_loadDefaults();
} }
@ -358,6 +360,6 @@ void settings_load_ini_end(void)
} }
if (SystemSettings.loading_inifile == 'S') { if (SystemSettings.loading_inifile == 'S') {
systemsettings_mco_init(); systemsettings_finalize_load();
} }
} }

@ -2,6 +2,8 @@
// Created by MightyPork on 2017/12/02. // Created by MightyPork on 2017/12/02.
// //
#include <platform/debug_uart.h>
#include <comm/interfaces.h>
#include "platform.h" #include "platform.h"
#include "system_settings.h" #include "system_settings.h"
#include "utils/str_utils.h" #include "utils/str_utils.h"
@ -10,6 +12,11 @@
#include "resources.h" #include "resources.h"
#include "unit_base.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; struct system_settings SystemSettings;
/** Load defaults only */ /** Load defaults only */
@ -19,6 +26,13 @@ void systemsettings_loadDefaults(void)
SystemSettings.ini_comments = true; SystemSettings.ini_comments = true;
SystemSettings.enable_mco = false; SystemSettings.enable_mco = false;
SystemSettings.mco_prediv = 7; 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 */ /** Load defaults and init flags */
@ -35,14 +49,20 @@ void systemsettings_init(void)
void systemsettings_save(PayloadBuilder *pb) void systemsettings_save(PayloadBuilder *pb)
{ {
pb_char(pb, 'S'); pb_char(pb, 'S');
pb_u8(pb, 1); // settings format version pb_u8(pb, 2); // settings format version
{ // system settings { // system settings
pb_bool(pb, SystemSettings.visible_vcom); pb_bool(pb, SystemSettings.visible_vcom);
pb_bool(pb, SystemSettings.ini_comments); pb_bool(pb, SystemSettings.ini_comments);
// 1
pb_bool(pb, SystemSettings.enable_mco); pb_bool(pb, SystemSettings.enable_mco);
pb_u8(pb, SystemSettings.mco_prediv); 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 } // 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 // from binary
bool systemsettings_load(PayloadParser *pp) bool systemsettings_load(PayloadParser *pp)
{ {
if (pp_char(pp) != 'S') return false; if (pp_char(pp) != 'S') return false;
systemsettings_mco_teardown(); systemsettings_begin_load();
uint8_t version = pp_u8(pp); uint8_t version = pp_u8(pp);
@ -85,9 +133,16 @@ bool systemsettings_load(PayloadParser *pp)
SystemSettings.enable_mco = pp_bool(pp); SystemSettings.enable_mco = pp_bool(pp);
SystemSettings.mco_prediv = pp_u8(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 } // end system settings
systemsettings_mco_init(); systemsettings_finalize_load();
return pp->ok; return pp->ok;
} }
@ -106,11 +161,31 @@ void systemsettings_build_ini(IniWriter *iw)
iw_comment(iw, "Show comments in INI files (Y, N)"); iw_comment(iw, "Show comments in INI files (Y, N)");
iw_entry_s(iw, "ini-comments", str_yn(SystemSettings.ini_comments)); 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_cmt_newline(iw);
iw_comment(iw, "Output core clock on PA8 (Y, N)"); iw_comment(iw, "Output core clock on PA8 (Y, N)");
iw_entry_s(iw, "mco-enable", str_yn(SystemSettings.enable_mco)); iw_entry_s(iw, "mco-enable", str_yn(SystemSettings.enable_mco));
iw_comment(iw, "Output clock prediv (1,2,...,128)"); iw_comment(iw, "Output clock prediv (1,2,...,128)");
iw_entry_d(iw, "mco-prediv", (1<<SystemSettings.mco_prediv)); 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; return suc;
} }

@ -20,6 +20,13 @@ struct system_settings {
bool ini_comments; bool ini_comments;
bool enable_mco; bool enable_mco;
uint8_t mco_prediv; 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 // 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 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); bool systemsettings_load_ini(const char *restrict key, const char *restrict value);
void systemsettings_mco_teardown(void); /** Release system resources before system settings init */
void systemsettings_mco_init(void); void systemsettings_begin_load(void);
/** Claim system resources and apply system settings */
void systemsettings_finalize_load(void);
#endif //GEX_SYSTEM_SETTINGS_H #endif //GEX_SYSTEM_SETTINGS_H

@ -10,12 +10,14 @@
#include "platform/debug_uart.h" #include "platform/debug_uart.h"
#include "gex_hooks.h" #include "gex_hooks.h"
#include "unit_registry.h" #include "unit_registry.h"
#include "comm/interfaces.h"
/** /**
* This is a systick callback for GEX application logic * This is a systick callback for GEX application logic
*/ */
void GEX_MsTick(void) void GEX_MsTick(void)
{ {
com_iface_flush_buffer();
TF_Tick(comm); TF_Tick(comm);
Indicator_Tick(); Indicator_Tick();
ureg_tick_units(); ureg_tick_units();

@ -7,6 +7,7 @@
#include "debug_uart.h" #include "debug_uart.h"
#include "plat_compat.h" #include "plat_compat.h"
#include "hw_utils.h" #include "hw_utils.h"
#include "framework/system_settings.h"
#if USE_DEBUG_UART #if USE_DEBUG_UART
@ -52,18 +53,26 @@
#endif #endif
static bool debug_uart_inited = false;
static bool debug_uart_preinited = false;
/** Init the submodule. */ /** Init the submodule. */
void DebugUart_Init(void) void DebugUart_Init(void)
{ {
if (debug_uart_inited) return;
if (!debug_uart_preinited) DebugUart_PreInit();
// Debug UART // Debug UART
assert_param(E_SUCCESS == rsc_claim(&UNIT_SYSTEM, DEBUG_USART_RSC)); 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)); 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 */ /** Init the hardware peripheral - this is called early in the boot process */
void DebugUart_PreInit(void) void DebugUart_PreInit(void)
{ {
debug_uart_preinited = true;
// configure AF only if platform uses AF numbers // configure AF only if platform uses AF numbers
#if !PLAT_NO_AFNUM #if !PLAT_NO_AFNUM
#pragma GCC diagnostic push #pragma GCC diagnostic push
@ -89,8 +98,35 @@ void DebugUart_PreInit(void)
LL_USART_Enable(DEBUG_USART); 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) 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++) { for (uint16_t i = 0; i < len; i++) {
while (!LL_USART_IsActiveFlag_TC(DEBUG_USART)); while (!LL_USART_IsActiveFlag_TC(DEBUG_USART));
LL_USART_TransmitData8(DEBUG_USART, (uint8_t) *buf++); LL_USART_TransmitData8(DEBUG_USART, (uint8_t) *buf++);

@ -8,6 +8,8 @@
#ifndef GEX_DEBUG_UART_H #ifndef GEX_DEBUG_UART_H
#define GEX_DEBUG_UART_H #define GEX_DEBUG_UART_H
#include "platform.h"
/** /**
* Pre-init the debug uart * Pre-init the debug uart
* *
@ -17,7 +19,13 @@
void DebugUart_PreInit(void); 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); void DebugUart_Init(void);

@ -99,14 +99,19 @@ void hw_deinit_unit_pins(Unit *unit)
{ {
for (uint32_t rsc = R_PA0; rsc <= R_PF15; rsc++) { for (uint32_t rsc = R_PA0; rsc <= R_PF15; rsc++) {
if (RSC_IS_HELD(unit->resources, (Resource)rsc)) { if (RSC_IS_HELD(unit->resources, (Resource)rsc)) {
rsc_dbg("Freeing pin %s", rsc_get_name((Resource)rsc)); hw_deinit_pin_rsc((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);
} }
} }
} }
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 */ /** Configure a pin to alternate function */
error_t hw_configure_gpio_af(char port_name, uint8_t pin_num, uint32_t ll_af) 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)); 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 * Spread packed port pins using a mask
* *

@ -56,9 +56,9 @@
#define IWBUFFER_LEN 80 // Ini writer buffer for sprintf #define IWBUFFER_LEN 80 // Ini writer buffer for sprintf
// -------- Timeouts ------------ // -------- Timeouts ------------
#define TF_PARSER_TIMEOUT_TICKS 300 // Timeout for receiving & parsing a frame #define TF_PARSER_TIMEOUT_TICKS 100 // Timeout for receiving & parsing a frame
#define BULK_LST_TIMEOUT_MS 500 // timeout for the bulk transaction to expire #define BULK_LST_TIMEOUT_MS 2000 // timeout for the bulk transaction to expire
#define MSG_QUE_POST_TIMEOUT 100 // Time to post to the messages / jobs queue #define MSG_QUE_POST_TIMEOUT 200 // Time to post to the messages / jobs queue
// -------- Platform specific includes and defines --------- // -------- Platform specific includes and defines ---------

@ -2,7 +2,6 @@
// Created by MightyPork on 2017/11/26. // Created by MightyPork on 2017/11/26.
// //
#include <units/dac/unit_dac.h>
#include "platform.h" #include "platform.h"
#include "usbd_core.h" #include "usbd_core.h"
#include "USB/usb_device.h" #include "USB/usb_device.h"
@ -22,6 +21,8 @@
#include "units/fcap/unit_fcap.h" #include "units/fcap/unit_fcap.h"
#include "units/touch/unit_touch.h" #include "units/touch/unit_touch.h"
#include "units/simple_pwm/unit_pwmdim.h" #include "units/simple_pwm/unit_pwmdim.h"
#include "units/dac/unit_dac.h"
#include "comm/interfaces.h"
#include "hw_utils.h" #include "hw_utils.h"
void plat_init_resources(void) void plat_init_resources(void)
@ -258,6 +259,8 @@ void plat_init_resources(void)
*/ */
void plat_usb_reconnect(void) void plat_usb_reconnect(void)
{ {
if (gActiveComport != COMPORT_USB) return;
// TODO add better reset methods available on different chips // TODO add better reset methods available on different chips
USBD_LL_Reset(&hUsbDeviceFS); USBD_LL_Reset(&hUsbDeviceFS);

@ -12,6 +12,7 @@
#include "usb_device.h" #include "usb_device.h"
#include "usbd_msc.h" #include "usbd_msc.h"
#include "task_main.h" #include "task_main.h"
#include "comm/interfaces.h"
/* TaskUsbEvent function */ /* TaskUsbEvent function */
void TaskMain(void const * argument) void TaskMain(void const * argument)
@ -25,14 +26,16 @@ void TaskMain(void const * argument)
Indicator_Effect(STATUS_WELCOME); Indicator_Effect(STATUS_WELCOME);
uint32_t startTime = xTaskGetTickCount(); const uint32_t bootTime = HAL_GetTick();
uint32_t startTime = bootTime;
uint32_t cnt = 1; uint32_t cnt = 1;
bool waiting_for_usb = true;
while(1) { while(1) {
uint32_t msg; uint32_t msg;
xTaskNotifyWait(0, UINT32_MAX, &msg, 100); // time out if nothing happened xTaskNotifyWait(0, UINT32_MAX, &msg, 100); // time out if nothing happened
// periodic updates to the VFS driver // periodic updates to the VFS driver
uint32_t now = xTaskGetTickCount(); uint32_t now = HAL_GetTick();
uint32_t elapsed = now - startTime; uint32_t elapsed = now - startTime;
if (elapsed >= 100) { if (elapsed >= 100) {
// interval 100ms or more - slow periodic // interval 100ms or more - slow periodic
@ -48,6 +51,9 @@ void TaskMain(void const * argument)
Indicator_Heartbeat(); Indicator_Heartbeat();
wd_restart(); 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... // if no message and it just timed out, go wait some more...
@ -61,35 +67,39 @@ void TaskMain(void const * argument)
continue; continue;
} }
// Endpoint 0 - control messages for the different classes if (gActiveComport == COMPORT_USB) {
if (msg & USBEVT_FLAG_EP0_RX_RDY) { // Endpoint 0 - control messages for the different classes
USBD_CDC_EP0_RxReady(&hUsbDeviceFS); 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 #ifndef DISABLE_MSC
// MSC - read/write etc // MSC - read/write etc
if (msg & (USBEVT_FLAG_EPx_IN(MSC_EPIN_ADDR))) { if (msg & (USBEVT_FLAG_EPx_IN(MSC_EPIN_ADDR))) {
USBD_MSC_DataIn(&hUsbDeviceFS, MSC_EPIN_ADDR); USBD_MSC_DataIn(&hUsbDeviceFS, MSC_EPIN_ADDR);
} }
if (msg & (USBEVT_FLAG_EPx_OUT(MSC_EPOUT_ADDR))) { if (msg & (USBEVT_FLAG_EPx_OUT(MSC_EPOUT_ADDR))) {
USBD_MSC_DataOut(&hUsbDeviceFS, MSC_EPOUT_ADDR); USBD_MSC_DataOut(&hUsbDeviceFS, MSC_EPOUT_ADDR);
} }
#endif #endif
// CDC - config packets and data in/out // CDC - config packets and data in/out
// if (msg & (USBEVT_FLAG_EPx_IN(CDC_IN_EP))) { // if (msg & (USBEVT_FLAG_EPx_IN(CDC_IN_EP))) {
// USBD_CDC_DataIn(&hUsbDeviceFS, 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_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);
if (msg & (USBEVT_FLAG_EPx_OUT(CDC_OUT_EP))) {
USBD_CDC_DataOut(&hUsbDeviceFS, CDC_OUT_EP);
}
} }
} }
} }

Loading…
Cancel
Save