stm32: Add support for Nation N32G45x mcus (#6116)
N32G452/G455 are mostly compatible with STM32F103 but have M4 core and different ADC. Signed-off-by: Alexey Golyshin <stas2z@gmail.com>
This commit is contained in:
@@ -97,6 +97,14 @@ choice
|
||||
config MACH_STM32L412
|
||||
bool "STM32L412"
|
||||
select MACH_STM32L4
|
||||
config MACH_N32G452
|
||||
bool "Nation N32G452"
|
||||
select MACH_N32G45x
|
||||
select MACH_STM32F1
|
||||
config MACH_N32G455
|
||||
bool "Nation N32G455"
|
||||
select MACH_N32G45x
|
||||
select MACH_STM32F1
|
||||
endchoice
|
||||
|
||||
config MACH_STM32F103x6
|
||||
@@ -127,10 +135,12 @@ config MACH_STM32F4x5 # F405, F407, F429 series
|
||||
bool
|
||||
config MACH_STM32L4
|
||||
bool
|
||||
config MACH_N32G45x
|
||||
bool
|
||||
config HAVE_STM32_USBFS
|
||||
bool
|
||||
default y if MACH_STM32F0x2 || MACH_STM32G0Bx || MACH_STM32L4 || MACH_STM32G4
|
||||
default y if (MACH_STM32F103 || MACH_STM32F070) && !STM32_CLOCK_REF_INTERNAL
|
||||
default y if (MACH_STM32F1 || MACH_STM32F070) && !STM32_CLOCK_REF_INTERNAL
|
||||
config HAVE_STM32_USBOTG
|
||||
bool
|
||||
default y if MACH_STM32F2 || MACH_STM32F4 || MACH_STM32H7
|
||||
@@ -144,7 +154,7 @@ config HAVE_STM32_USBCANBUS
|
||||
bool
|
||||
depends on HAVE_STM32_USBFS || HAVE_STM32_USBOTG
|
||||
depends on HAVE_STM32_CANBUS || HAVE_STM32_FDCANBUS
|
||||
depends on !MACH_STM32F103
|
||||
depends on !MACH_STM32F1
|
||||
default y
|
||||
|
||||
config MCU
|
||||
@@ -169,6 +179,7 @@ config MCU
|
||||
default "stm32h743xx" if MACH_STM32H743
|
||||
default "stm32h750xx" if MACH_STM32H750
|
||||
default "stm32l412xx" if MACH_STM32L412
|
||||
default "stm32f103xe" if MACH_N32G45x
|
||||
|
||||
config CLOCK_FREQ
|
||||
int
|
||||
@@ -183,6 +194,8 @@ config CLOCK_FREQ
|
||||
default 150000000 if MACH_STM32G431
|
||||
default 400000000 if MACH_STM32H7 # 400Mhz is max Klipper currently supports
|
||||
default 80000000 if MACH_STM32L412
|
||||
default 64000000 if MACH_N32G45x && STM32_CLOCK_REF_INTERNAL
|
||||
default 128000000 if MACH_N32G45x
|
||||
|
||||
config FLASH_SIZE
|
||||
hex
|
||||
@@ -195,6 +208,7 @@ config FLASH_SIZE
|
||||
default 0x20000 if MACH_STM32G0 || MACH_STM32G431
|
||||
default 0x20000 if MACH_STM32H750
|
||||
default 0x200000 if MACH_STM32H743
|
||||
default 0x20000 if MACH_N32G45x
|
||||
|
||||
config FLASH_BOOT_ADDRESS
|
||||
hex
|
||||
@@ -219,6 +233,7 @@ config RAM_SIZE
|
||||
default 0x9000 if MACH_STM32G07x
|
||||
default 0x24000 if MACH_STM32G0Bx
|
||||
default 0x20000 if MACH_STM32H7
|
||||
default 0x10000 if MACH_N32G45x
|
||||
|
||||
config STACK_SIZE
|
||||
int
|
||||
@@ -251,11 +266,11 @@ config STM32_DFU_ROM_ADDRESS
|
||||
choice
|
||||
prompt "Bootloader offset"
|
||||
config STM32_FLASH_START_2000
|
||||
bool "8KiB bootloader" if MACH_STM32F103 || MACH_STM32F070 || MACH_STM32G0 || MACH_STM32F0x2
|
||||
bool "8KiB bootloader" if MACH_STM32F1 || MACH_STM32F070 || MACH_STM32G0 || MACH_STM32F0x2
|
||||
config STM32_FLASH_START_5000
|
||||
bool "20KiB bootloader" if MACH_STM32F103
|
||||
config STM32_FLASH_START_7000
|
||||
bool "28KiB bootloader" if MACH_STM32F103
|
||||
bool "28KiB bootloader" if MACH_STM32F1
|
||||
config STM32_FLASH_START_8000
|
||||
bool "32KiB bootloader" if MACH_STM32F1 || MACH_STM32F2 || MACH_STM32F4
|
||||
config STM32_FLASH_START_8800
|
||||
|
@@ -6,6 +6,7 @@ CROSS_PREFIX=arm-none-eabi-
|
||||
dirs-y += src/stm32 src/generic lib/fast-hash
|
||||
dirs-$(CONFIG_MACH_STM32F0) += lib/stm32f0
|
||||
dirs-$(CONFIG_MACH_STM32F1) += lib/stm32f1
|
||||
dirs-$(CONFIG_MACH_N32G45x) += lib/n32g45x
|
||||
dirs-$(CONFIG_MACH_STM32F2) += lib/stm32f2
|
||||
dirs-$(CONFIG_MACH_STM32F4) += lib/stm32f4
|
||||
dirs-$(CONFIG_MACH_STM32G0) += lib/stm32g0
|
||||
@@ -17,7 +18,9 @@ MCU := $(shell echo $(CONFIG_MCU))
|
||||
MCU_UPPER := $(shell echo $(CONFIG_MCU) | tr a-z A-Z | tr X x)
|
||||
|
||||
CFLAGS-$(CONFIG_MACH_STM32F0) += -mcpu=cortex-m0 -Ilib/stm32f0/include
|
||||
CFLAGS-$(CONFIG_MACH_STM32F1) += -mcpu=cortex-m3 -Ilib/stm32f1/include
|
||||
CFLAGS-$(CONFIG_MACH_STM32F103) += -mcpu=cortex-m3
|
||||
CFLAGS-$(CONFIG_MACH_N32G45x) += -mcpu=cortex-m4 -Ilib/n32g45x/include
|
||||
CFLAGS-$(CONFIG_MACH_STM32F1) += -Ilib/stm32f1/include
|
||||
CFLAGS-$(CONFIG_MACH_STM32F2) += -mcpu=cortex-m3 -Ilib/stm32f2/include
|
||||
CFLAGS-$(CONFIG_MACH_STM32F4) += -mcpu=cortex-m4 -Ilib/stm32f4/include
|
||||
CFLAGS-$(CONFIG_MACH_STM32G0) += -mcpu=cortex-m0plus -Ilib/stm32g0/include
|
||||
@@ -38,9 +41,11 @@ src-$(CONFIG_MACH_STM32F0) += ../lib/stm32f0/system_stm32f0xx.c
|
||||
src-$(CONFIG_MACH_STM32F0) += generic/timer_irq.c stm32/stm32f0_timer.c
|
||||
src-$(CONFIG_MACH_STM32F0) += stm32/stm32f0.c stm32/gpioperiph.c
|
||||
src-$(CONFIG_MACH_STM32F0) += stm32/stm32f0_adc.c stm32/stm32f0_i2c.c
|
||||
src-$(CONFIG_MACH_STM32F1) += ../lib/stm32f1/system_stm32f1xx.c
|
||||
src-$(CONFIG_MACH_STM32F1) += stm32/stm32f1.c generic/armcm_timer.c
|
||||
src-$(CONFIG_MACH_STM32F1) += stm32/adc.c stm32/i2c.c
|
||||
src-$(CONFIG_MACH_STM32F103) += ../lib/stm32f1/system_stm32f1xx.c
|
||||
src-$(CONFIG_MACH_STM32F103) += stm32/adc.c
|
||||
src-$(CONFIG_MACH_N32G45x) += ../lib/stm32f1/system_stm32f1xx.c
|
||||
src-$(CONFIG_MACH_N32G45x) += ../lib/n32g45x/n32g45x_adc.c stm32/n32g45x_adc.c
|
||||
src-$(CONFIG_MACH_STM32F1) += stm32/stm32f1.c generic/armcm_timer.c stm32/i2c.c
|
||||
src-$(CONFIG_MACH_STM32F2) += ../lib/stm32f2/system_stm32f2xx.c
|
||||
src-$(CONFIG_MACH_STM32F2) += stm32/stm32f4.c generic/armcm_timer.c
|
||||
src-$(CONFIG_MACH_STM32F2) += stm32/gpioperiph.c stm32/adc.c stm32/i2c.c
|
||||
|
@@ -20,7 +20,7 @@ struct gpio_pwm_info {
|
||||
};
|
||||
|
||||
static const struct gpio_pwm_info pwm_regs[] = {
|
||||
#if CONFIG_MACH_STM32F103
|
||||
#if CONFIG_MACH_STM32F103 || CONFIG_MACH_N32G45x
|
||||
{TIM2, GPIO('A', 0), 1, GPIO_FUNCTION(2)},
|
||||
{TIM2, GPIO('A', 1), 2, GPIO_FUNCTION(2)},
|
||||
{TIM2, GPIO('A', 2), 3, GPIO_FUNCTION(2)},
|
||||
|
185
src/stm32/n32g45x_adc.c
Normal file
185
src/stm32/n32g45x_adc.c
Normal file
@@ -0,0 +1,185 @@
|
||||
// ADC functions on N32G45x
|
||||
//
|
||||
// Copyright (C) 2022-2023 Alexey Golyshin <stas2z@gmail.com>
|
||||
//
|
||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
|
||||
#include "board/irq.h" // irq_save
|
||||
#include "board/misc.h" // timer_from_us
|
||||
#include "command.h" // shutdown
|
||||
#include "compiler.h" // ARRAY_SIZE
|
||||
#include "generic/armcm_timer.h" // udelay
|
||||
#include "gpio.h" // gpio_adc_setup
|
||||
#include "internal.h" // GPIO
|
||||
#include "sched.h" // sched_shutdown
|
||||
#include "n32g45x_adc.h" // ADC
|
||||
|
||||
DECL_CONSTANT("ADC_MAX", 4095);
|
||||
|
||||
#define ADC_TEMPERATURE_PIN 0xfe
|
||||
DECL_ENUMERATION("pin", "ADC_TEMPERATURE", ADC_TEMPERATURE_PIN);
|
||||
|
||||
static const uint8_t adc_pins[] = {
|
||||
// ADC1
|
||||
0, GPIO('A', 0), GPIO('A', 1), GPIO('A', 6),
|
||||
GPIO('A', 3), GPIO('F', 4), 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
ADC_TEMPERATURE_PIN, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
// ADC2
|
||||
0, GPIO('A', 4), GPIO('A', 5), GPIO('B', 1),
|
||||
GPIO('A', 7), GPIO('C', 4), GPIO('C', 0), GPIO('C', 1),
|
||||
GPIO('C', 2), GPIO('C', 3), GPIO('F', 2), GPIO('A', 2),
|
||||
GPIO('C', 5), GPIO('B', 2), 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
#if CONFIG_MACH_N32G455 // ADC3/4 for G455 only
|
||||
// ADC3
|
||||
0, GPIO('B', 11), GPIO('E', 9), GPIO('E', 13),
|
||||
GPIO('E', 12), GPIO('B', 13), GPIO('E', 8), GPIO('D', 10),
|
||||
GPIO('D', 11), GPIO('D', 12), GPIO('D', 13), GPIO('D', 14),
|
||||
GPIO('B', 0), GPIO('E', 7), GPIO('E', 10), GPIO('E', 11),
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
// ADC4
|
||||
0, GPIO('E', 14), GPIO('E', 15), GPIO('B', 12),
|
||||
GPIO('B', 14), GPIO('B', 15), 0, 0,
|
||||
0, 0, 0, 0,
|
||||
GPIO('D', 8), GPIO('D', 9), 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
// Perform calibration
|
||||
static void
|
||||
adc_calibrate(ADC_Module *adc)
|
||||
{
|
||||
adc->CTRL2 = CTRL2_AD_ON_SET;
|
||||
while (!(adc->CTRL3 & ADC_FLAG_RDY))
|
||||
;
|
||||
adc->CTRL3 &= (~ADC_CTRL3_BPCAL_MSK);
|
||||
udelay(10);
|
||||
adc->CTRL2 = CTRL2_AD_ON_SET | CTRL2_CAL_SET;
|
||||
while (adc->CTRL2 & CTRL2_CAL_SET)
|
||||
;
|
||||
}
|
||||
|
||||
struct gpio_adc
|
||||
gpio_adc_setup(uint32_t pin)
|
||||
{
|
||||
// Find pin in adc_pins table
|
||||
int chan;
|
||||
for (chan=0; ; chan++) {
|
||||
if (chan >= ARRAY_SIZE(adc_pins))
|
||||
shutdown("Not a valid ADC pin");
|
||||
if (adc_pins[chan] == pin)
|
||||
break;
|
||||
}
|
||||
|
||||
// Determine which ADC block to use
|
||||
ADC_Module *adc;
|
||||
if ((chan >> 5) == 0)
|
||||
adc = NS_ADC1;
|
||||
if ((chan >> 5) == 1)
|
||||
adc = NS_ADC2;
|
||||
if ((chan >> 5) == 2)
|
||||
adc = NS_ADC3;
|
||||
if ((chan >> 5) == 3)
|
||||
adc = NS_ADC4;
|
||||
chan &= 0x1F;
|
||||
|
||||
// Enable the ADC
|
||||
uint32_t reg_temp;
|
||||
reg_temp = ADC_RCC_AHBPCLKEN;
|
||||
reg_temp |= (RCC_AHB_PERIPH_ADC1 | RCC_AHB_PERIPH_ADC2 |
|
||||
RCC_AHB_PERIPH_ADC3 | RCC_AHB_PERIPH_ADC4);
|
||||
ADC_RCC_AHBPCLKEN = reg_temp;
|
||||
|
||||
reg_temp = ADC_RCC_CFG2;
|
||||
reg_temp &= CFG2_ADCPLLPRES_RESET_MASK;
|
||||
reg_temp |= RCC_ADCPLLCLK_DIV1;
|
||||
reg_temp &= RCC_ADCPLLCLK_DISABLE;
|
||||
ADC_RCC_CFG2 = reg_temp;
|
||||
|
||||
reg_temp = ADC_RCC_CFG2;
|
||||
reg_temp &= CFG2_ADCHPRES_RESET_MASK;
|
||||
reg_temp |= RCC_ADCHCLK_DIV16;
|
||||
ADC_RCC_CFG2 = reg_temp;
|
||||
|
||||
ADC_InitType ADC_InitStructure;
|
||||
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;
|
||||
ADC_InitStructure.MultiChEn = 0;
|
||||
ADC_InitStructure.ContinueConvEn = 0;
|
||||
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE;
|
||||
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
|
||||
ADC_InitStructure.ChsNumber = 1;
|
||||
ADC_Init(adc, &ADC_InitStructure);
|
||||
|
||||
adc_calibrate(adc);
|
||||
|
||||
if (pin == ADC_TEMPERATURE_PIN) {
|
||||
NS_ADC1->CTRL2 |= CTRL2_TSVREFE_SET;
|
||||
VREF1P2_CTRL |= (1<<10);
|
||||
} else {
|
||||
gpio_peripheral(pin, GPIO_ANALOG, 0);
|
||||
}
|
||||
|
||||
return (struct gpio_adc){ .adc = adc, .chan = chan };
|
||||
}
|
||||
|
||||
// Try to sample a value. Returns zero if sample ready, otherwise
|
||||
// returns the number of clock ticks the caller should wait before
|
||||
// retrying this function.
|
||||
uint32_t
|
||||
gpio_adc_sample(struct gpio_adc g)
|
||||
{
|
||||
ADC_Module *adc = g.adc;
|
||||
uint32_t sr = adc->STS;
|
||||
if (sr & ADC_STS_STR) {
|
||||
if (!(sr & ADC_STS_ENDC) || adc->RSEQ3 != g.chan)
|
||||
// Conversion still in progress or busy on another channel
|
||||
goto need_delay;
|
||||
// Conversion ready
|
||||
return 0;
|
||||
}
|
||||
// ADC timing: clock=4Mhz, Tconv=12.5, Tsamp=41.5, total=13.500us
|
||||
ADC_ConfigRegularChannel(adc, g.chan, 1, ADC_SAMP_TIME_41CYCLES5);
|
||||
adc->CTRL2 |= CTRL2_AD_ON_SET;
|
||||
adc->CTRL2 |= CTRL2_EXT_TRIG_SWSTART_SET;
|
||||
|
||||
need_delay:
|
||||
return timer_from_us(20);
|
||||
}
|
||||
|
||||
// Read a value; use only after gpio_adc_sample() returns zero
|
||||
uint16_t
|
||||
gpio_adc_read(struct gpio_adc g)
|
||||
{
|
||||
ADC_Module *adc = g.adc;
|
||||
adc->STS &= ~ADC_STS_ENDC;
|
||||
adc->STS &= ~ADC_STS_STR;
|
||||
adc->CTRL2 &= CTRL2_EXT_TRIG_SWSTART_RESET;
|
||||
uint16_t result = adc->DAT;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Cancel a sample that may have been started with gpio_adc_sample()
|
||||
void
|
||||
gpio_adc_cancel_sample(struct gpio_adc g)
|
||||
{
|
||||
ADC_Module *adc = g.adc;
|
||||
irqstatus_t flag = irq_save();
|
||||
if (adc->STS & ADC_STS_STR)
|
||||
gpio_adc_read(g);
|
||||
irq_restore(flag);
|
||||
}
|
@@ -15,7 +15,7 @@
|
||||
#include "internal.h" // GPIO
|
||||
#include "sched.h" // DECL_INIT
|
||||
|
||||
#if CONFIG_MACH_STM32F103 || CONFIG_MACH_STM32G4
|
||||
#if CONFIG_MACH_STM32F103 || CONFIG_MACH_STM32G4 || CONFIG_MACH_N32G45x
|
||||
// Transfer memory is accessed with 32bits, but contains only 16bits of data
|
||||
typedef volatile uint32_t epmword_t;
|
||||
#define WSIZE 2
|
||||
|
Reference in New Issue
Block a user