add USART snippet (Rx by USART interrupts, Tx by DMA; double buffering for both Tx/Rx)

This commit is contained in:
eddyem 2018-11-05 22:00:52 +03:00
parent 7886dce593
commit 13f2c3a588
7 changed files with 115 additions and 37 deletions

View File

@ -38,8 +38,8 @@
gpioport->BSRR = ((__port & gpios) << 16) | (~__port & gpios);}while(0) gpioport->BSRR = ((__port & gpios) << 16) | (~__port & gpios);}while(0)
#define pin_set(gpioport, gpios) do{gpioport->BSRR = 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_clear(gpioport, gpios) do{gpioport->BSRR = ((gpios) << 16);}while(0)
#define pin_read(gpioport, gpios) (gpioport->IDR & gpios ? 1 : 0) #define pin_read(gpioport, gpios) (gpioport->IDR & (gpios) ? 1 : 0)
#define pin_write(gpioport, gpios) do{gpioport->ODR = gpios;}while(0) #define pin_write(gpioport, gpios) do{gpioport->ODR = gpios;}while(0)

View File

@ -3434,6 +3434,30 @@ typedef struct
#define DMA_IFCR_CHTIF7 ((uint32_t)0x04000000) /*!< Channel 7 Half Transfer clear */ #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_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 *******************/ /******************* Bit definition for DMA_CCR1 register *******************/
#define DMA_CCR1_EN ((uint16_t)0x0001) /*!< Channel enable*/ #define DMA_CCR1_EN ((uint16_t)0x0001) /*!< Channel enable*/
#define DMA_CCR1_TCIE ((uint16_t)0x0002) /*!< Transfer complete interrupt enable */ #define DMA_CCR1_TCIE ((uint16_t)0x0002) /*!< Transfer complete interrupt enable */

View File

@ -1,5 +1,4 @@
Toggle LEDs (PB8/PB9) on STM32F103 development board depending on buttons PC0,PC1: Toggle LED PB9 on STM32F103 development board once per second
- no buttons pressed == 'SOS' in Morze @ LED D1 Allow to turn on/off LED PB8 depending on user commands over USART (0/1) and check its state (s)
- Button S2 pressed - D1 blinks with period of 5s Show information in USART console about S2/S3 buttons pressed
- Button S1 pressed - D2 blinks with period of 1s USART: 115200 8n1

View File

@ -22,6 +22,9 @@
#include "stm32f1.h" #include "stm32f1.h"
#include "usart.h" #include "usart.h"
// debounce pause (ms - 1)
#define DEBOUNCE_PAUSE (9)
static volatile uint32_t Tms = 0; // milliseconds from last reset static volatile uint32_t Tms = 0; // milliseconds from last reset
// Called when systick fires // 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); 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 main(){
int L; int L;
char *txt; char *txt;
@ -98,6 +142,26 @@ int main(){
transmit_tbuf(); transmit_tbuf();
L = 0; 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 uint8_t

Binary file not shown.

View File

@ -53,32 +53,15 @@ int usart_getline(char **line){
// transmit current tbuf and swap buffers // transmit current tbuf and swap buffers
void transmit_tbuf(){ void transmit_tbuf(){
uint32_t tmout = 16000000; uint32_t tmout = 16000000;
while(!txrdy){if(--tmout == 0) break;}; // wait for previos buffer transmission while(!txrdy){if(--tmout == 0) return;}; // wait for previos buffer transmission
register int l = odatalen[tbufno]; register int l = odatalen[tbufno];
if(!l) return; if(!l) return;
//txrdy = 0; txrdy = 0;
odatalen[tbufno] = 0; odatalen[tbufno] = 0;
char *buf = tbuf[tbufno];
for(int i = 0; i < l; ++i){
USART1->DR = *buf++;
tmout = 16000000;
while(!(USART1->SR & USART_SR_TXE)){if(--tmout == 0)break;};
}
/*
#if USARTNUM == 2
DMA1_Channel4->CCR &= ~DMA_CCR_EN; DMA1_Channel4->CCR &= ~DMA_CCR_EN;
DMA1_Channel4->CMAR = (uint32_t) tbuf[tbufno]; // mem DMA1_Channel4->CMAR = (uint32_t) tbuf[tbufno]; // mem
DMA1_Channel4->CNDTR = l; DMA1_Channel4->CNDTR = l;
DMA1_Channel4->CCR |= DMA_CCR_EN; // start transmission DMA1_Channel4->CCR |= DMA_CCR_EN;
#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
*/
tbufno = !tbufno; tbufno = !tbufno;
} }
@ -113,16 +96,15 @@ void usart_setup(){
uint32_t tmout = 16000000; uint32_t tmout = 16000000;
// PA9 - Tx, PA10 - Rx // PA9 - Tx, PA10 - Rx
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN; 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); GPIOA->CRH = CRH(9, CNF_AFPP|MODE_NORMAL) | CRH(10, CNF_FLINPUT|MODE_INPUT);
/*
// USART1 Tx DMA - Channel2 (default value in SYSCFG_CFGR1) // USART1 Tx DMA - Channel4 (Rx - channel 5)
DMA1_Channel2->CPAR = (uint32_t) &USART1->TDR; // periph DMA1_Channel4->CPAR = (uint32_t) &USART1->DR; // periph
DMA1_Channel2->CMAR = (uint32_t) tbuf; // mem DMA1_Channel4->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq
DMA1_Channel2->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 // Tx CNDTR set @ each transmission due to data size
NVIC_SetPriority(DMA1_Channel2_3_IRQn, 3); NVIC_SetPriority(DMA1_Channel4_IRQn, 3);
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);*/ NVIC_EnableIRQ(DMA1_Channel4_IRQn);
//USART1->CR3 = USART_CR3_DMAT; // enable DMA Tx
NVIC_SetPriority(USART1_IRQn, 0); NVIC_SetPriority(USART1_IRQn, 0);
// setup usart1 // setup usart1
USART1->BRR = 72000000 / 115200; 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 while(!(USART1->SR & USART_SR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission
USART1->SR = 0; // clear flags USART1->SR = 0; // clear flags
USART1->CR1 |= USART_CR1_RXNEIE; // allow Rx IRQ USART1->CR1 |= USART_CR1_RXNEIE; // allow Rx IRQ
USART1->CR3 = USART_CR3_DMAT; // enable DMA Tx
NVIC_EnableIRQ(USART1_IRQn); NVIC_EnableIRQ(USART1_IRQn);
} }
@ -220,6 +203,14 @@ void hexdump(uint8_t *arr, uint16_t len){
else if(l & 1) usart_putchar(' '); 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 #if USARTNUM == 2
void dma1_channel4_5_isr(){ void dma1_channel4_5_isr(){

View File

@ -24,8 +24,8 @@
#define __USART_H__ #define __USART_H__
// input and output buffers size // input and output buffers size
#define UARTBUFSZI (32) #define UARTBUFSZI (16)
#define UARTBUFSZO (512) #define UARTBUFSZO (32)
// timeout between data bytes // timeout between data bytes
#ifndef TIMEOUT_MS #ifndef TIMEOUT_MS
#define TIMEOUT_MS (1500) #define TIMEOUT_MS (1500)