add uarths
This commit is contained in:
parent
11397da1d0
commit
ca1172b60e
|
@ -184,7 +184,7 @@ void plicinit(void);
|
|||
void plicinithart(void);
|
||||
int plic_claim(void);
|
||||
void plic_complete(int);
|
||||
void device_init(unsigned long);
|
||||
void device_init(unsigned long, uint64);
|
||||
|
||||
// virtio_disk.c
|
||||
void virtio_disk_init(void);
|
||||
|
|
|
@ -25,7 +25,7 @@ main(unsigned long hartid, unsigned long dtb_pa)
|
|||
trapinithart(); // install kernel trap vector
|
||||
timerinit(); // set up timer interrupt handler
|
||||
procinit();
|
||||
device_init(dtb_pa);
|
||||
device_init(dtb_pa, hartid);
|
||||
// plicinit(); // set up interrupt controller
|
||||
// plicinithart(); // ask PLIC for device interrupts
|
||||
// binit(); // buffer cache
|
||||
|
|
|
@ -22,12 +22,15 @@
|
|||
#define UART0 0x38000000L
|
||||
#define UART0_IRQ 10
|
||||
|
||||
#define UARTHS 0x38000000L
|
||||
#define UARTHS_IRQ 33
|
||||
|
||||
// virtio mmio interface
|
||||
#define VIRTIO0 0x10001000
|
||||
#define VIRTIO0_IRQ 1
|
||||
|
||||
// local interrupt controller, which contains the timer.
|
||||
#define CLINT 0x2000000L
|
||||
#define CLINT 0x02000000L
|
||||
#define CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 8*(hartid))
|
||||
#define CLINT_MTIME (CLINT + 0xBFF8) // cycles since boot.
|
||||
|
||||
|
|
|
@ -48,12 +48,12 @@ plic_complete(int irq)
|
|||
*(uint32*)PLIC_SCLAIM(hart) = irq;
|
||||
}
|
||||
|
||||
void device_init(unsigned long pa) {
|
||||
void device_init(unsigned long pa, uint64 hartid) {
|
||||
// after RustSBI, txen = rxen = 1, rxie = 1, rxcnt = 0
|
||||
// start UART interrupt configuration
|
||||
// disable external interrupt on hart1 by setting threshold
|
||||
uint32 *hart0_m_threshold = (uint32*)0x0c200000;
|
||||
uint32 *hart1_m_threshold = (uint32*)0x0c202000;
|
||||
uint32 *hart0_m_threshold = (uint32*)PLIC;
|
||||
uint32 *hart1_m_threshold = (uint32*)PLIC_MENABLE(hartid);
|
||||
*(hart0_m_threshold) = 0;
|
||||
*(hart1_m_threshold) = 1;
|
||||
// *(uint32*)0x0c200000 = 0;
|
||||
|
@ -64,7 +64,7 @@ void device_init(unsigned long pa) {
|
|||
// if(*(uint32*)(0x0c000000 + 33 * 4) != 1) panic("uarhs's priority is not 1\n");
|
||||
// printf("uart priority: %p\n", *(uint32*)(0x0c000000 + 33 * 4));
|
||||
// *(uint32*)(0x0c000000 + 33 * 4) = 0x1;
|
||||
uint32 *hart0_m_int_enable_hi = (uint32*)0x0c002004;
|
||||
uint32 *hart0_m_int_enable_hi = (uint32*)(PLIC_MENABLE(hartid) + 0x04);
|
||||
*(hart0_m_int_enable_hi) = (1 << 0x1);
|
||||
// *(uint32*)0x0c002004 = (1 << 0x1);
|
||||
sbi_set_extern_interrupt((uint64)supervisor_external_handler - 0xffffffff00000000);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "riscv.h"
|
||||
#include "defs.h"
|
||||
#include "sbi.h"
|
||||
#include "memlayout.h"
|
||||
#include "uarths.h"
|
||||
|
||||
static int tick = 0;
|
||||
|
||||
|
@ -34,6 +36,11 @@ void timer_tick() {
|
|||
tick++;
|
||||
if((tick % 10) == 0) {
|
||||
printf("[Timer]tick: %d\n", tick);
|
||||
sbi_console_putchar(*(uint32*)0x38000004);
|
||||
uint32 c = *(uint32*)(UARTHS + UARTHS_REG_RXFIFO);
|
||||
if(c <= 255) {
|
||||
printf("[UARTHS]receive: %p, ", c);
|
||||
sbi_console_putchar(c);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -234,5 +234,12 @@ devintr()
|
|||
|
||||
void
|
||||
supervisor_external_handler() {
|
||||
|
||||
int irq = *(uint32*)(PLIC + 0x04);
|
||||
if(irq == UARTHS_IRQ) {
|
||||
// UARTHS
|
||||
}
|
||||
else
|
||||
{
|
||||
while (1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,297 @@
|
|||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Universal Asynchronous Receiver/Transmitter (UART)
|
||||
*
|
||||
* The UART peripheral supports the following features:
|
||||
*
|
||||
* - 8-N-1 and 8-N-2 formats: 8 data bits, no parity bit, 1 start
|
||||
* bit, 1 or 2 stop bits
|
||||
*
|
||||
* - 8-entry transmit and receive FIFO buffers with programmable
|
||||
* watermark interrupts
|
||||
*
|
||||
* - 16× Rx oversampling with 2/3 majority voting per bit
|
||||
*
|
||||
* The UART peripheral does not support hardware flow control or
|
||||
* other modem control signals, or synchronous serial data
|
||||
* tranfesrs.
|
||||
*
|
||||
* @note UART RAM Layout
|
||||
*
|
||||
* | Address | Name | Description |
|
||||
* |-----------|----------|---------------------------------|
|
||||
* | 0x000 | txdata | Transmit data register |
|
||||
* | 0x004 | rxdata | Receive data register |
|
||||
* | 0x008 | txctrl | Transmit control register |
|
||||
* | 0x00C | rxctrl | Receive control register |
|
||||
* | 0x010 | ie | UART interrupt enable |
|
||||
* | 0x014 | ip | UART Interrupt pending |
|
||||
* | 0x018 | div | Baud rate divisor |
|
||||
*
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#ifndef _DRIVER_UARTHS_H
|
||||
#define _DRIVER_UARTHS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
/* Register address offsets */
|
||||
#define UARTHS_REG_TXFIFO (0x00)
|
||||
#define UARTHS_REG_RXFIFO (0x04)
|
||||
#define UARTHS_REG_TXCTRL (0x08)
|
||||
#define UARTHS_REG_RXCTRL (0x0c)
|
||||
#define UARTHS_REG_IE (0x10)
|
||||
#define UARTHS_REG_IP (0x14)
|
||||
#define UARTHS_REG_DIV (0x18)
|
||||
|
||||
/* TXCTRL register */
|
||||
#define UARTHS_TXEN (0x01)
|
||||
#define UARTHS_TXWM(x) (((x) & 0xffff) << 16)
|
||||
|
||||
/* RXCTRL register */
|
||||
#define UARTHS_RXEN (0x01)
|
||||
#define UARTHS_RXWM(x) (((x) & 0xffff) << 16)
|
||||
|
||||
/* IP register */
|
||||
#define UARTHS_IP_TXWM (0x01)
|
||||
#define UARTHS_IP_RXWM (0x02)
|
||||
/* clang-format on */
|
||||
|
||||
typedef struct _uarths_txdata
|
||||
{
|
||||
/* Bits [7:0] is data */
|
||||
uint32 data : 8;
|
||||
/* Bits [30:8] is 0 */
|
||||
uint32 zero : 23;
|
||||
/* Bit 31 is full status */
|
||||
uint32 full : 1;
|
||||
} __attribute__((packed, aligned(4))) uarths_txdata_t;
|
||||
|
||||
typedef struct _uarths_rxdata
|
||||
{
|
||||
/* Bits [7:0] is data */
|
||||
uint32 data : 8;
|
||||
/* Bits [30:8] is 0 */
|
||||
uint32 zero : 23;
|
||||
/* Bit 31 is empty status */
|
||||
uint32 empty : 1;
|
||||
} __attribute__((packed, aligned(4))) uarths_rxdata_t;
|
||||
|
||||
typedef struct _uarths_txctrl
|
||||
{
|
||||
/* Bit 0 is txen, controls whether the Tx channel is active. */
|
||||
uint32 txen : 1;
|
||||
/* Bit 1 is nstop, 0 for one stop bit and 1 for two stop bits */
|
||||
uint32 nstop : 1;
|
||||
/* Bits [15:2] is reserved */
|
||||
uint32 resv0 : 14;
|
||||
/* Bits [18:16] is threshold of interrupt triggers */
|
||||
uint32 txcnt : 3;
|
||||
/* Bits [31:19] is reserved */
|
||||
uint32 resv1 : 13;
|
||||
} __attribute__((packed, aligned(4))) uarths_txctrl_t;
|
||||
|
||||
typedef struct _uarths_rxctrl
|
||||
{
|
||||
/* Bit 0 is txen, controls whether the Tx channel is active. */
|
||||
uint32 rxen : 1;
|
||||
/* Bits [15:1] is reserved */
|
||||
uint32 resv0 : 15;
|
||||
/* Bits [18:16] is threshold of interrupt triggers */
|
||||
uint32 rxcnt : 3;
|
||||
/* Bits [31:19] is reserved */
|
||||
uint32 resv1 : 13;
|
||||
} __attribute__((packed, aligned(4))) uarths_rxctrl_t;
|
||||
|
||||
typedef struct _uarths_ip
|
||||
{
|
||||
/* Bit 0 is txwm, raised less than txcnt */
|
||||
uint32 txwm : 1;
|
||||
/* Bit 1 is txwm, raised greater than rxcnt */
|
||||
uint32 rxwm : 1;
|
||||
/* Bits [31:2] is 0 */
|
||||
uint32 zero : 30;
|
||||
} __attribute__((packed, aligned(4))) uarths_ip_t;
|
||||
|
||||
typedef struct _uarths_ie
|
||||
{
|
||||
/* Bit 0 is txwm, raised less than txcnt */
|
||||
uint32 txwm : 1;
|
||||
/* Bit 1 is txwm, raised greater than rxcnt */
|
||||
uint32 rxwm : 1;
|
||||
/* Bits [31:2] is 0 */
|
||||
uint32 zero : 30;
|
||||
} __attribute__((packed, aligned(4))) uarths_ie_t;
|
||||
|
||||
typedef struct _uarths_div
|
||||
{
|
||||
/* Bits [31:2] is baud rate divisor register */
|
||||
uint32 div : 16;
|
||||
/* Bits [31:16] is 0 */
|
||||
uint32 zero : 16;
|
||||
} __attribute__((packed, aligned(4))) uarths_div_t;
|
||||
|
||||
typedef struct _uarths
|
||||
{
|
||||
/* Address offset 0x00 */
|
||||
uarths_txdata_t txdata;
|
||||
/* Address offset 0x04 */
|
||||
uarths_rxdata_t rxdata;
|
||||
/* Address offset 0x08 */
|
||||
uarths_txctrl_t txctrl;
|
||||
/* Address offset 0x0c */
|
||||
uarths_rxctrl_t rxctrl;
|
||||
/* Address offset 0x10 */
|
||||
uarths_ie_t ie;
|
||||
/* Address offset 0x14 */
|
||||
uarths_ip_t ip;
|
||||
/* Address offset 0x18 */
|
||||
uarths_div_t div;
|
||||
} __attribute__((packed, aligned(4))) uarths_t;
|
||||
|
||||
typedef enum _uarths_interrupt_mode
|
||||
{
|
||||
UARTHS_SEND = 1,
|
||||
UARTHS_RECEIVE = 2,
|
||||
UARTHS_SEND_RECEIVE = 3,
|
||||
} uarths_interrupt_mode_t;
|
||||
|
||||
typedef enum _uarths_stopbit
|
||||
{
|
||||
UARTHS_STOP_1,
|
||||
UARTHS_STOP_2
|
||||
} uarths_stopbit_t;
|
||||
|
||||
extern volatile uarths_t *const uarths;
|
||||
|
||||
/**
|
||||
* @brief Initialization Core UART
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
void uarths_init(void);
|
||||
|
||||
/**
|
||||
* @brief Put a char to UART
|
||||
*
|
||||
* @param[in] c The char to put
|
||||
*
|
||||
* @return result
|
||||
* - Byte On success, returns the written character.
|
||||
* - EOF On failure, returns EOF and sets the error indicator (see ferror()) on stdout.
|
||||
*/
|
||||
int uarths_putchar(char c);
|
||||
|
||||
/**
|
||||
* @brief Get a byte from UART
|
||||
*
|
||||
* @return byte as int type from UART
|
||||
* - Byte The character read as an unsigned char cast to an int
|
||||
* - EOF EOF on end of file or error, no enough byte to read
|
||||
*/
|
||||
int uarths_getchar(void);
|
||||
|
||||
/**
|
||||
* @brief Send a string to UART
|
||||
*
|
||||
* @param[in] s The string to send
|
||||
*
|
||||
* @note The string must ending with '\0'
|
||||
*
|
||||
* @return result
|
||||
* - 0 Success
|
||||
* - Other Fail
|
||||
*/
|
||||
int uarths_puts(const char *s);
|
||||
|
||||
/**
|
||||
* @brief [Deprecated] Get a byte from UART
|
||||
*
|
||||
* @return byte as int type from UART
|
||||
* - Byte The character read as an unsigned char cast to an int
|
||||
* - EOF EOF on end of file or error, no enough byte to read
|
||||
*/
|
||||
int uarths_getc(void);
|
||||
|
||||
/**
|
||||
* @brief Set uarths interrupt callback
|
||||
*
|
||||
* @param[in] interrupt_mode Interrupt mode recevice or send
|
||||
* @param[in] uarths_callback Interrupt callback
|
||||
* @param[in] ctx Param of callback
|
||||
* @param[in] priority Interrupt priority
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Uarths receive data
|
||||
*
|
||||
* @param[in] buf The data received
|
||||
* @param[in] buf_len The length of data
|
||||
*
|
||||
* @return Number of received data
|
||||
*/
|
||||
uint64 uarths_receive_data(uint8 *buf, uint64 buf_len);
|
||||
|
||||
/**
|
||||
* @brief Uarths receive data
|
||||
*
|
||||
* @param[in] buf The data sended
|
||||
* @param[in] buf_len The length of data
|
||||
*
|
||||
* @return Number of sended data
|
||||
*/
|
||||
uint64 uarths_send_data(const uint8 *buf, uint64 buf_len);
|
||||
|
||||
/**
|
||||
* @brief Get interrupt mode
|
||||
*
|
||||
* @return Mode of interrupt
|
||||
*/
|
||||
uarths_interrupt_mode_t uarths_get_interrupt_mode(void);
|
||||
|
||||
/**
|
||||
* @brief Set uarths baud rate and stopbit
|
||||
*
|
||||
* @param[in] baud_rate The baud rate
|
||||
* @param[in] stopbit The stopbit of data
|
||||
*
|
||||
*/
|
||||
void uarths_config(uint32 baud_rate, uarths_stopbit_t stopbit);
|
||||
|
||||
/**
|
||||
* @brief Set uart interrupt condition
|
||||
*
|
||||
* @param[in] interrupt_mode The interrupt mode
|
||||
* @param[in] cnt The count of tigger
|
||||
*
|
||||
*/
|
||||
void uarths_set_interrupt_cnt(uarths_interrupt_mode_t interrupt_mode, uint8 cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRIVER_UARTHS_H */
|
Loading…
Reference in New Issue