atsamd: Use enumerations for buses and reserve pins
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
7e8ecfe177
commit
bc9fd03dab
|
@ -795,7 +795,7 @@
|
||||||
# SERCOM available. Each SERCOM must be configured prior to using it as
|
# SERCOM available. Each SERCOM must be configured prior to using it as
|
||||||
# SPI or I2C peripheral. Place this config section above any other section
|
# SPI or I2C peripheral. Place this config section above any other section
|
||||||
# that makes use of SPI or I2C buses.
|
# that makes use of SPI or I2C buses.
|
||||||
#[samd_sercom 0]
|
#[samd_sercom sercom0]
|
||||||
#tx_pin:
|
#tx_pin:
|
||||||
# MOSI pin for SPI communication, or SDA (data) pin for I2C
|
# MOSI pin for SPI communication, or SDA (data) pin for I2C
|
||||||
# communication. The pin must have a valid pinmux configuration
|
# communication. The pin must have a valid pinmux configuration
|
||||||
|
|
|
@ -8,30 +8,25 @@ class SamdSERCOM:
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.printer = config.get_printer()
|
self.printer = config.get_printer()
|
||||||
self.name = config.get_name().split()[1]
|
self.name = config.get_name().split()[1]
|
||||||
ppins = self.printer.lookup_object("pins")
|
|
||||||
try:
|
|
||||||
int(self.name)
|
|
||||||
except ValueError:
|
|
||||||
raise ppins.error("%s: SERCOM name must be an integer" % (
|
|
||||||
config.get_name(),))
|
|
||||||
|
|
||||||
self.tx_pin = config.get("tx_pin")
|
self.tx_pin = config.get("tx_pin")
|
||||||
self.rx_pin = config.get("rx_pin", None)
|
self.rx_pin = config.get("rx_pin", None)
|
||||||
self.clk_pin = config.get("clk_pin")
|
self.clk_pin = config.get("clk_pin")
|
||||||
|
|
||||||
|
ppins = self.printer.lookup_object("pins")
|
||||||
tx_pin_params = ppins.lookup_pin(self.tx_pin)
|
tx_pin_params = ppins.lookup_pin(self.tx_pin)
|
||||||
self.mcu = tx_pin_params['chip']
|
self.mcu = tx_pin_params['chip']
|
||||||
self.mcu.add_config_cmd(
|
self.mcu.add_config_cmd(
|
||||||
"set_sercom_pin sercom_id=%s pin_type=%d pin=%s" % (
|
"set_sercom_pin bus=%s sercom_pin_type=tx pin=%s" % (
|
||||||
self.name, 0, self.tx_pin))
|
self.name, self.tx_pin))
|
||||||
|
|
||||||
clk_pin_params = ppins.lookup_pin(self.clk_pin)
|
clk_pin_params = ppins.lookup_pin(self.clk_pin)
|
||||||
if self.mcu is not clk_pin_params['chip']:
|
if self.mcu is not clk_pin_params['chip']:
|
||||||
raise ppins.error("%s: SERCOM pins must be on same mcu" % (
|
raise ppins.error("%s: SERCOM pins must be on same mcu" % (
|
||||||
config.get_name(),))
|
config.get_name(),))
|
||||||
self.mcu.add_config_cmd(
|
self.mcu.add_config_cmd(
|
||||||
"set_sercom_pin sercom_id=%s pin_type=%d pin=%s" % (
|
"set_sercom_pin bus=%s sercom_pin_type=clk pin=%s" % (
|
||||||
self.name, 2, self.clk_pin))
|
self.name, self.clk_pin))
|
||||||
|
|
||||||
if self.rx_pin:
|
if self.rx_pin:
|
||||||
rx_pin_params = ppins.lookup_pin(self.rx_pin)
|
rx_pin_params = ppins.lookup_pin(self.rx_pin)
|
||||||
|
@ -39,8 +34,8 @@ class SamdSERCOM:
|
||||||
raise ppins.error("%s: SERCOM pins must be on same mcu" % (
|
raise ppins.error("%s: SERCOM pins must be on same mcu" % (
|
||||||
config.get_name(),))
|
config.get_name(),))
|
||||||
self.mcu.add_config_cmd(
|
self.mcu.add_config_cmd(
|
||||||
"set_sercom_pin sercom_id=%s pin_type=%d pin=%s" % (
|
"set_sercom_pin bus=%s sercom_pin_type=rx pin=%s" % (
|
||||||
self.name, 1, self.rx_pin))
|
self.name, self.rx_pin))
|
||||||
|
|
||||||
def load_config_prefix(config):
|
def load_config_prefix(config):
|
||||||
return SamdSERCOM(config)
|
return SamdSERCOM(config)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
//
|
//
|
||||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
|
|
||||||
|
#include "command.h" // DECL_CONSTANT_STR
|
||||||
#include "compiler.h" // DIV_ROUND_CLOSEST
|
#include "compiler.h" // DIV_ROUND_CLOSEST
|
||||||
#include "internal.h" // enable_pclock
|
#include "internal.h" // enable_pclock
|
||||||
|
|
||||||
|
@ -48,6 +49,10 @@ get_pclock_frequency(uint32_t pclk_id)
|
||||||
return FREQ_MAIN;
|
return FREQ_MAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_CLOCK_REF_X32K
|
||||||
|
DECL_CONSTANT_STR("RESERVE_PINS_crystal", "PA0,PA1");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Initialize the clocks using an external 32K crystal
|
// Initialize the clocks using an external 32K crystal
|
||||||
static void
|
static void
|
||||||
clock_init_32k(void)
|
clock_init_32k(void)
|
||||||
|
|
|
@ -45,12 +45,6 @@ i2c_init(uint32_t bus, SercomI2cm *si)
|
||||||
struct i2c_config
|
struct i2c_config
|
||||||
i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr)
|
i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr)
|
||||||
{
|
{
|
||||||
#ifdef SERCOM7
|
|
||||||
if (bus > 7)
|
|
||||||
#else
|
|
||||||
if (bus > 5)
|
|
||||||
#endif
|
|
||||||
shutdown("Unsupported i2c bus");
|
|
||||||
Sercom *sercom = sercom_enable_pclock(bus);
|
Sercom *sercom = sercom_enable_pclock(bus);
|
||||||
sercom_i2c_pins(bus);
|
sercom_i2c_pins(bus);
|
||||||
SercomI2cm *si = &sercom->I2CM;
|
SercomI2cm *si = &sercom->I2CM;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
//
|
//
|
||||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
|
|
||||||
|
#include "command.h" // DECL_CONSTANT_STR
|
||||||
#include "compiler.h" // DIV_ROUND_CLOSEST
|
#include "compiler.h" // DIV_ROUND_CLOSEST
|
||||||
#include "internal.h" // enable_pclock
|
#include "internal.h" // enable_pclock
|
||||||
|
|
||||||
|
@ -94,6 +95,10 @@ config_dfll(uint32_t dfllmul, uint32_t ctrlb)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_CLOCK_REF_X32K
|
||||||
|
DECL_CONSTANT_STR("RESERVE_PINS_crystal", "PA0,PA1");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Initialize the clocks using an external 32K crystal
|
// Initialize the clocks using an external 32K crystal
|
||||||
static void
|
static void
|
||||||
clock_init_32k(void)
|
clock_init_32k(void)
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
* Available sercom blocks
|
* Available sercom blocks
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
|
|
||||||
|
DECL_ENUMERATION_RANGE("bus", "sercom0", 0, 8);
|
||||||
|
|
||||||
struct sercom_bus {
|
struct sercom_bus {
|
||||||
Sercom *sercom;
|
Sercom *sercom;
|
||||||
uint32_t pclk_id, pm_id;
|
uint32_t pclk_id, pm_id;
|
||||||
|
@ -39,7 +41,7 @@ Sercom *
|
||||||
sercom_enable_pclock(uint32_t sercom_id)
|
sercom_enable_pclock(uint32_t sercom_id)
|
||||||
{
|
{
|
||||||
if (sercom_id >= ARRAY_SIZE(sercoms))
|
if (sercom_id >= ARRAY_SIZE(sercoms))
|
||||||
shutdown("Invalid sercom bus");
|
shutdown("Invalid SERCOM bus");
|
||||||
const struct sercom_bus *sb = &sercoms[sercom_id];
|
const struct sercom_bus *sb = &sercoms[sercom_id];
|
||||||
enable_pclock(sb->pclk_id, sb->pm_id);
|
enable_pclock(sb->pclk_id, sb->pm_id);
|
||||||
return sb->sercom;
|
return sb->sercom;
|
||||||
|
@ -290,6 +292,9 @@ sercom_lookup_pad(uint32_t sercom_id, uint8_t pin)
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
|
|
||||||
enum { TX_PIN, RX_PIN, CLK_PIN };
|
enum { TX_PIN, RX_PIN, CLK_PIN };
|
||||||
|
DECL_ENUMERATION("sercom_pin_type", "tx", TX_PIN);
|
||||||
|
DECL_ENUMERATION("sercom_pin_type", "rx", RX_PIN);
|
||||||
|
DECL_ENUMERATION("sercom_pin_type", "clk", CLK_PIN);
|
||||||
|
|
||||||
// Runtime configuration
|
// Runtime configuration
|
||||||
struct sercom_pin {
|
struct sercom_pin {
|
||||||
|
@ -308,7 +313,7 @@ command_set_sercom_pin(uint32_t *args)
|
||||||
sercom_pins[sercom_id].pins[pin_type] = pin;
|
sercom_pins[sercom_id].pins[pin_type] = pin;
|
||||||
}
|
}
|
||||||
DECL_COMMAND(command_set_sercom_pin,
|
DECL_COMMAND(command_set_sercom_pin,
|
||||||
"set_sercom_pin sercom_id=%u pin_type=%u pin=%u");
|
"set_sercom_pin bus=%u sercom_pin_type=%u pin=%u");
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
|
@ -349,6 +354,8 @@ sercom_lookup_spi_dopo(uint8_t tx_pad, uint8_t clk_pad)
|
||||||
uint32_t
|
uint32_t
|
||||||
sercom_spi_pins(uint32_t sercom_id)
|
sercom_spi_pins(uint32_t sercom_id)
|
||||||
{
|
{
|
||||||
|
if (sercom_id >= ARRAY_SIZE(sercom_pins))
|
||||||
|
shutdown("Invalid SERCOM bus");
|
||||||
uint8_t tx_pin = sercom_pins[sercom_id].pins[TX_PIN];
|
uint8_t tx_pin = sercom_pins[sercom_id].pins[TX_PIN];
|
||||||
const struct sercom_pad *tx_sp = sercom_lookup_pad(sercom_id, tx_pin);
|
const struct sercom_pad *tx_sp = sercom_lookup_pad(sercom_id, tx_pin);
|
||||||
uint8_t rx_pin = sercom_pins[sercom_id].pins[RX_PIN];
|
uint8_t rx_pin = sercom_pins[sercom_id].pins[RX_PIN];
|
||||||
|
|
|
@ -5,27 +5,30 @@
|
||||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
|
|
||||||
#include "board/serial_irq.h" // serial_rx_data
|
#include "board/serial_irq.h" // serial_rx_data
|
||||||
|
#include "command.h" // DECL_CONSTANT_STR
|
||||||
#include "internal.h" // enable_pclock
|
#include "internal.h" // enable_pclock
|
||||||
#include "sched.h" // DECL_INIT
|
#include "sched.h" // DECL_INIT
|
||||||
|
|
||||||
|
DECL_CONSTANT_STR("RESERVE_PINS_serial", "PA11,PA10");
|
||||||
|
|
||||||
void
|
void
|
||||||
serial_init(void)
|
serial_init(void)
|
||||||
{
|
{
|
||||||
// Enable serial clock
|
// Enable serial clock
|
||||||
enable_pclock(SERCOM0_GCLK_ID_CORE, ID_SERCOM0);
|
enable_pclock(SERCOM0_GCLK_ID_CORE, ID_SERCOM0);
|
||||||
// Enable pins
|
// Enable pins
|
||||||
gpio_peripheral(GPIO('A', 10), 'C', 0);
|
|
||||||
gpio_peripheral(GPIO('A', 11), 'C', 0);
|
gpio_peripheral(GPIO('A', 11), 'C', 0);
|
||||||
|
gpio_peripheral(GPIO('A', 10), 'C', 0);
|
||||||
// Configure serial
|
// Configure serial
|
||||||
SercomUsart *su = &SERCOM0->USART;
|
SercomUsart *su = &SERCOM0->USART;
|
||||||
su->CTRLA.reg = 0;
|
su->CTRLA.reg = 0;
|
||||||
uint32_t areg = (SERCOM_USART_CTRLA_MODE(1)
|
uint32_t areg = (SERCOM_USART_CTRLA_MODE(1)
|
||||||
| SERCOM_USART_CTRLA_DORD
|
| SERCOM_USART_CTRLA_DORD
|
||||||
| SERCOM_USART_CTRLA_SAMPR(1)
|
| SERCOM_USART_CTRLA_SAMPR(1)
|
||||||
| SERCOM_USART_CTRLA_TXPO(1)
|
| SERCOM_USART_CTRLA_RXPO(3)
|
||||||
| SERCOM_USART_CTRLA_RXPO(3));
|
| SERCOM_USART_CTRLA_TXPO(1));
|
||||||
su->CTRLA.reg = areg;
|
su->CTRLA.reg = areg;
|
||||||
su->CTRLB.reg = SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN;
|
su->CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN;
|
||||||
uint32_t freq = get_pclock_frequency(SERCOM0_GCLK_ID_CORE);
|
uint32_t freq = get_pclock_frequency(SERCOM0_GCLK_ID_CORE);
|
||||||
uint32_t baud8 = freq / (2 * CONFIG_SERIAL_BAUD);
|
uint32_t baud8 = freq / (2 * CONFIG_SERIAL_BAUD);
|
||||||
su->BAUD.reg = (SERCOM_USART_BAUD_FRAC_BAUD(baud8 / 8)
|
su->BAUD.reg = (SERCOM_USART_BAUD_FRAC_BAUD(baud8 / 8)
|
||||||
|
|
|
@ -28,13 +28,6 @@ spi_init(uint32_t bus, SercomSpi *ss, uint32_t ctrla, uint32_t baud)
|
||||||
struct spi_config
|
struct spi_config
|
||||||
spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
|
spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
|
||||||
{
|
{
|
||||||
#ifdef SERCOM7
|
|
||||||
if (bus > 7)
|
|
||||||
#else
|
|
||||||
if (bus > 5)
|
|
||||||
#endif
|
|
||||||
shutdown("Invalid spi bus");
|
|
||||||
|
|
||||||
uint32_t dipo_dopo = sercom_spi_pins(bus);
|
uint32_t dipo_dopo = sercom_spi_pins(bus);
|
||||||
uint32_t ctrla = (SERCOM_SPI_CTRLA_MODE(3)
|
uint32_t ctrla = (SERCOM_SPI_CTRLA_MODE(3)
|
||||||
| (mode << SERCOM_SPI_CTRLA_CPHA_Pos)
|
| (mode << SERCOM_SPI_CTRLA_CPHA_Pos)
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "board/irq.h" // irq_disable
|
#include "board/irq.h" // irq_disable
|
||||||
#include "board/usb_cdc.h" // usb_notify_ep0
|
#include "board/usb_cdc.h" // usb_notify_ep0
|
||||||
#include "board/usb_cdc_ep.h" // USB_CDC_EP_BULK_IN
|
#include "board/usb_cdc_ep.h" // USB_CDC_EP_BULK_IN
|
||||||
|
#include "command.h" // DECL_CONSTANT_STR
|
||||||
#include "internal.h" // enable_pclock
|
#include "internal.h" // enable_pclock
|
||||||
#include "sched.h" // DECL_INIT
|
#include "sched.h" // DECL_INIT
|
||||||
|
|
||||||
|
@ -184,6 +185,8 @@ usb_request_bootloader(void)
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECL_CONSTANT_STR("RESERVE_PINS_USB", "PA24,PA25");
|
||||||
|
|
||||||
void
|
void
|
||||||
usbserial_init(void)
|
usbserial_init(void)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue