diff options
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | controller/fw/Makefile | 15 | ||||
-rw-r--r-- | controller/fw/src/adc.c | 20 | ||||
-rw-r--r-- | controller/fw/src/con_usart.c | 33 | ||||
-rw-r--r-- | controller/fw/src/con_usart.h | 16 | ||||
-rw-r--r-- | controller/fw/src/dma_util.c | 46 | ||||
-rw-r--r-- | controller/fw/src/dma_util.h | 10 | ||||
-rw-r--r-- | controller/fw/src/freq_meas.c | 8 | ||||
-rw-r--r-- | controller/fw/src/main.c | 80 | ||||
-rw-r--r-- | controller/fw/src/protocol.c | 10 | ||||
-rw-r--r-- | controller/fw/src/serial.c | 153 | ||||
-rw-r--r-- | controller/fw/src/serial.h | 82 | ||||
-rw-r--r-- | controller/fw/src/sr_global.h | 13 | ||||
m--------- | controller/fw/tinyprintf | 0 |
14 files changed, 447 insertions, 42 deletions
diff --git a/.gitmodules b/.gitmodules index 755dc2f..9da9307 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/controller/fw/Makefile b/controller/fw/Makefile index 0fea8ae..50d162d 100644 --- a/controller/fw/Makefile +++ b/controller/fw/Makefile @@ -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 diff --git a/controller/fw/src/adc.c b/controller/fw/src/adc.c index 74f0aa9..81f5ac1 100644 --- a/controller/fw/src/adc.c +++ b/controller/fw/src/adc.c @@ -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; } diff --git a/controller/fw/src/con_usart.c b/controller/fw/src/con_usart.c new file mode 100644 index 0000000..f80fa79 --- /dev/null +++ b/controller/fw/src/con_usart.c @@ -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); +} + diff --git a/controller/fw/src/con_usart.h b/controller/fw/src/con_usart.h new file mode 100644 index 0000000..a1ad963 --- /dev/null +++ b/controller/fw/src/con_usart.h @@ -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__ */ diff --git a/controller/fw/src/dma_util.c b/controller/fw/src/dma_util.c new file mode 100644 index 0000000..48de215 --- /dev/null +++ b/controller/fw/src/dma_util.c @@ -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; + } +} + diff --git a/controller/fw/src/dma_util.h b/controller/fw/src/dma_util.h new file mode 100644 index 0000000..5ea2676 --- /dev/null +++ b/controller/fw/src/dma_util.h @@ -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__ */ diff --git a/controller/fw/src/freq_meas.c b/controller/fw/src/freq_meas.c index 020e12d..6b9b54e 100644 --- a/controller/fw/src/freq_meas.c +++ b/controller/fw/src/freq_meas.c @@ -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; } diff --git a/controller/fw/src/main.c b/controller/fw/src/main.c index fa5d50b..b100b16 100644 --- a/controller/fw/src/main.c +++ b/controller/fw/src/main.c @@ -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"); } diff --git a/controller/fw/src/protocol.c b/controller/fw/src/protocol.c index 17020bd..bbee5ef 100644 --- a/controller/fw/src/protocol.c +++ b/controller/fw/src/protocol.c @@ -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"); } diff --git a/controller/fw/src/serial.c b/controller/fw/src/serial.c new file mode 100644 index 0000000..71e1868 --- /dev/null +++ b/controller/fw/src/serial.c @@ -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); +} + diff --git a/controller/fw/src/serial.h b/controller/fw/src/serial.h new file mode 100644 index 0000000..02f6f5d --- /dev/null +++ b/controller/fw/src/serial.h @@ -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__
diff --git a/controller/fw/src/sr_global.h b/controller/fw/src/sr_global.h index ac77359..451cce0 100644 --- a/controller/fw/src/sr_global.h +++ b/controller/fw/src/sr_global.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); diff --git a/controller/fw/tinyprintf b/controller/fw/tinyprintf new file mode 160000 +Subproject 2ee30120ec15e321566b43f83c731d060bb437f |