diff options
author | jaseg <git@jaseg.net> | 2017-09-01 15:44:39 +0200 |
---|---|---|
committer | jaseg <git@jaseg.net> | 2017-09-01 15:44:39 +0200 |
commit | 6b40626a1bbb08968d3c615023f04fedff9254af (patch) | |
tree | 98cb753697c1ddc16acb653bda9d543d721df558 | |
parent | a832816d61aea37bea349dcd50098511712bc315 (diff) | |
download | 7seg-6b40626a1bbb08968d3c615023f04fedff9254af.tar.gz 7seg-6b40626a1bbb08968d3c615023f04fedff9254af.tar.bz2 7seg-6b40626a1bbb08968d3c615023f04fedff9254af.zip |
DMA channel assignments redone, basic protocol stuff working
-rw-r--r-- | fw/main.c | 134 | ||||
-rw-r--r-- | fw/stm32_flash.ld | 11 | ||||
-rw-r--r-- | fw/transpose.c | 10 |
3 files changed, 121 insertions, 34 deletions
@@ -43,15 +43,48 @@ void strobe_leds(void) { GPIOA->BSRR = GPIO_BSRR_BR_9; } -static volatile unsigned int sys_time = 0; +volatile unsigned int sys_time = 0; volatile struct framebuf fb[2] = {0}; volatile struct framebuf *read_fb=fb+0, *write_fb=fb+1; volatile int led_state = 0; volatile enum { FB_WRITE, FB_FORMAT, FB_UPDATE } fb_op; volatile uint8_t rx_buf[sizeof(struct framebuf) + 4 /* crc */]; +volatile union { + struct { + uint32_t millifps; + } fps_reply; +} tx_buf; volatile uint8_t this_addr = 0x05; /* FIXME */ +union { + struct { + uint8_t device_id __attribute__((aligned(2))); + }; + uint16_t flash_data[0]; +} flash_data __attribute__((section ("configflash"))); + +void write_config(void *target, uint16_t value) { + FLASH->KEYR = 0x45670123; + FLASH->KEYR = 0xCDEF89AB; + FLASH->CR = FLASH_CR_PG; + *(uint16_t *)target = value; + while (FLASH->SR & FLASH_SR_BSY) + ; + FLASH->CR = FLASH_CR_LOCK; +} + +void erase_config() { + FLASH->KEYR = 0x45670123; + FLASH->KEYR = 0xCDEF89AB; + FLASH->CR = FLASH_CR_PER; + FLASH->AR = (uint32_t)&flash_data; + FLASH->CR = FLASH_CR_STRT; + while (FLASH->SR & FLASH_SR_BSY) + ; + FLASH->CR = FLASH_CR_LOCK; +} + #define LED_COMM 0x0001 #define LED_ERROR 0x0002 #define LED_ID 0x0004 @@ -66,6 +99,10 @@ inline unsigned int stk_end(unsigned int start) { return (start - SysTick->VAL) & 0xffffff; } +inline unsigned int stk_microseconds() { + return sys_time*1000 + (1000 - (SysTick->VAL / (SystemCoreClock/1000000))); +} + enum { SPI_AUX, SPI_WORD0, @@ -117,15 +154,16 @@ void SPI1_IRQHandler() { spi_state ++; } -static volatile int frame_duration; +uint8_t segment_map[8] = {5, 7, 6, 4, 1, 3, 0, 2}; + +static volatile int frame_duration_us; /* returns new bit time in cycles */ int shift_data() { static int active_segment = 0; static unsigned int active_bit = 0; - static int last_frame_sys_time; + static unsigned int last_frame_time; /* Note: On boot, multiplexing will start with bit 1 due to the next few lines. This is perfectly ok. */ - int rv = 1<<active_bit; active_bit++; if (active_bit == nbits) { active_bit = 0; @@ -134,9 +172,9 @@ int shift_data() { if (active_segment == nsegments) { active_segment = 0; - int time = sys_time; - frame_duration = time - last_frame_sys_time; - last_frame_sys_time = sys_time; + int time = stk_microseconds(); + frame_duration_us = time - last_frame_time; + last_frame_time = time; if (fb_op == FB_UPDATE) { volatile struct framebuf *tmp = read_fb; read_fb = write_fb; @@ -149,7 +187,7 @@ int shift_data() { spi_state = SPI_AUX; SPI1->DR = (read_fb->brightness ? SR_ILED_HIGH : SR_ILED_LOW) | (led_state<<1) - | (0xff00 ^ (0x100<<active_segment)); + | (0xff00 ^ (0x100<<segment_map[active_segment])); } else { spi_word = read_fb->data[active_bit*frame_size_words + active_segment]; spi_state = SPI_WORD0; @@ -157,7 +195,7 @@ int shift_data() { } SPI1->CR2 |= SPI_CR2_TXEIE; - return rv; + return 1<<active_bit; } void cfg_timer3() { @@ -198,8 +236,16 @@ enum Command { CMD_SET_ADDR, CMD_SET_FB, CMD_GET_DESC, + CMD_GET_FRAMERATE, + CMD_ERASE_CONFIG, }; +enum { + PROT_ADDR, + PROT_CMD, + PROT_ +} protocol_state = PROT_ADDR; + int gaddr; void USART1_IRQHandler() { gaddr = USART1->RDR; @@ -214,11 +260,16 @@ void USART1_IRQHandler() { } /* Are we addressed? */ if (addr != this_addr) { + asm("bkpt"); /* We are not. Mute USART until next idle condition */ USART1->RQR |= USART_RQR_MMRQ; } else { /* We are. Switch by command. */ switch (cmd) { + case CMD_PING: + USART1->TDR = 42; + USART1->RQR |= USART_RQR_MMRQ; + break; case CMD_SET_FB: /* Are we ready to process new frame data? */ if (fb_op != FB_WRITE) { @@ -232,6 +283,13 @@ void USART1_IRQHandler() { DMA1_Channel3->CCR |= DMA_CCR_EN; USART1->CR3 |= USART_CR3_DMAR; break; + case CMD_GET_FRAMERATE: + tx_buf.fps_reply.millifps = frame_duration_us > 0 ? 1000000000 / frame_duration_us : 0; + DMA1_Channel4->CNDTR = sizeof(tx_buf.fps_reply); + USART1->ICR |= USART_ICR_TCCF; /* FIXME: (1) is this necessary? (2) where should this be done? */ + DMA1_Channel4->CCR |= DMA_CCR_EN; + USART1->RQR |= USART_RQR_MMRQ; + break; } } errout: @@ -252,6 +310,11 @@ void DMA1_Channel2_3_IRQHandler() { USART1->CR1 |= USART_CR1_RXNEIE; } +void DMA1_Channel4_5_IRQHandler() { + DMA1->IFCR |= DMA_IFCR_CGIF4; + DMA1_Channel4->CCR &= ~DMA_CCR_EN_Msk; +} + void uart_config(void) { USART1->CR1 = /* 8-bit -> M1, M0 clear */ /* RTOIE clear */ @@ -267,16 +330,17 @@ void uart_config(void) { | USART_CR1_TE | USART_CR1_RE; //USART1->CR2 = USART_CR2_RTOEN; /* Timeout enable */ - USART1->CR3 = USART_CR3_DEM; /* RS485 DE enable (output on RTS) */ + USART1->CR3 = USART_CR3_DEM /* RS485 DE enable (output on RTS) */ + | USART_CR3_DMAT; int usartdiv = 25; USART1->BRR = usartdiv; USART1->CR1 |= USART_CR1_UE; - /* Configure DMA for USART frame data reception */ + /* Configure DMA 1 / Channel 3 for USART frame data reception: USART1->RDR -> rx_buf */ DMA1_Channel3->CPAR = (unsigned int)&USART1->RDR; DMA1_Channel3->CMAR = (unsigned int)rx_buf; DMA1_Channel3->CNDTR = sizeof(rx_buf); - DMA1_Channel3->CCR = (0<<DMA_CCR_PL_Pos); + DMA1_Channel3->CCR = (1<<DMA_CCR_PL_Pos); DMA1_Channel3->CCR |= (0<<DMA_CCR_MSIZE_Pos) /* 8 bit */ | (0<<DMA_CCR_PSIZE_Pos) /* 8 bit */ @@ -284,20 +348,36 @@ void uart_config(void) { | DMA_CCR_TCIE | DMA_CCR_CIRC; - DMA1_Channel4->CPAR = (unsigned int)&CRC->DR; - DMA1_Channel4->CMAR = (unsigned int)rx_buf; - DMA1_Channel4->CCR = (0<<DMA_CCR_PL_Pos); - DMA1_Channel4->CCR |= + /* Configure DMA 1 / Channel 5 for USART frame data CRC check: rx_buf -> CRC->DR */ + DMA1_Channel5->CPAR = (unsigned int)&CRC->DR; + DMA1_Channel5->CMAR = (unsigned int)rx_buf; + DMA1_Channel5->CCR = (0<<DMA_CCR_PL_Pos); + DMA1_Channel5->CCR |= DMA_CCR_MEM2MEM /* Software trigger (precludes CIRC) */ | DMA_CCR_DIR /* Read from memory */ | (0<<DMA_CCR_MSIZE_Pos) /* 8 bit */ | (0<<DMA_CCR_PSIZE_Pos) /* 8 bit */ | DMA_CCR_MINC; + /* Configure DMA 1 / Channel 4 for USART reply transmission */ + DMA1_Channel4->CPAR = (unsigned int)&USART1->TDR; + DMA1_Channel4->CMAR = (unsigned int)&tx_buf; + DMA1_Channel4->CCR = (0<<DMA_CCR_PL_Pos); + DMA1_Channel4->CCR |= + DMA_CCR_DIR /* Read from memory */ + | (0<<DMA_CCR_MSIZE_Pos) /* 8 bit */ + | (0<<DMA_CCR_PSIZE_Pos) /* 8 bit */ + | DMA_CCR_MINC + | DMA_CCR_TCIE; + + SYSCFG->CFGR1 |= SYSCFG_CFGR1_USART1TX_DMA_RMP; + NVIC_EnableIRQ(USART1_IRQn); NVIC_SetPriority(USART1_IRQn, 4); NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); NVIC_SetPriority(DMA1_Channel2_3_IRQn, 3); + NVIC_EnableIRQ(DMA1_Channel4_5_IRQn); + NVIC_SetPriority(DMA1_Channel4_5_IRQn, 5); } int errcnt = 0; @@ -313,10 +393,8 @@ int main(void) { RCC->CFGR |= (2<<RCC_CFGR_SW_Pos); SystemCoreClockUpdate(); - LL_Init1msTick(SystemCoreClock); - RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_DMAEN | RCC_AHBENR_CRCEN; - RCC->APB2ENR |= RCC_APB2ENR_SPI1EN | RCC_APB2ENR_USART1EN; + RCC->APB2ENR |= RCC_APB2ENR_SPI1EN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_SYSCFGEN; RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; GPIOA->MODER |= @@ -365,31 +443,27 @@ int main(void) { SysTick_Config(SystemCoreClock/1000); /* 1ms interval */ uart_config(); - uint8_t i=0; - int last_sys_time=0; while (42) { - led_state = (sys_time>>8)&7; - last_sys_time = sys_time; if (fb_op == FB_FORMAT) { CRC->CR |= CRC_CR_RESET; - DMA1_Channel4->CNDTR = sizeof(struct framebuf); - DMA1_Channel4->CCR |= DMA_CCR_EN; + DMA1_Channel5->CNDTR = sizeof(struct framebuf); + DMA1_Channel5->CCR |= DMA_CCR_EN; transpose_data(rx_buf, write_fb); while (!(DMA1->ISR & DMA_ISR_TCIF4)) ; DMA1->IFCR |= DMA_IFCR_CGIF4; - DMA1_Channel4->CCR &= ~DMA_CCR_EN_Msk; + DMA1_Channel5->CCR &= ~DMA_CCR_EN_Msk; if (CRC->DR != *(uint32_t *)(rx_buf+sizeof(struct framebuf))) { fb_op = FB_WRITE; errcnt++; + } else { + fb_op = FB_UPDATE; + while (fb_op == FB_UPDATE) + ; } - - fb_op = FB_UPDATE; - while (fb_op == FB_UPDATE) - ; } } } diff --git a/fw/stm32_flash.ld b/fw/stm32_flash.ld index 87e095e..5d22b48 100644 --- a/fw/stm32_flash.ld +++ b/fw/stm32_flash.ld @@ -2,7 +2,8 @@ ENTRY(Reset_Handler)
MEMORY {
- FLASH (rx): ORIGIN = 0x08000000, LENGTH = 16K
+ FLASH (rx): ORIGIN = 0x08000000, LENGTH = 14K
+ CONFIGFLASH (rw): ORIGIN = 0x08003800, LENGTH = 2K
RAM (xrw): ORIGIN = 0x20000000, LENGTH = 4K
}
@@ -31,12 +32,18 @@ SECTIONS { /* Necessary KEEP sections (see http://sourceware.org/ml/newlib/2005/msg00255.html) */
KEEP (*(.init))
KEEP (*(.fini))
-
+
. = ALIGN(4);
_etext = .;
/* This is used by the startup in order to initialize the .data section */
_sidata = _etext;
} >FLASH
+
+ .configflash : {
+ . = ALIGN(2048);
+ *(.configdata)
+ _econfig = .;
+ } >CONFIGFLASH
/* This is the initialized data section
The program executes knowing that the data is in the RAM
diff --git a/fw/transpose.c b/fw/transpose.c index 5060920..a6c7e71 100644 --- a/fw/transpose.c +++ b/fw/transpose.c @@ -4,6 +4,12 @@ #include "transpose.h" +uint8_t digit_map[33] = { + 0, 1, 2, 3, 28,29,30,31, + 4, 5, 6, 7, 24,25,26,27, + 8, 9,10,11, 20,21,22,23, + 12,13,14,15, 16,17,18,19 +}; void transpose_data(volatile uint8_t *rx_buf, volatile struct framebuf *out_fb) { memset((uint8_t *)out_fb, 0, sizeof(*out_fb)); struct data_format *rxp = (struct data_format *)rx_buf; @@ -15,7 +21,7 @@ void transpose_data(volatile uint8_t *rx_buf, volatile struct framebuf *out_fb) uint32_t acc = 0; uint8_t *inp = start_inp++; for (int digit=0; digit<32; digit++) { - acc |= (*inp & bit_mask) >> bit << digit; + acc |= (*inp & bit_mask) >> bit << digit_map[digit]; inp += sizeof(struct data_format); } *outp = acc; @@ -28,7 +34,7 @@ void transpose_data(volatile uint8_t *rx_buf, volatile struct framebuf *out_fb) uint32_t mask = 1 << bit << (seg*2); uint32_t acc = 0; for (int digit=0; digit<32; digit++) { - acc |= (*inp & mask) >> bit >> seg << digit; + acc |= (*inp & mask) >> bit >> (seg*2) << digit_map[digit]; inp += sizeof(struct data_format)/sizeof(uint16_t); } frame_data[seg] = acc; |