Files
Maison/OpenSky_BL/uart.c
2026-04-21 12:19:15 +02:00

207 lines
5.4 KiB
C

/*
Copyright 2016 fishpepper <AT> gmail.com
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/>.
author: fishpepper <AT> gmail.com
*/
#include "uart.h"
#include "config.h"
#include "led.h"
#include "cc25xx.h"
#if (BOOTLOADER_UART_NUM == 0)
#define UxBAUD U0BAUD
#define UxGCR U0GCR
#define UxGCR_ORDER U0GCR_ORDER
#define UxCSR U0CSR
#define UxCSR_TX_BYTE U0CSR_TX_BYTE
#define UxUCR U0UCR
#define UxDBUF U0DBUF
#define URXxIF URX0IF
#define UTXxIF UTX0IF
#else
#define UxBAUD U1BAUD
#define UxGCR U1GCR
#define UxGCR_ORDER U1GCR_ORDER
#define UxCSR U1CSR
#define UxCSR_TX_BYTE U1CSR_TX_BYTE
#define UxUCR U1UCR
#define UxDBUF U1DBUF
#define URXxIF URX1IF
#define UTXxIF UTX1IF
#endif // BOOTLOADER_UART
void uart_init(void) {
__xdata union uart_config_t uart_config;
#if ((BOOTLOADER_UART_NUM) == 0) && ((BOOTLOADER_UART_PORT) == 0)
// -> USART0_P0
// use ALT1 -> Clear flag -> P0_3 = TX / P0_2 = RX
PERCFG &= ~(PERCFG_U0CFG);
// configure pins as peripheral:
P0SEL |= (1<<3) | (1<<2);
// make sure all P1 pins switch to normal GPIO
P1SEL &= ~(0x3C);
// make tx pin output:
P0DIR |= (1<<3);
#elif ((BOOTLOADER_UART_NUM) == 0) && ((BOOTLOADER_UART_PORT) == 1)
// -> USART0_P1
// use ALT2 -> Set flag -> P1_5 = TX / P1_4 = RX
PERCFG |= (PERCFG_U0CFG);
// configure pins as peripheral:
P1SEL |= (1<<5) | (1<<4);
// make sure all P0 pins switch to normal GPIO
P0SEL &= ~(0x3C);
// make tx pin output:
P1DIR |= (1<<5);
#elif ((BOOTLOADER_UART_NUM) == 1) && ((BOOTLOADER_UART_PORT) == 0)
// -> USART1_P0
// use ALT1 -> Clear flag -> P0_4 = TX / P0_5 = RX
PERCFG &= ~(PERCFG_U1CFG);
// USART1 has priority when USART0 is also enabled
P2DIR = (P2DIR & 0x3F) | 0b01000000;
// configure pins as peripheral:
P0SEL |= (1<<4) | (1<<5);
// make sure all P1 pins switch to normal GPIO
P1SEL &= ~(0xF0);
// make tx pin output:
P0DIR |= (1<<4);
#elif ((BOOTLOADER_UART_NUM) == 1) && ((BOOTLOADER_UART_PORT) == 1)
// -> USART1_P1
// use ALT2 -> set flag -> P1_6 = TX / P1_7 = RX
PERCFG |= (PERCFG_U1CFG);
// USART1 has priority when USART0 is also enabled
P2DIR = (P2DIR & 0x3F) | 0b01000000;
// configure pins as peripheral:
P1SEL |= (1<<6) | (1<<7);
// make sure all P0 pins switch to normal GPIO
P0SEL &= ~(0x3C);
// make tx pin output:
P1DIR |= (1<<6);
#else
#error "ERROR: UNSUPPORTED DEBUG UART"
#endif // BOOTLOADER_UART_*
// this assumes cpu runs from XOSC (26mhz) !
// set baudrate
UxBAUD = UART_BAUD_M;
UxGCR = (UxGCR & ~0x1F) | (UART_BAUD_E);
// set up config
#if BOOTLOADER_UART_INVERTED
// this is a really nice feature of the cc2510:
// we can invert the idle level of the usart
// by setting STOP to zero. by inverting
// the parity, the startbit, and the data
// we can effectively invert the usart in software :)
uart_config.bit.START = 1; // startbit level = low
uart_config.bit.STOP = 0; // stopbit level = high
uart_config.bit.D9 = 1; // UNEven parity
#else
// standard usart, non-inverted mode
uart_config.bit.START = 0; // startbit level = low
uart_config.bit.STOP = 1; // stopbit level = high
uart_config.bit.D9 = 0; // Even parity
#endif // BOOTLOADER_UART_INVERTED
#if BOOTLOADER_UART_USE_2STOPBITS
uart_config.bit.SPB = 1; // 2 stopbit
#else
uart_config.bit.SPB = 0; // 1 stopbit
#endif // BOOTLOADER_UART_USE_2STOPBITS
#if BOOTLOADER_UART_USE_PARITY
// use parity
uart_config.bit.PARITY = 1; // 1 = parity enabled, D9=0 -> even parity
uart_config.bit.BIT9 = 1; // 8+1 parity bit
#else
// no parity
uart_config.bit.PARITY = 0; // no parity
uart_config.bit.BIT9 = 0; // 8+0 parity bit
#endif // BOOTLOADER_USE_PARITY
uart_config.bit.FLOW = 0; // no hw flow control
uart_config.bit.ORDER = 0; // lsb first
// enable uart mode
UxCSR |= 0x80;
// store config to UxUCR register
UxUCR = uart_config.byte & (0x7F);
// store config to UxGCR: (msb/lsb)
if (uart_config.bit.ORDER) {
UxGCR |= UxGCR_ORDER;
} else {
UxGCR &= ~UxGCR_ORDER;
}
// enable receiver
UxCSR |= 0x40;
}
uint8_t uart_getc(void) {
uint8_t res = 0;
led_green_toggle();
// wait for RX
while (!URXxIF) {}
// fetch data
#if BOOTLOADER_UART_INVERTED
res = 0xFF ^ UxDBUF;
#else
res = UxDBUF;
#endif // BOOTLOADER_UART_INVERTED
// clear flag
URXxIF = 0;
return res;
}
void uart_putc(uint8_t c) {
UTXxIF = 0;
#if BOOTLOADER_UART_INVERTED
UxDBUF = 0xFF ^ c;
#else
UxDBUF = c;
#endif // BOOTLOADER_UART_INVERTED
led_red_toggle();
while (!UTXxIF) {}
UTXxIF = 0;
}