application: add UART autodetection (copied from BusVoodoo)
This commit is contained in:
parent
1aa498d5bc
commit
666ae736ef
319
application.c
319
application.c
|
@ -27,6 +27,7 @@
|
||||||
#include <libopencm3/stm32/flash.h> // flash utilities
|
#include <libopencm3/stm32/flash.h> // flash utilities
|
||||||
#include <libopencm3/stm32/adc.h> // ADC utilities
|
#include <libopencm3/stm32/adc.h> // ADC utilities
|
||||||
#include <libopencm3/stm32/timer.h> // timer library
|
#include <libopencm3/stm32/timer.h> // timer library
|
||||||
|
#include <libopencm3/stm32/usart.h> // universal synchronous asynchronous receiver transmitter library
|
||||||
|
|
||||||
/* own libraries */
|
/* own libraries */
|
||||||
#include "global.h" // board definitions
|
#include "global.h" // board definitions
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
#include "usb_cdcacm.h" // USB CDC ACM utilities
|
#include "usb_cdcacm.h" // USB CDC ACM utilities
|
||||||
#include "terminal.h" // handle the terminal interface
|
#include "terminal.h" // handle the terminal interface
|
||||||
#include "menu.h" // menu utilities
|
#include "menu.h" // menu utilities
|
||||||
|
#include "usart_enhanced.h" // USART utilities got frame checking
|
||||||
|
|
||||||
/** watchdog period in ms */
|
/** watchdog period in ms */
|
||||||
#define WATCHDOG_PERIOD 10000
|
#define WATCHDOG_PERIOD 10000
|
||||||
|
@ -561,7 +563,7 @@ void TIM_ISR(FREQUENCY_TIMER)(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** monitor single channel for activity
|
/** monitor single channel for activity and measure frequency
|
||||||
* @param[in] argument channel number
|
* @param[in] argument channel number
|
||||||
*/
|
*/
|
||||||
static void command_monitor_single(void* argument)
|
static void command_monitor_single(void* argument)
|
||||||
|
@ -685,6 +687,7 @@ static void command_monitor_single(void* argument)
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
gpio_set(GPIO_PORT(SHIFT_EN_PIN), GPIO_PIN(SHIFT_EN_PIN)); // remove power from level shifters pull-up
|
gpio_set(GPIO_PORT(SHIFT_EN_PIN), GPIO_PIN(SHIFT_EN_PIN)); // remove power from level shifters pull-up
|
||||||
|
gpio_mode_setup(GPIO_PORT(UART_RX), GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN(UART_RX)); // put pin back to safe floating mode
|
||||||
mux_select(-1); // disable multiplexer
|
mux_select(-1); // disable multiplexer
|
||||||
timer_disable_counter(TIM(MONITOR_TIMER)); // disable timer
|
timer_disable_counter(TIM(MONITOR_TIMER)); // disable timer
|
||||||
rcc_periph_reset_pulse(RST_TIM(MONITOR_TIMER)); // reset timer state
|
rcc_periph_reset_pulse(RST_TIM(MONITOR_TIMER)); // reset timer state
|
||||||
|
@ -698,6 +701,310 @@ static void command_monitor_single(void* argument)
|
||||||
rcc_periph_clock_disable(RCC_TIM(FREQUENCY_TIMER)); // disable clock for timer peripheral
|
rcc_periph_clock_disable(RCC_TIM(FREQUENCY_TIMER)); // disable clock for timer peripheral
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** the possible properties of a UART configuration (to be updated with every character) */
|
||||||
|
struct uart_configuration_t {
|
||||||
|
uint8_t databits; /**< data word size in bits */
|
||||||
|
bool databits_matching; /**< if the data is still matching the data bits */
|
||||||
|
bool parity_even; /**< if the date is still matching the additional even parity bit */
|
||||||
|
bool parity_odd; /**< if the date is still matching the additional odd parity bit */
|
||||||
|
bool parity_mark; /**< if the date is still matching the additional mark parity bit */
|
||||||
|
bool parity_space; /**< if the date is still matching the additional space parity bit */
|
||||||
|
uint8_t parity_possibilities; /**< the number to still matching parity possibilities (number of parity_* at true) */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** reset all matching values of UART configuration
|
||||||
|
* @param[out] configuration UART configuration to reset
|
||||||
|
*/
|
||||||
|
static void uart_configuration_reset(struct uart_configuration_t* configuration)
|
||||||
|
{
|
||||||
|
configuration->databits_matching = true;
|
||||||
|
configuration->parity_even = true;
|
||||||
|
configuration->parity_odd = true;
|
||||||
|
configuration->parity_mark = true;
|
||||||
|
configuration->parity_space = true;
|
||||||
|
configuration->parity_possibilities = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** autodetect UART configuration on single channel
|
||||||
|
* @param[in] argument channel number
|
||||||
|
*/
|
||||||
|
static void command_uart_autodetect(void* argument)
|
||||||
|
{
|
||||||
|
(void)argument; // we won't use the argument
|
||||||
|
|
||||||
|
// get input channel
|
||||||
|
if (NULL == argument) {
|
||||||
|
puts("provide channel to monitor for UART activity\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const uint32_t channel = *(uint32_t*)argument; // get channel argument
|
||||||
|
if (!(channel < CHANNEL_NUMBERS)) { // verify argument
|
||||||
|
printf("channel %u out of range (0-%u)\n", channel, CHANNEL_NUMBERS - 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify target voltage is OK
|
||||||
|
const float* voltages = measure_voltages(); // get target voltage
|
||||||
|
if (voltages[1] < 1.5) {
|
||||||
|
puts("target voltage too low: ");
|
||||||
|
print_fpu(voltages[1], 2);
|
||||||
|
puts(" < 1.5V\n");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
puts("target voltage: ");
|
||||||
|
print_fpu(voltages[1], 2);
|
||||||
|
puts("V\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup USART to receive character
|
||||||
|
uint8_t uart_databits = 8; // start with 8 bits since this is the most common case (i.e. no additional parity bit is used)
|
||||||
|
rcc_periph_clock_enable(RCC_USART(UART_ID)); // enable USART peripheral
|
||||||
|
rcc_periph_reset_pulse(RST_USART(FREQUENCY_TIMER)); // reset USART peripheral
|
||||||
|
usart_set_baudrate(USART(UART_ID), 1200); // configure UART to slowest baud rate
|
||||||
|
usart_set_databits(USART(UART_ID), uart_databits); // configure UART to pre-selected data-bits
|
||||||
|
usart_set_stopbits(USART(UART_ID), USART_STOPBITS_1); // 1 stop-bits also complies to 2 stop-bits
|
||||||
|
usart_set_parity(USART(UART_ID), USART_PARITY_NONE); // get the raw data since we will do the parity check ourselves
|
||||||
|
usart_set_mode(USART(UART_ID), USART_MODE_RX); // we will only receive data
|
||||||
|
USART_CR3(USART(UART_ID)) |= USART_CR3_HDSEL; // we will use the half-duplex mode to use the TX pin as RX
|
||||||
|
// USART will be enabled by the autodetection loop
|
||||||
|
|
||||||
|
// select channel
|
||||||
|
rcc_periph_clock_enable(GPIO_RCC(UART_RX)); // enable clock for USART RX pin port peripheral
|
||||||
|
gpio_mode_setup(GPIO_PORT(UART_RX), GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN(UART_RX)); // use as input for the timer (it is pulled up by level shifter)
|
||||||
|
gpio_set_af(GPIO_PORT(UART_RX), FREQUENCY_AF, GPIO_PIN(UART_RX)); // set alternate function to timer channel
|
||||||
|
rcc_periph_clock_enable(GPIO_RCC(UART_TX)); // enable clock for USART TX pin port peripheral
|
||||||
|
gpio_mode_setup(GPIO_PORT(UART_TX), GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN(UART_TX)); // use pin for UART data (normally output, but in half duplex it can become input)
|
||||||
|
gpio_set_af(GPIO_PORT(UART_TX), UART_AF, GPIO_PIN(UART_TX)); // set alternate function to UART
|
||||||
|
mux_select(channel); // select channel
|
||||||
|
gpio_clear(GPIO_PORT(SHIFT_EN_PIN), GPIO_PIN(SHIFT_EN_PIN)); // connect target voltage to level shifters pull-up
|
||||||
|
|
||||||
|
// show help
|
||||||
|
printf("CH%02u is pulled to target voltage by 10 kOhm\n", channel);
|
||||||
|
puts("high = 1.5-5.5V, data is shown as decoded\n");
|
||||||
|
puts("UART configuration autodetection improves with incoming data\n");
|
||||||
|
puts("press any key to stop autodetection\n");
|
||||||
|
|
||||||
|
// setup timer to measure frequency
|
||||||
|
rcc_periph_clock_enable(RCC_TIM(FREQUENCY_TIMER)); // enable clock for timer peripheral
|
||||||
|
rcc_periph_reset_pulse(RST_TIM(FREQUENCY_TIMER)); // reset timer state
|
||||||
|
timer_disable_counter(TIM(FREQUENCY_TIMER)); // disable timer to configure it
|
||||||
|
timer_set_mode(TIM(FREQUENCY_TIMER), TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); // set timer mode, use undivided timer clock, edge alignment (simple count), and count up
|
||||||
|
timer_set_prescaler(TIM(FREQUENCY_TIMER), 0); // don't use prescale so to get the most precise measurement
|
||||||
|
timer_ic_set_input(TIM(FREQUENCY_TIMER), TIM_IC(FREQUENCY_CHANNEL), TIM_IC_IN_TI(FREQUENCY_CHANNEL)); // configure the input capture ICx to use the right channel TIn
|
||||||
|
timer_ic_set_filter(TIM(FREQUENCY_TIMER), TIM_IC(FREQUENCY_CHANNEL), TIM_IC_OFF); // use no filter input to keep precise timing
|
||||||
|
timer_ic_set_polarity(TIM(FREQUENCY_TIMER), TIM_IC(FREQUENCY_CHANNEL), TIM_IC_FALLING); // capture on falling edge
|
||||||
|
timer_ic_set_prescaler(TIM(FREQUENCY_TIMER), TIM_IC(FREQUENCY_CHANNEL), TIM_IC_PSC_OFF); // don't use any prescaler since we want to capture every pulse
|
||||||
|
timer_ic_enable(TIM(FREQUENCY_TIMER), TIM_IC(FREQUENCY_CHANNEL)); // enable capture interrupt
|
||||||
|
timer_clear_flag(TIM(FREQUENCY_TIMER), TIM_SR_CCIF(FREQUENCY_CHANNEL)); // clear input compare flag
|
||||||
|
timer_enable_irq(TIM(FREQUENCY_TIMER), TIM_DIER_CCIE(FREQUENCY_CHANNEL)); // enable capture interrupt
|
||||||
|
timer_update_on_overflow(TIM(FREQUENCY_TIMER)); // only use counter overflow as UEV source (use overflow to measure longer times)
|
||||||
|
timer_clear_flag(TIM(FREQUENCY_TIMER), TIM_SR_UIF); // clear overflow flag
|
||||||
|
timer_enable_irq(TIM(FREQUENCY_TIMER), TIM_DIER_UIE); // enable update interrupt for timer
|
||||||
|
nvic_enable_irq(NVIC_TIM_IRQ(FREQUENCY_TIMER)); // catch interrupts for this timer
|
||||||
|
pulse_duration = UINT32_MAX; // reset pulse duration
|
||||||
|
timer_enable_counter(TIM(FREQUENCY_TIMER)); // enable timer
|
||||||
|
|
||||||
|
// start autodetection
|
||||||
|
bool reset_state = true; // flag to know if we need to reset the states
|
||||||
|
uint8_t rx_errors; // number of UART receive errors received
|
||||||
|
bool wait_for_idle = false; // flag to wait for an IDLE frame
|
||||||
|
/** the possible UART configurations
|
||||||
|
* @note since the first valid configuration will be chosen, order in decreasing probability of being valid and decreasing probability or getting invalidated */
|
||||||
|
struct uart_configuration_t uart_configurations[] = {
|
||||||
|
{ .databits = 5 },
|
||||||
|
{ .databits = 6 },
|
||||||
|
{ .databits = 8 },
|
||||||
|
{ .databits = 7 },
|
||||||
|
};
|
||||||
|
uint8_t uart_configuration_valid = LENGTH(uart_configurations); // current best valid UART configuration index
|
||||||
|
char uart_configuration_parity = '?'; // current best valid UART parity
|
||||||
|
const uint32_t baudrates[] = { 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 576000, 921600, 1000000 }; // list of standard baud rates, to match with measured frequency
|
||||||
|
uint32_t uart_baudrate = 0; // fastest found baud rate
|
||||||
|
while (!user_input_available) { // run until user breaks it
|
||||||
|
// time to do periodic checks
|
||||||
|
if (wakeup_flag || second_flag) {
|
||||||
|
iwdg_reset(); // kick the dog
|
||||||
|
wakeup_flag = false; // clear flag
|
||||||
|
second_flag = false; // clear flag
|
||||||
|
}
|
||||||
|
if (reset_state) { // reset the configuration
|
||||||
|
rx_errors = 0;
|
||||||
|
for (uint8_t i = 0; i < LENGTH(uart_configurations); i++) {
|
||||||
|
uart_configuration_reset(&uart_configurations[i]);
|
||||||
|
}
|
||||||
|
usart_recv(USART(UART_ID)); // clear input buffer and allow flag to be set
|
||||||
|
usart_enable(USART(UART_ID)); // ensure UART is enabled
|
||||||
|
reset_state = false;
|
||||||
|
}
|
||||||
|
if (pulse_flag) { // new pulse duration has been measured
|
||||||
|
pulse_flag = false; // clear flag
|
||||||
|
uint32_t baudrate = rcc_ahb_frequency / (pulse_duration / 2); // calculate baud rate based on measured timing
|
||||||
|
if (baudrate > uart_baudrate + 100) { // new higher baud rate detected
|
||||||
|
uart_baudrate = baudrate; // save new baud rate
|
||||||
|
if (uart_baudrate >= 1200) { // ensure minimum hardware supported baud rate is respected
|
||||||
|
// search for closest standard baud rate
|
||||||
|
uint32_t standard_baudrate = 0;
|
||||||
|
for (uint8_t i = 0; i < LENGTH(baudrates); i++) {
|
||||||
|
if (uart_baudrate >= baudrates[i] * 0.9 && uart_baudrate <= baudrates[i] * 1.1) { // measured baud rate matches standard baud rate within factor
|
||||||
|
standard_baudrate = baudrates[i]; // remember matching baud rate
|
||||||
|
break; // stop searching for matching baud rate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (standard_baudrate) { // matching standard baud rate found
|
||||||
|
uart_baudrate = standard_baudrate; // save matching baud rate
|
||||||
|
}
|
||||||
|
usart_disable(USART(UART_ID)); // disable UART before reconfiguring
|
||||||
|
usart_set_baudrate(USART(UART_ID), uart_baudrate); // set new baud rate
|
||||||
|
reset_state = true; // reset the states since we set a new baud rate
|
||||||
|
printf("\nnew baud rate: %u bps\n", uart_baudrate); // show measurement frequency
|
||||||
|
} else {
|
||||||
|
printf("\ndetected %u bps baud rate is lower than minimum supported 1200 bps\n", baudrate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (USART_SR(USART(UART_ID)) & (USART_SR_NE|USART_SR_FE)) { // error on UART received
|
||||||
|
usart_recv(USART(UART_ID)); // clear input buffer and flags
|
||||||
|
rx_errors++; // increment number of errors
|
||||||
|
if (rx_errors >= 5) { // the format seems wrong
|
||||||
|
// the threshold must be high enough so the UART peripheral has enough opportunities to synchronize to the start bit (just after an idle frame)
|
||||||
|
// too high frame error causes:
|
||||||
|
// - when set to 9 data-bits with high speed 8 data-bits traffic incoming: the next start bit comes right after the stop bit of and 8-bit frame, which is interpreted as faulty 9 data-bits frame stop bit
|
||||||
|
// - when set to 8 data-bits with 9 data-bits (8+1 parity) traffic incoming: the low parity bit is interpreted as faulty stop-bit
|
||||||
|
uart_databits = ((8 == uart_databits) ? 9 : 8); // switch between 8 and 9-bit packets
|
||||||
|
usart_disable(USART(UART_ID)); // disable UART before reconfiguring
|
||||||
|
usart_set_databits(USART(UART_ID), uart_databits); // set new data width
|
||||||
|
reset_state = true;
|
||||||
|
pulse_duration = UINT32_MAX; // also reset the baud rate
|
||||||
|
uart_baudrate = 0; // also reset the baud rate
|
||||||
|
rx_errors = 0; // reset error counter
|
||||||
|
printf("\nrestarting guessing because detected too many errors\n");
|
||||||
|
} else {
|
||||||
|
wait_for_idle = true; // wait form an IDLE frame so to better sync to the next start bit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wait_for_idle) {
|
||||||
|
/* we have to check the IDLE flag in the main loop instead of just looping over the flag because a hardware fault could prevent it from being set.
|
||||||
|
*/
|
||||||
|
if (USART(UART_ID) | USART_SR_IDLE) { // idle flag set
|
||||||
|
wait_for_idle = false; // no need to wait anymore
|
||||||
|
}
|
||||||
|
if (USART_SR(USART(UART_ID)) | USART_SR_RXNE) { // data is available
|
||||||
|
USART_DR(USART(UART_ID)); // empty receive buffer so the IDLE flag can retrigger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (USART_SR(USART(UART_ID)) & USART_SR_RXNE) { // data received
|
||||||
|
const uint16_t usart_data = usart_recv(USART(UART_ID)); // save received data (also clears flag)
|
||||||
|
if (0 == uart_baudrate) { // we did not find any valid baud rate yet
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const uint16_t usart_data_padded = ((8 == uart_databits) ? usart_data | 0xff00 : usart_data | 0xfe00); // pad with 1 (stop bit/idle state) for better word size detection
|
||||||
|
const uint16_t usart_data_relevant = usart_data & ~(0xffff << uart_configurations[uart_configuration_valid].databits); // get only the data bits
|
||||||
|
// verify parity and word size
|
||||||
|
for (uint8_t i = 0; i < LENGTH(uart_configurations); i++) {
|
||||||
|
// skip check if we already know the word size is wrong
|
||||||
|
if (!uart_configurations[i].databits_matching) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// do parity checks
|
||||||
|
if (uart_configurations[i].parity_even) {
|
||||||
|
uart_configurations[i].parity_even &= usart_enhanced_even_parity_lut[usart_data_relevant];
|
||||||
|
}
|
||||||
|
if (uart_configurations[i].parity_odd) {
|
||||||
|
uart_configurations[i].parity_odd &= !usart_enhanced_even_parity_lut[usart_data_relevant];
|
||||||
|
}
|
||||||
|
if (uart_configurations[i].parity_mark) {
|
||||||
|
uart_configurations[i].parity_mark &= (usart_data_padded & (1 << uart_configurations[i].databits));
|
||||||
|
}
|
||||||
|
if (uart_configurations[i].parity_space) {
|
||||||
|
uart_configurations[i].parity_space &= !(usart_data_padded & (1 << uart_configurations[i].databits));
|
||||||
|
}
|
||||||
|
// update parity count
|
||||||
|
uart_configurations[i].parity_possibilities = 0;
|
||||||
|
if (uart_configurations[i].parity_even) {
|
||||||
|
uart_configurations[i].parity_possibilities++;
|
||||||
|
}
|
||||||
|
if (uart_configurations[i].parity_odd) {
|
||||||
|
uart_configurations[i].parity_possibilities++;
|
||||||
|
}
|
||||||
|
if (uart_configurations[i].parity_mark) {
|
||||||
|
uart_configurations[i].parity_possibilities++;
|
||||||
|
}
|
||||||
|
if (uart_configurations[i].parity_space) {
|
||||||
|
uart_configurations[i].parity_possibilities++;
|
||||||
|
}
|
||||||
|
// verify word size
|
||||||
|
const uint16_t databits_mask = (0xffff << (uart_configurations[i].databits + ((0 == uart_configurations[i].parity_possibilities) ? 0 : 1))); // mask for bits which should not be cleared
|
||||||
|
if (~usart_data_padded & databits_mask) { // see if bit outside the word size are cleared
|
||||||
|
uart_configurations[i].databits_matching = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool no_valid_configuration = true;
|
||||||
|
uint8_t new_valid_configuration = LENGTH(uart_configurations);
|
||||||
|
char parity = '?';
|
||||||
|
for (uint8_t i = 0; i < LENGTH(uart_configurations); i++) {
|
||||||
|
// skip check the word size is wrong
|
||||||
|
if (!uart_configurations[i].databits_matching) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
no_valid_configuration = false;
|
||||||
|
if (uart_configurations[i].parity_possibilities > 1) { // parity is not yet clear
|
||||||
|
continue;
|
||||||
|
} else if (uart_configurations[i].parity_even) {
|
||||||
|
parity = 'E';
|
||||||
|
} else if (uart_configurations[i].parity_odd) {
|
||||||
|
parity = 'O';
|
||||||
|
} else if (uart_configurations[i].parity_mark) {
|
||||||
|
parity = 'M';
|
||||||
|
} else if (uart_configurations[i].parity_space) {
|
||||||
|
parity = 'S';
|
||||||
|
} else if (0==uart_configurations[i].parity_possibilities) {
|
||||||
|
parity = 'N';
|
||||||
|
}
|
||||||
|
new_valid_configuration = i;
|
||||||
|
break; // stop searching since we found a configuration
|
||||||
|
}
|
||||||
|
if (no_valid_configuration) {
|
||||||
|
reset_state = true; // reset the configurations
|
||||||
|
pulse_duration = UINT32_MAX; // also reset the baud rate
|
||||||
|
uart_baudrate = 0; // also reset the baud rate
|
||||||
|
} else if (new_valid_configuration < LENGTH(uart_configurations) && '?' != parity && (new_valid_configuration != uart_configuration_valid || parity != uart_configuration_parity)) { // we found a new valid configuration
|
||||||
|
uart_configuration_valid = new_valid_configuration;
|
||||||
|
uart_configuration_parity = parity;
|
||||||
|
printf("\nnew UART configuration found: %u %u%c1\n", uart_baudrate, uart_configurations[uart_configuration_valid].databits, uart_configuration_parity);
|
||||||
|
}
|
||||||
|
// print received data if a configuration has been found
|
||||||
|
if (uart_configuration_valid < LENGTH(uart_configurations)) { // valid configuration existing
|
||||||
|
if (uart_configurations[uart_configuration_valid].databits >= 7 && usart_data_relevant < 0x80) { // this is probably valid ASCII data
|
||||||
|
putc(usart_data_relevant);
|
||||||
|
} else {
|
||||||
|
printf("0x%02x ", usart_data_relevant);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("0b%09b\n", usart_data_relevant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
user_input_get(); // clean input
|
||||||
|
|
||||||
|
// clean up
|
||||||
|
gpio_set(GPIO_PORT(SHIFT_EN_PIN), GPIO_PIN(SHIFT_EN_PIN)); // remove power from level shifters pull-up
|
||||||
|
gpio_mode_setup(GPIO_PORT(UART_RX), GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN(UART_RX)); // put pin back to safe floating mode
|
||||||
|
gpio_mode_setup(GPIO_PORT(UART_TX), GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN(UART_TX)); // put pin back to safe floating mode
|
||||||
|
mux_select(-1); // disable multiplexer
|
||||||
|
timer_disable_counter(TIM(MONITOR_TIMER)); // disable timer
|
||||||
|
rcc_periph_reset_pulse(RST_TIM(MONITOR_TIMER)); // reset timer state
|
||||||
|
rcc_periph_clock_disable(RCC_TIM(MONITOR_TIMER)); // disable clock for timer peripheral
|
||||||
|
timer_disable_counter(TIM(FREQUENCY_TIMER)); // disable timer
|
||||||
|
nvic_disable_irq(NVIC_TIM_IRQ(FREQUENCY_TIMER)); // catch interrupts for this timer
|
||||||
|
timer_disable_irq(TIM(FREQUENCY_TIMER), TIM_DIER_UIE); // disable update interrupt for timer
|
||||||
|
timer_disable_irq(TIM(FREQUENCY_TIMER), TIM_DIER_CCIE(FREQUENCY_CHANNEL)); // disable capture interrupt
|
||||||
|
timer_ic_disable(TIM(FREQUENCY_TIMER), TIM_IC(FREQUENCY_CHANNEL)); // disable capture interrupt
|
||||||
|
rcc_periph_reset_pulse(RST_TIM(FREQUENCY_TIMER)); // reset timer state
|
||||||
|
rcc_periph_clock_disable(RCC_TIM(FREQUENCY_TIMER)); // disable clock for timer peripheral
|
||||||
|
rcc_periph_reset_pulse(RST_USART(UART_ID)); // reset USART peripheral
|
||||||
|
rcc_periph_clock_disable(RCC_USART(UART_ID)); // disable clock for USART peripheral
|
||||||
|
}
|
||||||
|
|
||||||
/** set first channel of range to scan
|
/** set first channel of range to scan
|
||||||
* @param[in] argument optional pointer to first channel number
|
* @param[in] argument optional pointer to first channel number
|
||||||
*/
|
*/
|
||||||
|
@ -889,9 +1196,17 @@ static const struct menu_command_t menu_commands[] = {
|
||||||
.name = "monitor_single",
|
.name = "monitor_single",
|
||||||
.command_description = "monitor single channel activity",
|
.command_description = "monitor single channel activity",
|
||||||
.argument = MENU_ARGUMENT_UNSIGNED,
|
.argument = MENU_ARGUMENT_UNSIGNED,
|
||||||
.argument_description = "channel",
|
.argument_description = "CH",
|
||||||
.command_handler = &command_monitor_single,
|
.command_handler = &command_monitor_single,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.shortcut = 'a',
|
||||||
|
.name = "uart_auto",
|
||||||
|
.command_description = "autodetect UART configuration",
|
||||||
|
.argument = MENU_ARGUMENT_UNSIGNED,
|
||||||
|
.argument_description = "CH",
|
||||||
|
.command_handler = &command_uart_autodetect,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.shortcut = 'c',
|
.shortcut = 'c',
|
||||||
.name = "start",
|
.name = "start",
|
||||||
|
|
Loading…
Reference in New Issue