Fix serial
This commit is contained in:
parent
fed186a49f
commit
a1dc923315
14 changed files with 447 additions and 41 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -19,3 +19,6 @@
|
|||
[submodule "controller/fw/crypto-algorithms"]
|
||||
path = controller/fw/crypto-algorithms
|
||||
url = https://github.com/B-Con/crypto-algorithms
|
||||
[submodule "controller/fw/tinyprintf"]
|
||||
path = controller/fw/tinyprintf
|
||||
url = https://github.com/cjlano/tinyprintf
|
||||
|
|
|
|||
|
|
@ -42,8 +42,18 @@ PRESIG_KEYFILE ?= presig_test_key.secret
|
|||
# Sources
|
||||
########################################################################################################################
|
||||
|
||||
C_SOURCES := src/main.c src/mspdebug_wrapper.c src/spi_flash.c src/freq_meas.c src/dsss_demod.c src/adc.c \
|
||||
src/protocol.c
|
||||
C_SOURCES := src/main.c
|
||||
C_SOURCES += src/mspdebug_wrapper.c
|
||||
C_SOURCES += src/spi_flash.c
|
||||
C_SOURCES += src/freq_meas.c
|
||||
C_SOURCES += src/dsss_demod.c
|
||||
C_SOURCES += src/adc.c
|
||||
C_SOURCES += src/protocol.c
|
||||
C_SOURCES += src/serial.c
|
||||
C_SOURCES += src/con_usart.c
|
||||
C_SOURCES += src/dma_util.c
|
||||
C_SOURCES += tinyprintf/tinyprintf.c
|
||||
|
||||
C_SOURCES += $(MSPDEBUG_DIR)/drivers/jtaglib.c
|
||||
|
||||
CMSIS_SOURCES += $(CMSIS_DIR)/CMSIS/DSP/Source/TransformFunctions/arm_rfft_fast_init_f32.c
|
||||
|
|
@ -121,6 +131,7 @@ SYSTEM_FLAGS ?= -nostdlib -ffreestanding -nostartfiles
|
|||
COMMON_CFLAGS += -Imspdebug/util -Imspdebug/drivers -Ilevmarq
|
||||
COMMON_CFLAGS += -I$(CMSIS_DIR_ABS)/CMSIS/DSP/Include -I$(CMSIS_DIR_ABS)/CMSIS/Core/Include
|
||||
CFLAGS += -I$(abspath musl_include_shims)
|
||||
CFLAGS += -Itinyprintf
|
||||
COMMON_CFLAGS += -I$(BUILDDIR) -Isrc -Itinyaes
|
||||
CFLAGS += -I$(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32F4xx/Include
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stm32f407xx.h>
|
||||
#include <stm32f4_isr.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "adc.h"
|
||||
#include "sr_global.h"
|
||||
|
|
@ -58,9 +57,10 @@ void adc_init() {
|
|||
TIM1->CR2 = (2<<TIM_CR2_MMS_Pos); /* Enable update event on TRGO to provide a 1ms reference to rest of system */
|
||||
TIM1->CCMR1 = (6<<TIM_CCMR1_OC1M_Pos) | (0<<TIM_CCMR1_CC1S_Pos);
|
||||
TIM1->CCER = TIM_CCER_CC1E;
|
||||
TIM1->PSC = 84-1; /* 1us ticks @ f_APB2=84MHz */
|
||||
TIM1->ARR = 1000-1; /* 1ms period */
|
||||
TIM1->CCR1 = 500-1;
|
||||
assert(apb2_timer_speed%1000000 == 0);
|
||||
TIM1->PSC = 1000-1;
|
||||
TIM1->ARR = (apb2_timer_speed/1000000)-1; /* 1ms period */
|
||||
TIM1->CCR1 = 1;
|
||||
TIM1->BDTR = TIM_BDTR_MOE;
|
||||
|
||||
/* DEBUG */
|
||||
|
|
@ -85,14 +85,12 @@ void TIM1_CC_IRQHandler(void) {
|
|||
|
||||
void DMA2_Stream0_IRQHandler(void) {
|
||||
uint8_t isr = (DMA2->LISR >> DMA_LISR_FEIF0_Pos) & 0x3f;
|
||||
|
||||
GPIOA->ODR ^= 1<<7;
|
||||
GPIOA->BSRR = 1<<10;
|
||||
GPIOA->BSRR = 1<<11;
|
||||
|
||||
if (isr & DMA_LISR_TCIF0) { /* Transfer complete */
|
||||
/* Check we're done processing the old buffer */
|
||||
if (adc_fft_buf_ready_idx != -1) { /* FIXME DEBUG */
|
||||
GPIOA->BSRR = 1<<10<<16;
|
||||
GPIOA->BSRR = 1<<11<<16;
|
||||
/* clear all flags */
|
||||
adc_dma->LIFCR = isr<<DMA_LISR_FEIF0_Pos;
|
||||
return;
|
||||
|
|
@ -110,7 +108,7 @@ void DMA2_Stream0_IRQHandler(void) {
|
|||
if (isr & DMA_LISR_TEIF0) /* Transfer error */
|
||||
panic();
|
||||
|
||||
GPIOA->BSRR = 1<<10<<16;
|
||||
GPIOA->BSRR = 1<<11<<16;
|
||||
/* clear all flags */
|
||||
adc_dma->LIFCR = isr<<DMA_LISR_FEIF0_Pos;
|
||||
}
|
||||
|
|
|
|||
33
controller/fw/src/con_usart.c
Normal file
33
controller/fw/src/con_usart.c
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
#include <stm32f4_isr.h>
|
||||
#include "con_usart.h"
|
||||
|
||||
volatile struct usart_desc con_usart = {
|
||||
.le_usart = USART1,
|
||||
.le_usart_irqn = USART1_IRQn,
|
||||
.tx_dmas = DMA2_Stream7,
|
||||
.tx_dma_sn = 7,
|
||||
.tx_dma_ch = 4,
|
||||
.tx_dma = DMA2,
|
||||
.tx_dma_irqn = DMA2_Stream7_IRQn,
|
||||
};
|
||||
|
||||
void con_usart_init() {
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_DMA2EN;
|
||||
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
|
||||
|
||||
/* GPIO config: A9 (TX), A10 (RX) */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODER9_Msk & ~GPIO_MODER_MODER10_Msk;
|
||||
GPIOA->MODER |= (2<<GPIO_MODER_MODER9_Pos) | (2<<GPIO_MODER_MODER10_Pos);
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED9_Msk & ~GPIO_OSPEEDR_OSPEED10_Msk;
|
||||
GPIOA->OSPEEDR |= (2<<GPIO_OSPEEDR_OSPEED9_Pos) | (2<<GPIO_OSPEEDR_OSPEED10_Pos);
|
||||
GPIOA->AFR[1] &= ~GPIO_AFRH_AFSEL9_Msk & ~GPIO_AFRH_AFSEL10_Msk;
|
||||
GPIOA->AFR[1] |= (7<<GPIO_AFRH_AFSEL9_Pos) | (7<<GPIO_AFRH_AFSEL10_Pos);
|
||||
|
||||
usart_dma_init(&con_usart, CON_USART_BAUDRATE);
|
||||
}
|
||||
|
||||
void DMA2_Stream7_IRQHandler(void) {
|
||||
usart_dma_stream_irq(&con_usart);
|
||||
}
|
||||
|
||||
16
controller/fw/src/con_usart.h
Normal file
16
controller/fw/src/con_usart.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef __CON_USART_H__
|
||||
#define __CON_USART_H__
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
extern volatile struct usart_desc con_usart;
|
||||
|
||||
#define con_printf(...) usart_printf(&con_usart, __VA_ARGS__)
|
||||
|
||||
#ifndef CON_USART_BAUDRATE
|
||||
#define CON_USART_BAUDRATE 115200
|
||||
#endif
|
||||
|
||||
void con_usart_init(void);
|
||||
|
||||
#endif /* __CON_USART_H__ */
|
||||
46
controller/fw/src/dma_util.c
Normal file
46
controller/fw/src/dma_util.c
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
#include "dma_util.h"
|
||||
|
||||
uint8_t dma_get_isr_and_clear(DMA_TypeDef *dma, int ch) {
|
||||
uint8_t isr_val;
|
||||
switch(ch) {
|
||||
case 0:
|
||||
isr_val = dma->LISR & 0x3f;
|
||||
dma->LIFCR = isr_val;
|
||||
return isr_val;
|
||||
case 1:
|
||||
isr_val = dma->LISR>>6 & 0x3f;
|
||||
dma->LIFCR = isr_val<<6;
|
||||
return isr_val;
|
||||
case 2:
|
||||
isr_val = dma->LISR>>16 & 0x3f;
|
||||
dma->LIFCR = isr_val<<16;
|
||||
return isr_val;
|
||||
case 3:
|
||||
isr_val = dma->LISR>>6>>16 & 0x3f;
|
||||
dma->LIFCR = isr_val<<6<<16;
|
||||
return isr_val;
|
||||
case 4:
|
||||
isr_val = dma->HISR & 0x3f;
|
||||
dma->HIFCR = isr_val;
|
||||
return isr_val;
|
||||
case 5:
|
||||
isr_val = dma->HISR>>6 & 0x3f;
|
||||
dma->HIFCR = isr_val<<6;
|
||||
return isr_val;
|
||||
case 6:
|
||||
isr_val = dma->HISR>>16 & 0x3f;
|
||||
dma->HIFCR = isr_val<<16;
|
||||
return isr_val;
|
||||
case 7:
|
||||
isr_val = dma->HISR>>6>>16 & 0x3f;
|
||||
dma->HIFCR = isr_val<<6<<16;
|
||||
return isr_val;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
10
controller/fw/src/dma_util.h
Normal file
10
controller/fw/src/dma_util.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef __DMA_UTIL_H__
|
||||
#define __DMA_UTIL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sr_global.h"
|
||||
|
||||
uint8_t dma_get_isr_and_clear(DMA_TypeDef *dma, int ch);
|
||||
|
||||
#endif /* __DMA_UTIL_H__ */
|
||||
|
|
@ -136,7 +136,13 @@ int adc_buf_measure_freq(uint16_t adc_buf[FMEAS_FFT_LEN], float *out) {
|
|||
|
||||
DEBUG_PRINT("done.");
|
||||
*/
|
||||
*out = (par[1] + first_bin) * binsize_hz;
|
||||
float res = (par[1] + first_bin) * binsize_hz;
|
||||
if (res < 5 || res > 150) {
|
||||
*out = NAN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,15 +6,25 @@
|
|||
#include <math.h>
|
||||
|
||||
#include <stm32f407xx.h>
|
||||
#include <stm32f4_isr.h>
|
||||
|
||||
#include "sr_global.h"
|
||||
#include "adc.h"
|
||||
#include "spi_flash.h"
|
||||
#include "freq_meas.h"
|
||||
#include "dsss_demod.h"
|
||||
#include "con_usart.h"
|
||||
|
||||
static struct spi_flash_if spif;
|
||||
|
||||
unsigned int sysclk_speed = 0;
|
||||
unsigned int apb1_speed = 0;
|
||||
unsigned int apb2_speed = 0;
|
||||
unsigned int auxclk_speed = 0;
|
||||
unsigned int apb1_timer_speed = 0;
|
||||
unsigned int apb2_timer_speed = 0;
|
||||
|
||||
struct leds leds;
|
||||
|
||||
void __libc_init_array(void) { /* we don't need this. */ }
|
||||
void __assert_func (unused_a const char *file, unused_a int line, unused_a const char *function, unused_a const char *expr) {
|
||||
|
|
@ -24,14 +34,14 @@ void __assert_func (unused_a const char *file, unused_a int line, unused_a const
|
|||
|
||||
static void clock_setup(void)
|
||||
{
|
||||
/* 8MHz HSE clock as PLL source.
|
||||
*
|
||||
* Divide by 8 -> 1 MHz */
|
||||
/* 8MHz HSE clock as PLL source. */
|
||||
#define HSE_SPEED 8000000
|
||||
/* Divide by 8 -> 1 MHz */
|
||||
#define PLL_M 8
|
||||
/* Multiply by 336 -> 336 MHz VCO frequency */
|
||||
#define PLL_N 336
|
||||
/* Divide by 4 -> 84 MHz (max freq for our chip) */
|
||||
#define PLL_P 4
|
||||
#define PLL_P 2
|
||||
/* Aux clock for USB OTG, SDIO, RNG: divide VCO frequency (336 MHz) by 7 -> 48 MHz (required by USB OTG) */
|
||||
#define PLL_Q 7
|
||||
|
||||
|
|
@ -54,10 +64,10 @@ static void clock_setup(void)
|
|||
|
||||
/* set AHB prescaler to /1 (CFGR:bits 7:4) */
|
||||
RCC->CFGR |= (0 << RCC_CFGR_HPRE_Pos);
|
||||
/* set ABP1 prescaler to 2 -> 42MHz */
|
||||
RCC->CFGR |= (4 << RCC_CFGR_PPRE1_Pos);
|
||||
/* set ABP2 prescaler to 1 -> 84MHz */
|
||||
RCC->CFGR |= (0 << RCC_CFGR_PPRE2_Pos);
|
||||
/* set ABP1 prescaler to 4 -> 42MHz */
|
||||
RCC->CFGR |= (5 << RCC_CFGR_PPRE1_Pos);
|
||||
/* set ABP2 prescaler to 2 -> 84MHz */
|
||||
RCC->CFGR |= (4 << RCC_CFGR_PPRE2_Pos);
|
||||
|
||||
if (RCC->CR & RCC_CR_PLLON)
|
||||
asm volatile ("bkpt");
|
||||
|
|
@ -79,6 +89,13 @@ static void clock_setup(void)
|
|||
| RCC_PLLCFGR_PLLSRC; /* select HSE as PLL source */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
sysclk_speed = HSE_SPEED / PLL_M * PLL_N / PLL_P;
|
||||
auxclk_speed = HSE_SPEED / PLL_M * PLL_N / PLL_Q;
|
||||
apb1_speed = sysclk_speed / 4;
|
||||
apb1_timer_speed = apb1_speed * 2;
|
||||
apb2_speed = sysclk_speed / 2;
|
||||
apb2_timer_speed = apb2_speed * 2;
|
||||
|
||||
/* Wait for main PLL */
|
||||
while(!(RCC->CR & RCC_CR_PLLRDY))
|
||||
;
|
||||
|
|
@ -170,7 +187,7 @@ int main(void)
|
|||
GPIOC->MODER &= ~GPIO_MODER_MODER9_Msk;
|
||||
GPIOC->MODER |= (2<<GPIO_MODER_MODER9_Pos);
|
||||
GPIOC->AFR[1] &= ~GPIO_AFRH_AFSEL9_Msk;
|
||||
GPIOC->OSPEEDR |= (3<<GPIO_OSPEEDR_OSPEED9_Pos); /* SCK */
|
||||
GPIOC->OSPEEDR |= (3<<GPIO_OSPEEDR_OSPEED9_Pos);
|
||||
RCC->CFGR |= (6<<RCC_CFGR_MCO2PRE_Pos) | (3<<RCC_CFGR_MCO2_Pos);
|
||||
#endif
|
||||
|
||||
|
|
@ -179,6 +196,9 @@ int main(void)
|
|||
}
|
||||
|
||||
clock_setup();
|
||||
con_usart_init();
|
||||
con_printf("\033[2J\033[HBooting...\r\n");
|
||||
|
||||
led_setup();
|
||||
spi_flash_setup();
|
||||
adc_init();
|
||||
|
|
@ -190,30 +210,38 @@ int main(void)
|
|||
GPIOA->AFR[1] &= ~GPIO_AFRH_AFSEL8_Msk;
|
||||
GPIOA->AFR[1] |= 1<<GPIO_AFRH_AFSEL8_Pos;
|
||||
|
||||
GPIOA->MODER |= (1<<GPIO_MODER_MODER9_Pos) | (1<<GPIO_MODER_MODER10_Pos) | (1<<GPIO_MODER_MODER11_Pos) |
|
||||
(1<<GPIO_MODER_MODER12_Pos) | (1<<GPIO_MODER_MODER15_Pos);
|
||||
GPIOA->MODER |= (1<<GPIO_MODER_MODER11_Pos) | (1<<GPIO_MODER_MODER12_Pos) | (1<<GPIO_MODER_MODER15_Pos);
|
||||
#endif
|
||||
|
||||
con_printf("Booted.\r\n");
|
||||
while (23) {
|
||||
if (adc_fft_buf_ready_idx != -1) {
|
||||
GPIOA->BSRR = 1<<9;
|
||||
GPIOA->BSRR = 1<<11;
|
||||
adc_fft_buf_ready_idx = !adc_fft_buf_ready_idx; /* DEBUG */
|
||||
memcpy(adc_fft_buf[!adc_fft_buf_ready_idx], adc_fft_buf[adc_fft_buf_ready_idx] + FMEAS_FFT_LEN/2, sizeof(adc_fft_buf[0][0]) * FMEAS_FFT_LEN/2);
|
||||
GPIOA->BSRR = 1<<9<<16;
|
||||
GPIOA->BSRR = 1<<11;
|
||||
GPIOA->BSRR = 1<<11<<16;
|
||||
|
||||
GPIOA->BSRR = 1<<11;
|
||||
float out;
|
||||
if (adc_buf_measure_freq(adc_fft_buf[adc_fft_buf_ready_idx], &out)) {
|
||||
con_printf("%012d: measurement error\r\n", freq_sample_ts);
|
||||
measurement_errors++;
|
||||
GPIOA->BSRR = 1<<7;
|
||||
debug_last_freq = NAN;
|
||||
|
||||
} else {
|
||||
debug_last_freq = out;
|
||||
con_printf("%012d: %2d.%03d Hz\r\n", freq_sample_ts, (int)out, (int)(out * 1000) % 1000);
|
||||
/* frequency ok led */
|
||||
if (48 < out && out < 52)
|
||||
GPIOA->BSRR = 1<<7<<16;
|
||||
else
|
||||
GPIOA->BSRR = 1<<7;
|
||||
|
||||
/*
|
||||
GPIOA->BSRR = 1<<12;
|
||||
dsss_demod_init(&demod_state);
|
||||
dsss_demod_step(&demod_state, out, freq_sample_ts);
|
||||
*/
|
||||
GPIOA->BSRR = 1<<12<<16;
|
||||
}
|
||||
GPIOA->BSRR = 1<<11<<16;
|
||||
|
||||
|
|
@ -226,38 +254,38 @@ int main(void)
|
|||
}
|
||||
|
||||
void NMI_Handler(void) {
|
||||
asm volatile ("bkpt");
|
||||
asm volatile ("bkpt #1");
|
||||
}
|
||||
|
||||
void HardFault_Handler(void) {
|
||||
asm volatile ("bkpt");
|
||||
asm volatile ("bkpt #2");
|
||||
}
|
||||
|
||||
void MemManage_Handler(void) {
|
||||
asm volatile ("bkpt");
|
||||
asm volatile ("bkpt #3");
|
||||
}
|
||||
|
||||
void BusFault_Handler(void) {
|
||||
asm volatile ("bkpt");
|
||||
asm volatile ("bkpt #4");
|
||||
}
|
||||
|
||||
void UsageFault_Handler(void) {
|
||||
asm volatile ("bkpt");
|
||||
asm volatile ("bkpt #5");
|
||||
}
|
||||
|
||||
void SVC_Handler(void) {
|
||||
asm volatile ("bkpt");
|
||||
asm volatile ("bkpt #6");
|
||||
}
|
||||
|
||||
void DebugMon_Handler(void) {
|
||||
asm volatile ("bkpt");
|
||||
asm volatile ("bkpt #7");
|
||||
}
|
||||
|
||||
void PendSV_Handler(void) {
|
||||
asm volatile ("bkpt");
|
||||
asm volatile ("bkpt #8");
|
||||
}
|
||||
|
||||
void SysTick_Handler(void) {
|
||||
asm volatile ("bkpt");
|
||||
asm volatile ("bkpt #9");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
|
||||
#include "sr_global.h"
|
||||
#include "dsss_demod.h"
|
||||
#include "con_usart.h"
|
||||
|
||||
void handle_dsss_received(uint8_t unused_a data[static TRANSMISSION_SYMBOLS]) {
|
||||
asm volatile ("bkpt");
|
||||
void handle_dsss_received(uint8_t data[static TRANSMISSION_SYMBOLS]) {
|
||||
con_printf("DSSS data received: ");
|
||||
for (int i=0; i<TRANSMISSION_SYMBOLS; i++) {
|
||||
int x = (data[i]>>1) * (data[i]&1 ? 1 : -1);
|
||||
con_printf("%3d ", x);
|
||||
}
|
||||
con_printf("\r\n");
|
||||
}
|
||||
|
|
|
|||
153
controller/fw/src/serial.c
Normal file
153
controller/fw/src/serial.c
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dma_util.h"
|
||||
#include "sr_global.h"
|
||||
#include "serial.h"
|
||||
|
||||
#include <tinyprintf.h>
|
||||
|
||||
static void usart_schedule_dma(volatile struct usart_desc *us);
|
||||
static void usart_dma_reset(volatile struct usart_desc *us);
|
||||
static void usart_putc_nonblocking_tpf(void *us, char c);
|
||||
|
||||
void usart_dma_reset(volatile struct usart_desc *us) {
|
||||
us->tx_buf.xfr_start = -1;
|
||||
us->tx_buf.xfr_end = 0;
|
||||
us->tx_buf.wr_pos = 0;
|
||||
us->tx_buf.wr_idx = 0;
|
||||
us->tx_buf.xfr_next = 0;
|
||||
us->tx_buf.wraparound = false;
|
||||
|
||||
for (size_t i=0; i<ARRAY_LENGTH(us->tx_buf.chunk_end); i++)
|
||||
us->tx_buf.chunk_end[i] = -1;
|
||||
}
|
||||
|
||||
void usart_dma_init(volatile struct usart_desc *us, unsigned int baudrate) {
|
||||
usart_dma_reset(us);
|
||||
|
||||
/* Configure DMA 1 Channel 2 to handle uart transmission */
|
||||
us->tx_dmas->PAR = (uint32_t)&(us->le_usart->DR);
|
||||
us->tx_dmas->CR =
|
||||
(us->tx_dma_ch<<DMA_SxCR_CHSEL_Pos)
|
||||
| (0<<DMA_SxCR_PL_Pos)
|
||||
| (1<<DMA_SxCR_DIR_Pos)
|
||||
| (0<<DMA_SxCR_MSIZE_Pos) /* 8 bit */
|
||||
| (0<<DMA_SxCR_PSIZE_Pos) /* 8 bit */
|
||||
| DMA_SxCR_MINC
|
||||
| DMA_SxCR_TCIE; /* Enable transfer complete interrupt. */
|
||||
|
||||
/* triggered on transfer completion. We use this to process the ADC data */
|
||||
NVIC_EnableIRQ(us->tx_dma_irqn);
|
||||
NVIC_SetPriority(us->tx_dma_irqn, 30);
|
||||
|
||||
us->le_usart->CR1 = USART_CR1_TE;
|
||||
/* Set divider for 115.2kBd @48MHz system clock. */
|
||||
us->le_usart->BRR = apb2_speed * 16 / baudrate / 16; /* 250kBd */
|
||||
us->le_usart->CR3 |= USART_CR3_DMAT; /* TX DMA enable */
|
||||
|
||||
/* And... go! */
|
||||
us->le_usart->CR1 |= USART_CR1_UE;
|
||||
}
|
||||
|
||||
void usart_schedule_dma(volatile struct usart_desc *us) {
|
||||
volatile struct dma_tx_buf *buf = &us->tx_buf;
|
||||
|
||||
ssize_t xfr_start, xfr_end, xfr_len;
|
||||
if (buf->wraparound) {
|
||||
buf->wraparound = false;
|
||||
xfr_start = 0;
|
||||
xfr_len = buf->xfr_end;
|
||||
xfr_end = buf->xfr_end;
|
||||
|
||||
} else {
|
||||
if (buf->chunk_end[buf->xfr_next] == -1)
|
||||
return; /* Nothing to trasnmit */
|
||||
|
||||
xfr_start = buf->xfr_end;
|
||||
xfr_end = buf->chunk_end[buf->xfr_next];
|
||||
buf->chunk_end[buf->xfr_next] = -1;
|
||||
buf->xfr_next = (buf->xfr_next + 1) % ARRAY_LENGTH(buf->chunk_end);
|
||||
|
||||
if (xfr_end > xfr_start) { /* no wraparound */
|
||||
xfr_len = xfr_end - xfr_start;
|
||||
|
||||
} else { /* wraparound */
|
||||
if (xfr_end != 0)
|
||||
buf->wraparound = true;
|
||||
xfr_len = sizeof(us->data) - xfr_start;
|
||||
}
|
||||
}
|
||||
|
||||
buf->xfr_start = xfr_start;
|
||||
buf->xfr_end = xfr_end;
|
||||
|
||||
us->comm_led = 100;
|
||||
|
||||
/* initiate transmission of new buffer */
|
||||
us->tx_dmas->M0AR = (uint32_t)(us->data + xfr_start);
|
||||
us->tx_dmas->NDTR = xfr_len;
|
||||
us->tx_dmas->CR |= DMA_SxCR_EN;
|
||||
}
|
||||
|
||||
void usart_dma_stream_irq(volatile struct usart_desc *us) {
|
||||
uint8_t iflags = dma_get_isr_and_clear(us->tx_dma, us->tx_dma_sn);
|
||||
|
||||
if (iflags & DMA_LISR_TCIF0) { /* Transfer complete */
|
||||
us->tx_dmas->CR &= ~DMA_SxCR_EN;
|
||||
//if (us->tx_buf.wraparound)
|
||||
usart_schedule_dma(us);
|
||||
}
|
||||
|
||||
if (iflags & DMA_LISR_FEIF0)
|
||||
us->tx_errors++;
|
||||
}
|
||||
|
||||
int usart_putc_nonblocking(volatile struct usart_desc *us, char c) {
|
||||
volatile struct dma_tx_buf *buf = &us->tx_buf;
|
||||
|
||||
if (buf->wr_pos == buf->xfr_start) {
|
||||
us->tx_byte_overruns++;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
buf->data[buf->wr_pos] = c;
|
||||
buf->wr_pos = (buf->wr_pos + 1) % sizeof(us->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usart_putc_nonblocking_tpf(void *us, char c) {
|
||||
usart_putc_nonblocking((struct usart_desc *)us, c);
|
||||
}
|
||||
|
||||
|
||||
int usart_send_chunk_nonblocking(volatile struct usart_desc *us, const char *chunk, size_t chunk_len) {
|
||||
for (size_t i=0; i<chunk_len; i++)
|
||||
usart_putc_nonblocking(us, chunk[i]);
|
||||
|
||||
return usart_flush(us);
|
||||
}
|
||||
|
||||
int usart_flush(volatile struct usart_desc *us) {
|
||||
/* Find a free slot for this chunk */
|
||||
if (us->tx_buf.chunk_end[us->tx_buf.wr_idx] != -1) {
|
||||
us->tx_chunk_overruns++;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
us->tx_buf.chunk_end[us->tx_buf.wr_idx] = us->tx_buf.wr_pos;
|
||||
us->tx_buf.wr_idx = (us->tx_buf.wr_idx + 1) % ARRAY_LENGTH(us->tx_buf.chunk_end);
|
||||
|
||||
if (!(us->tx_dmas->CR & DMA_SxCR_EN))
|
||||
usart_schedule_dma(us);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usart_printf(volatile struct usart_desc *us, char *fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
tfp_format((void *)us, usart_putc_nonblocking_tpf, fmt, va);
|
||||
return usart_flush(us);
|
||||
}
|
||||
|
||||
82
controller/fw/src/serial.h
Normal file
82
controller/fw/src/serial.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* This file is part of the libusbhost library
|
||||
* hosted at http://github.com/libusbhost/libusbhost
|
||||
*
|
||||
* Copyright (C) 2015 Amir Hammad <amir.hammad@hotmail.com>
|
||||
*
|
||||
*
|
||||
* libusbhost is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SERIAL_H__
|
||||
#define __SERIAL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "sr_global.h"
|
||||
|
||||
struct dma_tx_buf {
|
||||
/* The following fields are accessed only from DMA ISR */
|
||||
ssize_t xfr_start; /* Start index of running DMA transfer */
|
||||
ssize_t xfr_end; /* End index of running DMA transfer plus one */
|
||||
bool wraparound;
|
||||
ssize_t xfr_next;
|
||||
|
||||
/* The following fields are written only from non-interrupt code */
|
||||
ssize_t wr_pos; /* Next index to be written */
|
||||
ssize_t wr_idx;
|
||||
ssize_t chunk_end[8];
|
||||
|
||||
/* Make GCC shut up about the zero-size array member. */
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
/* Written outside ISR by usart_send_chunk_nonblocking, read via DMA */
|
||||
uint8_t data[0];
|
||||
#pragma GCC diagnostic pop
|
||||
};
|
||||
|
||||
struct usart_desc {
|
||||
struct dma_tx_buf tx_buf;
|
||||
uint8_t data[512];
|
||||
|
||||
uint32_t tx_chunk_overruns, tx_byte_overruns;
|
||||
uint32_t tx_errors;
|
||||
|
||||
volatile uint8_t rx_buf[32];
|
||||
|
||||
int comm_led;
|
||||
|
||||
USART_TypeDef *le_usart;
|
||||
int le_usart_irqn;
|
||||
DMA_Stream_TypeDef *tx_dmas;
|
||||
int tx_dma_sn;
|
||||
int tx_dma_ch;
|
||||
DMA_TypeDef *tx_dma;
|
||||
int tx_dma_irqn;
|
||||
};
|
||||
|
||||
void usart_dma_init(volatile struct usart_desc *us, unsigned int baudrate);
|
||||
int usart_send_chunk_nonblocking(volatile struct usart_desc *us, const char *chunk, size_t chunk_len);
|
||||
int usart_putc_nonblocking(volatile struct usart_desc *us, char c);
|
||||
|
||||
void usart_dma_stream_irq(volatile struct usart_desc *us);
|
||||
int usart_flush(volatile struct usart_desc *us);
|
||||
int usart_printf(volatile struct usart_desc *us, char *fmt, ...);
|
||||
|
||||
#endif // __SERIAL_H__
|
||||
|
|
@ -2,12 +2,25 @@
|
|||
#define __SR_GLOBAL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stm32f407xx.h>
|
||||
#include <stm32f4_isr.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define UNUSED(x) ((void) x)
|
||||
#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
#define unused_a __attribute__((unused))
|
||||
|
||||
extern unsigned int sysclk_speed;
|
||||
extern unsigned int apb1_speed;
|
||||
extern unsigned int apb2_speed;
|
||||
extern unsigned int auxclk_speed;
|
||||
extern unsigned int apb1_timer_speed;
|
||||
extern unsigned int apb2_timer_speed;
|
||||
|
||||
extern struct leds {
|
||||
unsigned int comm_tx;
|
||||
} leds;
|
||||
static inline uint16_t htole(uint16_t val) { return val; }
|
||||
|
||||
void __libc_init_array(void);
|
||||
|
|
|
|||
1
controller/fw/tinyprintf
Submodule
1
controller/fw/tinyprintf
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 2ee30120ec15e321566b43f83c731d060bb437f5
|
||||
Loading…
Add table
Add a link
Reference in a new issue