foboot: move software stuff to sw directory
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
24
sw/include/console.h
Normal file
24
sw/include/console.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __CONSOLE_H
|
||||
#define __CONSOLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*console_write_hook)(char);
|
||||
typedef char (*console_read_hook)(void);
|
||||
typedef int (*console_read_nonblock_hook)(void);
|
||||
|
||||
void console_set_write_hook(console_write_hook h);
|
||||
void console_set_read_hook(console_read_hook r, console_read_nonblock_hook rn);
|
||||
|
||||
char readchar(void);
|
||||
int readchar_nonblock(void);
|
||||
|
||||
void putsnonl(const char *s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CONSOLE_H */
|
15
sw/include/crc.h
Normal file
15
sw/include/crc.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef __CRC_H
|
||||
#define __CRC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
unsigned short crc16(const unsigned char *buffer, int len);
|
||||
unsigned int crc32(const unsigned char *buffer, unsigned int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
11
sw/include/csr-defs.h
Normal file
11
sw/include/csr-defs.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef CSR_DEFS__H
|
||||
#define CSR_DEFS__H
|
||||
|
||||
#define CSR_MSTATUS_MIE 0x8
|
||||
|
||||
#define CSR_IRQ_MASK 0xBC0
|
||||
#define CSR_IRQ_PENDING 0xFC0
|
||||
|
||||
#define CSR_DCACHE_INFO 0xCC0
|
||||
|
||||
#endif /* CSR_DEFS__H */
|
413
sw/include/generated/csr.h
Normal file
413
sw/include/generated/csr.h
Normal file
@ -0,0 +1,413 @@
|
||||
#ifndef __GENERATED_CSR_H
|
||||
#define __GENERATED_CSR_H
|
||||
#include <stdint.h>
|
||||
#ifdef CSR_ACCESSORS_DEFINED
|
||||
extern void csr_writeb(uint8_t value, uint32_t addr);
|
||||
extern uint8_t csr_readb(uint32_t addr);
|
||||
extern void csr_writew(uint16_t value, uint32_t addr);
|
||||
extern uint16_t csr_readw(uint32_t addr);
|
||||
extern void csr_writel(uint32_t value, uint32_t addr);
|
||||
extern uint32_t csr_readl(uint32_t addr);
|
||||
#else /* ! CSR_ACCESSORS_DEFINED */
|
||||
#include <hw/common.h>
|
||||
#endif /* ! CSR_ACCESSORS_DEFINED */
|
||||
|
||||
/* spiflash */
|
||||
#define CSR_SPIFLASH_BASE 0xe0004800
|
||||
#define CSR_SPIFLASH_BITBANG_ADDR 0xe0004800
|
||||
#define CSR_SPIFLASH_BITBANG_SIZE 1
|
||||
static inline unsigned char spiflash_bitbang_read(void) {
|
||||
unsigned char r = csr_readl(0xe0004800);
|
||||
return r;
|
||||
}
|
||||
static inline void spiflash_bitbang_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0004800);
|
||||
}
|
||||
#define CSR_SPIFLASH_MISO_ADDR 0xe0004804
|
||||
#define CSR_SPIFLASH_MISO_SIZE 1
|
||||
static inline unsigned char spiflash_miso_read(void) {
|
||||
unsigned char r = csr_readl(0xe0004804);
|
||||
return r;
|
||||
}
|
||||
#define CSR_SPIFLASH_BITBANG_EN_ADDR 0xe0004808
|
||||
#define CSR_SPIFLASH_BITBANG_EN_SIZE 1
|
||||
static inline unsigned char spiflash_bitbang_en_read(void) {
|
||||
unsigned char r = csr_readl(0xe0004808);
|
||||
return r;
|
||||
}
|
||||
static inline void spiflash_bitbang_en_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0004808);
|
||||
}
|
||||
|
||||
/* timer0 */
|
||||
#define CSR_TIMER0_BASE 0xe0002800
|
||||
#define CSR_TIMER0_LOAD_ADDR 0xe0002800
|
||||
#define CSR_TIMER0_LOAD_SIZE 4
|
||||
static inline unsigned int timer0_load_read(void) {
|
||||
unsigned int r = csr_readl(0xe0002800);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0002804);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0002808);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe000280c);
|
||||
return r;
|
||||
}
|
||||
static inline void timer0_load_write(unsigned int value) {
|
||||
csr_writel(value >> 24, 0xe0002800);
|
||||
csr_writel(value >> 16, 0xe0002804);
|
||||
csr_writel(value >> 8, 0xe0002808);
|
||||
csr_writel(value, 0xe000280c);
|
||||
}
|
||||
#define CSR_TIMER0_RELOAD_ADDR 0xe0002810
|
||||
#define CSR_TIMER0_RELOAD_SIZE 4
|
||||
static inline unsigned int timer0_reload_read(void) {
|
||||
unsigned int r = csr_readl(0xe0002810);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0002814);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0002818);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe000281c);
|
||||
return r;
|
||||
}
|
||||
static inline void timer0_reload_write(unsigned int value) {
|
||||
csr_writel(value >> 24, 0xe0002810);
|
||||
csr_writel(value >> 16, 0xe0002814);
|
||||
csr_writel(value >> 8, 0xe0002818);
|
||||
csr_writel(value, 0xe000281c);
|
||||
}
|
||||
#define CSR_TIMER0_EN_ADDR 0xe0002820
|
||||
#define CSR_TIMER0_EN_SIZE 1
|
||||
static inline unsigned char timer0_en_read(void) {
|
||||
unsigned char r = csr_readl(0xe0002820);
|
||||
return r;
|
||||
}
|
||||
static inline void timer0_en_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0002820);
|
||||
}
|
||||
#define CSR_TIMER0_UPDATE_VALUE_ADDR 0xe0002824
|
||||
#define CSR_TIMER0_UPDATE_VALUE_SIZE 1
|
||||
static inline unsigned char timer0_update_value_read(void) {
|
||||
unsigned char r = csr_readl(0xe0002824);
|
||||
return r;
|
||||
}
|
||||
static inline void timer0_update_value_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0002824);
|
||||
}
|
||||
#define CSR_TIMER0_VALUE_ADDR 0xe0002828
|
||||
#define CSR_TIMER0_VALUE_SIZE 4
|
||||
static inline unsigned int timer0_value_read(void) {
|
||||
unsigned int r = csr_readl(0xe0002828);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe000282c);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0002830);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0002834);
|
||||
return r;
|
||||
}
|
||||
#define CSR_TIMER0_EV_STATUS_ADDR 0xe0002838
|
||||
#define CSR_TIMER0_EV_STATUS_SIZE 1
|
||||
static inline unsigned char timer0_ev_status_read(void) {
|
||||
unsigned char r = csr_readl(0xe0002838);
|
||||
return r;
|
||||
}
|
||||
static inline void timer0_ev_status_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0002838);
|
||||
}
|
||||
#define CSR_TIMER0_EV_PENDING_ADDR 0xe000283c
|
||||
#define CSR_TIMER0_EV_PENDING_SIZE 1
|
||||
static inline unsigned char timer0_ev_pending_read(void) {
|
||||
unsigned char r = csr_readl(0xe000283c);
|
||||
return r;
|
||||
}
|
||||
static inline void timer0_ev_pending_write(unsigned char value) {
|
||||
csr_writel(value, 0xe000283c);
|
||||
}
|
||||
#define CSR_TIMER0_EV_ENABLE_ADDR 0xe0002840
|
||||
#define CSR_TIMER0_EV_ENABLE_SIZE 1
|
||||
static inline unsigned char timer0_ev_enable_read(void) {
|
||||
unsigned char r = csr_readl(0xe0002840);
|
||||
return r;
|
||||
}
|
||||
static inline void timer0_ev_enable_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0002840);
|
||||
}
|
||||
|
||||
/* uart */
|
||||
#define CSR_UART_BASE 0xe0001800
|
||||
#define CSR_UART_RXTX_ADDR 0xe0001800
|
||||
#define CSR_UART_RXTX_SIZE 1
|
||||
static inline unsigned char uart_rxtx_read(void) {
|
||||
unsigned char r = csr_readl(0xe0001800);
|
||||
return r;
|
||||
}
|
||||
static inline void uart_rxtx_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0001800);
|
||||
}
|
||||
#define CSR_UART_TXFULL_ADDR 0xe0001804
|
||||
#define CSR_UART_TXFULL_SIZE 1
|
||||
static inline unsigned char uart_txfull_read(void) {
|
||||
unsigned char r = csr_readl(0xe0001804);
|
||||
return r;
|
||||
}
|
||||
#define CSR_UART_RXEMPTY_ADDR 0xe0001808
|
||||
#define CSR_UART_RXEMPTY_SIZE 1
|
||||
static inline unsigned char uart_rxempty_read(void) {
|
||||
unsigned char r = csr_readl(0xe0001808);
|
||||
return r;
|
||||
}
|
||||
#define CSR_UART_EV_STATUS_ADDR 0xe000180c
|
||||
#define CSR_UART_EV_STATUS_SIZE 1
|
||||
static inline unsigned char uart_ev_status_read(void) {
|
||||
unsigned char r = csr_readl(0xe000180c);
|
||||
return r;
|
||||
}
|
||||
static inline void uart_ev_status_write(unsigned char value) {
|
||||
csr_writel(value, 0xe000180c);
|
||||
}
|
||||
#define CSR_UART_EV_PENDING_ADDR 0xe0001810
|
||||
#define CSR_UART_EV_PENDING_SIZE 1
|
||||
static inline unsigned char uart_ev_pending_read(void) {
|
||||
unsigned char r = csr_readl(0xe0001810);
|
||||
return r;
|
||||
}
|
||||
static inline void uart_ev_pending_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0001810);
|
||||
}
|
||||
#define CSR_UART_EV_ENABLE_ADDR 0xe0001814
|
||||
#define CSR_UART_EV_ENABLE_SIZE 1
|
||||
static inline unsigned char uart_ev_enable_read(void) {
|
||||
unsigned char r = csr_readl(0xe0001814);
|
||||
return r;
|
||||
}
|
||||
static inline void uart_ev_enable_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0001814);
|
||||
}
|
||||
|
||||
/* uart_phy */
|
||||
#define CSR_UART_PHY_BASE 0xe0001000
|
||||
#define CSR_UART_PHY_TUNING_WORD_ADDR 0xe0001000
|
||||
#define CSR_UART_PHY_TUNING_WORD_SIZE 4
|
||||
static inline unsigned int uart_phy_tuning_word_read(void) {
|
||||
unsigned int r = csr_readl(0xe0001000);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0001004);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe0001008);
|
||||
r <<= 8;
|
||||
r |= csr_readl(0xe000100c);
|
||||
return r;
|
||||
}
|
||||
static inline void uart_phy_tuning_word_write(unsigned int value) {
|
||||
csr_writel(value >> 24, 0xe0001000);
|
||||
csr_writel(value >> 16, 0xe0001004);
|
||||
csr_writel(value >> 8, 0xe0001008);
|
||||
csr_writel(value, 0xe000100c);
|
||||
}
|
||||
|
||||
/* usb */
|
||||
#define CSR_USB_BASE 0xe0005000
|
||||
#define CSR_USB_PULLUP_OUT_ADDR 0xe0005000
|
||||
#define CSR_USB_PULLUP_OUT_SIZE 1
|
||||
static inline unsigned char usb_pullup_out_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005000);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_pullup_out_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0005000);
|
||||
}
|
||||
#define CSR_USB_EP_0_OUT_EV_STATUS_ADDR 0xe0005004
|
||||
#define CSR_USB_EP_0_OUT_EV_STATUS_SIZE 1
|
||||
static inline unsigned char usb_ep_0_out_ev_status_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005004);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_ep_0_out_ev_status_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0005004);
|
||||
}
|
||||
#define CSR_USB_EP_0_OUT_EV_PENDING_ADDR 0xe0005008
|
||||
#define CSR_USB_EP_0_OUT_EV_PENDING_SIZE 1
|
||||
static inline unsigned char usb_ep_0_out_ev_pending_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005008);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_ep_0_out_ev_pending_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0005008);
|
||||
}
|
||||
#define CSR_USB_EP_0_OUT_EV_ENABLE_ADDR 0xe000500c
|
||||
#define CSR_USB_EP_0_OUT_EV_ENABLE_SIZE 1
|
||||
static inline unsigned char usb_ep_0_out_ev_enable_read(void) {
|
||||
unsigned char r = csr_readl(0xe000500c);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_ep_0_out_ev_enable_write(unsigned char value) {
|
||||
csr_writel(value, 0xe000500c);
|
||||
}
|
||||
#define CSR_USB_EP_0_OUT_LAST_TOK_ADDR 0xe0005010
|
||||
#define CSR_USB_EP_0_OUT_LAST_TOK_SIZE 1
|
||||
static inline unsigned char usb_ep_0_out_last_tok_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005010);
|
||||
return r;
|
||||
}
|
||||
#define CSR_USB_EP_0_OUT_RESPOND_ADDR 0xe0005014
|
||||
#define CSR_USB_EP_0_OUT_RESPOND_SIZE 1
|
||||
static inline unsigned char usb_ep_0_out_respond_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005014);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_ep_0_out_respond_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0005014);
|
||||
}
|
||||
#define CSR_USB_EP_0_OUT_DTB_ADDR 0xe0005018
|
||||
#define CSR_USB_EP_0_OUT_DTB_SIZE 1
|
||||
static inline unsigned char usb_ep_0_out_dtb_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005018);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_ep_0_out_dtb_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0005018);
|
||||
}
|
||||
#define CSR_USB_EP_0_OUT_OBUF_HEAD_ADDR 0xe000501c
|
||||
#define CSR_USB_EP_0_OUT_OBUF_HEAD_SIZE 1
|
||||
static inline unsigned char usb_ep_0_out_obuf_head_read(void) {
|
||||
unsigned char r = csr_readl(0xe000501c);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_ep_0_out_obuf_head_write(unsigned char value) {
|
||||
csr_writel(value, 0xe000501c);
|
||||
}
|
||||
#define CSR_USB_EP_0_OUT_OBUF_EMPTY_ADDR 0xe0005020
|
||||
#define CSR_USB_EP_0_OUT_OBUF_EMPTY_SIZE 1
|
||||
static inline unsigned char usb_ep_0_out_obuf_empty_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005020);
|
||||
return r;
|
||||
}
|
||||
#define CSR_USB_EP_0_IN_EV_STATUS_ADDR 0xe0005024
|
||||
#define CSR_USB_EP_0_IN_EV_STATUS_SIZE 1
|
||||
static inline unsigned char usb_ep_0_in_ev_status_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005024);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_ep_0_in_ev_status_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0005024);
|
||||
}
|
||||
#define CSR_USB_EP_0_IN_EV_PENDING_ADDR 0xe0005028
|
||||
#define CSR_USB_EP_0_IN_EV_PENDING_SIZE 1
|
||||
static inline unsigned char usb_ep_0_in_ev_pending_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005028);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_ep_0_in_ev_pending_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0005028);
|
||||
}
|
||||
#define CSR_USB_EP_0_IN_EV_ENABLE_ADDR 0xe000502c
|
||||
#define CSR_USB_EP_0_IN_EV_ENABLE_SIZE 1
|
||||
static inline unsigned char usb_ep_0_in_ev_enable_read(void) {
|
||||
unsigned char r = csr_readl(0xe000502c);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_ep_0_in_ev_enable_write(unsigned char value) {
|
||||
csr_writel(value, 0xe000502c);
|
||||
}
|
||||
#define CSR_USB_EP_0_IN_LAST_TOK_ADDR 0xe0005030
|
||||
#define CSR_USB_EP_0_IN_LAST_TOK_SIZE 1
|
||||
static inline unsigned char usb_ep_0_in_last_tok_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005030);
|
||||
return r;
|
||||
}
|
||||
#define CSR_USB_EP_0_IN_RESPOND_ADDR 0xe0005034
|
||||
#define CSR_USB_EP_0_IN_RESPOND_SIZE 1
|
||||
static inline unsigned char usb_ep_0_in_respond_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005034);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_ep_0_in_respond_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0005034);
|
||||
}
|
||||
#define CSR_USB_EP_0_IN_DTB_ADDR 0xe0005038
|
||||
#define CSR_USB_EP_0_IN_DTB_SIZE 1
|
||||
static inline unsigned char usb_ep_0_in_dtb_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005038);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_ep_0_in_dtb_write(unsigned char value) {
|
||||
csr_writel(value, 0xe0005038);
|
||||
}
|
||||
#define CSR_USB_EP_0_IN_IBUF_HEAD_ADDR 0xe000503c
|
||||
#define CSR_USB_EP_0_IN_IBUF_HEAD_SIZE 1
|
||||
static inline unsigned char usb_ep_0_in_ibuf_head_read(void) {
|
||||
unsigned char r = csr_readl(0xe000503c);
|
||||
return r;
|
||||
}
|
||||
static inline void usb_ep_0_in_ibuf_head_write(unsigned char value) {
|
||||
csr_writel(value, 0xe000503c);
|
||||
}
|
||||
#define CSR_USB_EP_0_IN_IBUF_EMPTY_ADDR 0xe0005040
|
||||
#define CSR_USB_EP_0_IN_IBUF_EMPTY_SIZE 1
|
||||
static inline unsigned char usb_ep_0_in_ibuf_empty_read(void) {
|
||||
unsigned char r = csr_readl(0xe0005040);
|
||||
return r;
|
||||
}
|
||||
#define CSR_IDENTIFIER_MEM_BASE 0xe0002000
|
||||
|
||||
/* constants */
|
||||
#define NMI_INTERRUPT 0
|
||||
static inline int nmi_interrupt_read(void) {
|
||||
return 0;
|
||||
}
|
||||
#define TIMER0_INTERRUPT 1
|
||||
static inline int timer0_interrupt_read(void) {
|
||||
return 1;
|
||||
}
|
||||
#define UART_INTERRUPT 2
|
||||
static inline int uart_interrupt_read(void) {
|
||||
return 2;
|
||||
}
|
||||
#define USB_INTERRUPT 3
|
||||
static inline int usb_interrupt_read(void) {
|
||||
return 3;
|
||||
}
|
||||
#define CSR_DATA_WIDTH 8
|
||||
static inline int csr_data_width_read(void) {
|
||||
return 8;
|
||||
}
|
||||
#define SYSTEM_CLOCK_FREQUENCY 12000000
|
||||
static inline int system_clock_frequency_read(void) {
|
||||
return 12000000;
|
||||
}
|
||||
#define SPIFLASH_PAGE_SIZE 256
|
||||
static inline int spiflash_page_size_read(void) {
|
||||
return 256;
|
||||
}
|
||||
#define SPIFLASH_SECTOR_SIZE 65536
|
||||
static inline int spiflash_sector_size_read(void) {
|
||||
return 65536;
|
||||
}
|
||||
#define ROM_DISABLE 1
|
||||
static inline int rom_disable_read(void) {
|
||||
return 1;
|
||||
}
|
||||
#define CONFIG_CLOCK_FREQUENCY 12000000
|
||||
static inline int config_clock_frequency_read(void) {
|
||||
return 12000000;
|
||||
}
|
||||
#define CONFIG_CPU_RESET_ADDR 0
|
||||
static inline int config_cpu_reset_addr_read(void) {
|
||||
return 0;
|
||||
}
|
||||
#define CONFIG_CPU_TYPE "VEXRISCV"
|
||||
static inline const char * config_cpu_type_read(void) {
|
||||
return "VEXRISCV";
|
||||
}
|
||||
#define CONFIG_CPU_VARIANT "VEXRISCV"
|
||||
static inline const char * config_cpu_variant_read(void) {
|
||||
return "VEXRISCV";
|
||||
}
|
||||
#define CONFIG_CSR_DATA_WIDTH 8
|
||||
static inline int config_csr_data_width_read(void) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
#endif
|
13
sw/include/generated/mem.h
Normal file
13
sw/include/generated/mem.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef __GENERATED_MEM_H
|
||||
#define __GENERATED_MEM_H
|
||||
|
||||
#define SPIFLASH_BASE 0x20000000
|
||||
#define SPIFLASH_SIZE 0x00200000
|
||||
|
||||
#define SRAM_BASE 0x10000000
|
||||
#define SRAM_SIZE 0x00020000
|
||||
|
||||
#define ROM_BASE 0x00000000
|
||||
#define ROM_SIZE 0x00002000
|
||||
|
||||
#endif
|
602
sw/include/grainuum.h
Normal file
602
sw/include/grainuum.h
Normal file
@ -0,0 +1,602 @@
|
||||
/****************************************************************************
|
||||
* Grainuum Software USB Stack *
|
||||
* *
|
||||
* MIT License: *
|
||||
* Copyright (c) 2016 Sean Cross *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a *
|
||||
* copy of this software and associated documentation files (the *
|
||||
* "Software"), to deal in the Software without restriction, including *
|
||||
* without limitation the rights to use, copy, modify, merge, publish, *
|
||||
* distribute, distribute with modifications, sublicense, and/or sell *
|
||||
* copies of the Software, and to permit persons to whom the Software is *
|
||||
* furnished to do so, subject to the following conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included *
|
||||
* in all copies or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
|
||||
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
|
||||
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
* *
|
||||
* Except as contained in this notice, the name(s) of the above copyright *
|
||||
* holders shall not be used in advertising or otherwise to promote the *
|
||||
* sale, use or other dealings in this Software without prior written *
|
||||
* authorization. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _GRAINUUM_H
|
||||
#define _GRAINUUM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Extra fields for GrainuumState struct.
|
||||
* @note You probably can ignore this.
|
||||
*/
|
||||
#ifndef GRAINUUM_STATE_EXTRA
|
||||
#define GRAINUUM_STATE_EXTRA
|
||||
#endif /* GRAINUUM_STATE_EXTRA */
|
||||
|
||||
#define GRAINUUM_PACKET_SIZE_MAX 64
|
||||
|
||||
/**
|
||||
* @brief Extra fields for GrainuumUSB struct.
|
||||
* @note Use this to store context and thread information.
|
||||
*/
|
||||
#ifndef GRAINUUM_EXTRA
|
||||
#define GRAINUUM_EXTRA
|
||||
#endif /* GRAINUUM_EXTRA */
|
||||
|
||||
#define GET_STATUS 0
|
||||
#define CLEAR_FEATURE 1
|
||||
#define SET_FEATURE 3
|
||||
#define SET_ADDRESS 5
|
||||
#define GET_DESCRIPTOR 6
|
||||
#define SET_DESCRIPTOR 7
|
||||
#define GET_CONFIGURATION 8
|
||||
#define SET_CONFIGURATION 9
|
||||
#define GET_INTERFACE 10
|
||||
#define SET_INTERFACE 11
|
||||
#define SYNC_FRAME 12
|
||||
|
||||
#define GET_REPORT 1
|
||||
#define GET_IDLE 2
|
||||
#define GET_PROTOCOL 3
|
||||
#define SET_REPORT 9
|
||||
#define SET_IDLE 10
|
||||
#define SET_PROTOCOL 11
|
||||
|
||||
enum usb_pids {
|
||||
USB_PID_RESERVED = 0xf0,
|
||||
USB_PID_OUT = 0xe1,
|
||||
USB_PID_ACK = 0xd2,
|
||||
USB_PID_DATA0 = 0xc3,
|
||||
USB_PID_PING = 0xb4,
|
||||
USB_PID_SOF = 0xa5,
|
||||
USB_PID_NYET = 0x96,
|
||||
USB_PID_DATA2 = 0x87,
|
||||
USB_PID_SPLIT = 0x78,
|
||||
USB_PID_IN = 0x69,
|
||||
USB_PID_NAK = 0x5a,
|
||||
USB_PID_DATA1 = 0x4b,
|
||||
USB_PID_ERR = 0x3c,
|
||||
USB_PID_SETUP = 0x2d,
|
||||
USB_PID_STALL = 0x1e,
|
||||
USB_PID_MDATA = 0x0f,
|
||||
};
|
||||
|
||||
enum valenty_usb_pids {
|
||||
VUSB_PID_IN = 0x2,
|
||||
VUSB_PID_OUT = 0x0,
|
||||
VUSB_PID_SETUP = 0x3,
|
||||
};
|
||||
|
||||
struct GrainuumUSB;
|
||||
struct GrainuumState;
|
||||
struct GrainuumConfig;
|
||||
|
||||
/* Function callbacks */
|
||||
|
||||
/* Each of these functions are called by the USB system to get a buffer.
|
||||
* On return, *data will point to the buffer, and the number of bytes
|
||||
* in the buffer will be returned.
|
||||
*
|
||||
* If the data does not exist, return 0.
|
||||
*/
|
||||
typedef int (*get_usb_descriptor_t)(struct GrainuumUSB *usb,
|
||||
const void *pkt,
|
||||
const void **data);
|
||||
typedef void (*usb_set_config_num_t)(struct GrainuumUSB *usb,
|
||||
int configNum);
|
||||
|
||||
/*
|
||||
* Called when doing an OUT xfer (data to device) to get a buffer for
|
||||
* the specified endpoint.
|
||||
* It is up to the user to ensure the buffer is large enough.
|
||||
*/
|
||||
typedef void * (*usb_get_buffer_t)(struct GrainuumUSB *usb,
|
||||
uint8_t epnum,
|
||||
int32_t *size);
|
||||
|
||||
/*
|
||||
* When data is received (i.e. OUT EP), this function will be called.
|
||||
*/
|
||||
typedef int (*usb_data_in_t)(struct GrainuumUSB *usb,
|
||||
uint8_t epnum,
|
||||
uint32_t bytes,
|
||||
const void *data);
|
||||
|
||||
/**
|
||||
* @brief Called immediately after @p grainuumSendData() has queued data.
|
||||
* @note This function can be used to e.g. sleep a thread.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object
|
||||
* @param[in] epnum endpoint number of the transfer
|
||||
* @param[in] data pointer to the data being written
|
||||
* @param[in] size number of bytes being written
|
||||
* @api
|
||||
*/
|
||||
typedef void (*usb_data_out_start_t)(struct GrainuumUSB *usb,
|
||||
int epnum,
|
||||
const void *data,
|
||||
int size);
|
||||
|
||||
/**
|
||||
* @brief Called once all data has been sent.
|
||||
* @note This function can be used to e.g. wake up a thread.
|
||||
* @param[out] usb pointer to the @p GrainuumUSB object
|
||||
* @param[out] result whether the transfer was successful (0), or had an error.
|
||||
* @api
|
||||
*/
|
||||
typedef int (*usb_data_out_finish_t)(struct GrainuumUSB *usb,
|
||||
int result);
|
||||
|
||||
/* Structure of a USB packet on the wire, plus size field */
|
||||
struct usb_packet {
|
||||
union {
|
||||
struct {
|
||||
// uint8_t pid;
|
||||
uint8_t data[GRAINUUM_PACKET_SIZE_MAX + 2]; /* Including CRC */
|
||||
} __attribute((packed, aligned(4)));
|
||||
uint8_t raw_data[GRAINUUM_PACKET_SIZE_MAX + 2];
|
||||
} __attribute((packed, aligned(4)));
|
||||
uint8_t size; /* Not including pid (so may be 0) */
|
||||
/* Checksum omitted */
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
/* USB Descriptors */
|
||||
|
||||
#define DT_DEVICE 0x01
|
||||
#define DT_CONFIGURATION 0x02
|
||||
#define DT_STRING 0x03
|
||||
#define DT_INTERFACE 0x04
|
||||
#define DT_ENDPOINT 0x05
|
||||
#define DT_DEVICE_QUALIFIER 0x06
|
||||
#define DT_OTHER_SPEED_CONFIGURATION 0x07
|
||||
#define DT_INTERFACE_POWER 0x08
|
||||
|
||||
#define DT_HID 0x21
|
||||
#define DT_HID_REPORT 0x22
|
||||
#define DT_PID 0x23
|
||||
|
||||
struct usb_setup_packet {
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
union {
|
||||
uint16_t wValue;
|
||||
struct {
|
||||
uint8_t wValueL;
|
||||
uint8_t wValueH;
|
||||
};
|
||||
};
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
struct usb_device_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdUSB;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint8_t bMaxPacketSize0;
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
uint16_t bcdDevice;
|
||||
uint8_t iManufacturer;
|
||||
uint8_t iProduct;
|
||||
uint8_t iSerialNumber;
|
||||
uint8_t bNumConfigurations;
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
struct usb_configuration_descriptor {
|
||||
uint8_t bLength; /* Size of this descriptor, in bytes (9) */
|
||||
uint8_t bDescriptorType; /* DT_CONFIGURATION (2) */
|
||||
uint16_t wTotalLength; /* Total length of this, plus sizeof(data) */
|
||||
uint8_t bNumInterfaces; /* Number of interfaces supported by config */
|
||||
uint8_t bConfigurationValue; /* Value used by Set Configuration */
|
||||
uint8_t iConfiguration; /* index of string descriptor for config */
|
||||
uint8_t bmAttributes; /* Bitmap of attributes. D7 must be 1. */
|
||||
uint8_t bMaxPower; /* Maximum power, in units of 2mA */
|
||||
uint8_t data[]; /* Remaining descriptors */
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
struct usb_string_descriptor {
|
||||
uint8_t bLength; /* sizeof(usb_string_descriptor) + sizeof(data) */
|
||||
uint8_t bDescriptorType; /* DT_STRING (3) */
|
||||
uint8_t data[]; /* UTF-16LE string data or lang data(for string 0 */
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
struct usb_interface_descriptor {
|
||||
uint8_t bLength; /* sizeof(usb_interface_descriptor) (9) */
|
||||
uint8_t bDescriptorType; /* DT_INTERFACE (4) */
|
||||
uint8_t bInterfaceNumber; /* Which interface this describes. Usually 0. */
|
||||
uint8_t bAlternateSetting; /* ??? */
|
||||
uint8_t bNumEndpoints; /* Number of endpoints, minus 1 */
|
||||
uint8_t bInterfaceClass; /* Class code */
|
||||
uint8_t bInterfaceSubclass; /* Class sub-code */
|
||||
uint8_t bInterfaceProtocol; /* Protocol code, assigned by USB */
|
||||
uint8_t iInterface; /* Index of string for this interface */
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
struct usb_endpoint_descriptor {
|
||||
uint8_t bLength; /* sizeof(usb_endpoint_descriptor) (7) */
|
||||
uint8_t bDescriptorType; /* DT_ENDPOINT (5) */
|
||||
uint8_t bEndpointAddress; /* High bit 1:IN, 0:OUT. Lower 4-bits are EP# */
|
||||
uint8_t bmAttributes; /* 0=control, 2=bulk, 3=interrupt */
|
||||
uint16_t wMaxPacketSize; /* Max packet size for this EP */
|
||||
uint8_t bInterval; /* Polling rate (in 1ms units) */
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
struct usb_hid_descriptor {
|
||||
uint8_t bLength; /* sizeof(usb_hid_descriptor) (9) */
|
||||
uint8_t bDescriptorType; /* DT_HID (0x21) */
|
||||
uint16_t bcdHID; /* HID class version number, in BCD */
|
||||
uint8_t bCountryCode; /* Target country (usually 0) */
|
||||
uint8_t bNumDescriptors; /* Number of HID class descriptors (usually 1) */
|
||||
uint8_t bReportDescriptorType; /* Report descriptor type (usually 0x22) */
|
||||
uint16_t wReportDescriptorLength; /* Length of the HID/PID report descriptor */
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
#define GRAINUUM_BUFFER_ELEMENT_SIZE 12 /* 1 PID, 8 data, 2 CRC16, 1 size */
|
||||
/* grainuum_buffer is aligned such that its first byte is on a word boundary.
|
||||
* This is because the first byte of every packet is a PID, which is
|
||||
* immediately discarded. This leaves the remainder of the packet
|
||||
* word-aligned.
|
||||
*/
|
||||
|
||||
#define GRAINUUM_BUFFER(name, sz) \
|
||||
struct { \
|
||||
uint8_t head; \
|
||||
uint8_t tail; \
|
||||
uint8_t padding; \
|
||||
union { \
|
||||
uint8_t buffer[(sz) * GRAINUUM_BUFFER_ELEMENT_SIZE]; \
|
||||
uint8_t elements[sz][GRAINUUM_BUFFER_ELEMENT_SIZE]; \
|
||||
}; \
|
||||
} name __attribute__((aligned(4))); \
|
||||
uint8_t * name ## _head_ptr;
|
||||
#define GRAINUUM_BUFFER_INIT(name) \
|
||||
do { \
|
||||
(name).head = 0; \
|
||||
(name).tail = 0; \
|
||||
name ## _head_ptr = (name).buffer; \
|
||||
} while(0)
|
||||
#define GRAINUUM_BUFFER_ADVANCE(name) \
|
||||
do { \
|
||||
(name).head += GRAINUUM_BUFFER_ELEMENT_SIZE; \
|
||||
if ((name).head >= sizeof((name).buffer)) \
|
||||
(name).head = 0; \
|
||||
name ## _head_ptr = ((name).buffer + (name).head); \
|
||||
} while(0)
|
||||
#define GRAINUUM_BUFFER_TOP(name) \
|
||||
(&((name).buffer[(name).tail]))
|
||||
#define GRAINUUM_BUFFER_REMOVE(name) \
|
||||
do { \
|
||||
(name).tail += GRAINUUM_BUFFER_ELEMENT_SIZE; \
|
||||
if ((name).tail >= sizeof((name).buffer)) \
|
||||
(name).tail = 0; \
|
||||
} while(0)
|
||||
#define GRAINUUM_BUFFER_IS_EMPTY(name) \
|
||||
((name).head == (name).tail)
|
||||
#define GRAINUUM_BUFFER_ENTRY(name) \
|
||||
name ## _head_ptr
|
||||
|
||||
/* Grainuum Structs */
|
||||
|
||||
struct GrainuumConfig {
|
||||
get_usb_descriptor_t getDescriptor;
|
||||
usb_set_config_num_t setConfigNum;
|
||||
usb_get_buffer_t getReceiveBuffer;
|
||||
usb_data_in_t receiveData;
|
||||
usb_data_out_start_t sendDataStarted;
|
||||
usb_data_out_finish_t sendDataFinished;
|
||||
void *data;
|
||||
struct GrainuumUSB *usb;
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
struct GrainuumState {
|
||||
struct GrainuumUSB *usb;
|
||||
|
||||
const void *data_out; /* Pointer to the data that's being sent */
|
||||
int32_t data_out_left; /* How much data has yet to be sent */
|
||||
int32_t data_out_max; /* The maximum number of bytes to send */
|
||||
int32_t data_out_epnum; /* Which endpoint the data is for */
|
||||
|
||||
struct usb_packet packet; /* Currently-queued packet */
|
||||
int packet_queued; /* Whether a packet is queued */
|
||||
|
||||
uint32_t tok_pos; /* Position within the current token */
|
||||
void *tok_buf; /* Buffer storing current token's data */
|
||||
uint8_t tok_epnum; /* Last token's endpoint */
|
||||
|
||||
uint8_t data_buffer; /* Whether we're sending DATA0 or DATA1 */
|
||||
uint8_t packet_type; /* PACKET_SETUP, PACKET_IN, or PACKET_OUT */
|
||||
|
||||
uint8_t address; /* Our configured address */
|
||||
|
||||
GRAINUUM_STATE_EXTRA
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
struct GrainuumUSB {
|
||||
|
||||
struct GrainuumConfig *cfg; /* Callbacks */
|
||||
int initialized;
|
||||
|
||||
/* USB D- pin specification */
|
||||
uint32_t usbdnIAddr;
|
||||
uint32_t usbdnSAddr;
|
||||
uint32_t usbdnCAddr;
|
||||
uint32_t usbdnDAddr;
|
||||
uint32_t usbdnShift;
|
||||
|
||||
/* USB D+ pin specification */
|
||||
uint32_t usbdpIAddr;
|
||||
uint32_t usbdpSAddr;
|
||||
uint32_t usbdpCAddr;
|
||||
uint32_t usbdpDAddr;
|
||||
uint32_t usbdpShift;
|
||||
|
||||
uint32_t usbdnMask;
|
||||
uint32_t usbdpMask;
|
||||
|
||||
uint32_t queued_size;
|
||||
uint32_t queued_epnum;
|
||||
const void *queued_data;
|
||||
|
||||
struct GrainuumState state; /* Associated state */
|
||||
|
||||
GRAINUUM_EXTRA
|
||||
} __attribute__((packed, aligned(4)));
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void grainuumWritel(uint32_t value, uint32_t addr)
|
||||
{
|
||||
*((volatile uint32_t *)addr) = value;
|
||||
}
|
||||
|
||||
static inline uint32_t grainuumReadl(uint32_t addr)
|
||||
{
|
||||
return *(volatile uint32_t *)addr;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Weak hook functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Called just before the USB device is plugged in.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object
|
||||
* @api
|
||||
*/
|
||||
void grainuumConnectPre(struct GrainuumUSB *usb);
|
||||
|
||||
/**
|
||||
* @brief Called just after the USB device is plugged in.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object
|
||||
* @api
|
||||
*/
|
||||
void grainuumConnectPost(struct GrainuumUSB *usb);
|
||||
|
||||
/**
|
||||
* @brief Called just before the USB device is unplugged.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object
|
||||
* @api
|
||||
*/
|
||||
void grainuumDisconnectPre(struct GrainuumUSB *usb);
|
||||
|
||||
/**
|
||||
* @brief Called just after the USB device is unplugged.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object
|
||||
* @api
|
||||
*/
|
||||
void grainuumDisconnectPost(struct GrainuumUSB *usb);
|
||||
|
||||
/**
|
||||
* @brief Called just before the USB device is first initialized.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object
|
||||
* @api
|
||||
*/
|
||||
void grainuumInitPre(struct GrainuumUSB *usb);
|
||||
|
||||
/**
|
||||
* @brief Called just before the USB device is first initialized.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object
|
||||
* @api
|
||||
*/
|
||||
void grainuumInitPost(struct GrainuumUSB *usb);
|
||||
|
||||
/**
|
||||
* @brief Called immediately after a packet has been received.
|
||||
* @note This is called from an interrupt context. Data will
|
||||
* be stored in the buffer that was passed to @p grainuumCaptureI()
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object
|
||||
* @iclass
|
||||
*/
|
||||
void grainuumReceivePacket(struct GrainuumUSB *usb);
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Returns nonzero if Grainuum has been initialized.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object.
|
||||
* @return nonzero if @p GrainuumUSB is initialized.
|
||||
* @retval 0 Object is not initilized.
|
||||
* @api
|
||||
*/
|
||||
int grainuumInitialized(struct GrainuumUSB *usb);
|
||||
|
||||
/**
|
||||
* @brief Queues some data to be sent to the host.
|
||||
* @note After the first 8 bytes, @p data must remain valid
|
||||
* until the transfer has completed. This generally
|
||||
* means you can send const data stored in the text
|
||||
* section, or small 8-byte packets.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object.
|
||||
* @param[in] epnum endpoint number of the transfer.
|
||||
* @param[in] data pointer to the data being written.
|
||||
* @param[in] size number of bytes being written.
|
||||
* @return 0 if the transfer completed successfully.
|
||||
* @retval 0 Transfer completed successfully.
|
||||
* @api
|
||||
*/
|
||||
int grainuumSendData(struct GrainuumUSB *usb, int epnum, const void *data, int size);
|
||||
|
||||
/**
|
||||
* @brief Clears the send buffer, if not empty.
|
||||
* @note If data has already been queued for the PHY, then
|
||||
* this will not prevent it from being sent.
|
||||
* This function is intended to be used to prevent
|
||||
* grainuumSendData() from returning -EAGAIN.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object.
|
||||
* @api
|
||||
*/
|
||||
void grainuumDropData(struct GrainuumUSB *usb);
|
||||
|
||||
/**
|
||||
* @brief Determines if data is already queued.
|
||||
* @note If data has been queued, then this will return
|
||||
* nonzero. If this returns zero, then you can
|
||||
* trust grainuumSendData() will succeed.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object.
|
||||
* @return Nonzero if data is already queued.
|
||||
* @api
|
||||
*/
|
||||
int grainuumDataQueued(struct GrainuumUSB *usb);
|
||||
|
||||
/**
|
||||
* @brief Process one received packet through the Grainuum state machine.
|
||||
* @note This feeds USB packets into the state machine. It should not
|
||||
* be called as part of an interrupt.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object.
|
||||
* @param[in] packet The USB packet that was most recently received, with byte 12 holding the size.
|
||||
* @api
|
||||
*/
|
||||
void grainuumProcess(struct GrainuumUSB *usb,
|
||||
uint8_t pid,
|
||||
const uint8_t packet[12],
|
||||
uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief Initialize the Grainuum USB system.
|
||||
* @note This is meant to run as part of an interrupt. Pass
|
||||
* the storage buffer in as @p samples. The number
|
||||
* of bytes that were read will be stored in the last
|
||||
* byte of the array. For best performance, make
|
||||
* sure that @p sample is on byte 3 of a 4-byte boundary,
|
||||
* so that samples[1] is on a word boundary. The @p GrainuumUSB
|
||||
* object will start out disconnected.
|
||||
* @param[in] usb Pointer to the @p GrainuumUSB object to initialize.
|
||||
* @param[in] link Pointer to the @p GrainuumConfig object to use.
|
||||
* @api
|
||||
*/
|
||||
void grainuumInit(struct GrainuumUSB *usb, struct GrainuumConfig *link);
|
||||
|
||||
/**
|
||||
* @brief Capture a USB packet from the wire.
|
||||
* @note This is meant to run as part of an interrupt. Pass
|
||||
* the storage buffer in as @p samples. The number
|
||||
* of bytes that were read will be stored in the last
|
||||
* byte of the array. For best performance, make
|
||||
* sure that @p sample is on byte 3 of a 4-byte boundary,
|
||||
* so that samples[1] is on a word boundary.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object.
|
||||
* @param[in] packet Buffer to store the read samples.
|
||||
* @api
|
||||
*/
|
||||
int grainuumCaptureI(struct GrainuumUSB *usb, uint8_t samples[67]);
|
||||
|
||||
/**
|
||||
* @brief Internal function. Queues 8 bytes to be sent by the phy.
|
||||
* @note This is an internal function, and is not meant to be called.
|
||||
* It is meant to queue properly-formatted USB packets complete
|
||||
* with CRC-16 (if required).
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object.
|
||||
* @param[in] epnum The endpoint number to queue data for.
|
||||
* @param[in] buffer The data to queue.
|
||||
* @param[in] size The number of bytes that are queued.
|
||||
* @notapi
|
||||
*/
|
||||
void grainuumWriteQueue(struct GrainuumUSB *usb, int epnum,
|
||||
const void *buffer, int size);
|
||||
|
||||
/**
|
||||
* @brief Simulates plugging the device into USB.
|
||||
* @note All USB Connect hooks will be called.
|
||||
* The default USB state is "disconnected",
|
||||
* so @p grainuumConnect() must be called
|
||||
* to start communications.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object.
|
||||
* @api
|
||||
*/
|
||||
void grainuumConnect(struct GrainuumUSB *usb);
|
||||
|
||||
/**
|
||||
* @brief Simulates unplugging the device from USB.
|
||||
* @note All USB Disconnect hooks will be called.
|
||||
* @param[in] usb pointer to the @p GrainuumUSB object.
|
||||
* @api
|
||||
*/
|
||||
void grainuumDisconnect(struct GrainuumUSB *usb);
|
||||
|
||||
/**
|
||||
* @brief Reads one packet from the wire.
|
||||
* @note This must be called from an interrupt context with
|
||||
* interrupts disabled.
|
||||
* @param[in] usb Pointer to the @p GrainuumUSB object.
|
||||
* @param[out] samples Buffer where the samples will be stored.
|
||||
* @return The number of bytes read, or negative on error
|
||||
* @retval -1 Timeout while reading.
|
||||
* @retval -2 Read too many bits.
|
||||
* @retval -3 Unable to find sync end.
|
||||
* @retval -4 Probably a keepalive packet.
|
||||
* @notapi
|
||||
*/
|
||||
int usbPhyReadI(const struct GrainuumUSB *usb, uint8_t samples[11]);
|
||||
|
||||
/**
|
||||
* @brief Writes one packet from the wire.
|
||||
* @note This must be called from an interrupt context with
|
||||
* interrupts disabled.
|
||||
* @param[in] usb Pointer to the @p GrainuumUSB object.
|
||||
* @param[in] samples Buffer where the samples will be stored.
|
||||
* @param[in] size Number of bytes to write.
|
||||
* @notapi
|
||||
*/
|
||||
void usbPhyWriteI(const struct GrainuumUSB *usb, const void *buffer, uint32_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _GRAINUUM_H */
|
52
sw/include/hw/common.h
Normal file
52
sw/include/hw/common.h
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef __HW_COMMON_H
|
||||
#define __HW_COMMON_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* To overwrite CSR accessors, define extern, non-inlined versions
|
||||
* of csr_read[bwl]() and csr_write[bwl](), and define
|
||||
* CSR_ACCESSORS_DEFINED.
|
||||
*/
|
||||
|
||||
#ifndef CSR_ACCESSORS_DEFINED
|
||||
#define CSR_ACCESSORS_DEFINED
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
#define MMPTR(x) x
|
||||
#else /* ! __ASSEMBLER__ */
|
||||
#define MMPTR(x) (*((volatile unsigned int *)(x)))
|
||||
|
||||
static inline void csr_writeb(uint8_t value, uint32_t addr)
|
||||
{
|
||||
*((volatile uint8_t *)addr) = value;
|
||||
}
|
||||
|
||||
static inline uint8_t csr_readb(uint32_t addr)
|
||||
{
|
||||
return *(volatile uint8_t *)addr;
|
||||
}
|
||||
|
||||
static inline void csr_writew(uint16_t value, uint32_t addr)
|
||||
{
|
||||
*((volatile uint16_t *)addr) = value;
|
||||
}
|
||||
|
||||
static inline uint16_t csr_readw(uint32_t addr)
|
||||
{
|
||||
return *(volatile uint16_t *)addr;
|
||||
}
|
||||
|
||||
static inline void csr_writel(uint32_t value, uint32_t addr)
|
||||
{
|
||||
*((volatile uint32_t *)addr) = value;
|
||||
}
|
||||
|
||||
static inline uint32_t csr_readl(uint32_t addr)
|
||||
{
|
||||
return *(volatile uint32_t *)addr;
|
||||
}
|
||||
#endif /* ! __ASSEMBLER__ */
|
||||
|
||||
#endif /* ! CSR_ACCESSORS_DEFINED */
|
||||
|
||||
#endif /* __HW_COMMON_H */
|
40
sw/include/hw/flags.h
Normal file
40
sw/include/hw/flags.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef __HW_FLAGS_H
|
||||
#define __HW_FLAGS_H
|
||||
|
||||
#define UART_EV_TX 0x1
|
||||
#define UART_EV_RX 0x2
|
||||
|
||||
#define DFII_CONTROL_SEL 0x01
|
||||
#define DFII_CONTROL_CKE 0x02
|
||||
#define DFII_CONTROL_ODT 0x04
|
||||
#define DFII_CONTROL_RESET_N 0x08
|
||||
|
||||
#define DFII_COMMAND_CS 0x01
|
||||
#define DFII_COMMAND_WE 0x02
|
||||
#define DFII_COMMAND_CAS 0x04
|
||||
#define DFII_COMMAND_RAS 0x08
|
||||
#define DFII_COMMAND_WRDATA 0x10
|
||||
#define DFII_COMMAND_RDDATA 0x20
|
||||
|
||||
#define ETHMAC_EV_SRAM_WRITER 0x1
|
||||
#define ETHMAC_EV_SRAM_READER 0x1
|
||||
|
||||
#define CLKGEN_STATUS_BUSY 0x1
|
||||
#define CLKGEN_STATUS_PROGDONE 0x2
|
||||
#define CLKGEN_STATUS_LOCKED 0x4
|
||||
|
||||
#define DVISAMPLER_TOO_LATE 0x1
|
||||
#define DVISAMPLER_TOO_EARLY 0x2
|
||||
|
||||
#define DVISAMPLER_DELAY_MASTER_CAL 0x01
|
||||
#define DVISAMPLER_DELAY_MASTER_RST 0x02
|
||||
#define DVISAMPLER_DELAY_SLAVE_CAL 0x04
|
||||
#define DVISAMPLER_DELAY_SLAVE_RST 0x08
|
||||
#define DVISAMPLER_DELAY_INC 0x10
|
||||
#define DVISAMPLER_DELAY_DEC 0x20
|
||||
|
||||
#define DVISAMPLER_SLOT_EMPTY 0
|
||||
#define DVISAMPLER_SLOT_LOADED 1
|
||||
#define DVISAMPLER_SLOT_PENDING 2
|
||||
|
||||
#endif /* __HW_FLAGS_H */
|
144
sw/include/irq.h
Normal file
144
sw/include/irq.h
Normal file
@ -0,0 +1,144 @@
|
||||
#ifndef __IRQ_H
|
||||
#define __IRQ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <system.h>
|
||||
|
||||
#ifdef __picorv32__
|
||||
// PicoRV32 has a very limited interrupt support, implemented via custom
|
||||
// instructions. It also doesn't have a global interrupt enable/disable, so
|
||||
// we have to emulate it via saving and restoring a mask and using 0/~1 as a
|
||||
// hardware mask.
|
||||
// Due to all this somewhat low-level mess, all of the glue is implemented in
|
||||
// the RiscV crt0, and this header is kept as a thin wrapper. Since interrupts
|
||||
// managed by this layer, do not call interrupt instructions directly, as the
|
||||
// state will go out of sync with the hardware.
|
||||
|
||||
// Read only.
|
||||
extern unsigned int _irq_pending;
|
||||
// Read only.
|
||||
extern unsigned int _irq_mask;
|
||||
// Read only.
|
||||
extern unsigned int _irq_enabled;
|
||||
extern void _irq_enable(void);
|
||||
extern void _irq_disable(void);
|
||||
extern void _irq_setmask(unsigned int);
|
||||
#endif
|
||||
|
||||
static inline unsigned int irq_getie(void)
|
||||
{
|
||||
#if defined (__lm32__)
|
||||
unsigned int ie;
|
||||
__asm__ __volatile__("rcsr %0, IE" : "=r" (ie));
|
||||
return ie;
|
||||
#elif defined (__or1k__)
|
||||
return !!(mfspr(SPR_SR) & SPR_SR_IEE);
|
||||
#elif defined (__picorv32__)
|
||||
return _irq_enabled != 0;
|
||||
#elif defined (__vexriscv__)
|
||||
return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
|
||||
#elif defined (__minerva__)
|
||||
return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
|
||||
#else
|
||||
#error Unsupported architecture
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void irq_setie(unsigned int ie)
|
||||
{
|
||||
#if defined (__lm32__)
|
||||
__asm__ __volatile__("wcsr IE, %0" : : "r" (ie));
|
||||
#elif defined (__or1k__)
|
||||
if (ie & 0x1)
|
||||
mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE);
|
||||
else
|
||||
mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_IEE);
|
||||
#elif defined (__picorv32__)
|
||||
if (ie & 0x1)
|
||||
_irq_enable();
|
||||
else
|
||||
_irq_disable();
|
||||
#elif defined (__vexriscv__)
|
||||
if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
|
||||
#elif defined (__minerva__)
|
||||
if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
|
||||
#else
|
||||
#error Unsupported architecture
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned int irq_getmask(void)
|
||||
{
|
||||
#if defined (__lm32__)
|
||||
unsigned int mask;
|
||||
__asm__ __volatile__("rcsr %0, IM" : "=r" (mask));
|
||||
return mask;
|
||||
#elif defined (__or1k__)
|
||||
return mfspr(SPR_PICMR);
|
||||
#elif defined (__picorv32__)
|
||||
// PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how
|
||||
// LiteX sees things.
|
||||
return ~_irq_mask;
|
||||
#elif defined (__vexriscv__)
|
||||
unsigned int mask;
|
||||
asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK));
|
||||
return mask;
|
||||
#elif defined (__minerva__)
|
||||
unsigned int mask;
|
||||
asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK));
|
||||
return mask;
|
||||
#else
|
||||
#error Unsupported architecture
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void irq_setmask(unsigned int mask)
|
||||
{
|
||||
#if defined (__lm32__)
|
||||
__asm__ __volatile__("wcsr IM, %0" : : "r" (mask));
|
||||
#elif defined (__or1k__)
|
||||
mtspr(SPR_PICMR, mask);
|
||||
#elif defined (__picorv32__)
|
||||
// PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how
|
||||
// LiteX sees things.
|
||||
_irq_setmask(~mask);
|
||||
#elif defined (__vexriscv__)
|
||||
asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask));
|
||||
#elif defined (__minerva__)
|
||||
asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask));
|
||||
#else
|
||||
#error Unsupported architecture
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned int irq_pending(void)
|
||||
{
|
||||
#if defined (__lm32__)
|
||||
unsigned int pending;
|
||||
__asm__ __volatile__("rcsr %0, IP" : "=r" (pending));
|
||||
return pending;
|
||||
#elif defined (__or1k__)
|
||||
return mfspr(SPR_PICSR);
|
||||
#elif defined (__picorv32__)
|
||||
return _irq_pending;
|
||||
#elif defined (__vexriscv__)
|
||||
unsigned int pending;
|
||||
asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING));
|
||||
return pending;
|
||||
#elif defined (__minerva__)
|
||||
unsigned int pending;
|
||||
asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING));
|
||||
return pending;
|
||||
#else
|
||||
#error Unsupported architecture
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __IRQ_H */
|
124
sw/include/printf.h
Normal file
124
sw/include/printf.h
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
File: printf.h
|
||||
|
||||
Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
This library is realy just two files: 'printf.h' and 'printf.c'.
|
||||
|
||||
They provide a simple and small (+200 loc) printf functionality to
|
||||
be used in embedded systems.
|
||||
|
||||
I've found them so usefull in debugging that I do not bother with a
|
||||
debugger at all.
|
||||
|
||||
They are distributed in source form, so to use them, just compile them
|
||||
into your project.
|
||||
|
||||
Two printf variants are provided: printf and sprintf.
|
||||
|
||||
The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'.
|
||||
|
||||
Zero padding and field width are also supported.
|
||||
|
||||
If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the
|
||||
long specifier is also
|
||||
supported. Note that this will pull in some long math routines (pun intended!)
|
||||
and thus make your executable noticably longer.
|
||||
|
||||
The memory foot print of course depends on the target cpu, compiler and
|
||||
compiler options, but a rough guestimate (based on a H8S target) is about
|
||||
1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space.
|
||||
Not too bad. Your milage may vary. By hacking the source code you can
|
||||
get rid of some hunred bytes, I'm sure, but personally I feel the balance of
|
||||
functionality and flexibility versus code size is close to optimal for
|
||||
many embedded systems.
|
||||
|
||||
To use the printf you need to supply your own character output function,
|
||||
something like :
|
||||
|
||||
void putc ( void* p, char c)
|
||||
{
|
||||
while (!SERIAL_PORT_EMPTY) ;
|
||||
SERIAL_PORT_TX_REGISTER = c;
|
||||
}
|
||||
|
||||
Before you can call printf you need to initialize it to use your
|
||||
character output function with something like:
|
||||
|
||||
init_printf(NULL,putc);
|
||||
|
||||
Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc',
|
||||
the NULL (or any pointer) you pass into the 'init_printf' will eventually be
|
||||
passed to your 'putc' routine. This allows you to pass some storage space (or
|
||||
anything realy) to the character output function, if necessary.
|
||||
This is not often needed but it was implemented like that because it made
|
||||
implementing the sprintf function so neat (look at the source code).
|
||||
|
||||
The code is re-entrant, except for the 'init_printf' function, so it
|
||||
is safe to call it from interupts too, although this may result in mixed output.
|
||||
If you rely on re-entrancy, take care that your 'putc' function is re-entrant!
|
||||
|
||||
The printf and sprintf functions are actually macros that translate to
|
||||
'tfp_printf' and 'tfp_sprintf'. This makes it possible
|
||||
to use them along with 'stdio.h' printf's in a single source file.
|
||||
You just need to undef the names before you include the 'stdio.h'.
|
||||
Note that these are not function like macros, so if you have variables
|
||||
or struct members with these names, things will explode in your face.
|
||||
Without variadic macros this is the best we can do to wrap these
|
||||
fucnction. If it is a problem just give up the macros and use the
|
||||
functions directly or rename them.
|
||||
|
||||
For further details see source code.
|
||||
|
||||
regs Kusti, 23.10.2004
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TFP_PRINTF__
|
||||
#define __TFP_PRINTF__
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
void init_printf(void* putp,void (*putf) (void*,char));
|
||||
|
||||
void tfp_printf(char *fmt, ...);
|
||||
void tfp_sprintf(char* s,char *fmt, ...);
|
||||
|
||||
void tfp_format(void* putp,void (*putf) (void*,char),char *fmt, va_list va);
|
||||
|
||||
#define printf tfp_printf
|
||||
#define sprintf tfp_sprintf
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
8
sw/include/spiflash.h
Normal file
8
sw/include/spiflash.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __SPIFLASH_H
|
||||
#define __SPIFLASH_H
|
||||
|
||||
void write_to_flash_page(unsigned int addr, const unsigned char *c, unsigned int len);
|
||||
void erase_flash_sector(unsigned int addr);
|
||||
void write_to_flash(unsigned int addr, const unsigned char *c, unsigned int len);
|
||||
|
||||
#endif /* __SPIFLASH_H */
|
59
sw/include/system.h
Normal file
59
sw/include/system.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef __SYSTEM_H
|
||||
#define __SYSTEM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void flush_cpu_icache(void);
|
||||
void flush_cpu_dcache(void);
|
||||
void flush_l2_cache(void);
|
||||
|
||||
#ifdef __or1k__
|
||||
#include <spr-defs.h>
|
||||
static inline unsigned long mfspr(unsigned long add)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
__asm__ __volatile__ ("l.mfspr %0,%1,0" : "=r" (ret) : "r" (add));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void mtspr(unsigned long add, unsigned long val)
|
||||
{
|
||||
__asm__ __volatile__ ("l.mtspr %0,%1,0" : : "r" (add), "r" (val));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__vexriscv__) || defined(__minerva__)
|
||||
#include <csr-defs.h>
|
||||
#define csrr(reg) ({ unsigned long __tmp; \
|
||||
asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
|
||||
__tmp; })
|
||||
|
||||
#define csrw(reg, val) ({ \
|
||||
if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
|
||||
asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
|
||||
else \
|
||||
asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
|
||||
|
||||
#define csrs(reg, bit) ({ \
|
||||
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
|
||||
asm volatile ("csrrs x0, " #reg ", %0" :: "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrs x0, " #reg ", %0" :: "r"(bit)); })
|
||||
|
||||
#define csrc(reg, bit) ({ \
|
||||
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
|
||||
asm volatile ("csrrc x0, " #reg ", %0" :: "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrc x0, " #reg ", %0" :: "r"(bit)); })
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SYSTEM_H */
|
15
sw/include/time.h
Normal file
15
sw/include/time.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef __TIME_H
|
||||
#define __TIME_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void time_init(void);
|
||||
int elapsed(int *last_event, int period);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TIME_H */
|
20
sw/include/uart.h
Normal file
20
sw/include/uart.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef __UART_H
|
||||
#define __UART_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void uart_init(void);
|
||||
void uart_isr(void);
|
||||
void uart_sync(void);
|
||||
|
||||
void uart_write(char c);
|
||||
char uart_read(void);
|
||||
int uart_read_nonblock(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
15
sw/include/usb.h
Normal file
15
sw/include/usb.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef __USB_H
|
||||
#define __USB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void usb_isr(void);
|
||||
void usb_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user