aos/usr/drivers/lpuart/main.c
Daniel Schwyn 6d444bf552 Main handout
Signed-off-by: Daniel Schwyn <daniel.schwyn@inf.ethz.ch>
2022-03-03 14:57:51 +01:00

122 lines
3.1 KiB
C

/**
* \file
* \brief Serial port driver.
*/
/*
* Copyright (c) 2020, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* If you do not find this file, copies can be found by writing to:
* ETH Zurich D-INFK, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich,
* Attn: Systems Group.
*/
#include <drivers/lpuart.h>
#include <dev/lpuart_dev.h>
struct lpuart_s {
struct event_closure int_handler;
struct lpuart_t dev;
};
static void hw_init(struct lpuart_s *s)
{
// Disable transceiver
lpuart_ctrl_t ctrl = lpuart_ctrl_rawrd(&s->dev);
ctrl = lpuart_ctrl_te_insert(ctrl, 0);
ctrl = lpuart_ctrl_re_insert(ctrl, 0);
lpuart_ctrl_rawwr(&s->dev, ctrl);
// Set baudrate
// baudrate = clock rate / (over sampling rate * SBR)
// TODO: Currently we assume UART clock is set to 8MHz
lpuart_baud_t baud = lpuart_baud_default;
baud = lpuart_baud_osr_insert(baud, lpuart_ratio5);
// OSR of 5 needs bothedge set
baud = lpuart_baud_bothedge_insert(baud, 1);
baud = lpuart_baud_sbr_insert(baud, 139);
lpuart_baud_rawwr(&s->dev, baud);
// enable FIFOs
ctrl = lpuart_ctrl_default;
ctrl = lpuart_ctrl_te_insert(ctrl, 0);
ctrl = lpuart_ctrl_re_insert(ctrl, 0);
lpuart_ctrl_rawwr(&s->dev, ctrl);
lpuart_fifo_t fcr = lpuart_fifo_default;
fcr = lpuart_fifo_rxfe_insert(fcr, 1);
lpuart_fifo_rawwr(&s->dev, fcr);
fcr = lpuart_fifo_txfe_insert(fcr, 1);
lpuart_fifo_rawwr(&s->dev, fcr);
// Set both watermarks to 0 (and also reset their counts)
lpuart_water_rawwr(&s->dev, 0);
// Enable transceiver
ctrl = lpuart_ctrl_default;
ctrl = lpuart_ctrl_te_insert(ctrl, 1);
ctrl = lpuart_ctrl_re_insert(ctrl, 1);
lpuart_ctrl_rawwr(&s->dev, ctrl);
}
errval_t lpuart_init(struct lpuart_s** s_ret, void *base)
{
LPUART_DEBUG("Driver init\n");
assert(s_ret != NULL);
assert(base != NULL);
struct lpuart_s *s = calloc(1, sizeof(struct lpuart_s));
assert(s);
*s_ret = s;
lpuart_initialize(&s->dev, base);
uint8_t major = lpuart_verid_major_rdf(&s->dev);
uint8_t minor = lpuart_verid_minor_rdf(&s->dev);
LPUART_DEBUG("Read version major=%d, minor=%d\n", major, minor);
if(major != 4 || minor != 1){
return LPUART_ERR_INVALID_DEV;
}
LPUART_DEBUG("Initializing hw...");
hw_init(s);
return SYS_ERR_OK;
}
errval_t lpuart_getchar(struct lpuart_s *s, char *c)
{
if (lpuart_stat_or_rdf(&s->dev)) {
lpuart_stat_or_wrf(&s->dev, 1);
return LPUART_ERR_RCV_OVERRUN;
}
if (lpuart_stat_rdrf_rdf(&s->dev) == 0) {
return LPUART_ERR_NO_DATA;
}
*c = lpuart_rxdata_buf_rdf(&s->dev);
return SYS_ERR_OK;
}
errval_t lpuart_enable_interrupt(struct lpuart_s *s)
{
// Receive interrupt enable
lpuart_ctrl_rie_wrf(&s->dev,1);
return SYS_ERR_OK;
}
errval_t lpuart_putchar(struct lpuart_s *s, char c)
{
lpuart_t *u = &s->dev;
assert(u->base != 0);
while (lpuart_stat_tdre_rdf(u) == 0)
;
lpuart_txdata_wr(u, c);
return SYS_ERR_OK;
}