gadget-tester/uart.c
2019-11-22 11:12:54 +01:00

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");
}