Skip to content

Commit

Permalink
Firmware revision 6
Browse files Browse the repository at this point in the history
+ Brushed mode
+ Drag brake at 75% by default
+ DSHOT command 40 (select timing)
+ DSHOT command 41 (select PWM frequency)

Support for GD32F350
New targets: LUMENIER1
Drop WWDG for predictable flash programming
Minor bug fixes
  • Loading branch information
neoxic committed Aug 12, 2023
1 parent 59f0e64 commit 8178db2
Show file tree
Hide file tree
Showing 14 changed files with 375 additions and 45 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ add_target(HGLRC1 STM32F051 DEAD_TIME=26 COMP_MAP=123 SENS_MAP=0xA6 VOLT_MUL=210
add_target(IFLIGHT1 STM32F051 DEAD_TIME=26 COMP_MAP=321 SENS_MAP=0xA3A6 VOLT_MUL=110 CURR_MUL=20 LED_MAP=0xB8B5B3 LED_INV)
add_target(IFLIGHT2 STM32G071 DEAD_TIME=35 COMP_MAP=213 SENS_MAP=0xA5A4 VOLT_MUL=110 CURR_MUL=20 LED_WS2812 IO_PA6)
add_target(IFLIGHT3 STM32G071 DEAD_TIME=35 COMP_MAP=132 SENS_MAP=0xA0 VOLT_MUL=110 LED_WS2812)
add_target(LUMENIER1 GD32F350 DEAD_TIME=57 COMP_MAP=321 SENS_MAP=0xA3 VOLT_MUL=110)
add_target(NEUTRONRC1 STM32G071 DEAD_TIME=35 COMP_MAP=123 SENS_MAP=0xA6A4 VOLT_MUL=210 CURR_MUL=50 LED_WS2812)
add_target(NEUTRONRC2 AT32F421 DEAD_TIME=66 COMP_MAP=321)
add_target(SKYSTARS1 GD32E230 DEAD_TIME=40 COMP_MAP=321 SENS_MAP=0xA3 VOLT_MUL=110 LED_MAP=0xB5B3A15)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Features
+ Analog/serial/iBUS/SBUS input mode
+ KISS/iBUS/S.Port telemetry
+ DSHOT 3D mode, turtle mode, beacon, LED, programming
+ Sine startup mode (crawler mode)
+ Sine startup mode (crawler mode), brushed mode
+ Proportional brake, drag brake
+ Temperature/voltage/current protection
+ Variable PWM frequency, active freewheeling
Expand Down
6 changes: 3 additions & 3 deletions boot/src/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ void initio(void) {
USART2_CR3 = USART_CR3_HDSEL;
USART2_CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
#else
TIM3_SMCR = TIM_SMCR_SMS_RM | TIM_SMCR_TS_TI1F_ED; // Reset on any edge on TI1
TIM3_CCMR1 = TIM_CCMR1_OC1PE | TIM_CCMR1_OC1M_PWM2 | TIM_CCMR1_CC2S_IN_TI1 | TIM_CCMR1_IC2F_CK_INT_N_8;
TIM3_CCER = TIM_CCER_CC2E | TIM_CCER_CC2P; // IC2 on falling edge on TI1
TIM3_ARR = CLK_CNT(38400) - 1; // Bit time
TIM3_CCR1 = CLK_CNT(76800); // Half-bit time
TIM3_EGR = TIM_EGR_UG;
TIM3_CR1 = TIM_CR1_CEN;
TIM3_SMCR = TIM_SMCR_SMS_RM | TIM_SMCR_TS_TI1F_ED; // Reset on any edge on TI1
TIM3_CCMR1 = TIM_CCMR1_OC1PE | TIM_CCMR1_OC1M_PWM2 | TIM_CCMR1_CC2S_IN_TI1 | TIM_CCMR1_IC2F_CK_INT_N_8;
TIM3_CCER = TIM_CCER_CC2E | TIM_CCER_CC2P; // IC2 on falling edge on TI1
#endif
TIM14_PSC = CLK / 10000 - 1; // 0.1ms resolution
TIM14_ARR = 4999; // 500ms I/O timeout
Expand Down
194 changes: 194 additions & 0 deletions mcu/GD32F350/config.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/*
** Copyright (C) 2022-2023 Arseny Vakhrushev <arseny.vakhrushev@me.com>
**
** This firmware 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 firmware 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 firmware. If not, see <http://www.gnu.org/licenses/>.
*/

#include <libopencm3/cm3/common.h>
#include <libopencm3/stm32/f1/adc.h>
#include "common.h"

#define ADC1_BASE ADC_BASE
#define COMP_CSR MMIO32(SYSCFG_COMP_BASE + 0x1c)

static char len, ain;
static uint16_t buf[5];

void init(void) {
RCC_CFGR &= ~RCC_CFGR_SW_PLL;
while (RCC_CFGR & RCC_CFGR_SWS_PLL);
RCC_CR &= ~RCC_CR_PLLON;
RCC_CFGR = 0x8240000; // PLLMUL=11001 (x26)
RCC_CR |= RCC_CR_PLLON;
while (!(RCC_CR & RCC_CR_PLLRDY));
RCC_CFGR |= RCC_CFGR_SW_PLL;

RCC_APB2RSTR = -1;
RCC_APB1RSTR = -1;
RCC_APB2RSTR = 0;
RCC_APB1RSTR = 0;
RCC_AHBENR = RCC_AHBENR_DMAEN | RCC_AHBENR_SRAMEN | RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN;
RCC_APB2ENR = RCC_APB2ENR_SYSCFGCOMPEN | RCC_APB2ENR_ADCEN | RCC_APB2ENR_TIM1EN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_TIM17EN;
RCC_APB1ENR = RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM14EN | RCC_APB1ENR_WWDGEN;
SCB_VTOR = (uint32_t)_rom; // Set vector table address

// Default GPIO state - analog input
GPIOA_AFRL = 0x20000000; // A7 (TIM1_CH1N)
GPIOA_AFRH = 0x00000222; // A8 (TIM1_CH1), A9 (TIM1_CH2), A10 (TIM1_CH3)
GPIOB_AFRL = 0x00000022; // B0 (TIM1_CH2N), B1 (TIM1_CH3N)
GPIOB_AFRH = 0x00000000;
GPIOA_PUPDR = 0x24000000;
GPIOB_PUPDR = 0x00001000; // B6 (pull-up)
GPIOA_MODER = 0xebeabfff; // A7 (TIM1_CH1N), A8 (TIM1_CH1), A9 (TIM1_CH2), A10 (TIM1_CH3)
GPIOB_MODER = 0xffffeffa; // B0 (TIM1_CH2N), B1 (TIM1_CH3N), B6 (USART1_TX)
#ifndef ANALOG
#ifdef IO_PA2
RCC_APB2ENR |= RCC_APB2ENR_TIM15EN;
GPIOA_PUPDR |= 0x10; // A2 (pull-up)
GPIOA_MODER &= ~0x10; // A2 (TIM15_CH1)
#else
RCC_APB1ENR |= RCC_APB1ENR_TIM3EN;
GPIOB_AFRL |= 0x10000; // B4 (TIM3_CH1)
GPIOB_PUPDR |= 0x100; // B4 (pull-up)
GPIOB_MODER &= ~0x100; // B4 (TIM3_CH1)
#endif
#endif

nvic_set_priority(NVIC_TIM3_IRQ, 0x40);
nvic_set_priority(NVIC_TIM15_IRQ, 0x40);
nvic_set_priority(NVIC_USART1_IRQ, 0x80);
nvic_set_priority(NVIC_USART2_IRQ, 0x40);
nvic_set_priority(NVIC_DMA1_CHANNEL1_IRQ, 0x80); // ADC
nvic_set_priority(NVIC_DMA1_CHANNEL2_3_DMA2_CHANNEL1_2_IRQ, 0x80); // USART1
nvic_set_priority(NVIC_DMA1_CHANNEL4_7_DMA2_CHANNEL3_5_IRQ, 0x40); // TIM3 or TIM15 or USART2

nvic_enable_irq(NVIC_TIM1_BRK_UP_TRG_COM_IRQ);
nvic_enable_irq(NVIC_TIM1_CC_IRQ);
nvic_enable_irq(NVIC_TIM2_IRQ);
nvic_enable_irq(NVIC_TIM3_IRQ);
nvic_enable_irq(NVIC_TIM15_IRQ);
nvic_enable_irq(NVIC_USART1_IRQ);
nvic_enable_irq(NVIC_USART2_IRQ);
nvic_enable_irq(NVIC_DMA1_CHANNEL1_IRQ);
nvic_enable_irq(NVIC_DMA1_CHANNEL2_3_DMA2_CHANNEL1_2_IRQ);
nvic_enable_irq(NVIC_DMA1_CHANNEL4_7_DMA2_CHANNEL3_5_IRQ);

RCC_CR2 |= RCC_CR2_HSI14ON; // Enable IRC28M
while (!(RCC_CR2 & RCC_CR2_HSI14RDY));
ADC1_CR2 = ADC_CR2_ADON | ADC_CR2_TSVREFE;
TIM17_ARR = CLK_MHZ - 1;
TIM17_CR1 = TIM_CR1_CEN | TIM_CR1_OPM;
while (TIM17_CR1 & TIM_CR1_CEN); // Wait for 1us (RM 11.4.1)
ADC1_CR2 |= ADC_CR2_CAL;
while (ADC1_CR2 & ADC_CR2_CAL);
ADC1_CR1 = ADC_CR1_SCAN;
ADC1_SMPR1 = -1; // Sampling time ~17us @ IRC28M/2=14Mhz
ADC1_SMPR2 = -1;
ADC1_SQR3 = SENS_CHAN;
len = SENS_CNT;
if (IO_ANALOG) {
ADC1_SQR3 |= THROT_CHAN << (len++ * 5);
ain = 1;
}
ADC1_SQR3 |= 0x230 << (len * 5); // CH16 (temp), CH17 (vref)
len += 2;
ADC1_SQR1 = (len - 1) << ADC_SQR1_L_LSB;
DMA1_CPAR(1) = (uint32_t)&ADC1_DR;
DMA1_CMAR(1) = (uint32_t)buf;

TIM1_DIER = TIM_DIER_UIE | TIM_DIER_CC1IE | TIM_DIER_CC4IE; // Software comparator blanking, ADC trigger
TIM1_SMCR = TIM_SMCR_TS_ITR1; // TRGI=TIM2
TIM2_CR2 = TIM_CR2_MMS_COMPARE_OC1REF; // TRGO=OC1REF
TIM2_CCMR1 = TIM_CCMR1_OC1PE | TIM_CCMR1_OC1M_PWM2; // Inverted PWM on OC1
TIM2_CCMR2 = TIM_CCMR2_CC4S_IN_TI4 | TIM_CCMR2_IC4F_DTF_DIV_16_N_8;
TIM2_CCER = TIM_CCER_CC4E; // IC4 on rising edge on TI4 (COMP1_OUT)
}

void compctl(int x) {
int cr = 0;
switch (x & 3) {
case COMP_IN1:
cr = 0x61; // A1>A0
break;
case COMP_IN2:
cr = 0x41; // A1>A4
break;
case COMP_IN3:
cr = 0x51; // A1>A5
break;
}
if (x & 4) cr |= 0x800; // Change polarity
COMP_CSR = cr;
}

void io_serial(void) {
TIM15_DIER = 0;
nvic_clear_pending_irq(NVIC_TIM15_IRQ);
RCC_APB2ENR &= ~RCC_APB2ENR_TIM15EN;
RCC_APB1ENR |= RCC_APB1ENR_USART2EN;
GPIOA_AFRL |= 0x100; // A2 (USART2_TX)
}

void io_analog(void) {
TIM15_DIER = 0;
nvic_clear_pending_irq(NVIC_TIM15_IRQ);
RCC_APB2ENR &= ~RCC_APB2ENR_TIM15EN;
GPIOA_PUPDR &= ~0x30; // A2 (no pull-up/pull-down)
GPIOA_MODER |= 0x30; // A2 (analog)
}

void adc_trig(void) {
if (DMA1_CCR(1) & DMA_CCR_EN) return;
DMA1_CNDTR(1) = len;
DMA1_CCR(1) = DMA_CCR_EN | DMA_CCR_TCIE | DMA_CCR_MINC | DMA_CCR_PSIZE_16BIT | DMA_CCR_MSIZE_16BIT;
ADC1_CR2 = ADC_CR2_ADON | ADC_CR2_TSVREFE | ADC_CR2_DMA | ADC_CR2_EXTTRIG | ADC_CR2_EXTSEL_SWSTART;
}

void tim1_brk_up_trg_com_isr(void) {
int sr = TIM1_SR;
if (sr & TIM_SR_UIF) {
TIM1_SR = ~TIM_SR_UIF;
if (TIM1_CCR4) COMP_CSR &= ~0x700; // COMP_OUT off
}
if (sr & TIM_SR_COMIF) tim1_com_isr();
}

void tim1_cc_isr(void) {
int sr = TIM1_SR;
if (sr & TIM_SR_CC4IF) {
TIM1_SR = ~TIM_SR_CC4IF;
COMP_CSR |= 0x400; // COMP1_OUT=TIM2_IC4
}
if (!(sr & TIM_SR_CC1IF)) return;
TIM1_SR = ~TIM_SR_CC1IF;
if (!(ADC1_CR2 & ADC_CR2_DMA)) return;
ADC1_CR2 = ADC_CR2_ADON | ADC_CR2_TSVREFE | ADC_CR2_DMA | ADC_CR2_EXTTRIG | ADC_CR2_EXTSEL_SWSTART | ADC_CR2_SWSTART;
}

void dma1_channel1_isr(void) {
DMA1_IFCR = DMA_IFCR_CTCIF(1);
DMA1_CCR(1) = 0;
ADC1_CR2 = ADC_CR2_ADON | ADC_CR2_TSVREFE;
int i = 0, v = 0, c = 0, x = 0;
#if SENS_CNT == 2
c = buf[i++];
#endif
#if SENS_CNT >= 1
v = buf[i++];
#endif
if (ain) x = buf[i++];
int r = 4914000 / buf[i + 1];
int t = (1450 - (buf[i] * r >> 12)) * 10 / 43 + 25;
adc_data(t, v * r >> 12, c * r >> 12, x);
}
3 changes: 3 additions & 0 deletions mcu/GD32F350/config.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
set(opts -mcpu=cortex-m4 -mthumb)
set(libs opencm3_stm32f0)
set(defs STM32F0)
59 changes: 59 additions & 0 deletions mcu/GD32F350/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
** Copyright (C) 2022-2023 Arseny Vakhrushev <arseny.vakhrushev@me.com>
**
** This firmware 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 firmware 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 firmware. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#if SENS_MAP == 0xA3 // A3 (volt)
#define SENS_CNT 1
#define SENS_CHAN 0x3
#endif

#ifndef THROT_CHAN
#define THROT_CHAN 2 // A2
#endif

#define CLK 104000000

#define IFTIM TIM2
#define IFTIM_ICF 128
#define IFTIM_ICE TIM_DIER_CC4IE
#define IFTIM_ICR TIM2_CCR4
#define IFTIM_OCR TIM2_CCR1
#define iftim_isr tim2_isr

#ifdef IO_PA2
#define IO_TYPE 0
#define IOTIM TIM15
#define IOTIM_IDR (GPIOA_IDR & 0x4) // A2
#define IOTIM_DMA 5
#define iotim_isr tim15_isr
#else
#define IO_TYPE 2
#define IOTIM TIM3
#define IOTIM_IDR (GPIOB_IDR & 0x10) // B4
#define IOTIM_DMA 4
#define iotim_isr tim3_isr
#endif
#define iodma_isr dma1_channel4_7_dma2_channel3_5_isr

#define USART1_TX_DMA 2
#define USART1_RX_DMA 3
#define usart1_dma_isr dma1_channel2_3_dma2_channel1_2_isr

#define USART2_RX_DMA 5

void tim1_com_isr(void);
6 changes: 6 additions & 0 deletions mcu/GD32F350/config.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
MEMORY {
boot (rx) : ORIGIN = 0x8000000, LENGTH = 4K
cfg (rx) : ORIGIN = ORIGIN(boot) + LENGTH(boot), LENGTH = 1K
rom (rx) : ORIGIN = ORIGIN(cfg) + LENGTH(cfg), LENGTH = 32K - LENGTH(boot) - LENGTH(cfg)
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
}
33 changes: 33 additions & 0 deletions mcu/GD32F350/preset.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
** Copyright (C) 2022-2023 Arseny Vakhrushev <arseny.vakhrushev@me.com>
**
** This firmware 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 firmware 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 firmware. If not, see <http://www.gnu.org/licenses/>.
*/

#include "common.h"

const uint16_t sinedata[] = {
346, 352, 358, 364, 370, 376, 382, 388, 394, 400, 406, 412, 418, 424, 430, 436, 441, 447, 453, 459, 464, 470, 476, 481, 487, 492, 498, 503, 508, 514,
519, 524, 529, 534, 539, 544, 549, 554, 559, 564, 568, 573, 578, 582, 586, 591, 595, 599, 603, 607, 611, 615, 619, 622, 626, 629, 633, 636, 639, 643,
646, 649, 651, 654, 657, 660, 662, 664, 667, 669, 671, 673, 675, 677, 679, 680, 682, 683, 684, 686, 687, 688, 689, 689, 690, 691, 691, 692, 692, 692,
692, 692, 692, 692, 691, 691, 690, 689, 689, 688, 687, 686, 684, 683, 682, 680, 679, 677, 675, 673, 671, 669, 667, 664, 662, 660, 657, 654, 651, 649,
646, 643, 639, 636, 633, 629, 626, 622, 619, 615, 611, 607, 603, 599, 595, 591, 586, 582, 578, 573, 568, 564, 559, 554, 549, 544, 539, 534, 529, 524,
519, 514, 508, 503, 498, 492, 487, 481, 476, 470, 464, 459, 453, 447, 441, 436, 430, 424, 418, 412, 406, 400, 394, 388, 382, 376, 370, 364, 358, 352,
346, 340, 334, 328, 322, 316, 310, 304, 298, 292, 286, 280, 274, 268, 262, 256, 251, 245, 239, 233, 228, 222, 216, 211, 205, 200, 194, 189, 184, 178,
173, 168, 163, 158, 153, 148, 143, 138, 133, 128, 124, 119, 114, 110, 106, 101, 97, 93, 89, 85, 81, 77, 73, 70, 66, 63, 59, 56, 53, 49,
46, 43, 41, 38, 35, 32, 30, 28, 25, 23, 21, 19, 17, 15, 13, 12, 10, 9, 8, 6, 5, 4, 3, 3, 2, 1, 1, 0, 0, 0,
0, 0, 0, 0, 1, 1, 2, 3, 3, 4, 5, 6, 8, 9, 10, 12, 13, 15, 17, 19, 21, 23, 25, 28, 30, 32, 35, 38, 41, 43,
46, 49, 53, 56, 59, 63, 66, 70, 73, 77, 81, 85, 89, 93, 97, 101, 106, 110, 114, 119, 124, 128, 133, 138, 143, 148, 153, 158, 163, 168,
173, 178, 184, 189, 194, 200, 205, 211, 216, 222, 228, 233, 239, 245, 251, 256, 262, 268, 274, 280, 286, 292, 298, 304, 310, 316, 322, 328, 334, 340,
};
1 change: 1 addition & 0 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
XX(28, val, volume) \
XX(29, val, beacon) \
XX(30, val, led) \
XX(31, val, brushed) \

static int beep = -1;

Expand Down
1 change: 1 addition & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ typedef struct {
char volume;
char beacon;
char led;
char brushed;
} Cfg;

typedef struct {
Expand Down
5 changes: 4 additions & 1 deletion src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@
#define DUTY_RAMP 25
#endif
#ifndef DUTY_DRAG
#define DUTY_DRAG 0
#define DUTY_DRAG 75
#endif
#ifndef THROT_MODE
#define THROT_MODE 0
Expand Down Expand Up @@ -228,3 +228,6 @@
#ifndef LED
#define LED 0
#endif
#ifndef BRUSHED
#define BRUSHED 0
#endif
Loading

0 comments on commit 8178db2

Please sign in to comment.