diff --git a/F0-nolib/CANbus_stepper/src/canstepper.bin b/F0-nolib/CANbus_stepper/src/canstepper.bin index 0a5b949..7ddd110 100755 Binary files a/F0-nolib/CANbus_stepper/src/canstepper.bin and b/F0-nolib/CANbus_stepper/src/canstepper.bin differ diff --git a/F0-nolib/CANbus_stepper/src/spi.c b/F0-nolib/CANbus_stepper/src/spi.c index 9dbddf2..335eb41 100644 --- a/F0-nolib/CANbus_stepper/src/spi.c +++ b/F0-nolib/CANbus_stepper/src/spi.c @@ -32,7 +32,7 @@ void spi_setup(){ /* (2) AF0 for SPI1 signals */ GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER5 | GPIO_MODER_MODER6 | GPIO_MODER_MODER7)) | (GPIO_MODER_MODER5_AF | GPIO_MODER_MODER6_AF | GPIO_MODER_MODER7_AF); /* (1) */ - GPIOA->AFR[0] = (GPIOA->AFR[0] & (GPIO_AFRL_AFRL5 | GPIO_AFRL_AFRL6 | GPIO_AFRL_AFRL7)); /* (2) */ + GPIOA->AFR[0] = (GPIOA->AFR[0] & ~(GPIO_AFRL_AFRL5 | GPIO_AFRL_AFRL6 | GPIO_AFRL_AFRL7)); /* (2) */ // Configure DMA SPI /* Enable the peripheral clock DMA11 */ RCC->AHBENR |= RCC_AHBENR_DMA1EN; diff --git a/F0-nolib/F0_testbrd/Makefile b/F0-nolib/F0_testbrd/Makefile index ccda417..0e07fa0 100644 --- a/F0-nolib/F0_testbrd/Makefile +++ b/F0-nolib/F0_testbrd/Makefile @@ -7,7 +7,6 @@ FAMILY = F0 #MCU = F042x6 MCU = F072xB # hardware definitions -DEFS += -DUSARTNUM=1 #DEFS += -DCHECK_TMOUT #DEFS += -DEBUG # change this linking script depending on particular MCU model diff --git a/F0-nolib/F0_testbrd/Readme.md b/F0-nolib/F0_testbrd/Readme.md index 50ad9db..91f95ee 100644 --- a/F0-nolib/F0_testbrd/Readme.md +++ b/F0-nolib/F0_testbrd/Readme.md @@ -1 +1,2 @@ -Simple test for STM32F0x2, blinking PA0, PWM for TIM14CH1, two user buttons (PA14 and PA15) and USB (PL2303 emulator) <> USART1 echo. +Simple test for STM32F0x2, PWM for all 4 channels of TIM3, USB (PL2303 emulator); USART1/2/3, SPI1/2, +I2C1 tests, ADC1 IN0/1 connected to variable resistor. diff --git a/F0-nolib/F0_testbrd/adc.c b/F0-nolib/F0_testbrd/adc.c index 65880fc..fa786bb 100644 --- a/F0-nolib/F0_testbrd/adc.c +++ b/F0-nolib/F0_testbrd/adc.c @@ -21,9 +21,12 @@ /** * @brief ADC_array - array for ADC channels with median filtering: * 0 - Rvar - * 1 - internal Tsens - * 2 - Vref + * 1 - Rvar/2 + * 2 - internal Tsens + * 3 - Vref */ +#define CHTSENS (2) +#define CHVREF (3) uint16_t ADC_array[NUMBER_OF_ADC_CHANNELS*9]; /** @@ -51,12 +54,20 @@ uint16_t getADCval(int nch){ #undef PIX_SWAP } +// get voltage @input nch (1/100V) +uint32_t getADCvoltate(int nch){ + uint32_t v = getADCval(nch); + v *= getVdd(); + v /= 0xfff; // 12bit ADC + return v; +} + // return MCU temperature (degrees of celsius * 10) int32_t getMCUtemp(){ - getVdd(); +// getVdd(); // make correction on Vdd value // int32_t temperature = (int32_t)ADC_array[4] * VddValue / 330; - int32_t ADval = getADCval(1); + int32_t ADval = getADCval(CHTSENS); int32_t temperature = (int32_t) *TEMP30_CAL_ADDR - ADval; temperature *= (int32_t)(1100 - 300); temperature /= (int32_t)(*TEMP30_CAL_ADDR - *TEMP110_CAL_ADDR); @@ -64,9 +75,9 @@ int32_t getMCUtemp(){ return(temperature); } -// return Vdd * 100 (V) +// return Vdd (1/100V) uint32_t getVdd(){ uint32_t vdd = ((uint32_t) *VREFINT_CAL_ADDR) * (uint32_t)330; // 3.3V - vdd /= getADCval(2); + vdd /= getADCval(CHVREF); return vdd; } diff --git a/F0-nolib/F0_testbrd/adc.h b/F0-nolib/F0_testbrd/adc.h index fe26926..d797087 100644 --- a/F0-nolib/F0_testbrd/adc.h +++ b/F0-nolib/F0_testbrd/adc.h @@ -19,11 +19,12 @@ #define ADC_H #include "stm32f0.h" -#define NUMBER_OF_ADC_CHANNELS (3) +#define NUMBER_OF_ADC_CHANNELS (4) extern uint16_t ADC_array[]; int32_t getMCUtemp(); uint32_t getVdd(); uint16_t getADCval(int nch); +uint32_t getADCvoltate(int nch); #endif // ADC_H diff --git a/F0-nolib/F0_testbrd/hardware.c b/F0-nolib/F0_testbrd/hardware.c index 716eb3c..021ed31 100644 --- a/F0-nolib/F0_testbrd/hardware.c +++ b/F0-nolib/F0_testbrd/hardware.c @@ -23,28 +23,49 @@ #include "adc.h" #include "hardware.h" -#include "usart.h" + +void iwdg_setup(){ + uint32_t tmout = 16000000; + /* Enable the peripheral clock RTC */ + /* (1) Enable the LSI (40kHz) */ + /* (2) Wait while it is not ready */ + RCC->CSR |= RCC_CSR_LSION; /* (1) */ + while((RCC->CSR & RCC_CSR_LSIRDY) != RCC_CSR_LSIRDY){if(--tmout == 0) break;} /* (2) */ + /* Configure IWDG */ + /* (1) Activate IWDG (not needed if done in option bytes) */ + /* (2) Enable write access to IWDG registers */ + /* (3) Set prescaler by 64 (1.6ms for each tick) */ + /* (4) Set reload value to have a rollover each 2s */ + /* (5) Check if flags are reset */ + /* (6) Refresh counter */ + IWDG->KR = IWDG_START; /* (1) */ + IWDG->KR = IWDG_WRITE_ACCESS; /* (2) */ + IWDG->PR = IWDG_PR_PR_1; /* (3) */ + IWDG->RLR = 1250; /* (4) */ + tmout = 16000000; + while(IWDG->SR){if(--tmout == 0) break;} /* (5) */ + IWDG->KR = IWDG_REFRESH; /* (6) */ +} static inline void gpio_setup(){ // here we turn on clocking for all periph. RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_DMAEN; - // Set LEDS (PA0/4) as Oun & AF (PWM) - GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER0 | GPIO_MODER_MODER4) - ) | - GPIO_MODER_MODER0_O | GPIO_MODER_MODER4_AF ; - pin_set(LED0_port, LED0_pin); // clear LEDs - pin_set(LED1_port, LED1_pin); - // Buttons - PA14/15 - GPIOA->PUPDR = (GPIOA->PUPDR & ~(GPIO_PUPDR_PUPDR14 | GPIO_PUPDR_PUPDR15) - ) | - GPIO_PUPDR_PUPDR14_0 | GPIO_PUPDR_PUPDR15_0; - // alternate functions: PA4 - TIM14_CH1 (AF4) - GPIOA->AFR[0] = (GPIOA->AFR[0] &~ (GPIO_AFRL_AFRL4)) \ - | (4 << (4 * 4)) ; + // Set LEDS (PA6-8, PB0/1) as Oun & AF (PWM) + GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER6 | GPIO_MODER_MODER7 | GPIO_MODER_MODER8)) | + GPIO_MODER_MODER6_AF | GPIO_MODER_MODER7_AF | GPIO_MODER_MODER8_AF; + GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER0 | GPIO_MODER_MODER1)) | + GPIO_MODER_MODER0_AF | GPIO_MODER_MODER1_AF; + // alternate functions: PA6-8: TIM3CH1,2 and TIM1_CH1 (AF1, AF1, AF2) + // PB0-1: TIM3CH3,4 (AF1, AF1) + GPIOA->AFR[0] = (GPIOA->AFR[0] & ~(GPIO_AFRL_AFRL6 | GPIO_AFRL_AFRL7)) | + (1 << (6 * 4)) | (1 << (7 * 4)); + GPIOA->AFR[1] = (GPIOA->AFR[1] & ~(GPIO_AFRH_AFRH0)) | + (2 << (0 * 4)); + GPIOB->AFR[0] = (GPIOB->AFR[0] & ~(GPIO_AFRL_AFRL0 | GPIO_AFRL_AFRL1)) | + (1 << (0 * 4)) | (1 << (1 * 4)); } static inline void adc_setup(){ - GPIOB->MODER = GPIO_MODER_MODER0_AI; // PB0 - ADC channel 8 uint16_t ctr = 0; // 0xfff0 - more than 1.3ms // Enable clocking /* (1) Enable the peripheral clock of the ADC */ @@ -72,12 +93,12 @@ static inline void adc_setup(){ // configure ADC /* (1) Select HSI14 by writing 00 in CKMODE (reset value) */ /* (2) Select the continuous mode */ - /* (3) Select CHSEL0..3 - ADC inputs, 16,17 - t. sensor and vref */ + /* (3) Select CHSEL0,1 - ADC inputs, 16,17 - t. sensor and vref */ /* (4) Select a sampling mode of 111 i.e. 239.5 ADC clk to be greater than 17.1us */ /* (5) Wake-up the VREFINT and Temperature sensor (only for VBAT, Temp sensor and VRefInt) */ // ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; /* (1) */ ADC1->CFGR1 |= ADC_CFGR1_CONT; /* (2)*/ - ADC1->CHSELR = ADC_CHSELR_CHSEL8 | ADC_CHSELR_CHSEL16 | ADC_CHSELR_CHSEL17; /* (3)*/ + ADC1->CHSELR = ADC_CHSELR_CHSEL0 | ADC_CHSELR_CHSEL1 | ADC_CHSELR_CHSEL16 | ADC_CHSELR_CHSEL17; /* (3)*/ ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2; /* (4) */ ADC->CCR |= ADC_CCR_TSEN | ADC_CCR_VREFEN; /* (5) */ // configure DMA for ADC @@ -100,16 +121,32 @@ static inline void adc_setup(){ } static inline void pwm_setup(){ - RCC->APB1ENR |= RCC_APB1ENR_TIM14EN; // enable clocking for tim14 + // enable clocking for tim1 & tim3 + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; + RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // PWM mode 2 - TIM14->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; - TIM14->PSC = 5; // frequency - 8MHz for 31kHz PWM + TIM1->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; + TIM3->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0 | + TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_0; + TIM3->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0 | + TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_0; + // frequency - 8MHz for 31kHz PWM + TIM1->PSC = 5; + TIM3->PSC = 5; // ARR for 8-bit PWM - TIM14->ARR = 254; - TIM14->CCR1 = 127; // half light - TIM14->BDTR |= TIM_BDTR_MOE; // start in OFF state - TIM14->CCER = TIM_CCER_CC1E; // enable PWM output - TIM14->CR1 |= TIM_CR1_CEN; // enable timer + TIM1->ARR = 254; + TIM3->ARR = 254; + TIM1->CCR1 = 127; + TIM3->CCR1 = 63; TIM3->CCR2 = 127; TIM3->CCR3 = 191; TIM3->CCR4 = 250; + // enable main output + TIM1->BDTR |= TIM_BDTR_MOE; + TIM3->BDTR |= TIM_BDTR_MOE; + // enable PWM outputs + TIM1->CCER = TIM_CCER_CC1E; + TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E; + // start timers + TIM1->CR1 |= TIM_CR1_CEN; + TIM3->CR1 |= TIM_CR1_CEN; } void hw_setup(){ diff --git a/F0-nolib/F0_testbrd/hardware.h b/F0-nolib/F0_testbrd/hardware.h index 09b8b45..5c37479 100644 --- a/F0-nolib/F0_testbrd/hardware.h +++ b/F0-nolib/F0_testbrd/hardware.h @@ -30,42 +30,17 @@ #define STR_HELPER(s) #s #define STR(s) STR_HELPER(s) -#define FORMUSART(X) CONCAT(USART, X) -#define USARTX FORMUSART(USARTNUM) -#if USARTNUM == 2 - #define USARTDMA DMA1_Channel4 - #define DMAIRQn DMA1_Channel4_5_IRQn - #define USARTIRQn USART2_IRQn -#elif USARTNUM == 1 - #define USARTDMA DMA1_Channel2 - #define DMAIRQn DMA1_Channel2_3_IRQn - #define USARTIRQn USART1_IRQn -#else -#error "Wrong USARTNUM" -#endif +// PWM LEDS +#define SET_LED_PWM3(ch, N) do{TIM3->CCR ## ch = (uint32_t)N;}while(0) +#define GET_LED_PWM3(ch) (uint8_t)(TIM3->CCR ## ch) +#define SET_LED_PWM1(N) do{TIM1->CCR1 = (uint32_t)N;}while(0) +#define GET_LED_PWM1() (uint8_t)(TIM1->CCR1) -// LEDS: 0 - PA0, 1 - PA4 -// LED0 - blinking each second -#define LED0_port GPIOA -#define LED0_pin (1<<0) -// LED1 - PWM -#define LED1_port GPIOA -#define LED1_pin (1<<4) -#define SET_LED_PWM(N) do{TIM14->CCR1 = (uint32_t)N;}while(0) -#define GET_LED_PWM() (uint8_t)(TIM14->CCR1) - -// Buttons' state: PA14 (1)/PA15 (0) -#define GET_BTN0() ((GPIOA->IDR & (1<<15)) ? 0 : 1) -#define GET_BTN1() ((GPIOA->IDR & (1<<14)) ? 0 : 1) - -// USB pullup (not used in STM32F0x2!) - PA13 +// USB pullup (not used in STM32F0x2!) - PA15 #define USBPU_port GPIOA -#define USBPU_pin (1<<13) - -#define LED_blink(x) pin_toggle(x ## _port, x ## _pin) -#define LED_on(x) pin_clear(x ## _port, x ## _pin) -#define LED_off(x) pin_set(x ## _port, x ## _pin) +#define USBPU_pin (1<<15) +void iwdg_setup(); void hw_setup(); #endif // __HARDWARE_H__ diff --git a/F0-nolib/F0_testbrd/main.c b/F0-nolib/F0_testbrd/main.c index 2d862ae..ca228e1 100644 --- a/F0-nolib/F0_testbrd/main.c +++ b/F0-nolib/F0_testbrd/main.c @@ -22,6 +22,7 @@ #include "adc.h" #include "hardware.h" #include "usart.h" +#include "proto.h" #include "usb.h" #include "usb_lib.h" @@ -32,138 +33,13 @@ void sys_tick_handler(void){ ++Tms; } -void iwdg_setup(){ - uint32_t tmout = 16000000; - /* Enable the peripheral clock RTC */ - /* (1) Enable the LSI (40kHz) */ - /* (2) Wait while it is not ready */ - RCC->CSR |= RCC_CSR_LSION; /* (1) */ - while((RCC->CSR & RCC_CSR_LSIRDY) != RCC_CSR_LSIRDY){if(--tmout == 0) break;} /* (2) */ - /* Configure IWDG */ - /* (1) Activate IWDG (not needed if done in option bytes) */ - /* (2) Enable write access to IWDG registers */ - /* (3) Set prescaler by 64 (1.6ms for each tick) */ - /* (4) Set reload value to have a rollover each 2s */ - /* (5) Check if flags are reset */ - /* (6) Refresh counter */ - IWDG->KR = IWDG_START; /* (1) */ - IWDG->KR = IWDG_WRITE_ACCESS; /* (2) */ - IWDG->PR = IWDG_PR_PR_1; /* (3) */ - IWDG->RLR = 1250; /* (4) */ - tmout = 16000000; - while(IWDG->SR){if(--tmout == 0) break;} /* (5) */ - IWDG->KR = IWDG_REFRESH; /* (6) */ -} - -#define USND(str) do{USB_send((uint8_t*)str, sizeof(str)-1);}while(0) -char *parse_cmd(char *buf){ - static char btns[] = "BTN0=0, BTN1=0\n"; - if(buf[1] != '\n') return buf; - uint8_t pwm; - switch(*buf){ - case '+': - pwm = GET_LED_PWM(); - if(pwm < 255){ - SET_LED_PWM(pwm+1); - return u2str(GET_LED_PWM()); - }else return "MAX!\n"; - break; - case '-': - pwm = GET_LED_PWM(); - if(pwm > 0){ - SET_LED_PWM(pwm-1); - return u2str(GET_LED_PWM()); - }else return "MIN!\n"; - break; - case 'b': - btns[5] = GET_BTN0() + '0'; - btns[13] = GET_BTN1() + '0'; - return btns; - break; - case 'g': - return u2str(GET_LED_PWM()); - break; - case 'A': - return u2str(getADCval(0)); - break; - case 'L': - USND("Very long test string for USB (it's length is more than 64 bytes).\n" - "This is another part of the string! Can you see all of this?\n"); - return "Long test sent\n"; - break; - case 'R': - USND("Soft reset\n"); - SEND("Soft reset\n"); - NVIC_SystemReset(); - break; - case 'S': - USND("Test string for USB\n"); - return "Short test sent\n"; - break; - case 'T': - return u2str(getMCUtemp()); - break; - case 'V': - return u2str(getVdd()); - break; - case 'W': - USND("Wait for reboot\n"); - SEND("Wait for reboot\n"); - while(1){nop();}; - break; - default: // help - return - "'+'/'-' - increase/decrease PWM by 1\n" - "'b' - get buttons's state\n" - "'g' - get LED PWM value\n" - "'A' - get ADC8 value\n" - "'L' - send long string over USB\n" - "'R' - software reset\n" - "'S' - send short string over USB\n" - "'T' - MCU temperature\n" - "'V' - Vdd\n" - "'W' - test watchdog\n" - ; - break; - } - return NULL; -} - -// usb getline -char *get_USB(){ - static char tmpbuf[129], *curptr = tmpbuf; - static int rest = 128; - int x = USB_receive((uint8_t*)curptr); - curptr[x] = 0; - if(!x) return NULL; - if(curptr[x-1] == '\n'){ - curptr = tmpbuf; - rest = 128; - return tmpbuf; - } - curptr += x; rest -= x; - if(rest <= 0){ // buffer overflow - curptr = tmpbuf; - rest = 128; - } - return NULL; -} - int main(void){ - uint32_t lastT = 0, lastB = 0; + uint32_t lastT = 0; sysreset(); SysTick_Config(6000, 1); hw_setup(); usart_setup(); - SEND("Hello! I'm ready.\n"); - - if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured - SEND("WDGRESET=1\n"); - } - if(RCC->CSR & RCC_CSR_SFTRSTF){ // software reset occured - SEND("SOFTRESET=1\n"); - } RCC->CSR |= RCC_CSR_RMVF; // remove reset flags USB_setup(); @@ -172,49 +48,30 @@ int main(void){ while (1){ IWDG->KR = IWDG_REFRESH; // refresh watchdog if(lastT > Tms || Tms - lastT > 499){ - LED_blink(LED0); lastT = Tms; transmit_tbuf(); // non-blocking transmission of data from UART buffer every 0.5s } usb_proc(); - int r = 0; - char *txt, *ans; + char *txt; if((txt = get_USB())){ - ans = parse_cmd(txt); - SEND("Received data over USB:\n"); - SEND(txt); - newline(); + const char *ans = parse_cmd(txt); if(ans){ - uint16_t l = 0; char *p = ans; + uint16_t l = 0; const char *p = ans; while(*p++) l++; USB_send((uint8_t*)ans, l); if(ans[l-1] != '\n') USND("\n"); } } - if(usartrx()){ // usart1 received data, store in in buffer - r = usart_getline(&txt); - if(r){ - txt[r] = 0; - ans = parse_cmd(txt); - if(ans){ - usart_send(ans); - transmit_tbuf(); + for(int n = 1; n <= USARTNUM; ++n){ + if(usartrx(n)){ // usart1 received data, store in in buffer + int r = usart_getline(n, &txt); + if(r){ + txt[r] = 0; + USND("Got string over USART"); USB_sendstr(u2str(n)); + USND(":\n"); USB_sendstr(txt); } } } - // check buttons - each 50ms - if(Tms - lastB > 49){ - lastB = Tms; - uint8_t btn0 = GET_BTN0(), btn1 = GET_BTN1(), pwm = GET_LED_PWM(); - // both: set to middle - if(btn0 && btn1){ - SET_LED_PWM(127); - }else if(btn0){ - if(pwm < 255) SET_LED_PWM(pwm+1); - }else if(btn1){ - if(pwm > 0) SET_LED_PWM(pwm-1); - } - } } return 0; } diff --git a/F0-nolib/F0_testbrd/pl2303.bin b/F0-nolib/F0_testbrd/pl2303.bin index 46628c0..72d91b7 100755 Binary files a/F0-nolib/F0_testbrd/pl2303.bin and b/F0-nolib/F0_testbrd/pl2303.bin differ diff --git a/F0-nolib/F0_testbrd/proto.c b/F0-nolib/F0_testbrd/proto.c new file mode 100644 index 0000000..b0dbad4 --- /dev/null +++ b/F0-nolib/F0_testbrd/proto.c @@ -0,0 +1,355 @@ +/* + * This file is part of the F0testbrd project. + * Copyright 2021 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "adc.h" +#include "proto.h" +#include "usart.h" +#include "usb.h" +#include "usb_lib.h" + +void USB_sendstr(const char *str){ + uint16_t l = 0; + const char *b = str; + while(*b++) ++l; + USB_send((const uint8_t*)str, l); +} + +static char *chPWM(volatile uint32_t *reg, char *buf){ + char *lbuf = buf; + lbuf = omit_spaces(lbuf); + char cmd = *lbuf; + lbuf = omit_spaces(lbuf + 1); + uint32_t N; + if(getnum(lbuf, &N) == lbuf) N = 1; + uint32_t oldval = *reg; + if(cmd == '-'){ // decrement + if(oldval < N) return "Already at minimum"; + else *reg -= N; + }else if(cmd == '+'){ // increment + if(oldval + N > 255) return "Already at maximum"; + else *reg += N; + }else{ + USND("Wrong command: "); + return buf; + } + return "OK"; +} + +static char *TIM3pwm(char *buf){ + uint8_t channel = *buf - '1'; + if(channel > 3) return "Wrong channel number"; + volatile uint32_t *reg = &TIM3->CCR1; + return chPWM(®[channel], buf+1); +} + +static char *getPWMvals(){ + USND("TIM1CH1: "); USB_sendstr(u2str(TIM1->CCR1)); + USND("\nTIM3CH1: "); USB_sendstr(u2str(TIM3->CCR1)); + USND("\nTIM3CH2: "); USB_sendstr(u2str(TIM3->CCR2)); + USND("\nTIM3CH3: "); USB_sendstr(u2str(TIM3->CCR3)); + USND("\nTIM3CH4: "); USB_sendstr(u2str(TIM3->CCR4)); + USND("\n"); + return NULL; +} + +static char *USARTsend(char *buf){ + uint32_t N; + if(buf == getnum(buf, &N)) return "Point number of USART"; + if(N < 1 || N > USARTNUM) return "Wrong USART number"; + buf = omit_spaces(buf + 1); + usart_send(N, buf); + transmit_tbuf(); + return "OK"; +} + +const char *helpstring = + "'+'/'-'[num] - increase/decrease TIM1ch1 PWM by 1 or `num`\n" + "1..4'+'/'-'[num] - increase/decrease TIM3chN PWM by 1 or `num`\n" + "'g' - get PWM values\n" + "'A' - get ADC values\n" + "'L' - send long string over USB\n" + "'R' - software reset\n" + "'S' - send short string over USB\n" + "'Ux' - send string to USARTx (1..3)\n" + "'T' - MCU temperature\n" + "'V' - Vdd\n" + "'W' - test watchdog\n" +; + +const char *parse_cmd(char *buf){ + // "long" commands + switch(*buf){ + case '+': + case '-': + return chPWM(&TIM1->CCR1, buf); + break; + case '1': + case '2': + case '3': + case '4': + return TIM3pwm(buf); + case 'U': + return USARTsend(buf + 1); + break; + } + // "short" commands + if(buf[1] != '\n') return buf; + switch(*buf){ + case 'g': + return getPWMvals(); + break; + case 'A': + USND("ADC0: "); USB_sendstr(u2str(getADCval(0))); + USND(" ("); USB_sendstr(u2str(getADCvoltate(0))); + USND("/100 V)\nADC1: "); USB_sendstr(u2str(getADCval(1))); + USND(" ("); USB_sendstr(u2str(getADCvoltate(1))); + USND("/100 V)\n"); + break; + case 'L': + USND("Very long test string for USB (it's length is more than 64 bytes).\n" + "This is another part of the string! Can you see all of this?\n"); + return "Long test sent"; + break; + case 'R': + USND("Soft reset\n"); + //SEND("Soft reset\n"); + NVIC_SystemReset(); + break; + case 'S': + USND("Test string for USB\n"); + return "Short test sent"; + break; + case 'T': + return u2str(getMCUtemp()); + break; + case 'V': + return u2str(getVdd()); + break; + case 'W': + USND("Wait for reboot\n"); + //SEND("Wait for reboot\n"); + while(1){nop();}; + break; + default: // help + return helpstring; + break; + } + return NULL; +} + +// usb getline +char *get_USB(){ + static char tmpbuf[129], *curptr = tmpbuf; + static int rest = 128; + int x = USB_receive((uint8_t*)curptr); + curptr[x] = 0; + if(!x) return NULL; + if(curptr[x-1] == '\n'){ + curptr = tmpbuf; + rest = 128; + return tmpbuf; + } + curptr += x; rest -= x; + if(rest <= 0){ // buffer overflow + curptr = tmpbuf; + rest = 128; + } + return NULL; +} + + +static char *_2str(uint32_t val, uint8_t minus){ + static char strbuf[12]; + char *bufptr = &strbuf[11]; + *bufptr = 0; + if(!val){ + *(--bufptr) = '0'; + }else{ + while(val){ + *(--bufptr) = val % 10 + '0'; + val /= 10; + } + } + if(minus) *(--bufptr) = '-'; + return bufptr; +} + +// return string with number `val` +char *u2str(uint32_t val){ + return _2str(val, 0); +} +char *i2str(int32_t i){ + uint8_t minus = 0; + uint32_t val; + if(i < 0){ + minus = 1; + val = -i; + }else val = i; + return _2str(val, minus); +} +// print 32bit unsigned int as hex +char *uhex2str(uint32_t val){ + static char buf[12] = "0x"; + int npos = 2; + uint8_t *ptr = (uint8_t*)&val + 3; + int8_t i, j, z=1; + for(i = 0; i < 4; ++i, --ptr){ + if(*ptr == 0){ // omit leading zeros + if(i == 3) z = 0; + if(z) continue; + } + else z = 0; + for(j = 1; j > -1; --j){ + uint8_t half = (*ptr >> (4*j)) & 0x0f; + if(half < 10) buf[npos++] = half + '0'; + else buf[npos++] = half - 10 + 'a'; + } + } + buf[npos] = 0; + return buf; +} + +char *omit_spaces(const char *buf){ + while(*buf){ + if(*buf > ' ') break; + ++buf; + } + return (char*)buf; +} + +// In case of overflow return `buf` and N==0xffffffff +// read decimal number & return pointer to next non-number symbol +static char *getdec(const char *buf, uint32_t *N){ + char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '9'){ + break; + } + if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow + *N = 0xffffff; + return start; + } + num *= 10; + num += c - '0'; + ++buf; + } + *N = num; + return (char*)buf; +} +// read hexadecimal number (without 0x prefix!) +static char *gethex(const char *buf, uint32_t *N){ + char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + uint8_t M = 0; + if(c >= '0' && c <= '9'){ + M = '0'; + }else if(c >= 'A' && c <= 'F'){ + M = 'A' - 10; + }else if(c >= 'a' && c <= 'f'){ + M = 'a' - 10; + } + if(M){ + if(num & 0xf0000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 4; + num += c - M; + }else{ + break; + } + ++buf; + } + *N = num; + return (char*)buf; +} +// read octal number (without 0 prefix!) +static char *getoct(const char *buf, uint32_t *N){ + char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '7'){ + break; + } + if(num & 0xe0000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 3; + num += c - '0'; + ++buf; + } + *N = num; + return (char*)buf; +} +// read binary number (without b prefix!) +static char *getbin(const char *buf, uint32_t *N){ + char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '1'){ + break; + } + if(num & 0x80000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 1; + if(c == '1') num |= 1; + ++buf; + } + *N = num; + return (char*)buf; +} + +/** + * @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111) + * @param buf - buffer with number and so on + * @param N - the number read + * @return pointer to first non-number symbol in buf + * (if it is == buf, there's no number or if *N==0xffffffff there was overflow) + */ +char *getnum(const char *txt, uint32_t *N){ + char *nxt = NULL; + char *s = omit_spaces(txt); + if(*s == '0'){ // hex, oct or 0 + if(s[1] == 'x' || s[1] == 'X'){ // hex + nxt = gethex(s+2, N); + if(nxt == s+2) nxt = (char*)txt; + }else if(s[1] > '0'-1 && s[1] < '8'){ // oct + nxt = getoct(s+1, N); + if(nxt == s+1) nxt = (char*)txt; + }else{ // 0 + nxt = s+1; + *N = 0; + } + }else if(*s == 'b' || *s == 'B'){ + nxt = getbin(s+1, N); + if(nxt == s+1) nxt = (char*)txt; + }else{ + nxt = getdec(s, N); + if(nxt == s) nxt = (char*)txt; + } + return nxt; +} diff --git a/F0-nolib/F0_testbrd/proto.h b/F0-nolib/F0_testbrd/proto.h new file mode 100644 index 0000000..0318b36 --- /dev/null +++ b/F0-nolib/F0_testbrd/proto.h @@ -0,0 +1,34 @@ +/* + * This file is part of the F0testbrd project. + * Copyright 2021 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#ifndef PROTO_H__ +#define PROTO_H__ + +#define USND(str) do{USB_send((uint8_t*)str, sizeof(str)-1);}while(0) + +void USB_sendstr(const char *str); +char *get_USB(); +const char *parse_cmd(char *buf); + +char *u2str(uint32_t val); +char *i2str(int32_t i); +char *uhex2str(uint32_t val); +char *getnum(const char *txt, uint32_t *N); +char *omit_spaces(const char *buf); + +#endif // PROTO_H__ diff --git a/F0-nolib/F0_testbrd/usart.c b/F0-nolib/F0_testbrd/usart.c index 4915aba..8c612cd 100644 --- a/F0-nolib/F0_testbrd/usart.c +++ b/F0-nolib/F0_testbrd/usart.c @@ -20,240 +20,232 @@ */ #include "stm32f0.h" #include "hardware.h" +#include "proto.h" #include "usart.h" +#include "usb.h" #include extern volatile uint32_t Tms; -static volatile int idatalen[2] = {0,0}; // received data line length (including '\n') -static volatile int odatalen[2] = {0,0}; +// USART tx DMA 1: DMA1_Channel2, 2: DMA1_Channel4, 3: DMA1_Channel7 +static DMA_Channel_TypeDef *USARTDMA[USARTNUM] = { + DMA1_Channel2, DMA1_Channel4 +#ifdef USART3 + ,DMA1_Channel7 +#endif +}; +static USART_TypeDef *USARTs[USARTNUM] = { + USART1, USART2 +#ifdef USART3 + ,USART3 +#endif +}; -volatile int linerdy = 0, // received data ready - dlen = 0, // length of data (including '\n') in current buffer - bufovr = 0, // input buffer overfull - txrdy = 1 // transmission done +static volatile int idatalen[USARTNUM][2] = {0}; // received data line length (including '\n') +static volatile int odatalen[USARTNUM][2] = {0}; + +volatile int linerdy[USARTNUM] = {0}, // received data ready + dlen[USARTNUM] = {0}, // length of data (including '\n') in current buffer + bufovr[USARTNUM] = {0}, // input buffer overfull + txrdy[USARTNUM] = {1,1 // transmission done +#ifdef USART3 + ,1 +#endif + } ; -int rbufno = 0, tbufno = 0; // current rbuf/tbuf numbers -static char rbuf[2][UARTBUFSZI], tbuf[2][UARTBUFSZO]; // receive & transmit buffers -static char *recvdata = NULL; +int rbufno[USARTNUM] = {0}, tbufno[USARTNUM] = {0}; // current rbuf/tbuf numbers +static char rbuf[USARTNUM][2][UARTBUFSZI], tbuf[USARTNUM][2][UARTBUFSZO]; // receive & transmit buffers +static char *recvdata[USARTNUM] = {0}; /** * return length of received data (without trailing zero + * usartno: 1, 2 or 3 */ -int usart_getline(char **line){ - if(bufovr){ - bufovr = 0; - linerdy = 0; +int usart_getline(int usartno, char **line){ + --usartno; + if(bufovr[usartno]){ + bufovr[usartno] = 0; + linerdy[usartno] = 0; return 0; } - *line = recvdata; - linerdy = 0; - return dlen; + *line = recvdata[usartno]; + linerdy[usartno] = 0; + return dlen[usartno]; } -// transmit current tbuf and swap buffers +// transmit current tbuf for all USARTs and swap buffers void transmit_tbuf(){ - uint32_t tmout = 16000000; - while(!txrdy){if(--tmout == 0) break;}; // wait for previos buffer transmission - register int l = odatalen[tbufno]; - if(!l) return; - txrdy = 0; - odatalen[tbufno] = 0; - USARTDMA->CCR &= ~DMA_CCR_EN; - USARTDMA->CMAR = (uint32_t) tbuf[tbufno]; // mem - USARTDMA->CNDTR = l; - USARTDMA->CCR |= DMA_CCR_EN; - tbufno = !tbufno; -} - -void usart_putchar(const char ch){ - if(odatalen[tbufno] == UARTBUFSZO) transmit_tbuf(); - tbuf[tbufno][odatalen[tbufno]++] = ch; -} - -void usart_send(const char *str){ - uint32_t x = 512; - while(*str && --x){ - if(odatalen[tbufno] == UARTBUFSZO) transmit_tbuf(); - tbuf[tbufno][odatalen[tbufno]++] = *str++; + for(int usartno = 0; usartno < USARTNUM; ++usartno){ + uint32_t p = 1000000; + while(!txrdy[usartno] && --p); + if(!txrdy[usartno]) continue; + register int l = odatalen[usartno][tbufno[usartno]]; + if(!l) continue; + txrdy[usartno] = 0; + odatalen[usartno][tbufno[usartno]] = 0; + USARTDMA[usartno]->CCR &= ~DMA_CCR_EN; + USARTDMA[usartno]->CMAR = (uint32_t) tbuf[usartno][tbufno[usartno]]; // mem + USARTDMA[usartno]->CNDTR = l; + USARTDMA[usartno]->CCR |= DMA_CCR_EN; + tbufno[usartno] = !tbufno[usartno]; } } -void usart_sendn(const char *str, uint8_t L){ - for(uint8_t i = 0; i < L; ++i){ - if(odatalen[tbufno] == UARTBUFSZO) transmit_tbuf(); - tbuf[tbufno][odatalen[tbufno]++] = *str++; +void usart_putchar(int usartno, const char ch){ + --usartno; + if(odatalen[usartno][tbufno[usartno]] == UARTBUFSZO) transmit_tbuf(); + tbuf[usartno][tbufno[usartno]][odatalen[usartno][tbufno[usartno]]++] = ch; +} + +void usart_send(int usartno, const char *str){ + --usartno; + while(*str){ + if(odatalen[usartno][tbufno[usartno]] == UARTBUFSZO) transmit_tbuf(); + tbuf[usartno][tbufno[usartno]][odatalen[usartno][tbufno[usartno]]++] = *str++; } } -void newline(){ - usart_putchar('\n'); +void usart_sendn(int usartno, const char *str, uint32_t L){ + --usartno; + for(uint32_t i = 0; i < L; ++i){ + if(odatalen[usartno][tbufno[usartno]] == UARTBUFSZO) transmit_tbuf(); + tbuf[usartno][tbufno[usartno]][odatalen[usartno][tbufno[usartno]]++] = *str++; + } +} + +void newline(int usartno){ + usart_putchar(usartno, '\n'); transmit_tbuf(); } void usart_setup(){ - uint32_t tmout = 16000000; -// Nucleo's USART2 connected to VCP proxy of st-link -#if USARTNUM == 2 - // setup pins: PA2 (Tx - AF1), PA15 (Rx - AF1) - // AF mode (AF1) - GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER2|GPIO_MODER_MODER15))\ - | (GPIO_MODER_MODER2_AF | GPIO_MODER_MODER15_AF); - GPIOA->AFR[0] = (GPIOA->AFR[0] &~GPIO_AFRH_AFRH2) | 1 << (2 * 4); // PA2 - GPIOA->AFR[1] = (GPIOA->AFR[1] &~GPIO_AFRH_AFRH7) | 1 << (7 * 4); // PA15 - RCC->APB1ENR |= RCC_APB1ENR_USART2EN; // clock -// USART1 of main board -#elif USARTNUM == 1 - // PA9 - Tx, PA10 - Rx (AF1) - GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10))\ - | (GPIO_MODER_MODER9_AF | GPIO_MODER_MODER10_AF); + // USART1: Rx - PA10, Tx - PA9 (AF1) + // USART2: Rx - PA3, Tx - PA2 (AF1) + // USART3: Rx - PB11, Tx - PB10 (AF4) + // setup pins: + GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER2|GPIO_MODER_MODER3|GPIO_MODER_MODER9 | GPIO_MODER_MODER10)) | + GPIO_MODER_MODER2_AF | GPIO_MODER_MODER3_AF | GPIO_MODER_MODER9_AF | GPIO_MODER_MODER10_AF; + GPIOA->AFR[0] = (GPIOA->AFR[0] & ~(GPIO_AFRL_AFRL2 | GPIO_AFRL_AFRL3)) | + 1 << (2 * 4) | 1 << (3 * 4); // PA2,3 GPIOA->AFR[1] = (GPIOA->AFR[1] & ~(GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2)) | 1 << (1 * 4) | 1 << (2 * 4); // PA9, PA10 + // clock RCC->APB2ENR |= RCC_APB2ENR_USART1EN; -#else -#error "Wrong USARTNUM" + RCC->APB1ENR |= RCC_APB1ENR_USART2EN; +#ifdef USART3 + GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER10 | GPIO_MODER_MODER11)) | + GPIO_MODER_MODER10_AF | GPIO_MODER_MODER11_AF; + GPIOB->AFR[1] = (GPIOB->AFR[1] & ~(GPIO_AFRH_AFRH2 | GPIO_AFRH_AFRH3)) | + 4 << (2 * 4) | 4 << (3 * 4); // PB10, PB11 +#endif + for(int i = 0; i < USARTNUM; ++i){ + USARTs[i]->ICR = 0xffffffff; // clear all flags + // USARTX Tx DMA + USARTDMA[i]->CPAR = (uint32_t) &USARTs[i]->TDR; // periph + USARTDMA[i]->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq + // setup usarts + USARTs[i]->BRR = 480000 / 1152; + USARTs[i]->CR3 = USART_CR3_DMAT; // enable DMA Tx + USARTs[i]->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE | USART_CR1_RXNEIE; // 1start,8data,nstop; enable Rx,Tx,USART + uint32_t tmout = 16000000; + while(!(USARTs[i]->ISR & USART_ISR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission + USARTs[i]->ICR = 0xffffffff; // clear all flags again + } + NVIC_SetPriority(DMA1_Channel2_3_IRQn, 3); + NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); + NVIC_SetPriority(USART1_IRQn, 0); + NVIC_EnableIRQ(USART1_IRQn); + NVIC_SetPriority(DMA1_Channel4_5_6_7_IRQn, 3); + NVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn); + NVIC_SetPriority(USART2_IRQn, 0); + NVIC_EnableIRQ(USART2_IRQn); +#ifdef USART3 + NVIC_SetPriority(USART3_4_IRQn, 0); + NVIC_EnableIRQ(USART3_4_IRQn); #endif - // USARTX Tx DMA - USARTDMA->CPAR = (uint32_t) &USARTX->TDR; // periph - USARTDMA->CMAR = (uint32_t) tbuf; // mem - USARTDMA->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(DMAIRQn, 3); - NVIC_EnableIRQ(DMAIRQn); - NVIC_SetPriority(USARTIRQn, 0); - // setup usart1 - USARTX->BRR = 480000 / 1152; - USARTX->CR3 = USART_CR3_DMAT; // enable DMA Tx - USARTX->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART - while(!(USARTX->ISR & USART_ISR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission - USARTX->ICR |= USART_ICR_TCCF; // clear TC flag - USARTX->CR1 |= USART_CR1_RXNEIE; - NVIC_EnableIRQ(USARTIRQn); } -#if USARTNUM == 2 -void usart2_isr(){ -// USART1 -#elif USARTNUM == 1 -void usart1_isr(){ -#else -#error "Wrong USARTNUM" -#endif + +static void usart_IRQ(int usartno){ + USART_TypeDef *USARTX = USARTs[usartno]; + //USND("USART"); USB_sendstr(u2str(usartno+1)); USND(" IRQ, ISR="); + //USB_sendstr(uhex2str(USARTX->ISR)); USND("\n"); #ifdef CHECK_TMOUT - static uint32_t tmout = 0; + static uint32_t tmout[USARTNUM] = {0}; #endif if(USARTX->ISR & USART_ISR_RXNE){ // RX not emty - receive next char #ifdef CHECK_TMOUT - if(tmout && Tms >= tmout){ // set overflow flag - bufovr = 1; - idatalen[rbufno] = 0; + if(tmout[usartno] && Tms >= tmout[usartno]){ // set overflow flag + bufovr[usartno] = 1; + idatalen[usartno][rbufno[usartno]] = 0; } - tmout = Tms + TIMEOUT_MS; - if(!tmout) tmout = 1; // prevent 0 + tmout[usartno] = Tms + TIMEOUT_MS; + if(!tmout[usartno]) tmout[usartno] = 1; // prevent 0 #endif // read RDR clears flag uint8_t rb = USARTX->RDR; - if(idatalen[rbufno] < UARTBUFSZI){ // put next char into buf - rbuf[rbufno][idatalen[rbufno]++] = rb; + //USND("RB="); USB_sendstr(uhex2str(rb)); USND("\n"); + if(idatalen[usartno][rbufno[usartno]] < UARTBUFSZI){ // put next char into buf + rbuf[usartno][rbufno[usartno]][idatalen[usartno][rbufno[usartno]]++] = rb; if(rb == '\n'){ // got newline - line ready - linerdy = 1; - dlen = idatalen[rbufno]; - recvdata = rbuf[rbufno]; + //USND("Newline\n"); + linerdy[usartno] = 1; + dlen[usartno] = idatalen[usartno][rbufno[usartno]]; + recvdata[usartno] = rbuf[usartno][rbufno[usartno]]; // prepare other buffer - rbufno = !rbufno; - idatalen[rbufno] = 0; + rbufno[usartno] = !rbufno[usartno]; + idatalen[usartno][rbufno[usartno]] = 0; #ifdef CHECK_TMOUT // clear timeout at line end - tmout = 0; + tmout[usartno] = 0; #endif } }else{ // buffer overrun - bufovr = 1; - idatalen[rbufno] = 0; + bufovr[usartno] = 1; + idatalen[usartno][rbufno[usartno]] = 0; #ifdef CHECK_TMOUT - tmout = 0; + tmout[usartno] = 0; #endif } } + USARTX->ICR = 0xffffffff; } -// return string buffer with val -char *u2str(uint32_t val){ - static char bufa[11]; - char bufb[10]; - int l = 0, bpos = 0; - if(!val){ - bufa[0] = '0'; - l = 1; - }else{ - while(val){ - bufb[l++] = val % 10 + '0'; - val /= 10; - } - int i; - bpos += l; - for(i = 0; i < l; ++i){ - bufa[--bpos] = bufb[i]; - } - } - bufa[l + bpos] = 0; - return bufa; -} -// print 32bit unsigned int -void printu(uint32_t val){ - usart_send(u2str(val)); +void usart1_isr(){ + usart_IRQ(0); } -// print 32bit unsigned int as hex -void printuhex(uint32_t val){ - usart_send("0x"); - uint8_t *ptr = (uint8_t*)&val + 3, start = 1; - int i, j; - for(i = 0; i < 4; ++i, --ptr){ - if(!*ptr && start) continue; - for(j = 1; j > -1; --j){ - start = 0; - register uint8_t half = (*ptr >> (4*j)) & 0x0f; - if(half < 10) usart_putchar(half + '0'); - else usart_putchar(half - 10 + 'a'); - } - } - if(start){ - usart_putchar('0'); - usart_putchar('0'); - } +void usart2_isr(){ + usart_IRQ(1); } -// dump memory buffer -void hexdump(uint8_t *arr, uint16_t len){ - for(uint16_t l = 0; l < len; ++l, ++arr){ - for(int16_t j = 1; j > -1; --j){ - register uint8_t half = (*arr >> (4*j)) & 0x0f; - if(half < 10) usart_putchar(half + '0'); - else usart_putchar(half - 10 + 'a'); - } - if(l % 16 == 15) usart_putchar('\n'); - else if(l & 1) usart_putchar(' '); - } -} -#if USARTNUM == 2 -void dma1_channel4_5_isr(){ - if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx - DMA1->IFCR |= DMA_IFCR_CTCIF4; // clear TC flag - txrdy = 1; - } +// work with USART3 only @ boards that have it +#ifdef USART3 +void usart3_4_isr(){ + usart_IRQ(2); } +#endif + // USART1 -#elif USARTNUM == 1 void dma1_channel2_3_isr(){ if(DMA1->ISR & DMA_ISR_TCIF2){ // Tx DMA1->IFCR |= DMA_IFCR_CTCIF2; // clear TC flag - txrdy = 1; + txrdy[0] = 1; } } -#else -#error "Wrong USARTNUM" +// USART2 + USART3 +void dma1_channel4_5_isr(){ + if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx + DMA1->IFCR |= DMA_IFCR_CTCIF4; // clear TC flag + txrdy[1] = 1; + } +#ifdef USART3 + if(DMA1->ISR & DMA_ISR_TCIF7){ // Tx + DMA1->IFCR |= DMA_IFCR_CTCIF7; // clear TC flag + txrdy[2] = 1; + } #endif +} diff --git a/F0-nolib/F0_testbrd/usart.h b/F0-nolib/F0_testbrd/usart.h index ae4f618..32e758f 100644 --- a/F0-nolib/F0_testbrd/usart.h +++ b/F0-nolib/F0_testbrd/usart.h @@ -24,6 +24,13 @@ #include "hardware.h" +#ifdef USART3 +#define USARTNUM (3) +#else +#define USARTNUM (2) +#endif + + // input and output buffers size #define UARTBUFSZI (32) #define UARTBUFSZO (512) @@ -33,23 +40,19 @@ #endif // macro for static strings -#define SEND(str) usart_send(str) +#define SEND(n, str) usart_send(n, str) -#define usartrx() (linerdy) -#define usartovr() (bufovr) +#define usartrx(n) (linerdy[n-1]) +#define usartovr(n) (bufovr[n-1]) -extern volatile int linerdy, bufovr, txrdy; +extern volatile int linerdy[], bufovr[], txrdy[]; void transmit_tbuf(); void usart_setup(); -int usart_getline(char **line); -void usart_send(const char *str); -void usart_sendn(const char *str, uint8_t L); -void newline(); -void usart_putchar(const char ch); -char *u2str(uint32_t val); -void printu(uint32_t val); -void printuhex(uint32_t val); -void hexdump(uint8_t *arr, uint16_t len); +int usart_getline(int usartno, char **line); +void usart_send(int usartno, const char *str); +void usart_sendn(int usartno, const char *str, uint32_t L); +void newline(int usartno); +void usart_putchar(int usartno, const char ch); #endif // __USART_H__ diff --git a/F0-nolib/F0_testbrd/usb.c b/F0-nolib/F0_testbrd/usb.c index aed0e0f..57872ab 100644 --- a/F0-nolib/F0_testbrd/usb.c +++ b/F0-nolib/F0_testbrd/usb.c @@ -23,7 +23,6 @@ #include "usb.h" #include "usb_lib.h" -#include "usart.h" static volatile uint8_t tx_succesfull = 1; static volatile uint8_t rxNE = 0; @@ -162,7 +161,6 @@ void usb_proc(){ */ uint8_t USB_receive(uint8_t *buf){ if(!usbON || !rxNE) return 0; - SEND((char*)buf); newline(); uint8_t sz = EP_Read(2, buf); uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]); // keep stat_tx & set ACK rx diff --git a/F0-nolib/F0_testbrd/usb_lib.c b/F0-nolib/F0_testbrd/usb_lib.c index 187c84b..d99f687 100644 --- a/F0-nolib/F0_testbrd/usb_lib.c +++ b/F0-nolib/F0_testbrd/usb_lib.c @@ -22,7 +22,6 @@ */ #include -#include "usart.h" #include "usb_lib.h" diff --git a/F0_F1_F3-LQFP48_testboard/stm32 b/F0_F1_F3-LQFP48_testboard/stm32 deleted file mode 100644 index e7214dd..0000000 --- a/F0_F1_F3-LQFP48_testboard/stm32 +++ /dev/null @@ -1,30 +0,0 @@ -"Source:","/Big/Data/00__Electronics/STM32/F0_F1_F3-LQFP48_testboard/stm32.sch" -"Date:","óÒ 23 ÉÀÎ 2021 22:52:44" -"Tool:","Eeschema 5.1.10" -"Generator:","/usr/share/kicad/plugins/bom_csv_grouped_by_value_with_fp.py" -"Component Count:","54" -"Ref","Qnty","Value","Cmp name","Footprint","Description","Vendor" -"C1, C2, C3, C7, C8, C9, C10, ","7","0.1","C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","","" -"C4, ","1","47u","CP","Capacitor_Tantalum_SMD:CP_EIA-6032-28_Kemet-C_Pad2.25x2.35mm_HandSolder","","" -"C5, C6, ","2","12","C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","","" -"D1, D2, D3, D4, D5, D6, ","6","LED","LED-RESCUE-stm32","LED_THT:LED_D3.0mm","","" -"J1, J5, J6, J7, J8, J9, J11, ","7","Conn_01x04_Female","Conn_01x04_Female","Connector_PinSocket_2.54mm:PinSocket_1x04_P2.54mm_Vertical","Generic connector, single row, 01x04, script generated (kicad-library-utils/schlib/autogen/connector/)","" -"J2, J4, J10, J12, ","4","Conn_01x01_Female","Conn_01x01_Female","Connector_PinSocket_2.54mm:PinSocket_1x01_P2.54mm_Vertical","Generic connector, single row, 01x01, script generated (kicad-library-utils/schlib/autogen/connector/)","" -"J3, ","1","Conn_01x02_Female","Conn_01x02_Female","Connector_PinSocket_2.54mm:PinSocket_1x02_P2.54mm_Vertical","Generic connector, single row, 01x02, script generated (kicad-library-utils/schlib/autogen/connector/)","" -"P1, ","1","USART1","Conn_01x03_Female","Connector_PinSocket_2.54mm:PinSocket_1x03_P2.54mm_Vertical","Generic connector, single row, 01x03, script generated (kicad-library-utils/schlib/autogen/connector/)","" -"P2, ","1","USART2/3","Conn_01x03_Female","Connector_PinSocket_2.54mm:PinSocket_1x03_P2.54mm_Vertical","Generic connector, single row, 01x03, script generated (kicad-library-utils/schlib/autogen/connector/)","" -"P3, ","1","USB_B","USB_A-RESCUE-stm32","Connector_USB:USB_B_OST_USB-B1HSxx_Horizontal","","" -"Q1, ","1","DTA114Y","DTA114Y","Package_TO_SOT_SMD:SOT-323_SC-70_Handsoldering","Digital PNP Transistor, 10k/47k, SOT-23","" -"R1, R2, R14, R15, ","4","4k7","R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","","" -"R3, ","1","10k","R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","","" -"R5, ","1","100k","R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","","" -"R6, R7, R8, R9, R10, R11, ","6","220","R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","","" -"R12, R13, ","2","22","R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","","" -"R16, ","1","1k5","R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","","" -"RV1, ","1","20k","R_POT","my_footprints:Potentiometer","Potentiometer","" -"SW1, ","1","Reset","SW_Push","Button_Switch_THT:SW_PUSH_6mm","","" -"SW2, ","1","Boot","SW_Push","Button_Switch_THT:SW_PUSH_6mm","","" -"U1, ","1","LM1117-3.3","LM1117-3.3-RESCUE-stm32","Package_TO_SOT_SMD:SOT-223","","" -"U2, ","1","STM32LQFP48","STM32F042C6Tx","Package_DIP:DIP-48_W15.24mm_Socket_LongPads","","" -"U3, ","1","USBLC6-2SC6","USBLC6-2SC6","Package_TO_SOT_SMD:SOT-23-6_Handsoldering","Bidirectional ESD Protection Diode, SOT-23-6","" -"Y1, ","1","8MHz","Crystal","Crystal:Crystal_HC49-U_Vertical","Two pin crystal","" diff --git a/F0_F1_F3-LQFP48_testboard/stm32.bom b/F0_F1_F3-LQFP48_testboard/stm32.bom index 6015de6..0893acb 100644 --- a/F0_F1_F3-LQFP48_testboard/stm32.bom +++ b/F0_F1_F3-LQFP48_testboard/stm32.bom @@ -1,73 +1,30 @@ -"Source:","/home/eddy/Docs/SAO/ELECTRONICS/STM32/F0-srcs/F0_F1_testboard/kicad/stm32.sch" -"Date:","þÔ 16 ÍÁÑ 2019 13:55:26" -"Tool:","Eeschema (6.0.0-rc1-dev-1613-ga55d9819b)" -"Generator:","/usr/local/share/kicad/plugins/bom_csv_grouped_by_value.py" -"Component Count:","35" - -"Individual Components:" - -"Item","Qty","Reference(s)","Value","LibPart","Footprint","Datasheet" -"","","C1","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","C2","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","C3","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","C4","47u","stm32-rescue:CP","Capacitor_Tantalum_SMD:CP_EIA-3216-18_Kemet-A_Pad1.58x1.35mm_HandSolder","" -"","","C5","12","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","C6","12","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","C7","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","C8","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","C9","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","C10","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","D1","LED","stm32-rescue:LED-RESCUE-stm32","LED_THT:LED_D3.0mm","" -"","","D2","IP4220CZ6","Power_Protection:SP0505BAHT","TO_SOT_Packages_SMD:SOT-23-6_Handsoldering","http://www.littelfuse.com/~/media/files/littelfuse/technical%20resources/documents/data%20sheets/sp05xxba.pdf" -"","","D3","LED","stm32-rescue:LED-RESCUE-stm32","LED_THT:LED_D5.0mm","" -"","","D4","LED","stm32-rescue:LED-RESCUE-stm32","LED_THT:LED_D5.0mm","" -"","","P1","USART1","stm32-rescue:CONN_01X03","Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical","" -"","","P2","USB_B","stm32-rescue:USB_A-RESCUE-stm32","Connectors_USB:USB_Micro-B_Wuerth_629105150521","" -"","","Q1","DTA114Y","Transistor_BJT:DTA114Y","TO_SOT_Packages_SMD:SOT-323_SC-70_Handsoldering","" -"","","R1","10k","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","R2","10k","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","R3","100k","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","R4","220","stm32-rescue:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","" -"","","R5","220","stm32-rescue:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","" -"","","R6","220","stm32-rescue:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","" -"","","R7","22","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","R8","22","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","R9","1k5","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"","","RV1","10k","Device:R_POT","my_footprints:Potentiometer","~" -"","","SW1","Reset","stm32-rescue:SW_Push","Button_Switch_THT:SW_PUSH_6mm","" -"","","SW2","Boot","stm32-rescue:SW_Push","Button_Switch_THT:SW_PUSH_6mm","" -"","","SW3","Button0","stm32-rescue:SW_Push","Button_Switch_THT:SW_PUSH_6mm","" -"","","SW4","Button1","stm32-rescue:SW_Push","Button_Switch_THT:SW_PUSH_6mm","" -"","","U1","LM1117-3.3","stm32-rescue:LM1117-3.3-RESCUE-stm32","TO_SOT_Packages_SMD:SOT-223","" -"","","U2","STM32F042C6Tx","stm32-rescue:STM32F042C6Tx","Package_DIP:DIP-48_W15.24mm_Socket_LongPads","" -"","","U3","USBLC6-2SC6","Power_Protection:USBLC6-2SC6","TO_SOT_Packages_SMD:SOT-23-6_Handsoldering","http://www2.st.com/resource/en/datasheet/CD00050750.pdf" -"","","Y1","8MHz","Device:Crystal","Crystal:Crystal_HC49-U_Vertical","~" - - - -"Collated Components:" - -"Item","Qty","Reference(s)","Value","LibPart","Footprint","Datasheet" -"1","7","C1, C2, C3, C7, C8, C9, C10","0.1","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"2","1","C4","47u","stm32-rescue:CP","Capacitor_Tantalum_SMD:CP_EIA-3216-18_Kemet-A_Pad1.58x1.35mm_HandSolder","" -"3","2","C5, C6","12","stm32-rescue:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"4","1","D1","LED","stm32-rescue:LED-RESCUE-stm32","LED_THT:LED_D3.0mm","" -"5","1","D2","IP4220CZ6","Power_Protection:SP0505BAHT","TO_SOT_Packages_SMD:SOT-23-6_Handsoldering","http://www.littelfuse.com/~/media/files/littelfuse/technical%20resources/documents/data%20sheets/sp05xxba.pdf" -"6","2","D3, D4","LED","stm32-rescue:LED-RESCUE-stm32","LED_THT:LED_D5.0mm","" -"7","1","P1","USART1","stm32-rescue:CONN_01X03","Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical","" -"8","1","P2","USB_B","stm32-rescue:USB_A-RESCUE-stm32","Connectors_USB:USB_Micro-B_Wuerth_629105150521","" -"9","1","Q1","DTA114Y","Transistor_BJT:DTA114Y","TO_SOT_Packages_SMD:SOT-323_SC-70_Handsoldering","" -"10","2","R1, R2","10k","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"11","1","R3","100k","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"12","3","R4, R5, R6","220","stm32-rescue:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","" -"13","2","R7, R8","22","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"14","1","R9","1k5","stm32-rescue:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","" -"15","1","RV1","10k","Device:R_POT","my_footprints:Potentiometer","~" -"16","1","SW1","Reset","stm32-rescue:SW_Push","Button_Switch_THT:SW_PUSH_6mm","" -"17","1","SW2","Boot","stm32-rescue:SW_Push","Button_Switch_THT:SW_PUSH_6mm","" -"18","1","SW3","Button0","stm32-rescue:SW_Push","Button_Switch_THT:SW_PUSH_6mm","" -"19","1","SW4","Button1","stm32-rescue:SW_Push","Button_Switch_THT:SW_PUSH_6mm","" -"20","1","U1","LM1117-3.3","stm32-rescue:LM1117-3.3-RESCUE-stm32","TO_SOT_Packages_SMD:SOT-223","" -"21","1","U2","STM32F042C6Tx","stm32-rescue:STM32F042C6Tx","Package_DIP:DIP-48_W15.24mm_Socket_LongPads","" -"22","1","U3","USBLC6-2SC6","Power_Protection:USBLC6-2SC6","TO_SOT_Packages_SMD:SOT-23-6_Handsoldering","http://www2.st.com/resource/en/datasheet/CD00050750.pdf" -"23","1","Y1","8MHz","Device:Crystal","Crystal:Crystal_HC49-U_Vertical","~" +"Source:","/Big/Data/00__Electronics/STM32/F0_F1_F3-LQFP48_testboard/stm32.sch" +"Date:","þÔ 24 ÉÀÎ 2021 22:21:07" +"Tool:","Eeschema 5.1.10" +"Generator:","/usr/share/kicad/plugins/bom_csv_grouped_by_value_with_fp.py" +"Component Count:","54" +"Ref","Qnty","Value","Cmp name","Footprint","Description","Vendor" +"C1, C2, C3, C7, C8, C9, C10, ","7","0.1","C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","","" +"C4, ","1","47u","CP","Capacitor_Tantalum_SMD:CP_EIA-6032-28_Kemet-C_Pad2.25x2.35mm_HandSolder","","" +"C5, C6, ","2","12","C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder","","" +"D1, D2, D3, D4, D5, D6, ","6","LED","LED-RESCUE-stm32","LED_THT:LED_D3.0mm","","" +"J1, J5, J6, J7, J8, J9, J11, ","7","Conn_01x04_Female","Conn_01x04_Female","Connector_PinSocket_2.54mm:PinSocket_1x04_P2.54mm_Vertical","Generic connector, single row, 01x04, script generated (kicad-library-utils/schlib/autogen/connector/)","" +"J2, J4, J10, J12, ","4","Conn_01x01_Female","Conn_01x01_Female","Connector_PinSocket_2.54mm:PinSocket_1x01_P2.54mm_Vertical","Generic connector, single row, 01x01, script generated (kicad-library-utils/schlib/autogen/connector/)","" +"J3, ","1","Conn_01x02_Female","Conn_01x02_Female","Connector_PinSocket_2.54mm:PinSocket_1x02_P2.54mm_Vertical","Generic connector, single row, 01x02, script generated (kicad-library-utils/schlib/autogen/connector/)","" +"P1, ","1","USART1","Conn_01x03_Female","Connector_PinSocket_2.54mm:PinSocket_1x03_P2.54mm_Vertical","Generic connector, single row, 01x03, script generated (kicad-library-utils/schlib/autogen/connector/)","" +"P2, ","1","USART2/3","Conn_01x03_Female","Connector_PinSocket_2.54mm:PinSocket_1x03_P2.54mm_Vertical","Generic connector, single row, 01x03, script generated (kicad-library-utils/schlib/autogen/connector/)","" +"P3, ","1","USB_B","USB_A-RESCUE-stm32","Connector_USB:USB_B_OST_USB-B1HSxx_Horizontal","","" +"Q1, ","1","DTA114Y","DTA114Y","Package_TO_SOT_SMD:SOT-323_SC-70_Handsoldering","Digital PNP Transistor, 10k/47k, SOT-23","" +"R1, R2, R14, R15, ","4","4k7","R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","","" +"R3, ","1","10k","R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","","" +"R5, ","1","100k","R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","","" +"R6, R7, R8, R9, R10, R11, ","6","220","R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder","","" +"R12, R13, ","2","22","R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","","" +"R16, ","1","1k5","R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","","" +"RV1, ","1","20k","R_POT","my_footprints:Potentiometer","Potentiometer","" +"SW1, ","1","Reset","SW_Push","Button_Switch_THT:SW_PUSH_6mm","","" +"SW2, ","1","Boot","SW_Push","Button_Switch_THT:SW_PUSH_6mm","","" +"U1, ","1","LM1117-3.3","LM1117-3.3-RESCUE-stm32","Package_TO_SOT_SMD:SOT-223","","" +"U2, ","1","STM32LQFP48","STM32F042C6Tx","Package_DIP:DIP-48_W15.24mm_Socket_LongPads","","" +"U3, ","1","USBLC6-2SC6","USBLC6-2SC6","Package_TO_SOT_SMD:SOT-23-6_Handsoldering","Bidirectional ESD Protection Diode, SOT-23-6","" +"Y1, ","1","8MHz","Crystal","Crystal:Crystal_HC49-U_Vertical","Two pin crystal",""