rp2040: Add initial adc support
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
045bfa4e8d
commit
59fe878241
|
@ -62,6 +62,7 @@ class PrinterTemperatureMCU:
|
|||
self.mcu_type = mcu.get_constants().get("MCU", "")
|
||||
# Run MCU specific configuration
|
||||
cfg_funcs = [
|
||||
('rp2040', self.config_rp2040),
|
||||
('sam3', self.config_sam3), ('sam4', self.config_sam4),
|
||||
('samd21', self.config_samd21), ('samd51', self.config_samd51),
|
||||
('stm32f1', self.config_stm32f1), ('stm32f2', self.config_stm32f2),
|
||||
|
@ -89,6 +90,9 @@ class PrinterTemperatureMCU:
|
|||
def config_unknown(self):
|
||||
raise self.printer.config_error("MCU temperature not supported on %s"
|
||||
% (self.mcu_type,))
|
||||
def config_rp2040(self):
|
||||
self.slope = 3.3 / -0.001721
|
||||
self.base_temperature = self.calc_base(27., 0.706 / 3.3)
|
||||
def config_sam3(self):
|
||||
self.slope = 3.3 / .002650
|
||||
self.base_temperature = self.calc_base(27., 0.8 / 3.3)
|
||||
|
|
|
@ -6,6 +6,7 @@ config RP2040_SELECT
|
|||
bool
|
||||
default y
|
||||
select HAVE_GPIO
|
||||
select HAVE_GPIO_ADC
|
||||
select HAVE_GPIO_BITBANGING
|
||||
select HAVE_STRICT_TIMING
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ CFLAGS_klipper.elf += -T $(OUT)src/rp2040/rp2040_link.ld
|
|||
$(OUT)klipper.elf: $(OUT)stage2.o $(OUT)src/rp2040/rp2040_link.ld
|
||||
|
||||
# Add source files
|
||||
src-y += rp2040/main.c rp2040/gpio.c generic/crc16_ccitt.c
|
||||
src-y += rp2040/main.c rp2040/gpio.c rp2040/adc.c generic/crc16_ccitt.c
|
||||
src-y += generic/armcm_boot.c generic/armcm_irq.c generic/armcm_reset.c
|
||||
src-y += generic/timer_irq.c rp2040/timer.c
|
||||
src-$(CONFIG_SERIAL) += rp2040/serial.c generic/serial_irq.c
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
// ADC functions on rp2040
|
||||
//
|
||||
// Copyright (C) 2021 Kevin O'Connor <kevin@koconnor.net>
|
||||
//
|
||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
|
||||
#include "board/misc.h" // timer_from_us
|
||||
#include "command.h" // shutdown
|
||||
#include "gpio.h" // gpio_adc_setup
|
||||
#include "hardware/structs/adc.h" // adc_hw
|
||||
#include "hardware/structs/padsbank0.h" // padsbank0_hw
|
||||
#include "hardware/structs/resets.h" // RESETS_RESET_ADC_BITS
|
||||
#include "internal.h" // enable_pclock
|
||||
#include "sched.h" // sched_shutdown
|
||||
|
||||
DECL_CONSTANT("ADC_MAX", 4095);
|
||||
|
||||
#define ADC_TEMPERATURE_PIN 0xfe
|
||||
DECL_ENUMERATION("pin", "ADC_TEMPERATURE", ADC_TEMPERATURE_PIN);
|
||||
|
||||
struct gpio_adc
|
||||
gpio_adc_setup(uint32_t pin)
|
||||
{
|
||||
if ((pin < 26 || pin > 29) && pin != ADC_TEMPERATURE_PIN)
|
||||
shutdown("Not a valid ADC pin");
|
||||
|
||||
// Enable the ADC
|
||||
if (!is_enabled_pclock(RESETS_RESET_ADC_BITS)) {
|
||||
enable_pclock(RESETS_RESET_ADC_BITS);
|
||||
adc_hw->cs = ADC_CS_EN_BITS;
|
||||
}
|
||||
|
||||
uint8_t chan;
|
||||
if (pin == ADC_TEMPERATURE_PIN) {
|
||||
chan = 4;
|
||||
adc_hw->cs |= ADC_CS_TS_EN_BITS;
|
||||
} else {
|
||||
chan = pin - 26;
|
||||
padsbank0_hw->io[pin] = PADS_BANK0_GPIO0_OD_BITS;
|
||||
}
|
||||
|
||||
return (struct gpio_adc){ .chan = chan };
|
||||
}
|
||||
|
||||
enum { ADC_DUMMY=0xff };
|
||||
static uint8_t last_analog_read = ADC_DUMMY;
|
||||
|
||||
// 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)
|
||||
{
|
||||
uint32_t cs = adc_hw->cs;
|
||||
if (!(cs & ADC_CS_READY_BITS))
|
||||
// ADC is busy
|
||||
goto need_delay;
|
||||
if (last_analog_read == g.chan)
|
||||
// Sample now ready
|
||||
return 0;
|
||||
if (last_analog_read != ADC_DUMMY)
|
||||
// Sample on another channel in progress
|
||||
goto need_delay;
|
||||
|
||||
// Begin sample
|
||||
last_analog_read = g.chan;
|
||||
adc_hw->cs = ((cs & ADC_CS_TS_EN_BITS) | ADC_CS_START_ONCE_BITS
|
||||
| ADC_CS_EN_BITS | (g.chan << ADC_CS_AINSEL_LSB));
|
||||
|
||||
need_delay:
|
||||
return timer_from_us(5); // Sample takes 2us but provide extra time
|
||||
}
|
||||
|
||||
// Read a value; use only after gpio_adc_sample() returns zero
|
||||
uint16_t
|
||||
gpio_adc_read(struct gpio_adc g)
|
||||
{
|
||||
last_analog_read = ADC_DUMMY;
|
||||
return adc_hw->result;
|
||||
}
|
||||
|
||||
// Cancel a sample that may have been started with gpio_adc_sample()
|
||||
void
|
||||
gpio_adc_cancel_sample(struct gpio_adc g)
|
||||
{
|
||||
if (last_analog_read == g.chan)
|
||||
last_analog_read = ADC_DUMMY;
|
||||
}
|
|
@ -19,4 +19,12 @@ struct gpio_in gpio_in_setup(uint8_t pin, int8_t pull_up);
|
|||
void gpio_in_reset(struct gpio_in g, int8_t pull_up);
|
||||
uint8_t gpio_in_read(struct gpio_in g);
|
||||
|
||||
struct gpio_adc {
|
||||
uint8_t chan;
|
||||
};
|
||||
struct gpio_adc gpio_adc_setup(uint32_t pin);
|
||||
uint32_t gpio_adc_sample(struct gpio_adc g);
|
||||
uint16_t gpio_adc_read(struct gpio_adc g);
|
||||
void gpio_adc_cancel_sample(struct gpio_adc g);
|
||||
|
||||
#endif // gpio.h
|
||||
|
|
|
@ -42,6 +42,7 @@ DECL_INIT(watchdog_init);
|
|||
|
||||
#define FREQ_XOSC 12000000
|
||||
#define FREQ_SYS 125000000
|
||||
#define FREQ_USB 48000000
|
||||
|
||||
void
|
||||
enable_pclock(uint32_t reset_bit)
|
||||
|
@ -126,8 +127,13 @@ clock_setup(void)
|
|||
while (!(csys->selected & (1 << 1)))
|
||||
;
|
||||
|
||||
// Setup clk_peri
|
||||
// Setup pll_usb
|
||||
enable_pclock(RESETS_RESET_PLL_USB_BITS);
|
||||
pll_setup(pll_usb_hw, 40, 40*FREQ_XOSC/FREQ_USB);
|
||||
|
||||
// Setup clk_peri and clk_adc
|
||||
clk_aux_setup(clk_peri, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS);
|
||||
clk_aux_setup(clk_adc, CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB);
|
||||
|
||||
// Enable watchdog tick (at 12Mhz)
|
||||
cref->div = 1<<CLOCKS_CLK_REF_DIV_INT_LSB;
|
||||
|
|
Loading…
Reference in New Issue