diff options
Diffstat (limited to 'src/lib/usart.c')
-rw-r--r-- | src/lib/usart.c | 345 |
1 files changed, 0 insertions, 345 deletions
diff --git a/src/lib/usart.c b/src/lib/usart.c deleted file mode 100644 index 9987641..0000000 --- a/src/lib/usart.c +++ /dev/null @@ -1,345 +0,0 @@ -/* ***************************************************************************** - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * Created: 12/18/09 02:38:26 - * Copyright (c) 2009 Perry L. Hung. All rights reserved. - * - * ****************************************************************************/ - -/** - * @file usart.c - * - * @brief USART control routines - */ - -#include "libmaple.h" -#include "stm32f10x_rcc.h" -#include "usart.h" -#include "nvic.h" - -#define USART1_BASE 0x40013800 -#define USART2_BASE 0x40004400 -#define USART3_BASE 0x40004800 - -#define USART_UE BIT(13) -#define USART_M BIT(12) -#define USART_TE BIT(3) -#define USART_RE BIT(2) -#define USART_RXNEIE BIT(5) // read data register not empty interrupt enable -#define USART_TXE BIT(7) -#define USART_TC BIT(6) - -#define USART_STOP_BITS_1 BIT_MASK_SHIFT(0b0, 12) -#define USART_STOP_BITS_05 BIT_MASK_SHIFT(0b01, 12) -#define USART_STOP_BITS_2 BIT_MASK_SHIFT(0b02, 12) -#define USART_STOP_BITS_15 BIT_MASK_SHIFT(0b02, 12) - -#define USART1_CLK 72000000UL -#define USART2_CLK 36000000UL -#define USART3_CLK 36000000UL - -#define USART_RECV_BUF_SIZE 64 - -/* Ring buffer notes: - * The buffer is empty when head == tail. - * The buffer is full when the head is one byte in front of the tail - * The total buffer size must be a power of two - * Note, one byte is necessarily left free with this scheme */ -typedef struct usart_ring_buf { - uint32 head; - uint32 tail; - uint8 buf[USART_RECV_BUF_SIZE]; -} usart_ring_buf; - -static usart_ring_buf ring_buf1; -static usart_ring_buf ring_buf2; -static usart_ring_buf ring_buf3; - -typedef struct usart_port { - volatile uint32 SR; // Status register - volatile uint32 DR; // Data register - volatile uint32 BRR; // Baud rate register - volatile uint32 CR1; // Control register 1 - volatile uint32 CR2; // Control register 2 - volatile uint32 CR3; // Control register 3 - volatile uint32 GTPR; // Guard time and prescaler register -} usart_port; - -void USART1_IRQHandler(void) { - /* Read the data */ - ring_buf1.buf[ring_buf1.tail++] = (uint8_t)(((usart_port*)(USART1_BASE))->DR); - ring_buf1.tail %= USART_RECV_BUF_SIZE; -} - -/* Don't overrun your buffer, seriously */ -void USART2_IRQHandler(void) { - /* Read the data */ - ring_buf2.buf[ring_buf2.tail++] = (uint8_t)(((usart_port*)(USART2_BASE))->DR); - ring_buf2.tail %= USART_RECV_BUF_SIZE; -} -/* Don't overrun your buffer, seriously */ -void USART3_IRQHandler(void) { - /* Read the data */ - ring_buf3.buf[ring_buf3.tail++] = (uint8_t)(((usart_port*)(USART3_BASE))->DR); - ring_buf3.tail %= USART_RECV_BUF_SIZE; -} - -/** - * @brief Enable a USART in single buffer transmission mode, multibuffer - * receiver mode. - * - * @param usart_num USART to be initialized - * @param baud Baud rate to be set at - * @param recvBuf buf buffer for receiver - * @param len size of recvBuf - * - * @sideeffect Turns on the specified USART - */ -void usart_init(uint8 usart_num, uint32 baud) { - ASSERT((usart_num <= NR_USARTS) && (usart_num > 0)); - ASSERT(baud && (baud < USART_MAX_BAUD)); - - usart_port *port; - usart_ring_buf *ring_buf; - - uint32 clk_speed; - uint32 integer_part; - uint32 fractional_part; - uint32 tmp; - - switch (usart_num) { - case 1: - port = (usart_port*)USART1_BASE; - ring_buf = &ring_buf1; - clk_speed = USART1_CLK; - RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); - REG_SET(NVIC_ISER1, BIT(5)); - break; - case 2: - port = (usart_port*)USART2_BASE; - ring_buf = &ring_buf2; - clk_speed = USART2_CLK; - RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); - REG_SET(NVIC_ISER1, BIT(6)); - break; - case 3: - port = (usart_port*)USART3_BASE; - ring_buf = &ring_buf3; - clk_speed = USART3_CLK; - RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); - REG_SET(NVIC_ISER1, BIT(7)); - break; - default: - /* should never get here */ - ASSERT(0); - } - - /* Initialize ring buffer */ - ring_buf->head = 0; - ring_buf->tail = 0; - - /* Set baud rate */ - integer_part = ((25 * clk_speed) / (4 * baud)); - tmp = (integer_part / 100) << 4; - - fractional_part = integer_part - (100 * (tmp >> 4)); - tmp |= (((fractional_part * 16) + 50) / 100) & ((uint8)0x0F); - - port->BRR = (uint16_t)tmp; - - port->CR1 = USART_TE | // transmitter enable - USART_RE | // receiver enable - USART_RXNEIE; // receive interrupt enable - - - /* Enable the USART and set mode to 8n1 */ - port->CR1 |= USART_UE; -} - - -/** - * @brief Turn off a USART. - * - * @param USART to be disabled - * - * @sideeffect Turns off the specified USART - */ -void usart_disable(uint8 usart_num) { - ASSERT((usart_num <= NR_USARTS) && (usart_num > 0)); - usart_port *port; - - switch (usart_num) { - case 1: - port = (usart_port*)USART1_BASE; - break; - case 2: - port = (usart_port*)USART2_BASE; - break; - case 3: - port = (usart_port*)USART3_BASE; - break; - default: - /* should never get here */ - ASSERT(0); - } - - /* Is this usart enabled? */ - if (!(port->SR & USART_UE)) - return; - - /* TC bit must be high before disabling the usart */ - while ((port->SR & USART_TC) == 0) - ; - - /* Disable UE */ - port->CR1 = 0; -} - - -/** - * @brief Print a null terminated string to the specified USART - * - * @param[in] usart_num USART to send on - * @param[in] str String to send - */ -void usart_putstr(uint8 usart_num, const char* str) { - ASSERT((usart_num <= NR_USARTS) && (usart_num > 0)); - char ch; - - while((ch = *(str++)) != '\0') { - usart_putc(usart_num, ch); - } -} - -/** - * @brief Print an unsigned integer to the specified usart - * - * @param[in] usart_num usart to send on - * @param[in] val number to print - */ -void usart_putudec(uint8 usart_num, uint32 val) { - ASSERT((usart_num <= NR_USARTS) && (usart_num > 0)); - char digits[12]; - int i; - - i = 0; - do { - digits[i++] = val % 10 + '0'; - val /= 10; - } while (val > 0); - while (--i >= 0) { - usart_putc(usart_num, digits[i]); - } - -} - - -/** - * @brief Return one character from the receive buffer. Assumes - * that there is data available. - * - * @param[in] usart_num number of the usart to read from - * - * @return character from ring buffer - * - * @sideeffect may update the head pointer of the recv buffer - */ -uint8 usart_getc(uint8 usart_num) { - uint8 ch; - usart_ring_buf *rb; - - switch (usart_num) { - case 1: - rb = &ring_buf1; - break; - case 2: - rb = &ring_buf2; - break; - case 3: - rb = &ring_buf3; - break; - default: - ASSERT(0); - } - - /* Make sure there's actually data to be read */ - ASSERT(rb->head != rb->tail); - - /* Read the data and check for wraparound */ - ch = rb->buf[rb->head++]; - rb->head %= USART_RECV_BUF_SIZE; - - return ch; -} - -uint32 usart_data_available(uint8 usart_num) { - usart_ring_buf *rb; - - switch (usart_num) { - case 1: - rb = &ring_buf1; - break; - case 2: - rb = &ring_buf2; - break; - case 3: - rb = &ring_buf3; - break; - default: - ASSERT(0); - } - - return rb->tail - rb->head; -} - - - -/** - * @brief Output a byte out the uart - * - * @param[in] usart_num usart number to output on - * @param[in] byte byte to send - * - */ -void usart_putc(uint8 usart_num, uint8 byte) { - ASSERT((usart_num <= NR_USARTS) && (usart_num > 0)); - usart_port *port; - - switch (usart_num) { - case 1: - port = (usart_port*)USART1_BASE; - break; - case 2: - port = (usart_port*)USART2_BASE; - break; - case 3: - port = (usart_port*)USART3_BASE; - break; - default: - /* Should never get here */ - ASSERT(0); - } - -// if (ch == '\n') { -// usart_putc(usart_num, '\r'); -// } - - port->DR = byte; - - /* Wait for transmission to complete */ - while ((port->SR & USART_TXE) == 0) - ; -} - - |