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:
Alexey 2023-04-07 19:20:14 +03:00 committed by GitHub
parent 27dab0ee51
commit 23e82d37f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 845 additions and 10 deletions

View File

@ -0,0 +1,83 @@
# This file contains pin mappings for the Voxelab Aquila
# with the FFP0173 1.0.1 mainboard. To use this config, during
# "make menuconfig" select the STM32F103 for STM32/G32, or
# Nation N32G452 for N32 version, 28KB boot, serial PA9/PA10.
# See docs/Config_Reference.md for a description of parameters.
[stepper_x]
step_pin: PC2
dir_pin: PB9
enable_pin: !PC3
microsteps: 16
rotation_distance: 40
endstop_pin: ^PA5
position_endstop: 0
position_max: 235
homing_speed: 50
[stepper_y]
step_pin: PB8
dir_pin: PB7
enable_pin: !PC3
microsteps: 16
rotation_distance: 40
endstop_pin: ^PA6
position_endstop: 0
position_max: 235
homing_speed: 50
[stepper_z]
step_pin: PB6
dir_pin: !PB5
enable_pin: !PC3
microsteps: 16
rotation_distance: 8
endstop_pin: ^PA7
position_endstop: 0.0
position_max: 250
[extruder]
max_extrude_only_distance: 100.0
step_pin: PB4
dir_pin: PB3
enable_pin: !PC3
microsteps: 16
rotation_distance: 34.406
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: PA1
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PC5
control: pid
# tuned for stock hardware with 200 degree Celsius target
pid_Kp: 21.527
pid_Ki: 1.063
pid_Kd: 108.982
min_temp: 0
max_temp: 250
[heater_bed]
heater_pin: PA2
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PC4
control: pid
# tuned for stock hardware with 50 degree Celsius target
pid_Kp: 54.027
pid_Ki: 0.770
pid_Kd: 948.182
min_temp: 0
max_temp: 130
[fan]
pin: PA0
[mcu]
serial: /dev/serial/by-id/usb-1a86_USB_Serial-if00-port0
restart_method: command
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 5
max_z_accel: 100

View File

@ -160,3 +160,7 @@ revision 177b0073fe6f19281ee7f7fdbe9599e32d1b4b8b.
The Huada HC32F460 directory contains code from:
https://www.hdsc.com.cn/Category83-1490
version 2.2 DDL minus example directory, empty/extra files
The n32g45x directory contains parts of code from:
https://github.com/RT-Thread/rt-thread/tree/master/bsp/n32g452xx/Libraries/N32_Std_Driver
version v1.0.1 (77638c17877c4b6b0b81e189a36bb08b3384923b)

View File

