From 1dc7d758f96dd2b9bd7b03f01ca032d68b696cf0 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 2 Nov 2014 10:14:39 +0000 Subject: fish --- libopencm3/lib/sam/common/gpio.c | 64 ++++++++++++++++++++++ libopencm3/lib/sam/common/pmc.c | 97 +++++++++++++++++++++++++++++++++ libopencm3/lib/sam/common/usart.c | 110 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 271 insertions(+) create mode 100644 libopencm3/lib/sam/common/gpio.c create mode 100644 libopencm3/lib/sam/common/pmc.c create mode 100644 libopencm3/lib/sam/common/usart.c (limited to 'libopencm3/lib/sam/common') diff --git a/libopencm3/lib/sam/common/gpio.c b/libopencm3/lib/sam/common/gpio.c new file mode 100644 index 0000000..75929f8 --- /dev/null +++ b/libopencm3/lib/sam/common/gpio.c @@ -0,0 +1,64 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Gareth McMullin + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + +void gpio_init(uint32_t port, uint32_t pins, enum gpio_flags flags) +{ + switch (flags & 3) { + case GPIO_FLAG_GPINPUT: + /* input mode doesn't really exist, so we make a high + * output in open-drain mode + */ + PIO_SODR(port) = pins; + flags |= GPIO_FLAG_OPEN_DRAIN; + /* fall through */ + case GPIO_FLAG_GPOUTPUT: + PIO_OER(port) = pins; + PIO_PER(port) = pins; + break; + case GPIO_FLAG_PERIPHA: + PIO_ABSR(port) &= ~pins; + PIO_PDR(port) = pins; + break; + case GPIO_FLAG_PERIPHB: + PIO_ABSR(port) |= pins; + PIO_PDR(port) = pins; + } + + if (flags & GPIO_FLAG_OPEN_DRAIN) { + PIO_MDER(port) = pins; + } else { + PIO_MDDR(port) = pins; + } + + if (flags & GPIO_FLAG_PULL_UP) { + PIO_PUER(port) = pins; + } else { + PIO_PUDR(port) = pins; + } +} + +void gpio_toggle(uint32_t gpioport, uint32_t gpios) +{ + uint32_t odsr = PIO_ODSR(gpioport); + PIO_CODR(gpioport) = odsr & gpios; + PIO_SODR(gpioport) = ~odsr & gpios; +} + diff --git a/libopencm3/lib/sam/common/pmc.c b/libopencm3/lib/sam/common/pmc.c new file mode 100644 index 0000000..b4e0d7f --- /dev/null +++ b/libopencm3/lib/sam/common/pmc.c @@ -0,0 +1,97 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Gareth McMullin + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include + +/** Default peripheral clock frequency after reset. */ +uint32_t pmc_mck_frequency = 4000000; + +void pmc_xtal_enable(bool en, uint8_t startup_time) +{ + if (en) { + CKGR_MOR = (CKGR_MOR & ~CKGR_MOR_MOSCXTST_MASK) | + CKGR_MOR_KEY | CKGR_MOR_MOSCXTEN | + (startup_time << 8); + while (!(PMC_SR & PMC_SR_MOSCXTS)); + } else { + CKGR_MOR = CKGR_MOR_KEY | (CKGR_MOR & ~CKGR_MOR_MOSCXTEN); + } +} + +void pmc_plla_config(uint8_t mul, uint8_t div) +{ + CKGR_PLLAR = CKGR_PLLAR_ONE | ((mul - 1) << 16) | + CKGR_PLLAR_PLLACOUNT_MASK | div; + while (!(PMC_SR & PMC_SR_LOCKA)); +} + +void pmc_peripheral_clock_enable(uint8_t pid) +{ + if (pid < 32) { + PMC_PCER0 = 1 << pid; + } else { + PMC_PCER1 = 1 << (pid & 31); + } +} + +void pmc_peripheral_clock_disable(uint8_t pid) +{ + if (pid < 32) { + PMC_PCDR0 = 1 << pid; + } else { + PMC_PCDR1 = 1 << (pid & 31); + } +} + +void pmc_mck_set_source(enum mck_src src) +{ + PMC_MCKR = (PMC_MCKR & ~PMC_MCKR_CSS_MASK) | src; + while (!(PMC_SR & PMC_SR_MCKRDY)); +} + +void pmc_clock_setup_in_xtal_12mhz_out_84mhz(void) +{ + eefc_set_latency(4); + + /* 12MHz external xtal, maximum possible startup time */ + pmc_xtal_enable(true, 0xff); + /* Select as main oscillator */ + CKGR_MOR |= CKGR_MOR_KEY | CKGR_MOR_MOSCSEL; + /* Multiply by 7 for 84MHz */ + pmc_plla_config(7, 1); + pmc_mck_set_source(MCK_SRC_PLLA); + + pmc_mck_frequency = 84000000; +} + +void pmc_clock_setup_in_rc_4mhz_out_84mhz(void) +{ + eefc_set_latency(4); + + /* Select as main oscillator */ + CKGR_MOR = CKGR_MOR_KEY | + (CKGR_MOR & ~(CKGR_MOR_MOSCSEL | CKGR_MOR_MOSCRCF_MASK)); + /* Multiply by 21 for 84MHz */ + pmc_plla_config(21, 1); + pmc_mck_set_source(MCK_SRC_PLLA); + + pmc_mck_frequency = 84000000; +} + diff --git a/libopencm3/lib/sam/common/usart.c b/libopencm3/lib/sam/common/usart.c new file mode 100644 index 0000000..36833f7 --- /dev/null +++ b/libopencm3/lib/sam/common/usart.c @@ -0,0 +1,110 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Gareth McMullin + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include + +void usart_set_baudrate(uint32_t usart, uint32_t baud) +{ + USART_BRGR(usart) = pmc_mck_frequency / (16 * baud); +} + +void usart_set_databits(uint32_t usart, int bits) +{ + USART_MR(usart) = (USART_MR(usart) & ~USART_MR_CHRL_MASK) | + ((bits - 5) << 6); +} + +void usart_set_stopbits(uint32_t usart, enum usart_stopbits sb) +{ + USART_MR(usart) = (USART_MR(usart) & ~USART_MR_NBSTOP_MASK) | + (sb << 12); +} + +void usart_set_parity(uint32_t usart, enum usart_parity par) +{ + USART_MR(usart) = (USART_MR(usart) & ~USART_MR_PAR_MASK) | (par << 9); +} + +void usart_set_mode(uint32_t usart, enum usart_mode mode) +{ + USART_CR(usart) = + (mode & USART_MODE_RX) ? USART_CR_RXEN : USART_CR_RXDIS; + USART_CR(usart) = (mode & USART_MODE_TX) ? USART_CR_TXEN + : USART_CR_TXDIS; +} + +void usart_set_flow_control(uint32_t usart, enum usart_flowcontrol fc) +{ + USART_MR(usart) = (USART_MR(usart) & ~USART_MR_MODE_MASK) | + (fc ? USART_MR_MODE_HW_HANDSHAKING : 0); +} + +void usart_enable(uint32_t usart) +{ + (void)usart; +} + +void usart_disable(uint32_t usart) +{ + (void)usart; +} + +void usart_send(uint32_t usart, uint16_t data) +{ + USART_THR(usart) = data; +} + +uint16_t usart_recv(uint32_t usart) +{ + return USART_RHR(usart) & 0x1f; +} + +void usart_wait_send_ready(uint32_t usart) +{ + while ((USART_CSR(usart) & USART_CSR_TXRDY) == 0); +} + +void usart_wait_recv_ready(uint32_t usart) +{ + while ((USART_CSR(usart) & USART_CSR_RXRDY) == 0); +} + +void usart_send_blocking(uint32_t usart, uint16_t data) +{ + usart_wait_send_ready(usart); + usart_send(usart, data); +} + +uint16_t usart_recv_blocking(uint32_t usart) +{ + usart_wait_recv_ready(usart); + + return usart_recv(usart); +} + +void usart_enable_rx_interrupt(uint32_t usart) +{ + USART_IER(usart) = USART_CSR_RXRDY; +} + +void usart_disable_rx_interrupt(uint32_t usart) +{ + USART_IDR(usart) = USART_CSR_RXRDY; +} -- cgit v1.2.3