From 13f2c3a5886858552ce2f1ed98c30f033b3b0e6c Mon Sep 17 00:00:00 2001 From: eddyem Date: Mon, 5 Nov 2018 22:00:52 +0300 Subject: [PATCH] add USART snippet (Rx by USART interrupts, Tx by DMA; double buffering for both Tx/Rx) --- F1-nolib/inc/Fx/common_macros.h | 4 +- F1-nolib/inc/Fx/stm32f10x.h | 24 ++++++++++++ F1-nolib/uart/README | 9 ++--- F1-nolib/uart/main.c | 64 ++++++++++++++++++++++++++++++++ F1-nolib/uart/uart.bin | Bin 2032 -> 2336 bytes F1-nolib/uart/usart.c | 47 ++++++++++------------- F1-nolib/uart/usart.h | 4 +- 7 files changed, 115 insertions(+), 37 deletions(-) diff --git a/F1-nolib/inc/Fx/common_macros.h b/F1-nolib/inc/Fx/common_macros.h index e1cfe16..9e01f3b 100644 --- a/F1-nolib/inc/Fx/common_macros.h +++ b/F1-nolib/inc/Fx/common_macros.h @@ -38,8 +38,8 @@ gpioport->BSRR = ((__port & gpios) << 16) | (~__port & gpios);}while(0) #define pin_set(gpioport, gpios) do{gpioport->BSRR = gpios;}while(0) -#define pin_clear(gpioport, gpios) do{gpioport->BSRR = (gpios << 16);}while(0) -#define pin_read(gpioport, gpios) (gpioport->IDR & gpios ? 1 : 0) +#define pin_clear(gpioport, gpios) do{gpioport->BSRR = ((gpios) << 16);}while(0) +#define pin_read(gpioport, gpios) (gpioport->IDR & (gpios) ? 1 : 0) #define pin_write(gpioport, gpios) do{gpioport->ODR = gpios;}while(0) diff --git a/F1-nolib/inc/Fx/stm32f10x.h b/F1-nolib/inc/Fx/stm32f10x.h index 7c9753d..af784ab 100644 --- a/F1-nolib/inc/Fx/stm32f10x.h +++ b/F1-nolib/inc/Fx/stm32f10x.h @@ -3434,6 +3434,30 @@ typedef struct #define DMA_IFCR_CHTIF7 ((uint32_t)0x04000000) /*!< Channel 7 Half Transfer clear */ #define DMA_IFCR_CTEIF7 ((uint32_t)0x08000000) /*!< Channel 7 Transfer Error clear */ +#define DMA_CCR_EN ((uint16_t)0x0001) /*!< Channel enable*/ +#define DMA_CCR_TCIE ((uint16_t)0x0002) /*!< Transfer complete interrupt enable */ +#define DMA_CCR_HTIE ((uint16_t)0x0004) /*!< Half Transfer interrupt enable */ +#define DMA_CCR_TEIE ((uint16_t)0x0008) /*!< Transfer error interrupt enable */ +#define DMA_CCR_DIR ((uint16_t)0x0010) /*!< Data transfer direction */ +#define DMA_CCR_CIRC ((uint16_t)0x0020) /*!< Circular mode */ +#define DMA_CCR_PINC ((uint16_t)0x0040) /*!< Peripheral increment mode */ +#define DMA_CCR_MINC ((uint16_t)0x0080) /*!< Memory increment mode */ + +#define DMA_CCR_PSIZE ((uint16_t)0x0300) /*!< PSIZE[1:0] bits (Peripheral size) */ +#define DMA_CCR_PSIZE_0 ((uint16_t)0x0100) /*!< Bit 0 */ +#define DMA_CCR_PSIZE_1 ((uint16_t)0x0200) /*!< Bit 1 */ + +#define DMA_CCR_MSIZE ((uint16_t)0x0C00) /*!< MSIZE[1:0] bits (Memory size) */ +#define DMA_CCR_MSIZE_0 ((uint16_t)0x0400) /*!< Bit 0 */ +#define DMA_CCR_MSIZE_1 ((uint16_t)0x0800) /*!< Bit 1 */ + +#define DMA_CCR_PL ((uint16_t)0x3000) /*!< PL[1:0] bits(Channel Priority level) */ +#define DMA_CCR_PL_0 ((uint16_t)0x1000) /*!< Bit 0 */ +#define DMA_CCR_PL_1 ((uint16_t)0x2000) /*!< Bit 1 */ + +#define DMA_CCR_MEM2MEM ((uint16_t)0x4000) /*!< Memory to memory mode */ + + /******************* Bit definition for DMA_CCR1 register *******************/ #define DMA_CCR1_EN ((uint16_t)0x0001) /*!< Channel enable*/ #define DMA_CCR1_TCIE ((uint16_t)0x0002) /*!< Transfer complete interrupt enable */ diff --git a/F1-nolib/uart/README b/F1-nolib/uart/README index 35bb182..cd185fe 100644 --- a/F1-nolib/uart/README +++ b/F1-nolib/uart/README @@ -1,5 +1,4 @@ -Toggle LEDs (PB8/PB9) on STM32F103 development board depending on buttons PC0,PC1: -- no buttons pressed == 'SOS' in Morze @ LED D1 -- Button S2 pressed - D1 blinks with period of 5s -- Button S1 pressed - D2 blinks with period of 1s - +Toggle LED PB9 on STM32F103 development board once per second +Allow to turn on/off LED PB8 depending on user commands over USART (0/1) and check its state (s) +Show information in USART console about S2/S3 buttons pressed +USART: 115200 8n1 diff --git a/F1-nolib/uart/main.c b/F1-nolib/uart/main.c index 6132830..5314846 100644 --- a/F1-nolib/uart/main.c +++ b/F1-nolib/uart/main.c @@ -22,6 +22,9 @@ #include "stm32f1.h" #include "usart.h" +// debounce pause (ms - 1) +#define DEBOUNCE_PAUSE (9) + static volatile uint32_t Tms = 0; // milliseconds from last reset // Called when systick fires @@ -40,6 +43,47 @@ static void gpio_setup(void){ GPIOC->CRL = CRL(0, CNF_PUDINPUT|MODE_INPUT) | CRL(1, CNF_PUDINPUT|MODE_INPUT); } +typedef enum{ + BTN_PRESSED + ,BTN_RELEASED + ,BTN_DEBOUNCE + ,BTN_RELAX +} button_state; + +button_state check_state(uint8_t N){ + static uint32_t tlast[2] = {0,0}; + static button_state oldstate[2] = {BTN_RELEASED, BTN_RELEASED}; + button_state s = BTN_RELAX; + uint8_t b = pin_read(GPIOC, N+1); // == 1 if button released + if(b){ + switch(oldstate[N]){ + case BTN_PRESSED: // debounce pause for DEBOUNCE_PAUSE ms + s = oldstate[N] = BTN_DEBOUNCE; + tlast[N] = Tms; + break; + case BTN_DEBOUNCE: // check debounce pause + if(Tms - tlast[N] > DEBOUNCE_PAUSE){ + s = oldstate[N] = BTN_RELEASED; + } + break; + default: // BTN_RELEASED - do nothing -> return BTN_RELAX + ; + } + }else{ + switch(oldstate[N]){ + case BTN_RELEASED: + s = BTN_PRESSED; // button was just pressed + __attribute__((fallthrough)); // change oldstate too + case BTN_DEBOUNCE: // change old state to BTN_PRESSED again + oldstate[N] = BTN_PRESSED; // returned state still relax + break; + default: // BTN_PRESSED before - do nothing + ; + } + } + return s; +} + int main(){ int L; char *txt; @@ -98,6 +142,26 @@ int main(){ transmit_tbuf(); L = 0; } + for(int i = 0; i < 2; ++i){ + const char *st = NULL; + switch(check_state(i)){ + case BTN_PRESSED: + st = "pressed"; + break; + case BTN_RELEASED: + st = "released"; + break; + default: + ; // nothing + } + if(st){ + SEND("The button"); + usart_putchar('2' + i); + SEND(" was "); + SEND(st); + newline(); + } + } /* uint8_t diff --git a/F1-nolib/uart/uart.bin b/F1-nolib/uart/uart.bin index 1b5a8ce86ceebe257cf31e6d19f3301ab610231a..52f5580a47d54e9f3087d726bb5efd00d344bd06 100755 GIT binary patch literal 2336 zcmbVNeN0=|6+ibqf7`$_CaW=&Jf5LIoNi92)M_8XJcDCD6HE)VgtpV8n(1TesE5gh zqG>frRb@(5C84S)WLmaHQL082pQ@$?F;)9xQq#&tCCZ1Uu(p$vqDYs_!H;zE+j$Pt zqD=iKmVQ3xo^#JR*XRDuHFN>rWC2S(qV@s610Q{l4&AKFr^)}vJecFV*5rX&-?i^y z?7uKQ{J9>c-u*F*(Ze~Cbwyms}yWkEb_Ay>l#4K4AZ;z<*+&vpC z14jaQCA?nGfq48TjR7Ca?KH#N^Sq?%Lhd)^x)gIaP-1?X8u7^FZR46=WB$&e*T@93 z!YWf_a}{a_qy3m$pe&vUV<>}?oVb6lVI`=r)WKSOxy(_XeQdDdK;%W~*wBj|LF#6Y z4ZJL0k~taZ=oZwQ1;;9R|B(8g@BfA88`L<&|9h> zSC*|l{5E3VA8f(y%NbIP)bg7JX#5IexY@6>3hsDAWf~2knhZ?$kJ)zZOapya#d~95 z+S3b@K)+Uj9#=ofHbp*Ft_G_NOb$j^3Q1ScuAeXkbX=Xu0{yKDyT8nQn5`Py26PQ>2piV%+B#*QutmF0`LQJ**ze>bzr+cbW>fU=4WGbsjoMfLnvLmP!I|>TiV= zEDppZ>gN#`5EfjYLHQS5N50k}#!!D9Va550{@E&V3)V=5VwDWCUFH;hGQewyxMX+8 zUYxB8jOp2qb)$4eD7{$52R}}*1XQ5&4?%~bSXqnuu3W-OR zl1M!zMzSuJKPq39UqBZA$|_RAcx01Iu@+XV%Ygy&P9ho+ZNLQjP$m}b`|TY*#T4pM zy*$6mnzl-)am;$Ke1G+`J#DJDE3u^IKhk{42KMN`@p>#fW}nB|Y~?x)A#Q)O!o}dW z<}O+5#dtHuhpXF>krgVjcl8Kk((LJWa~geEUNOLeqjqE4t7cDDlx+O>n z>gkq>=mD9%6X-THPv8ufM_cJheTtjtI*1(Wg}b zrsv8U&3`9#;H?N7obB$oVM z(>Wr5>i7xGes=NV#l+&_8FHKpYk8AavSBusY_O&s80&RjowNFw4L=xYnc;8C%*Jz| zd)m!}XT@mJyl$@tIE2Z@n*Qdjql z#N(qw!!IXm0Xo{-_VTX|4(k4U`tUuO932>q|B%=1y1T*Oz(3B99vm6gck}vITf?6J s*@m}G$)YKq94)T-Vip_b=uzVQO9w|sUmeCn{dyp&C-#p45Q0GcKQ=zlqW}N^ delta 1432 zcma)5Z)jUp6hHUn-%A=z)^yOM8GTI}7M6<9bRsJBHEGiPX-wT}HwR*hQr=*$&lNR@ zkYw7?*?ri2ie-VV8*_+$>AF^!EJQ!rPl>KF9MZT6ud)iaU21L%Cf-*ojPApF;m7%N z&pG$r^E-E{5u4J`4_uoL*gX{1ZGde{iBX`q75NH!G-rE_$Jpsd4t-3*j^f8OJH1$X zr-3_b(x)&X~}Co23X-`5>qB+XfhbMwUPbqaS{uCHyR?LT=0@KlRJ2ym7#?vo*|1i2$A z!#+n5@Mi?l4#=s9frClF_Xyw#@_*{xpC1Un23pii1x~0ij9LP|p}hj&56FTH_){>3xUL)6qJDR>i zbJ$9)uSpv4EgIHOuF5>U<7JY-|0VxOy+M+b!_@l))w{^&GME`2pibZ~C<8}zGvdu< zD0f*Ah;*(M)|x3kr21KkDT*r;U_|^lm0wZlDa)}N`lxwUA88Ww(nYm3O+N-FY~>oM z6lZtGc1KVdy~q>|0_@u;T3)uq_6rAzi-!(tkcF+B zAX|KOtK4#_UOip+2}^Q*31`LLhYPTC22LrQUt;-s^}T{P3vG$Yr^Ec}JMI2eBkYPc z#-*cyN+uA%8kIC;id|ki>_49Th`20G*}(d5pWAHK_yPKCaELcKj*V#|w#@m{ zOyGPry!oj%>0=QOzf<~@R?w$Q$F$9;RT|T_BER&d)@OZ-_QXt~aMDhp@TqVjNGsYn z>X5p0t;jCDp>x`oYx)lL$|0C6s8_sDul`Y+^UEb>TFfu$qzgLt3-dL13a|*#IY~gHUHG)%}JxD fE0eWMr$><@WluW8cB)2>gH&LDR = *buf++; - tmout = 16000000; - while(!(USART1->SR & USART_SR_TXE)){if(--tmout == 0)break;}; - } - /* -#if USARTNUM == 2 DMA1_Channel4->CCR &= ~DMA_CCR_EN; DMA1_Channel4->CMAR = (uint32_t) tbuf[tbufno]; // mem DMA1_Channel4->CNDTR = l; - DMA1_Channel4->CCR |= DMA_CCR_EN; // start transmission -#elif USARTNUM == 1 - DMA1_Channel2->CCR &= ~DMA_CCR_EN; - DMA1_Channel2->CMAR = (uint32_t) tbuf[tbufno]; // mem - DMA1_Channel2->CNDTR = l; - DMA1_Channel2->CCR |= DMA_CCR_EN; -#else -#error "Not implemented" -#endif -*/ + DMA1_Channel4->CCR |= DMA_CCR_EN; tbufno = !tbufno; } @@ -113,16 +96,15 @@ void usart_setup(){ uint32_t tmout = 16000000; // PA9 - Tx, PA10 - Rx RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN; + RCC->AHBENR |= RCC_AHBENR_DMA1EN; GPIOA->CRH = CRH(9, CNF_AFPP|MODE_NORMAL) | CRH(10, CNF_FLINPUT|MODE_INPUT); -/* - // USART1 Tx DMA - Channel2 (default value in SYSCFG_CFGR1) - DMA1_Channel2->CPAR = (uint32_t) &USART1->TDR; // periph - DMA1_Channel2->CMAR = (uint32_t) tbuf; // mem - DMA1_Channel2->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq + + // USART1 Tx DMA - Channel4 (Rx - channel 5) + DMA1_Channel4->CPAR = (uint32_t) &USART1->DR; // periph + DMA1_Channel4->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq // Tx CNDTR set @ each transmission due to data size - NVIC_SetPriority(DMA1_Channel2_3_IRQn, 3); - NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);*/ - //USART1->CR3 = USART_CR3_DMAT; // enable DMA Tx + NVIC_SetPriority(DMA1_Channel4_IRQn, 3); + NVIC_EnableIRQ(DMA1_Channel4_IRQn); NVIC_SetPriority(USART1_IRQn, 0); // setup usart1 USART1->BRR = 72000000 / 115200; @@ -130,6 +112,7 @@ void usart_setup(){ while(!(USART1->SR & USART_SR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission USART1->SR = 0; // clear flags USART1->CR1 |= USART_CR1_RXNEIE; // allow Rx IRQ + USART1->CR3 = USART_CR3_DMAT; // enable DMA Tx NVIC_EnableIRQ(USART1_IRQn); } @@ -220,6 +203,14 @@ void hexdump(uint8_t *arr, uint16_t len){ else if(l & 1) usart_putchar(' '); } } + +void dma1_channel4_isr(){ + if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx + DMA1->IFCR = DMA_IFCR_CTCIF4; // clear TC flag + txrdy = 1; + } +} + /* #if USARTNUM == 2 void dma1_channel4_5_isr(){ diff --git a/F1-nolib/uart/usart.h b/F1-nolib/uart/usart.h index 3ade072..8ab243d 100644 --- a/F1-nolib/uart/usart.h +++ b/F1-nolib/uart/usart.h @@ -24,8 +24,8 @@ #define __USART_H__ // input and output buffers size -#define UARTBUFSZI (32) -#define UARTBUFSZO (512) +#define UARTBUFSZI (16) +#define UARTBUFSZO (32) // timeout between data bytes #ifndef TIMEOUT_MS #define TIMEOUT_MS (1500)