@ -0,0 +1,331 @@
/*****************************************************************************
* Copyright (c) 2019, Nations Technologies Inc.
*
* All rights reserved.
* ****************************************************************************
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Nations' name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ****************************************************************************/
#ifndef ____N32G45x_ADC____
#define ____N32G45x_ADC____
#define __IO volatile
typedef struct
{
uint32_t WorkMode;
uint32_t MultiChEn;
uint32_t ContinueConvEn;
uint32_t ExtTrigSelect;
uint32_t DatAlign;
uint8_t ChsNumber;
} ADC_InitType;
typedef struct
{
__IO uint32_t STS;
__IO uint32_t CTRL1;
__IO uint32_t CTRL2;
__IO uint32_t SAMPT1;
__IO uint32_t SAMPT2;
__IO uint32_t JOFFSET1;
__IO uint32_t JOFFSET2;
__IO uint32_t JOFFSET3;
__IO uint32_t JOFFSET4;
__IO uint32_t WDGHIGH;
__IO uint32_t WDGLOW;
__IO uint32_t RSEQ1;
__IO uint32_t RSEQ2;
__IO uint32_t RSEQ3;
__IO uint32_t JSEQ;
__IO uint32_t JDAT1;
__IO uint32_t JDAT2;
__IO uint32_t JDAT3;
__IO uint32_t JDAT4;
__IO uint32_t DAT;
__IO uint32_t DIFSEL;
__IO uint32_t CALFACT;
__IO uint32_t CTRL3;
__IO uint32_t SAMPT3;
} ADC_Module;
#define NS_ADC1_BASE ((uint32_t)0x40020800)
#define NS_ADC2_BASE ((uint32_t)0x40020c00)
#define NS_ADC3_BASE ((uint32_t)0x40021800)
#define NS_ADC4_BASE ((uint32_t)0x40021c00)
#define NS_ADC1 ((ADC_Module *)NS_ADC1_BASE)
#define NS_ADC2 ((ADC_Module *)NS_ADC2_BASE)
#define NS_ADC3 ((ADC_Module *)NS_ADC3_BASE)
#define NS_ADC4 ((ADC_Module *)NS_ADC4_BASE)
#define ADC_RCC_BASE ((uint32_t)0x40021000)
#define ADC_RCC_CTRL *((uint32_t *)(ADC_RCC_BASE + 0x00))
#define ADC_RCC_CFG *((uint32_t *)(ADC_RCC_BASE + 0x04))
#define ADC_RCC_CLKINT *((uint32_t *)(ADC_RCC_BASE + 0x08))
#define ADC_RCC_APB2PRST *((uint32_t *)(ADC_RCC_BASE + 0x0c))
#define ADC_RCC_APB1PRST *((uint32_t *)(ADC_RCC_BASE + 0x10))
#define ADC_RCC_AHBPCLKEN *((uint32_t *)(ADC_RCC_BASE + 0x14))
#define ADC_RCC_APB2PCLKEN *((uint32_t *)(ADC_RCC_BASE + 0x18))
#define ADC_RCC_APB1PCLKEN *((uint32_t *)(ADC_RCC_BASE + 0x1c))
#define ADC_RCC_BDCTRL *((uint32_t *)(ADC_RCC_BASE + 0x20))
#define ADC_RCC_CTRLSTS *((uint32_t *)(ADC_RCC_BASE + 0x24))
#define ADC_RCC_AHBPRST *((uint32_t *)(ADC_RCC_BASE + 0x28))
#define ADC_RCC_CFG2 *((uint32_t *)(ADC_RCC_BASE + 0x2c))
#define ADC_RCC_CFG3 *((uint32_t *)(ADC_RCC_BASE + 0x30))
/* CFG2 register bit mask */
#define CFG2_TIM18CLKSEL_SET_MASK ((uint32_t)0x20000000)
#define CFG2_TIM18CLKSEL_RESET_MASK ((uint32_t)0xDFFFFFFF)
#define CFG2_RNGCPRES_SET_MASK ((uint32_t)0x1F000000)
#define CFG2_RNGCPRES_RESET_MASK ((uint32_t)0xE0FFFFFF)
#define CFG2_ADC1MSEL_SET_MASK ((uint32_t)0x00000400)
#define CFG2_ADC1MSEL_RESET_MASK ((uint32_t)0xFFFFFBFF)
#define CFG2_ADC1MPRES_SET_MASK ((uint32_t)0x0000F800)
#define CFG2_ADC1MPRES_RESET_MASK ((uint32_t)0xFFFF07FF)
#define CFG2_ADCPLLPRES_SET_MASK ((uint32_t)0x000001F0)
#define CFG2_ADCPLLPRES_RESET_MASK ((uint32_t)0xFFFFFE0F)
#define CFG2_ADCHPRES_SET_MASK ((uint32_t)0x0000000F)
#define CFG2_ADCHPRES_RESET_MASK ((uint32_t)0xFFFFFFF0)
#define RCC_ADCPLLCLK_DISABLE ((uint32_t)0xFFFFFEFF)
#define RCC_ADCPLLCLK_DIV1 ((uint32_t)0x00000100)
#define RCC_ADCPLLCLK_DIV2 ((uint32_t)0x00000110)
#define RCC_ADCPLLCLK_DIV4 ((uint32_t)0x00000120)
#define RCC_ADCPLLCLK_DIV6 ((uint32_t)0x00000130)
#define RCC_ADCPLLCLK_DIV8 ((uint32_t)0x00000140)
#define RCC_ADCPLLCLK_DIV10 ((uint32_t)0x00000150)
#define RCC_ADCPLLCLK_DIV12 ((uint32_t)0x00000160)
#define RCC_ADCPLLCLK_DIV16 ((uint32_t)0x00000170)
#define RCC_ADCPLLCLK_DIV32 ((uint32_t)0x00000180)
#define RCC_ADCPLLCLK_DIV64 ((uint32_t)0x00000190)
#define RCC_ADCPLLCLK_DIV128 ((uint32_t)0x000001A0)
#define RCC_ADCPLLCLK_DIV256 ((uint32_t)0x000001B0)
#define RCC_ADCPLLCLK_DIV_OTHERS ((uint32_t)0x000001C0)
#define RCC_ADCHCLK_DIV1 ((uint32_t)0x00000000)
#define RCC_ADCHCLK_DIV2 ((uint32_t)0x00000001)
#define RCC_ADCHCLK_DIV4 ((uint32_t)0x00000002)
#define RCC_ADCHCLK_DIV6 ((uint32_t)0x00000003)
#define RCC_ADCHCLK_DIV8 ((uint32_t)0x00000004)
#define RCC_ADCHCLK_DIV10 ((uint32_t)0x00000005)
#define RCC_ADCHCLK_DIV12 ((uint32_t)0x00000006)
#define RCC_ADCHCLK_DIV16 ((uint32_t)0x00000007)
#define RCC_ADCHCLK_DIV32 ((uint32_t)0x00000008)
#define RCC_ADCHCLK_DIV_OTHERS ((uint32_t)0x00000008)
#define RCC_ADC1MCLK_SRC_HSI ((uint32_t)0x00000000)
#define RCC_ADC1MCLK_SRC_HSE ((uint32_t)0x00000400)
#define RCC_ADC1MCLK_DIV1 ((uint32_t)0x00000000)
#define RCC_ADC1MCLK_DIV2 ((uint32_t)0x00000800)
#define RCC_ADC1MCLK_DIV3 ((uint32_t)0x00001000)
#define RCC_ADC1MCLK_DIV4 ((uint32_t)0x00001800)
#define RCC_ADC1MCLK_DIV5 ((uint32_t)0x00002000)
#define RCC_ADC1MCLK_DIV6 ((uint32_t)0x00002800)
#define RCC_ADC1MCLK_DIV7 ((uint32_t)0x00003000)
#define RCC_ADC1MCLK_DIV8 ((uint32_t)0x00003800)
#define RCC_ADC1MCLK_DIV9 ((uint32_t)0x00004000)
#define RCC_ADC1MCLK_DIV10 ((uint32_t)0x00004800)
#define RCC_ADC1MCLK_DIV11 ((uint32_t)0x00005000)
#define RCC_ADC1MCLK_DIV12 ((uint32_t)0x00005800)
#define RCC_ADC1MCLK_DIV13 ((uint32_t)0x00006000)
#define RCC_ADC1MCLK_DIV14 ((uint32_t)0x00006800)
#define RCC_ADC1MCLK_DIV15 ((uint32_t)0x00007000)
#define RCC_ADC1MCLK_DIV16 ((uint32_t)0x00007800)
#define RCC_ADC1MCLK_DIV17 ((uint32_t)0x00008000)
#define RCC_ADC1MCLK_DIV18 ((uint32_t)0x00008800)
#define RCC_ADC1MCLK_DIV19 ((uint32_t)0x00009000)
#define RCC_ADC1MCLK_DIV20 ((uint32_t)0x00009800)
#define RCC_ADC1MCLK_DIV21 ((uint32_t)0x0000A000)
#define RCC_ADC1MCLK_DIV22 ((uint32_t)0x0000A800)
#define RCC_ADC1MCLK_DIV23 ((uint32_t)0x0000B000)
#define RCC_ADC1MCLK_DIV24 ((uint32_t)0x0000B800)
#define RCC_ADC1MCLK_DIV25 ((uint32_t)0x0000C000)
#define RCC_ADC1MCLK_DIV26 ((uint32_t)0x0000C800)
#define RCC_ADC1MCLK_DIV27 ((uint32_t)0x0000D000)
#define RCC_ADC1MCLK_DIV28 ((uint32_t)0x0000D800)
#define RCC_ADC1MCLK_DIV29 ((uint32_t)0x0000E000)
#define RCC_ADC1MCLK_DIV30 ((uint32_t)0x0000E800)
#define RCC_ADC1MCLK_DIV31 ((uint32_t)0x0000F000)
#define RCC_ADC1MCLK_DIV32 ((uint32_t)0x0000F800)
#define RCC_AHB_PERIPH_ADC1 ((uint32_t)0x00001000)
#define RCC_AHB_PERIPH_ADC2 ((uint32_t)0x00002000)
#define RCC_AHB_PERIPH_ADC3 ((uint32_t)0x00004000)
#define RCC_AHB_PERIPH_ADC4 ((uint32_t)0x00008000)
#define SAMPT1_SMP_SET ((uint32_t)0x00000007)
#define SAMPT2_SMP_SET ((uint32_t)0x00000007)
#define SQR4_SEQ_SET ((uint32_t)0x0000001F)
#define SQR3_SEQ_SET ((uint32_t)0x0000001F)
#define SQR2_SEQ_SET ((uint32_t)0x0000001F)
#define SQR1_SEQ_SET ((uint32_t)0x0000001F)
#define CTRL1_CLR_MASK ((uint32_t)0xFFF0FEFF)
#define RSEQ1_CLR_MASK ((uint32_t)0xFF0FFFFF)
#define CTRL2_CLR_MASK ((uint32_t)0xFFF1F7FD)
#define ADC_CH_0 ((uint8_t)0x00)
#define ADC_CH_1 ((uint8_t)0x01)
#define ADC_CH_2 ((uint8_t)0x02)
#define ADC_CH_3 ((uint8_t)0x03)
#define ADC_CH_4 ((uint8_t)0x04)
#define ADC_CH_5 ((uint8_t)0x05)
#define ADC_CH_6 ((uint8_t)0x06)
#define ADC_CH_7 ((uint8_t)0x07)
#define ADC_CH_8 ((uint8_t)0x08)
#define ADC_CH_9 ((uint8_t)0x09)
#define ADC_CH_10 ((uint8_t)0x0A)
#define ADC_CH_11 ((uint8_t)0x0B)
#define ADC_CH_12 ((uint8_t)0x0C)
#define ADC_CH_13 ((uint8_t)0x0D)
#define ADC_CH_14 ((uint8_t)0x0E)
#define ADC_CH_15 ((uint8_t)0x0F)
#define ADC_CH_16 ((uint8_t)0x10)
#define ADC_CH_17 ((uint8_t)0x11)
#define ADC_CH_18 ((uint8_t)0x12)
#define ADC_WORKMODE_INDEPENDENT ((uint32_t)0x00000000)
#define ADC_WORKMODE_REG_INJECT_SIMULT ((uint32_t)0x00010000)
#define ADC_WORKMODE_REG_SIMULT_ALTER_TRIG ((uint32_t)0x00020000)
#define ADC_WORKMODE_INJ_SIMULT_FAST_INTERL ((uint32_t)0x00030000)
#define ADC_WORKMODE_INJ_SIMULT_SLOW_INTERL ((uint32_t)0x00040000)
#define ADC_WORKMODE_INJ_SIMULT ((uint32_t)0x00050000)
#define ADC_WORKMODE_REG_SIMULT ((uint32_t)0x00060000)
#define ADC_WORKMODE_FAST_INTERL ((uint32_t)0x00070000)
#define ADC_WORKMODE_SLOW_INTERL ((uint32_t)0x00080000)
#define ADC_WORKMODE_ALTER_TRIG ((uint32_t)0x00090000)
#define ADC_EXT_TRIGCONV_T1_CC1 \
((uint32_t)0x00000000) /*!< For ADC1 and ADC2 */
#define ADC_EXT_TRIGCONV_T1_CC2 \
((uint32_t)0x00020000) /*!< For ADC1 and ADC2 */
#define ADC_EXT_TRIGCONV_T2_CC2 \
((uint32_t)0x00060000) /*!< For ADC1 and ADC2 */
#define ADC_EXT_TRIGCONV_T1_CC3 \
((uint32_t)0x00040000) /*!< For ADC1, ADC2 , ADC3 and ADC4 */
#define ADC_EXT_TRIGCONV_NONE \
((uint32_t)0x000E0000) /*!< For ADC1, ADC2 , ADC3 and ADC4 */
#define ADC_DAT_ALIGN_R ((uint32_t)0x00000000)
#define ADC_DAT_ALIGN_L ((uint32_t)0x00000800)
#define ADC_FLAG_RDY ((uint8_t)0x20)
#define ADC_FLAG_PD_RDY ((uint8_t)0x40)
#define CTRL2_AD_ON_SET ((uint32_t)0x00000001)
#define CTRL2_AD_ON_RESET ((uint32_t)0xFFFFFFFE)
#define CTRL2_CAL_SET ((uint32_t)0x00000004)
/* ADC Software start mask */
#define CTRL2_EXT_TRIG_SWSTART_SET ((uint32_t)0x00500000)
#define CTRL2_EXT_TRIG_SWSTART_RESET ((uint32_t)0xFFAFFFFF)
#define ADC_SAMP_TIME_1CYCLES5 ((uint8_t)0x00)
#define ADC_SAMP_TIME_7CYCLES5 ((uint8_t)0x01)
#define ADC_SAMP_TIME_13CYCLES5 ((uint8_t)0x02)
#define ADC_SAMP_TIME_28CYCLES5 ((uint8_t)0x03)
#define ADC_SAMP_TIME_41CYCLES5 ((uint8_t)0x04)
#define ADC_SAMP_TIME_55CYCLES5 ((uint8_t)0x05)
#define ADC_SAMP_TIME_71CYCLES5 ((uint8_t)0x06)
#define ADC_SAMP_TIME_239CYCLES5 ((uint8_t)0x07)
#define ADC_FLAG_AWDG ((uint8_t)0x01)
#define ADC_FLAG_ENDC ((uint8_t)0x02)
#define ADC_FLAG_JENDC ((uint8_t)0x04)
#define ADC_FLAG_JSTR ((uint8_t)0x08)
#define ADC_FLAG_STR ((uint8_t)0x10)
#define ADC_FLAG_EOC_ANY ((uint8_t)0x20)
#define ADC_FLAG_JEOC_ANY ((uint8_t)0x40)
#define ADC_STS_AWDG ((uint8_t)0x01) /*!< Analog watchdog flag */
#define ADC_STS_ENDC ((uint8_t)0x02) /*!< End of conversion */
#define ADC_STS_JENDC \
((uint8_t)0x04) /*!< Injected channel end of conversion */
#define ADC_STS_JSTR ((uint8_t)0x08) /*!< Injected channel Start flag */
#define ADC_STS_STR ((uint8_t)0x10) /*!< Regular channel Start flag */
#define ADC_STS_ENDCA ((uint8_t)0x20) /*!< Any end of conversion */
#define ADC_STS_JENDCA \
((uint8_t)0x40) /*!< Any injected channel end of conversion */
/* ADC DMA mask */
#define CTRL2_DMA_SET ((uint32_t)0x00000100)
#define CTRL2_DMA_RESET ((uint32_t)0xFFFFFEFF)
#define CTRL2_TSVREFE_SET ((uint32_t)0x00800000)
#define CTRL2_TSVREFE_RESET ((uint32_t)0xFF7FFFFF)
#define VREF1P2_CTRL (*(uint32_t *)(0x40001800 + 0x20))
/******************* Bit definition for ADC_CTRL2 register
* ********************/
#define ADC_CTRL2_ON ((uint32_t)0x00000001) /*!< A/D Converter ON / OFF */
#define ADC_CTRL2_CTU ((uint32_t)0x00000002) /*!< Continuous Conversion */
#define ADC_CTRL2_ENCAL ((uint32_t)0x00000004) /*!< A/D Calibration */
#define ADC_CTRL2_ENDMA \
((uint32_t)0x00000100) /*!< Direct Memory access mode */
#define ADC_CTRL2_ALIG ((uint32_t)0x00000800) /*!< Data Alignment */
#define ADC_CTRL2_EXTJSEL \
((uint32_t)0x00007000) /*!< INJ_EXT_SEL[2:0] bits (External event select \
for injected group) */
#define ADC_CTRL2_EXTJSEL_0 ((uint32_t)0x00001000) /*!< Bit 0 */
#define ADC_CTRL2_EXTJSEL_1 ((uint32_t)0x00002000) /*!< Bit 1 */
#define ADC_CTRL2_EXTJSEL_2 ((uint32_t)0x00004000) /*!< Bit 2 */
#define ADC_CTRL2_EXTJTRIG \
((uint32_t)0x00008000) /*!< External Trigger Conversion mode for injected \
channels */
#define ADC_CTRL2_EXTRSEL \
((uint32_t)0x000E0000) /*!< EXTSEL[2:0] bits (External Event Select for \
regular group) */
#define ADC_CTRL2_EXTRSEL_0 ((uint32_t)0x00020000) /*!< Bit 0 */
#define ADC_CTRL2_EXTRSEL_1 ((uint32_t)0x00040000) /*!< Bit 1 */
#define ADC_CTRL2_EXTRSEL_2 ((uint32_t)0x00080000) /*!< Bit 2 */
#define ADC_CTRL2_EXTRTRIG \
((uint32_t)0x00100000) /*!< External Trigger Conversion mode for regular \
channels */
#define ADC_CTRL2_SWSTRJCH \
((uint32_t)0x00200000) /*!< Start Conversion of injected channels */
#define ADC_CTRL2_SWSTRRCH \
((uint32_t)0x00400000) /*!< Start Conversion of regular channels */
#define ADC_CTRL2_TEMPEN \
((uint32_t)0x00800000) /*!< Temperature Sensor and VREFINT Enable */
#define ADC_CTRL3_VABTMEN_MSK ((uint32_t)0x01L << 11)
#define ADC_CTRL3_DPWMOD_MSK ((uint32_t)0x01L << 10)
#define ADC_CTRL3_JENDCAIEN_MSK ((uint32_t)0x01L << 9)
#define ADC_CTRL3_ENDCAIEN_MSK ((uint32_t)0x01L << 8)
#define ADC_CTRL3_BPCAL_MSK ((uint32_t)0x01L << 7)
#define ADC_CTRL3_PDRDY_MSK ((uint32_t)0x01L << 6)
#define ADC_CTRL3_RDY_MSK ((uint32_t)0x01L << 5)
#define ADC_CTRL3_CKMOD_MSK ((uint32_t)0x01L << 4)
#define ADC_CTRL3_CALALD_MSK ((uint32_t)0x01L << 3)
#define ADC_CTRL3_CALDIF_MSK ((uint32_t)0x01L << 2)
#define ADC_CTRL3_RES_MSK ((uint32_t)0x03L << 0)
void ADC_Init(ADC_Module* ADCx, ADC_InitType* ADC_InitStruct);
void ADC_ConfigRegularChannel(ADC_Module* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
#endif

211
lib/n32g45x/n32g45x_adc.c Normal file
View File

@ -0,0 +1,211 @@
/*****************************************************************************
* Copyright (c) 2019, Nations Technologies Inc.
*
* All rights reserved.
* ****************************************************************************
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Nations' name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ****************************************************************************/
#include "stdint.h"
#include "n32g45x_adc.h"
/**
* @brief Initializes the ADCx peripheral according to the specified parameters
* in the ADC_InitStruct.
* @param ADCx where x can be 1, 2 ,3 or 4 to select the ADC peripheral.
* @param ADC_InitStruct pointer to an ADC_InitType structure that contains
* the configuration information for the specified ADC peripheral.
*/
void ADC_Init(ADC_Module* ADCx, ADC_InitType* ADC_InitStruct)
{
uint32_t tmpreg1 = 0;
uint8_t tmpreg2 = 0;
/*---------------------------- ADCx CTRL1 Configuration -----------------*/
/* Get the ADCx CTRL1 value */
tmpreg1 = ADCx->CTRL1;
/* Clear DUALMOD and SCAN bits */
tmpreg1 &= CTRL1_CLR_MASK;
/* Configure ADCx: Dual mode and scan conversion mode */
/* Set DUALMOD bits according to WorkMode value */
/* Set SCAN bit according to MultiChEn value */
tmpreg1 |= (uint32_t)(ADC_InitStruct->WorkMode | ((uint32_t)ADC_InitStruct->MultiChEn << 8));
/* Write to ADCx CTRL1 */
ADCx->CTRL1 = tmpreg1;
/*---------------------------- ADCx CTRL2 Configuration -----------------*/
/* Get the ADCx CTRL2 value */
tmpreg1 = ADCx->CTRL2;
/* Clear CONT, ALIGN and EXTSEL bits */
tmpreg1 &= CTRL2_CLR_MASK;
/* Configure ADCx: external trigger event and continuous conversion mode */
/* Set ALIGN bit according to DatAlign value */
/* Set EXTSEL bits according to ExtTrigSelect value */
/* Set CONT bit according to ContinueConvEn value */
tmpreg1 |= (uint32_t)(ADC_InitStruct->DatAlign | ADC_InitStruct->ExtTrigSelect
| ((uint32_t)ADC_InitStruct->ContinueConvEn << 1));
/* Write to ADCx CTRL2 */
ADCx->CTRL2 = tmpreg1;
/*---------------------------- ADCx RSEQ1 Configuration -----------------*/
/* Get the ADCx RSEQ1 value */
tmpreg1 = ADCx->RSEQ1;
/* Clear L bits */
tmpreg1 &= RSEQ1_CLR_MASK;
/* Configure ADCx: regular channel sequence length */
/* Set L bits according to ChsNumber value */
tmpreg2 |= (uint8_t)(ADC_InitStruct->ChsNumber - (uint8_t)1);
tmpreg1 |= (uint32_t)tmpreg2 << 20;
/* Write to ADCx RSEQ1 */
ADCx->RSEQ1 = tmpreg1;
}
/**
* @brief Configures for the selected ADC regular channel its corresponding
* rank in the sequencer and its sample time.
* @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral.
* @param ADC_Channel the ADC channel to configure.
* This parameter can be one of the following values:
* @arg ADC_CH_0 ADC Channel0 selected
* @arg ADC_CH_1 ADC Channel1 selected
* @arg ADC_CH_2 ADC Channel2 selected
* @arg ADC_CH_3 ADC Channel3 selected
* @arg ADC_CH_4 ADC Channel4 selected
* @arg ADC_CH_5 ADC Channel5 selected
* @arg ADC_CH_6 ADC Channel6 selected
* @arg ADC_CH_7 ADC Channel7 selected
* @arg ADC_CH_8 ADC Channel8 selected
* @arg ADC_CH_9 ADC Channel9 selected
* @arg ADC_CH_10 ADC Channel10 selected
* @arg ADC_CH_11 ADC Channel11 selected
* @arg ADC_CH_12 ADC Channel12 selected
* @arg ADC_CH_13 ADC Channel13 selected
* @arg ADC_CH_14 ADC Channel14 selected
* @arg ADC_CH_15 ADC Channel15 selected
* @arg ADC_CH_16 ADC Channel16 selected
* @arg ADC_CH_17 ADC Channel17 selected
* @arg ADC_CH_18 ADC Channel18 selected
* @param Rank The rank in the regular group sequencer. This parameter must be between 1 to 16.
* @param ADC_SampleTime The sample time value to be set for the selected channel.
* This parameter can be one of the following values:
* @arg ADC_SAMP_TIME_1CYCLES5 Sample time equal to 1.5 cycles
* @arg ADC_SAMP_TIME_7CYCLES5 Sample time equal to 7.5 cycles
* @arg ADC_SAMP_TIME_13CYCLES5 Sample time equal to 13.5 cycles
* @arg ADC_SAMP_TIME_28CYCLES5 Sample time equal to 28.5 cycles
* @arg ADC_SAMP_TIME_41CYCLES5 Sample time equal to 41.5 cycles
* @arg ADC_SAMP_TIME_55CYCLES5 Sample time equal to 55.5 cycles
* @arg ADC_SAMP_TIME_71CYCLES5 Sample time equal to 71.5 cycles
* @arg ADC_SAMP_TIME_239CYCLES5 Sample time equal to 239.5 cycles
*/
void ADC_ConfigRegularChannel(ADC_Module* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)
{
uint32_t tmpreg1 = 0, tmpreg2 = 0;
if (ADC_Channel == ADC_CH_18)
{
tmpreg1 = ADCx->SAMPT3;
tmpreg1 &= (~0x00000007);
tmpreg1 |= ADC_SampleTime;
ADCx->SAMPT3 = tmpreg1;
}
else if (ADC_Channel > ADC_CH_9) /* if ADC_CH_10 ... ADC_CH_17 is selected */
{
/* Get the old register value */
tmpreg1 = ADCx->SAMPT1;
/* Calculate the mask to clear */
tmpreg2 = SAMPT1_SMP_SET << (3 * (ADC_Channel - 10));
/* Clear the old channel sample time */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10));
/* Set the new channel sample time */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SAMPT1 = tmpreg1;
}
else /* ADC_Channel include in ADC_Channel_[0..9] */
{
/* Get the old register value */
tmpreg1 = ADCx->SAMPT2;
/* Calculate the mask to clear */
tmpreg2 = SAMPT2_SMP_SET << (3 * ADC_Channel);
/* Clear the old channel sample time */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel);
/* Set the new channel sample time */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SAMPT2 = tmpreg1;
}
/* For Rank 1 to 6 */
if (Rank < 7)
{
/* Get the old register value */
tmpreg1 = ADCx->RSEQ3;
/* Calculate the mask to clear */
tmpreg2 = SQR3_SEQ_SET << (5 * (Rank - 1));
/* Clear the old SQx bits for the selected rank */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 1));
/* Set the SQx bits for the selected rank */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->RSEQ3 = tmpreg1;
}
/* For Rank 7 to 12 */
else if (Rank < 13)
{
/* Get the old register value */
tmpreg1 = ADCx->RSEQ2;
/* Calculate the mask to clear */
tmpreg2 = SQR2_SEQ_SET << (5 * (Rank - 7));
/* Clear the old SQx bits for the selected rank */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 7));
/* Set the SQx bits for the selected rank */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->RSEQ2 = tmpreg1;
}
/* For Rank 13 to 16 */
else
{
/* Get the old register value */
tmpreg1 = ADCx->RSEQ1;
/* Calculate the mask to clear */
tmpreg2 = SQR1_SEQ_SET << (5 * (Rank - 13));
/* Clear the old SQx bits for the selected rank */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 13));
/* Set the SQx bits for the selected rank */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->RSEQ1 = tmpreg1;
}
}

View File

@ -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

View File

@ -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

View File

@ -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
View 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);
}

View File

@ -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

View File

@ -196,6 +196,7 @@ CONFIG ../../config/printer-tronxy-xy-2-Pro-2020.cfg
CONFIG ../../config/printer-twotrees-sapphire-plus-sp-5-v1-2020.cfg
CONFIG ../../config/printer-twotrees-sapphire-plus-sp-5-v1.1-2021.cfg
CONFIG ../../config/printer-twotrees-sapphire-pro-sp-3-2020.cfg
CONFIG ../../config/printer-voxelab-aquila-2021.cfg
# Printers using the stm32f401
DICTIONARY stm32f401.dict