132 lines
3.3 KiB
C
132 lines
3.3 KiB
C
/*
|
|
* (c) danielinux 2019
|
|
*
|
|
* GPLv.2
|
|
*
|
|
* See LICENSE for details
|
|
*/
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include "uart.h"
|
|
#include "system.h"
|
|
|
|
#define UART2 (0x40004400)
|
|
|
|
#define UART2_SR (*(volatile uint32_t *)(UART2))
|
|
#define UART2_DR (*(volatile uint32_t *)(UART2 + 0x04))
|
|
#define UART2_BRR (*(volatile uint32_t *)(UART2 + 0x08))
|
|
#define UART2_CR1 (*(volatile uint32_t *)(UART2 + 0x0c))
|
|
#define UART2_CR2 (*(volatile uint32_t *)(UART2 + 0x10))
|
|
|
|
#define UART_CR1_UART_ENABLE (1 << 13)
|
|
#define UART_CR1_SYMBOL_LEN (1 << 12)
|
|
#define UART_CR1_PARITY_ENABLED (1 << 10)
|
|
#define UART_CR1_PARITY_ODD (1 << 9)
|
|
#define UART_CR1_TX_ENABLE (1 << 3)
|
|
#define UART_CR1_RX_ENABLE (1 << 2)
|
|
#define UART_CR2_STOPBITS (3 << 12)
|
|
#define UART_SR_TX_EMPTY (1 << 7)
|
|
#define UART_SR_RX_NOTEMPTY (1 << 5)
|
|
|
|
|
|
|
|
#define APB1_CLOCK_ER (*(volatile uint32_t *)(0x40023840))
|
|
#define UART2_APB1_CLOCK_ER_VAL (1 << 17)
|
|
|
|
#define AHB1_CLOCK_ER (*(volatile uint32_t *)(0x40023830))
|
|
#define GPIO_MODE_AF (2)
|
|
#define UART2_PIN_AF 7
|
|
#define UART2_RX_PIN 2
|
|
#define UART2_TX_PIN 3
|
|
|
|
static void uart2_pins_setup(void)
|
|
{
|
|
uint32_t reg;
|
|
AHB1_CLOCK_ER |= GPIOA_AHB1_CLOCK_ER;
|
|
/* Set mode = AF */
|
|
reg = GPIOA_MODE & ~ (0x03 << (UART2_RX_PIN * 2));
|
|
GPIOA_MODE = reg | (2 << (UART2_RX_PIN * 2));
|
|
reg = GPIOA_MODE & ~ (0x03 << (UART2_TX_PIN * 2));
|
|
GPIOA_MODE = reg | (2 << (UART2_TX_PIN * 2));
|
|
|
|
/* Alternate function: use low pins */
|
|
reg = GPIOA_AFL & ~(0xf << ((UART2_TX_PIN) * 4));
|
|
GPIOA_AFL = reg | (UART2_PIN_AF << ((UART2_TX_PIN) * 4));
|
|
reg = GPIOA_AFL & ~(0xf << ((UART2_RX_PIN) * 4));
|
|
GPIOA_AFL = reg | (UART2_PIN_AF << ((UART2_RX_PIN) * 4));
|
|
}
|
|
|
|
int uart2_setup(uint32_t bitrate, uint8_t data, char parity, uint8_t stop)
|
|
{
|
|
uint32_t reg;
|
|
int pin_rx, pin_tx, pin_af;
|
|
/* Enable pins and configure for AF7 */
|
|
uart2_pins_setup();
|
|
/* Turn on the device */
|
|
APB1_CLOCK_ER |= UART2_APB1_CLOCK_ER_VAL;
|
|
|
|
/* Configure for TX */
|
|
UART2_CR1 |= UART_CR1_TX_ENABLE;
|
|
|
|
/* Configure clock */
|
|
UART2_BRR = cpu_freq / bitrate;
|
|
|
|
/* Configure data bits */
|
|
if (data == 8)
|
|
UART2_CR1 &= ~UART_CR1_SYMBOL_LEN;
|
|
else
|
|
UART2_CR1 |= UART_CR1_SYMBOL_LEN;
|
|
|
|
/* Configure parity */
|
|
switch (parity) {
|
|
case 'O':
|
|
UART2_CR1 |= UART_CR1_PARITY_ODD;
|
|
/* fall through to enable parity */
|
|
case 'E':
|
|
UART2_CR1 |= UART_CR1_PARITY_ENABLED;
|
|
break;
|
|
default:
|
|
UART2_CR1 &= ~(UART_CR1_PARITY_ENABLED | UART_CR1_PARITY_ODD);
|
|
}
|
|
/* Set stop bits */
|
|
reg = UART2_CR2 & ~UART_CR2_STOPBITS;
|
|
if (stop > 1)
|
|
UART2_CR2 = reg & (2 << 12);
|
|
else
|
|
UART2_CR2 = reg;
|
|
|
|
/* Turn on uart */
|
|
UART2_CR1 |= UART_CR1_UART_ENABLE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int _write(void *r, uint8_t *text, int len)
|
|
{
|
|
char *p = (char *)text;
|
|
int i;
|
|
volatile uint32_t reg;
|
|
text[len - 1] = 0;
|
|
while(*p) {
|
|
do {
|
|
reg = UART2_SR;
|
|
} while ((reg & UART_SR_TX_EMPTY) == 0);
|
|
UART2_DR = *p;
|
|
p++;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
/* commodity to print binary buffers */
|
|
|
|
void printbin(const uint8_t *buf, int len)
|
|
{
|
|
int i;
|
|
for (i = 0; i < len; i++) {
|
|
if ((i % 16) == 0)
|
|
printf("\r\n%08x: ", i);
|
|
printf("%02x ", buf[i]);
|
|
}
|
|
printf("\r\n");
|
|
}
|
|
|