foboot-main: remove unused project

The `foboot-main` project was never completed, and probably
should never have been merged to the main branch. Move it onto
a side branch in case anyone wants to work on it.

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2022-12-31 21:51:17 +08:00
parent d9a72a8fde
commit 46556c1edf
40 changed files with 0 additions and 6067 deletions

View File

@ -1,131 +0,0 @@
GIT_VERSION := $(shell git describe --tags)
# There is no 64-bit gcc on Raspberry Pi, so use the 32-bit version
ifneq (,$(wildcard /etc/rpi-issue))
TRGT ?= riscv32-unknown-elf-
else
TRGT ?= riscv64-unknown-elf-
endif
CC := $(TRGT)gcc
CXX := $(TRGT)g++
OBJCOPY := $(TRGT)objcopy
RM := rm -rf
COPY := cp -a
PATH_SEP := /
ifeq ($(OS),Windows_NT)
COPY := copy
RM := del
PATH_SEP := \\
endif
ifeq ($(LITEX),1)
BASE_DIR := ../../../../sw
LDSCRIPT := $(BASE_DIR)/ld/linker.ld
LD_DIR := ../include/generated
ADD_CFLAGS := -I../include -I$(BASE_DIR)/include
ADD_LFLAGS :=
PACKAGE := bios
else
BASE_DIR := .
LD_DIR := $(BASE_DIR)/ld
LDSCRIPT := $(BASE_DIR)/ld/linker.ld
ADD_CFLAGS := -I$(BASE_DIR)/include
ADD_LFLAGS :=
PACKAGE := foboot-main
endif
LDSCRIPTS := $(LDSCRIPT) $(LD_DIR)/output_format.ld $(LD_DIR)/regions.ld
SRC_DIR := $(BASE_DIR)/src
THIRD_PARTY := $(BASE_DIR)/third_party
DBG_CFLAGS := -ggdb -g -DDEBUG -Wall
DBG_LFLAGS := -ggdb -g -Wall
CFLAGS := $(ADD_CFLAGS) \
-D__vexriscv__ -march=rv32i -mabi=ilp32 \
-Wall -Wextra \
-flto \
-ffunction-sections -fdata-sections -fno-common \
-fomit-frame-pointer -Os \
-march=rv32i \
-DGIT_VERSION=u\"$(GIT_VERSION)\" -std=gnu11
CXXFLAGS := $(CFLAGS) -std=c++11 -fno-rtti -fno-exceptions
LFLAGS := $(CFLAGS) $(ADD_LFLAGS) -L$(LD_DIR) \
-nostartfiles \
-nostdlib \
-Wl,--gc-sections \
-Wl,--no-warn-mismatch \
-Wl,--script=$(LDSCRIPT) \
-Wl,--build-id=none
OBJ_DIR := .obj
CSOURCES := $(wildcard $(SRC_DIR)/*.c) $(wildcard $(THIRD_PARTY)/libbase/*.c) $(wildcard $(THIRD_PARTY)/*.c)
CPPSOURCES := $(wildcard $(SRC_DIR)/*.cpp) $(wildcard $(THIRD_PARTY)/libbase/*.cpp) $(wildcard $(THIRD_PARTY)/*.cpp)
ASOURCES := $(wildcard $(SRC_DIR)/*.S) $(wildcard $(THIRD_PARTY)/libbase/*.S) $(wildcard $(THIRD_PARTY)/*.S)
COBJS := $(addprefix $(OBJ_DIR)/, $(notdir $(CSOURCES:.c=.o)))
CXXOBJS := $(addprefix $(OBJ_DIR)/, $(notdir $(CPPSOURCES:.cpp=.o)))
AOBJS := $(addprefix $(OBJ_DIR)/, $(notdir $(ASOURCES:.S=.o)))
OBJECTS := $(COBJS) $(CXXOBJS) $(AOBJS)
VPATH := $(SRC_DIR) $(THIRD_PARTY) $(THIRD_PARTY)/libbase
QUIET := @
ALL := all
TARGET := $(PACKAGE).elf
CLEAN := clean
$(ALL): $(TARGET) $(PACKAGE).bin $(PACKAGE).ihex
$(OBJECTS): | $(OBJ_DIR)
$(TARGET): $(OBJECTS) $(LDSCRIPTS)
$(QUIET) echo " LD $@"
$(QUIET) $(CC) $(OBJECTS) $(LFLAGS) -o $@
$(PACKAGE).bin: $(TARGET)
$(QUIET) echo " OBJCOPY $@"
$(QUIET) $(OBJCOPY) -O binary $(TARGET) $@
$(PACKAGE).dfu: $(TARGET)
$(QUIET) echo " DFU $@"
$(QUIET) $(COPY) $(PACKAGE).bin $@
$(QUIET) dfu-suffix -v 1209 -p 70b1 -a $@
$(PACKAGE).ihex: $(TARGET)
$(QUIET) echo " IHEX $(PACKAGE).ihex"
$(QUIET) $(OBJCOPY) -O ihex $(TARGET) $@
$(DEBUG): CFLAGS += $(DBG_CFLAGS)
$(DEBUG): LFLAGS += $(DBG_LFLAGS)
CFLAGS += $(DBG_CFLAGS)
LFLAGS += $(DBG_LFLAGS)
$(DEBUG): $(TARGET)
$(OBJ_DIR):
$(QUIET) mkdir $(OBJ_DIR)
$(COBJS) : $(OBJ_DIR)/%.o : %.c $(BASE_DIR)/Makefile
$(QUIET) echo " CC $< $(notdir $@)"
$(QUIET) $(CC) -c $< $(CFLAGS) -o $@ -MMD
$(OBJ_DIR)/%.o: %.cpp
$(QUIET) echo " CXX $< $(notdir $@)"
$(QUIET) $(CXX) -c $< $(CXXFLAGS) -o $@ -MMD
$(OBJ_DIR)/%.o: %.S
$(QUIET) echo " AS $< $(notdir $@)"
$(QUIET) $(CC) -x assembler-with-cpp -c $< $(CFLAGS) -o $@ -MMD
.PHONY: clean
clean:
$(QUIET) echo " RM $(subst /,$(PATH_SEP),$(wildcard $(OBJ_DIR)/*.d))"
-$(QUIET) $(RM) $(subst /,$(PATH_SEP),$(wildcard $(OBJ_DIR)/*.d))
$(QUIET) echo " RM $(subst /,$(PATH_SEP),$(wildcard $(OBJ_DIR)/*.d))"
-$(QUIET) $(RM) $(subst /,$(PATH_SEP),$(wildcard $(OBJ_DIR)/*.o))
$(QUIET) echo " RM $(TARGET) $(PACKAGE).bin $(PACKAGE).symbol $(PACKAGE).ihex $(PACKAGE).dfu"
-$(QUIET) $(RM) $(TARGET) $(PACKAGE).bin $(PACKAGE).symbol $(PACKAGE).ihex $(PACKAGE).dfu
include $(wildcard $(OBJ_DIR)/*.d)

View File

@ -1,24 +0,0 @@
#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 */

View File

@ -1,15 +0,0 @@
#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

View File

@ -1,11 +0,0 @@
#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 */

View File

@ -1,742 +0,0 @@
#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 */
/* ctrl */
#define CSR_CTRL_BASE 0xe0000000
#define CSR_CTRL_RESET_ADDR 0xe0000000
#define CSR_CTRL_RESET_SIZE 1
static inline unsigned char ctrl_reset_read(void) {
unsigned char r = csr_readl(0xe0000000);
return r;
}
static inline void ctrl_reset_write(unsigned char value) {
csr_writel(value, 0xe0000000);
}
#define CSR_CTRL_SCRATCH_ADDR 0xe0000004
#define CSR_CTRL_SCRATCH_SIZE 4
static inline unsigned int ctrl_scratch_read(void) {
unsigned int r = csr_readl(0xe0000004);
r <<= 8;
r |= csr_readl(0xe0000008);
r <<= 8;
r |= csr_readl(0xe000000c);
r <<= 8;
r |= csr_readl(0xe0000010);
return r;
}
static inline void ctrl_scratch_write(unsigned int value) {
csr_writel(value >> 24, 0xe0000004);
csr_writel(value >> 16, 0xe0000008);
csr_writel(value >> 8, 0xe000000c);
csr_writel(value, 0xe0000010);
}
#define CSR_CTRL_BUS_ERRORS_ADDR 0xe0000014
#define CSR_CTRL_BUS_ERRORS_SIZE 4
static inline unsigned int ctrl_bus_errors_read(void) {
unsigned int r = csr_readl(0xe0000014);
r <<= 8;
r |= csr_readl(0xe0000018);
r <<= 8;
r |= csr_readl(0xe000001c);
r <<= 8;
r |= csr_readl(0xe0000020);
return r;
}
/* picorvspi */
#define CSR_PICORVSPI_BASE 0xe0005000
#define CSR_PICORVSPI_CFG1_ADDR 0xe0005000
#define CSR_PICORVSPI_CFG1_SIZE 1
static inline unsigned char picorvspi_cfg1_read(void) {
unsigned char r = csr_readl(0xe0005000);
return r;
}
static inline void picorvspi_cfg1_write(unsigned char value) {
csr_writel(value, 0xe0005000);
}
#define CSR_PICORVSPI_CFG2_ADDR 0xe0005004
#define CSR_PICORVSPI_CFG2_SIZE 1
static inline unsigned char picorvspi_cfg2_read(void) {
unsigned char r = csr_readl(0xe0005004);
return r;
}
static inline void picorvspi_cfg2_write(unsigned char value) {
csr_writel(value, 0xe0005004);
}
#define CSR_PICORVSPI_CFG3_ADDR 0xe0005008
#define CSR_PICORVSPI_CFG3_SIZE 1
static inline unsigned char picorvspi_cfg3_read(void) {
unsigned char r = csr_readl(0xe0005008);
return r;
}
static inline void picorvspi_cfg3_write(unsigned char value) {
csr_writel(value, 0xe0005008);
}
#define CSR_PICORVSPI_CFG4_ADDR 0xe000500c
#define CSR_PICORVSPI_CFG4_SIZE 1
static inline unsigned char picorvspi_cfg4_read(void) {
unsigned char r = csr_readl(0xe000500c);
return r;
}
static inline void picorvspi_cfg4_write(unsigned char value) {
csr_writel(value, 0xe000500c);
}
#define CSR_PICORVSPI_STAT1_ADDR 0xe0005010
#define CSR_PICORVSPI_STAT1_SIZE 1
static inline unsigned char picorvspi_stat1_read(void) {
unsigned char r = csr_readl(0xe0005010);
return r;
}
#define CSR_PICORVSPI_STAT2_ADDR 0xe0005014
#define CSR_PICORVSPI_STAT2_SIZE 1
static inline unsigned char picorvspi_stat2_read(void) {
unsigned char r = csr_readl(0xe0005014);
return r;
}
#define CSR_PICORVSPI_STAT3_ADDR 0xe0005018
#define CSR_PICORVSPI_STAT3_SIZE 1
static inline unsigned char picorvspi_stat3_read(void) {
unsigned char r = csr_readl(0xe0005018);
return r;
}
#define CSR_PICORVSPI_STAT4_ADDR 0xe000501c
#define CSR_PICORVSPI_STAT4_SIZE 1
static inline unsigned char picorvspi_stat4_read(void) {
unsigned char r = csr_readl(0xe000501c);
return r;
}
/* reboot */
#define CSR_REBOOT_BASE 0xe0006000
#define CSR_REBOOT_CTRL_ADDR 0xe0006000
#define CSR_REBOOT_CTRL_SIZE 1
static inline unsigned char reboot_ctrl_read(void) {
unsigned char r = csr_readl(0xe0006000);
return r;
}
static inline void reboot_ctrl_write(unsigned char value) {
csr_writel(value, 0xe0006000);
}
#define CSR_REBOOT_ADDR_ADDR 0xe0006004
#define CSR_REBOOT_ADDR_SIZE 4
static inline unsigned int reboot_addr_read(void) {
unsigned int r = csr_readl(0xe0006004);
r <<= 8;
r |= csr_readl(0xe0006008);
r <<= 8;
r |= csr_readl(0xe000600c);
r <<= 8;
r |= csr_readl(0xe0006010);
return r;
}
static inline void reboot_addr_write(unsigned int value) {
csr_writel(value >> 24, 0xe0006004);
csr_writel(value >> 16, 0xe0006008);
csr_writel(value >> 8, 0xe000600c);
csr_writel(value, 0xe0006010);
}
/* rgb */
#define CSR_RGB_BASE 0xe0006800
#define CSR_RGB_DAT_ADDR 0xe0006800
#define CSR_RGB_DAT_SIZE 1
static inline unsigned char rgb_dat_read(void) {
unsigned char r = csr_readl(0xe0006800);
return r;
}
static inline void rgb_dat_write(unsigned char value) {
csr_writel(value, 0xe0006800);
}
#define CSR_RGB_ADDR_ADDR 0xe0006804
#define CSR_RGB_ADDR_SIZE 1
static inline unsigned char rgb_addr_read(void) {
unsigned char r = csr_readl(0xe0006804);
return r;
}
static inline void rgb_addr_write(unsigned char value) {
csr_writel(value, 0xe0006804);
}
#define CSR_RGB_CTRL_ADDR 0xe0006808
#define CSR_RGB_CTRL_SIZE 1
static inline unsigned char rgb_ctrl_read(void) {
unsigned char r = csr_readl(0xe0006808);
return r;
}
static inline void rgb_ctrl_write(unsigned char value) {
csr_writel(value, 0xe0006808);
}
/* 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);
}
/* touch */
#define CSR_TOUCH_BASE 0xe0005800
#define CSR_TOUCH_O_ADDR 0xe0005800
#define CSR_TOUCH_O_SIZE 1
static inline unsigned char touch_o_read(void) {
unsigned char r = csr_readl(0xe0005800);
return r;
}
static inline void touch_o_write(unsigned char value) {
csr_writel(value, 0xe0005800);
}
#define CSR_TOUCH_OE_ADDR 0xe0005804
#define CSR_TOUCH_OE_SIZE 1
static inline unsigned char touch_oe_read(void) {
unsigned char r = csr_readl(0xe0005804);
return r;
}
static inline void touch_oe_write(unsigned char value) {
csr_writel(value, 0xe0005804);
}
#define CSR_TOUCH_I_ADDR 0xe0005808
#define CSR_TOUCH_I_SIZE 1
static inline unsigned char touch_i_read(void) {
unsigned char r = csr_readl(0xe0005808);
return r;
}
/* usb */
#define CSR_USB_BASE 0xe0004800
#define CSR_USB_PULLUP_OUT_ADDR 0xe0004800
#define CSR_USB_PULLUP_OUT_SIZE 1
static inline unsigned char usb_pullup_out_read(void) {
unsigned char r = csr_readl(0xe0004800);
return r;
}
static inline void usb_pullup_out_write(unsigned char value) {
csr_writel(value, 0xe0004800);
}
#define CSR_USB_EP_0_OUT_EV_STATUS_ADDR 0xe0004804
#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(0xe0004804);
return r;
}
static inline void usb_ep_0_out_ev_status_write(unsigned char value) {
csr_writel(value, 0xe0004804);
}
#define CSR_USB_EP_0_OUT_EV_PENDING_ADDR 0xe0004808
#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(0xe0004808);
return r;
}
static inline void usb_ep_0_out_ev_pending_write(unsigned char value) {
csr_writel(value, 0xe0004808);
}
#define CSR_USB_EP_0_OUT_EV_ENABLE_ADDR 0xe000480c
#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(0xe000480c);
return r;
}
static inline void usb_ep_0_out_ev_enable_write(unsigned char value) {
csr_writel(value, 0xe000480c);
}
#define CSR_USB_EP_0_OUT_LAST_TOK_ADDR 0xe0004810
#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(0xe0004810);
return r;
}
#define CSR_USB_EP_0_OUT_RESPOND_ADDR 0xe0004814
#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(0xe0004814);
return r;
}
static inline void usb_ep_0_out_respond_write(unsigned char value) {
csr_writel(value, 0xe0004814);
}
#define CSR_USB_EP_0_OUT_DTB_ADDR 0xe0004818
#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(0xe0004818);
return r;
}
static inline void usb_ep_0_out_dtb_write(unsigned char value) {
csr_writel(value, 0xe0004818);
}
#define CSR_USB_EP_0_OUT_OBUF_HEAD_ADDR 0xe000481c
#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(0xe000481c);
return r;
}
static inline void usb_ep_0_out_obuf_head_write(unsigned char value) {
csr_writel(value, 0xe000481c);
}
#define CSR_USB_EP_0_OUT_OBUF_EMPTY_ADDR 0xe0004820
#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(0xe0004820);
return r;
}
#define CSR_USB_EP_0_IN_EV_STATUS_ADDR 0xe0004824
#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(0xe0004824);
return r;
}
static inline void usb_ep_0_in_ev_status_write(unsigned char value) {
csr_writel(value, 0xe0004824);
}
#define CSR_USB_EP_0_IN_EV_PENDING_ADDR 0xe0004828
#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(0xe0004828);
return r;
}
static inline void usb_ep_0_in_ev_pending_write(unsigned char value) {
csr_writel(value, 0xe0004828);
}
#define CSR_USB_EP_0_IN_EV_ENABLE_ADDR 0xe000482c
#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(0xe000482c);
return r;
}
static inline void usb_ep_0_in_ev_enable_write(unsigned char value) {
csr_writel(value, 0xe000482c);
}
#define CSR_USB_EP_0_IN_LAST_TOK_ADDR 0xe0004830
#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(0xe0004830);
return r;
}
#define CSR_USB_EP_0_IN_RESPOND_ADDR 0xe0004834
#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(0xe0004834);
return r;
}
static inline void usb_ep_0_in_respond_write(unsigned char value) {
csr_writel(value, 0xe0004834);
}
#define CSR_USB_EP_0_IN_DTB_ADDR 0xe0004838
#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(0xe0004838);
return r;
}
static inline void usb_ep_0_in_dtb_write(unsigned char value) {
csr_writel(value, 0xe0004838);
}
#define CSR_USB_EP_0_IN_IBUF_HEAD_ADDR 0xe000483c
#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(0xe000483c);
return r;
}
static inline void usb_ep_0_in_ibuf_head_write(unsigned char value) {
csr_writel(value, 0xe000483c);
}
#define CSR_USB_EP_0_IN_IBUF_EMPTY_ADDR 0xe0004840
#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(0xe0004840);
return r;
}
#define CSR_USB_EP_1_IN_EV_STATUS_ADDR 0xe0004844
#define CSR_USB_EP_1_IN_EV_STATUS_SIZE 1
static inline unsigned char usb_ep_1_in_ev_status_read(void) {
unsigned char r = csr_readl(0xe0004844);
return r;
}
static inline void usb_ep_1_in_ev_status_write(unsigned char value) {
csr_writel(value, 0xe0004844);
}
#define CSR_USB_EP_1_IN_EV_PENDING_ADDR 0xe0004848
#define CSR_USB_EP_1_IN_EV_PENDING_SIZE 1
static inline unsigned char usb_ep_1_in_ev_pending_read(void) {
unsigned char r = csr_readl(0xe0004848);
return r;
}
static inline void usb_ep_1_in_ev_pending_write(unsigned char value) {
csr_writel(value, 0xe0004848);
}
#define CSR_USB_EP_1_IN_EV_ENABLE_ADDR 0xe000484c
#define CSR_USB_EP_1_IN_EV_ENABLE_SIZE 1
static inline unsigned char usb_ep_1_in_ev_enable_read(void) {
unsigned char r = csr_readl(0xe000484c);
return r;
}
static inline void usb_ep_1_in_ev_enable_write(unsigned char value) {
csr_writel(value, 0xe000484c);
}
#define CSR_USB_EP_1_IN_LAST_TOK_ADDR 0xe0004850
#define CSR_USB_EP_1_IN_LAST_TOK_SIZE 1
static inline unsigned char usb_ep_1_in_last_tok_read(void) {
unsigned char r = csr_readl(0xe0004850);
return r;
}
#define CSR_USB_EP_1_IN_RESPOND_ADDR 0xe0004854
#define CSR_USB_EP_1_IN_RESPOND_SIZE 1
static inline unsigned char usb_ep_1_in_respond_read(void) {
unsigned char r = csr_readl(0xe0004854);
return r;
}
static inline void usb_ep_1_in_respond_write(unsigned char value) {
csr_writel(value, 0xe0004854);
}
#define CSR_USB_EP_1_IN_DTB_ADDR 0xe0004858
#define CSR_USB_EP_1_IN_DTB_SIZE 1
static inline unsigned char usb_ep_1_in_dtb_read(void) {
unsigned char r = csr_readl(0xe0004858);
return r;
}
static inline void usb_ep_1_in_dtb_write(unsigned char value) {
csr_writel(value, 0xe0004858);
}
#define CSR_USB_EP_1_IN_IBUF_HEAD_ADDR 0xe000485c
#define CSR_USB_EP_1_IN_IBUF_HEAD_SIZE 1
static inline unsigned char usb_ep_1_in_ibuf_head_read(void) {
unsigned char r = csr_readl(0xe000485c);
return r;
}
static inline void usb_ep_1_in_ibuf_head_write(unsigned char value) {
csr_writel(value, 0xe000485c);
}
#define CSR_USB_EP_1_IN_IBUF_EMPTY_ADDR 0xe0004860
#define CSR_USB_EP_1_IN_IBUF_EMPTY_SIZE 1
static inline unsigned char usb_ep_1_in_ibuf_empty_read(void) {
unsigned char r = csr_readl(0xe0004860);
return r;
}
#define CSR_USB_EP_2_OUT_EV_STATUS_ADDR 0xe0004864
#define CSR_USB_EP_2_OUT_EV_STATUS_SIZE 1
static inline unsigned char usb_ep_2_out_ev_status_read(void) {
unsigned char r = csr_readl(0xe0004864);
return r;
}
static inline void usb_ep_2_out_ev_status_write(unsigned char value) {
csr_writel(value, 0xe0004864);
}
#define CSR_USB_EP_2_OUT_EV_PENDING_ADDR 0xe0004868
#define CSR_USB_EP_2_OUT_EV_PENDING_SIZE 1
static inline unsigned char usb_ep_2_out_ev_pending_read(void) {
unsigned char r = csr_readl(0xe0004868);
return r;
}
static inline void usb_ep_2_out_ev_pending_write(unsigned char value) {
csr_writel(value, 0xe0004868);
}
#define CSR_USB_EP_2_OUT_EV_ENABLE_ADDR 0xe000486c
#define CSR_USB_EP_2_OUT_EV_ENABLE_SIZE 1
static inline unsigned char usb_ep_2_out_ev_enable_read(void) {
unsigned char r = csr_readl(0xe000486c);
return r;
}
static inline void usb_ep_2_out_ev_enable_write(unsigned char value) {
csr_writel(value, 0xe000486c);
}
#define CSR_USB_EP_2_OUT_LAST_TOK_ADDR 0xe0004870
#define CSR_USB_EP_2_OUT_LAST_TOK_SIZE 1
static inline unsigned char usb_ep_2_out_last_tok_read(void) {
unsigned char r = csr_readl(0xe0004870);
return r;
}
#define CSR_USB_EP_2_OUT_RESPOND_ADDR 0xe0004874
#define CSR_USB_EP_2_OUT_RESPOND_SIZE 1
static inline unsigned char usb_ep_2_out_respond_read(void) {
unsigned char r = csr_readl(0xe0004874);
return r;
}
static inline void usb_ep_2_out_respond_write(unsigned char value) {
csr_writel(value, 0xe0004874);
}
#define CSR_USB_EP_2_OUT_DTB_ADDR 0xe0004878
#define CSR_USB_EP_2_OUT_DTB_SIZE 1
static inline unsigned char usb_ep_2_out_dtb_read(void) {
unsigned char r = csr_readl(0xe0004878);
return r;
}
static inline void usb_ep_2_out_dtb_write(unsigned char value) {
csr_writel(value, 0xe0004878);
}
#define CSR_USB_EP_2_OUT_OBUF_HEAD_ADDR 0xe000487c
#define CSR_USB_EP_2_OUT_OBUF_HEAD_SIZE 1
static inline unsigned char usb_ep_2_out_obuf_head_read(void) {
unsigned char r = csr_readl(0xe000487c);
return r;
}
static inline void usb_ep_2_out_obuf_head_write(unsigned char value) {
csr_writel(value, 0xe000487c);
}
#define CSR_USB_EP_2_OUT_OBUF_EMPTY_ADDR 0xe0004880
#define CSR_USB_EP_2_OUT_OBUF_EMPTY_SIZE 1
static inline unsigned char usb_ep_2_out_obuf_empty_read(void) {
unsigned char r = csr_readl(0xe0004880);
return r;
}
#define CSR_USB_EP_2_IN_EV_STATUS_ADDR 0xe0004884
#define CSR_USB_EP_2_IN_EV_STATUS_SIZE 1
static inline unsigned char usb_ep_2_in_ev_status_read(void) {
unsigned char r = csr_readl(0xe0004884);
return r;
}
static inline void usb_ep_2_in_ev_status_write(unsigned char value) {
csr_writel(value, 0xe0004884);
}
#define CSR_USB_EP_2_IN_EV_PENDING_ADDR 0xe0004888
#define CSR_USB_EP_2_IN_EV_PENDING_SIZE 1
static inline unsigned char usb_ep_2_in_ev_pending_read(void) {
unsigned char r = csr_readl(0xe0004888);
return r;
}
static inline void usb_ep_2_in_ev_pending_write(unsigned char value) {
csr_writel(value, 0xe0004888);
}
#define CSR_USB_EP_2_IN_EV_ENABLE_ADDR 0xe000488c
#define CSR_USB_EP_2_IN_EV_ENABLE_SIZE 1
static inline unsigned char usb_ep_2_in_ev_enable_read(void) {
unsigned char r = csr_readl(0xe000488c);
return r;
}
static inline void usb_ep_2_in_ev_enable_write(unsigned char value) {
csr_writel(value, 0xe000488c);
}
#define CSR_USB_EP_2_IN_LAST_TOK_ADDR 0xe0004890
#define CSR_USB_EP_2_IN_LAST_TOK_SIZE 1
static inline unsigned char usb_ep_2_in_last_tok_read(void) {
unsigned char r = csr_readl(0xe0004890);
return r;
}
#define CSR_USB_EP_2_IN_RESPOND_ADDR 0xe0004894
#define CSR_USB_EP_2_IN_RESPOND_SIZE 1
static inline unsigned char usb_ep_2_in_respond_read(void) {
unsigned char r = csr_readl(0xe0004894);
return r;
}
static inline void usb_ep_2_in_respond_write(unsigned char value) {
csr_writel(value, 0xe0004894);
}
#define CSR_USB_EP_2_IN_DTB_ADDR 0xe0004898
#define CSR_USB_EP_2_IN_DTB_SIZE 1
static inline unsigned char usb_ep_2_in_dtb_read(void) {
unsigned char r = csr_readl(0xe0004898);
return r;
}
static inline void usb_ep_2_in_dtb_write(unsigned char value) {
csr_writel(value, 0xe0004898);
}
#define CSR_USB_EP_2_IN_IBUF_HEAD_ADDR 0xe000489c
#define CSR_USB_EP_2_IN_IBUF_HEAD_SIZE 1
static inline unsigned char usb_ep_2_in_ibuf_head_read(void) {
unsigned char r = csr_readl(0xe000489c);
return r;
}
static inline void usb_ep_2_in_ibuf_head_write(unsigned char value) {
csr_writel(value, 0xe000489c);
}
#define CSR_USB_EP_2_IN_IBUF_EMPTY_ADDR 0xe00048a0
#define CSR_USB_EP_2_IN_IBUF_EMPTY_SIZE 1
static inline unsigned char usb_ep_2_in_ibuf_empty_read(void) {
unsigned char r = csr_readl(0xe00048a0);
return r;
}
/* version */
#define CSR_VERSION_BASE 0xe0007000
#define CSR_VERSION_MAJOR_ADDR 0xe0007000
#define CSR_VERSION_MAJOR_SIZE 1
static inline unsigned char version_major_read(void) {
unsigned char r = csr_readl(0xe0007000);
return r;
}
#define CSR_VERSION_MINOR_ADDR 0xe0007004
#define CSR_VERSION_MINOR_SIZE 1
static inline unsigned char version_minor_read(void) {
unsigned char r = csr_readl(0xe0007004);
return r;
}
#define CSR_VERSION_REVISION_ADDR 0xe0007008
#define CSR_VERSION_REVISION_SIZE 1
static inline unsigned char version_revision_read(void) {
unsigned char r = csr_readl(0xe0007008);
return r;
}
#define CSR_VERSION_GITREV_ADDR 0xe000700c
#define CSR_VERSION_GITREV_SIZE 4
static inline unsigned int version_gitrev_read(void) {
unsigned int r = csr_readl(0xe000700c);
r <<= 8;
r |= csr_readl(0xe0007010);
r <<= 8;
r |= csr_readl(0xe0007014);
r <<= 8;
r |= csr_readl(0xe0007018);
return r;
}
#define CSR_VERSION_GITEXTRA_ADDR 0xe000701c
#define CSR_VERSION_GITEXTRA_SIZE 2
static inline unsigned short int version_gitextra_read(void) {
unsigned short int r = csr_readl(0xe000701c);
r <<= 8;
r |= csr_readl(0xe0007020);
return r;
}
#define CSR_VERSION_DIRTY_ADDR 0xe0007024
#define CSR_VERSION_DIRTY_SIZE 1
static inline unsigned char version_dirty_read(void) {
unsigned char r = csr_readl(0xe0007024);
return r;
}
/* 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 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

View File

@ -1,16 +0,0 @@
#ifndef __GENERATED_MEM_H
#define __GENERATED_MEM_H
#define VEXRISCV_DEBUG_BASE 0xf00f0000
#define VEXRISCV_DEBUG_SIZE 0x00000010
#define SRAM_BASE 0x10000000
#define SRAM_SIZE 0x00020000
#define ROM_BASE 0x00000000
#define ROM_SIZE 0x00002000
#define SPIFLASH_BASE 0x20000000
#define SPIFLASH_SIZE 0x00200000
#endif

View File

@ -1,52 +0,0 @@
#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 */

View File

@ -1,40 +0,0 @@
#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 */

View File

@ -1,144 +0,0 @@
#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 */

View File

@ -1,10 +0,0 @@
#ifndef _RGB_H_
#define _RGB_H_
void rgb_init(void);
void rgb_mode_idle(void);
void rgb_mode_done(void);
void rgb_mode_writing(void);
void rgb_mode_error(void);
#endif /* _RGB_H_ */

View File

@ -1,94 +0,0 @@
#ifndef BB_SPI_H_
#define BB_SPI_H_
#include <stdint.h>
enum spi_state {
SS_UNCONFIGURED = 0,
SS_SINGLE,
SS_DUAL_RX,
SS_DUAL_TX,
SS_QUAD_RX,
SS_QUAD_TX,
SS_HARDWARE,
};
enum spi_type {
ST_UNCONFIGURED,
ST_SINGLE,
ST_DUAL,
ST_QUAD,
ST_QPI,
};
enum spi_pin {
SP_MOSI,
SP_MISO,
SP_HOLD,
SP_WP,
SP_CS,
SP_CLK,
SP_D0,
SP_D1,
SP_D2,
SP_D3,
};
struct spi_id {
uint8_t manufacturer_id; // Result from 0x90
uint8_t device_id; // Result from 0x90
uint8_t _manufacturer_id; // Result from 0x9f
uint8_t memory_type; // Result from 0x9f
uint8_t memory_size; // Result from 0x9f
uint8_t signature; // Result from 0xab
uint8_t serial[4]; // Result from 0x4b
int bytes; // -1 if unknown
const char *manufacturer;
const char *model;
const char *capacity;
};
struct ff_spi;
void spiPause(struct ff_spi *spi);
void spiBegin(struct ff_spi *spi);
void spiEnd(struct ff_spi *spi);
//void spiSingleTx(struct ff_spi *spi, uint8_t out);
//uint8_t spiSingleRx(struct ff_spi *spi);
//void spiDualTx(struct ff_spi *spi, uint8_t out);
//void spiQuadTx(struct ff_spi *spi, uint8_t out);
void spiCommand(struct ff_spi *spi, uint8_t cmd);
//uint8_t spiDualRx(struct ff_spi *spi);
//uint8_t spiQuadRx(struct ff_spi *spi);
int spiTx(struct ff_spi *spi, uint8_t word);
uint8_t spiRx(struct ff_spi *spi);
uint8_t spiReadStatus(struct ff_spi *spi, uint8_t sr);
void spiWriteStatus(struct ff_spi *spi, uint8_t sr, uint8_t val);
void spiReadSecurity(struct ff_spi *spi, uint8_t sr, uint8_t security[256]);
void spiWriteSecurity(struct ff_spi *spi, uint8_t sr, uint8_t security[256]);
int spiSetType(struct ff_spi *spi, enum spi_type type);
int spiRead(struct ff_spi *spi, uint32_t addr, uint8_t *data, unsigned int count);
int spiIsBusy(struct ff_spi *spi);
int spiBeginErase32(struct ff_spi *spi, uint32_t erase_addr);
int spiBeginErase64(struct ff_spi *spi, uint32_t erase_addr);
int spiBeginWrite(struct ff_spi *spi, uint32_t addr, const void *data, unsigned int count);
void spiEnableQuad(void);
struct spi_id spiId(struct ff_spi *spi);
void spiOverrideSize(struct ff_spi *spi, uint32_t new_size);
//int spi_wait_for_not_busy(struct ff_spi *spi);
int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned int count);
uint8_t spiReset(struct ff_spi *spi);
int spiInit(struct ff_spi *spi);
void spiHold(struct ff_spi *spi);
void spiUnhold(struct ff_spi *spi);
void spiSwapTxRx(struct ff_spi *spi);
struct ff_spi *spiAlloc(void);
void spiSetPin(struct ff_spi *spi, enum spi_pin pin, int val);
void spiFree(void);
#endif /* BB_SPI_H_ */

View File

@ -1,8 +0,0 @@
#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 */

View File

@ -1,67 +0,0 @@
#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
#include <generated/csr.h>
__attribute__((noreturn)) void reboot(void);
__attribute__((noreturn)) static inline void warmboot_to_image(uint8_t image_index) {
reboot_ctrl_write(0xac | (image_index & 3) << 0);
while (1);
}
#endif /* __SYSTEM_H */

View File

@ -1,16 +0,0 @@
#ifndef __TIME_H
#define __TIME_H
#ifdef __cplusplus
extern "C" {
#endif
void time_init(void);
int elapsed(int *last_event, int period);
void msleep(int ms);
#ifdef __cplusplus
}
#endif
#endif /* __TIME_H */

View File

@ -1,20 +0,0 @@
#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

View File

@ -1,99 +0,0 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
*
* 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, 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:
*
* 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
*
* 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 AUTHORS OR 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.
*/
#ifndef _usb_desc_h_
#define _usb_desc_h_
#include <stdint.h>
#include <stddef.h>
#include <webusb-defs.h>
struct usb_setup_request {
union {
struct {
uint8_t bmRequestType;
uint8_t bRequest;
};
uint16_t wRequestAndType;
};
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
};
struct usb_string_descriptor_struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wString[];
};
#define NUM_USB_BUFFERS 8
#define VENDOR_ID 0x1209 // pid.codes
#define PRODUCT_ID 0x70b1 // Assigned to Tomu project
#define DEVICE_VER 0x0101 // Bootloader version
#define MANUFACTURER_NAME u"Foosn"
#define MANUFACTURER_NAME_LEN sizeof(MANUFACTURER_NAME)
#define PRODUCT_NAME u"Fomu Bootloader " GIT_VERSION
#define PRODUCT_NAME_LEN sizeof(PRODUCT_NAME)
#define SERIAL_NUMBER u"000000000000"
#define SERIAL_NUMBER_LEN sizeof(SERIAL_NUMBER)
#define EP0_SIZE 64
#define NUM_INTERFACE 1
// Microsoft Compatible ID Feature Descriptor
#define MSFT_VENDOR_CODE '~' // Arbitrary, but should be printable ASCII
#define MSFT_WCID_LEN 40
extern const uint8_t usb_microsoft_wcid[MSFT_WCID_LEN];
#define USB_DT_ENDPOINT 5
#define USB_DT_ENDPOINT_SIZE 7
#define USB_ENDPOINT_ATTR_BULK 0x02
typedef struct {
uint16_t wValue;
uint16_t length;
const uint8_t *addr;
} usb_descriptor_list_t;
extern const usb_descriptor_list_t usb_descriptor_list[];
// WebUSB Landing page URL descriptor
#define WEBUSB_VENDOR_CODE 2
#ifndef LANDING_PAGE_URL
#define LANDING_PAGE_URL "dfu.fomu.im"
#endif
#define LANDING_PAGE_DESCRIPTOR_SIZE (WEBUSB_DT_URL_DESCRIPTOR_SIZE \
+ sizeof(LANDING_PAGE_URL) - 1)
const uint8_t *get_landing_url_descriptor(uint32_t *datalen);
#endif

View File

@ -1,129 +0,0 @@
#ifndef USB_MSC_H
#define USB_MSC_H
#include <stdint.h>
/* The sense codes */
enum sbc_sense_key {
SBC_SENSE_KEY_NO_SENSE = 0x00,
SBC_SENSE_KEY_RECOVERED_ERROR = 0x01,
SBC_SENSE_KEY_NOT_READY = 0x02,
SBC_SENSE_KEY_MEDIUM_ERROR = 0x03,
SBC_SENSE_KEY_HARDWARE_ERROR = 0x04,
SBC_SENSE_KEY_ILLEGAL_REQUEST = 0x05,
SBC_SENSE_KEY_UNIT_ATTENTION = 0x06,
SBC_SENSE_KEY_DATA_PROTECT = 0x07,
SBC_SENSE_KEY_BLANK_CHECK = 0x08,
SBC_SENSE_KEY_VENDOR_SPECIFIC = 0x09,
SBC_SENSE_KEY_COPY_ABORTED = 0x0A,
SBC_SENSE_KEY_ABORTED_COMMAND = 0x0B,
SBC_SENSE_KEY_VOLUME_OVERFLOW = 0x0D,
SBC_SENSE_KEY_MISCOMPARE = 0x0E
};
enum sbc_asc {
SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION = 0x00,
SBC_ASC_PERIPHERAL_DEVICE_WRITE_FAULT = 0x03,
SBC_ASC_LOGICAL_UNIT_NOT_READY = 0x04,
SBC_ASC_UNRECOVERED_READ_ERROR = 0x11,
SBC_ASC_INVALID_COMMAND_OPERATION_CODE = 0x20,
SBC_ASC_LBA_OUT_OF_RANGE = 0x21,
SBC_ASC_INVALID_FIELD_IN_CDB = 0x24,
SBC_ASC_WRITE_PROTECTED = 0x27,
SBC_ASC_NOT_READY_TO_READY_CHANGE = 0x28,
SBC_ASC_FORMAT_ERROR = 0x31,
SBC_ASC_MEDIUM_NOT_PRESENT = 0x3A
};
enum sbc_ascq {
SBC_ASCQ_NA = 0x00,
SBC_ASCQ_FORMAT_COMMAND_FAILED = 0x01,
SBC_ASCQ_INITIALIZING_COMMAND_REQUIRED = 0x02,
SBC_ASCQ_OPERATION_IN_PROGRESS = 0x07
};
/**
* \brief SCSI Standard Inquiry data structure
*/
struct scsi_inquiry_data {
uint8_t pq_pdt; /**< Peripheral Qual / Peripheral Dev Type */
#define SCSI_INQ_PQ_CONNECTED 0x00 /**< Peripheral connected */
#define SCSI_INQ_PQ_NOT_CONN 0x20 /**< Peripheral not connected */
#define SCSI_INQ_PQ_NOT_SUPP 0x60 /**< Peripheral not supported */
#define SCSI_INQ_DT_DIR_ACCESS 0x00 /**< Direct Access (SBC) */
#define SCSI_INQ_DT_SEQ_ACCESS 0x01 /**< Sequential Access */
#define SCSI_INQ_DT_PRINTER 0x02 /**< Printer */
#define SCSI_INQ_DT_PROCESSOR 0x03 /**< Processor device */
#define SCSI_INQ_DT_WRITE_ONCE 0x04 /**< Write-once device */
#define SCSI_INQ_DT_CD_DVD 0x05 /**< CD/DVD device */
#define SCSI_INQ_DT_OPTICAL 0x07 /**< Optical Memory */
#define SCSI_INQ_DT_MC 0x08 /**< Medium Changer */
#define SCSI_INQ_DT_ARRAY 0x0c /**< Storage Array Controller */
#define SCSI_INQ_DT_ENCLOSURE 0x0d /**< Enclosure Services */
#define SCSI_INQ_DT_RBC 0x0e /**< Simplified Direct Access */
#define SCSI_INQ_DT_OCRW 0x0f /**< Optical card reader/writer */
#define SCSI_INQ_DT_BCC 0x10 /**< Bridge Controller Commands */
#define SCSI_INQ_DT_OSD 0x11 /**< Object-based Storage */
#define SCSI_INQ_DT_NONE 0x1f /**< No Peripheral */
uint8_t flags1; /**< Flags (byte 1) */
#define SCSI_INQ_RMB 0x80 /**< Removable Medium */
uint8_t version; /**< Version */
#define SCSI_INQ_VER_NONE 0x00 /**< No standards conformance */
#define SCSI_INQ_VER_SPC 0x03 /**< SCSI Primary Commands (link to SBC) */
#define SCSI_INQ_VER_SPC2 0x04 /**< SCSI Primary Commands - 2 (link to SBC-2) */
#define SCSI_INQ_VER_SPC3 0x05 /**< SCSI Primary Commands - 3 (link to SBC-2) */
#define SCSI_INQ_VER_SPC4 0x06 /**< SCSI Primary Commands - 4 (link to SBC-3) */
uint8_t flags3; /**< Flags (byte 3) */
#define SCSI_INQ_NORMACA 0x20 /**< Normal ACA Supported */
#define SCSI_INQ_HISUP 0x10 /**< Hierarchal LUN addressing */
#define SCSI_INQ_RSP_SPC2 0x02 /**< SPC-2 / SPC-3 response format */
uint8_t addl_len; /**< Additional Length (n-4) */
#define SCSI_INQ_ADDL_LEN(tot) ((tot)-5) /**< Total length is \a tot */
uint8_t flags5; /**< Flags (byte 5) */
#define SCSI_INQ_SCCS 0x80
uint8_t flags6; /**< Flags (byte 6) */
#define SCSI_INQ_BQUE 0x80
#define SCSI_INQ_ENCSERV 0x40
#define SCSI_INQ_MULTIP 0x10
#define SCSI_INQ_MCHGR 0x08
#define SCSI_INQ_ADDR16 0x01
uint8_t flags7; /**< Flags (byte 7) */
#define SCSI_INQ_WBUS16 0x20
#define SCSI_INQ_SYNC 0x10
#define SCSI_INQ_LINKED 0x08
#define SCSI_INQ_CMDQUE 0x02
uint8_t vendor_id[8]; /**< T10 Vendor Identification */
uint8_t product_id[16]; /**< Product Identification */
uint8_t product_rev[4]; /**< Product Revision Level */
} __attribute__((packed));
/* Command Status Wrapper */
#define CSW_SIGNATURE 0x53425355
#define CSW_STATUS_SUCCESS 0
#define CSW_STATUS_FAILED 1
#define CSW_STATUS_PHASE_ERROR 2
struct usb_msc_csw {
uint32_t dCSWSignature;
uint32_t dCSWTag;
uint32_t dCSWDataResidue;
uint8_t bCSWStatus;
} __attribute__((packed));
struct cbw {
// 'USBC'
uint8_t signature[4];
uint32_t tag;
uint32_t length;
uint8_t flags;
uint8_t lun;
uint8_t cbLength;
uint8_t data[0];
};
int usb_msc_setup(const struct usb_setup_request *setup);
void usb_msc_in(void);
void usb_msc_out(const void *data, size_t len);
#endif // USB_MSC_H

View File

@ -1,33 +0,0 @@
#ifndef __USB_H
#define __USB_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct usb_setup_request;
void usb_isr(void);
void usb_init(void);
void usb_connect(void);
void usb_idle(void);
void usb_disconnect(void);
int usb_irq_happened(void);
void usb_setup(const struct usb_setup_request *setup);
void usb_send(int epnum, const void *data, size_t total_count);
void usb_send_cb(int epnum, int (*cb)(uint8_t *, size_t, void *), void *ptr);
void usb_ack(int epnum);
void usb_stall(int epnum);
int usb_recv(void *buffer, size_t buffer_len);
void usb_poll(void);
void usb_wait_for_send_done(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,55 +0,0 @@
/*
* Copyright (c) 2016, Devan Lai
*
* Permission to use, copy, modify, and/or distribute this software
* for any purpose with or without fee is hereby granted, provided
* that the above copyright notice and this permission notice
* appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef WEBUSB_DEFS_H_INCLUDED
#define WEBUSB_DEFS_H_INCLUDED
#include <stdint.h>
#define WEBUSB_REQ_GET_URL 0x02
#define WEBUSB_DT_URL 3
#define WEBUSB_URL_SCHEME_HTTP 0
#define WEBUSB_URL_SCHEME_HTTPS 1
struct webusb_platform_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDevCapabilityType;
uint8_t bReserved;
uint8_t platformCapabilityUUID[16];
uint16_t bcdVersion;
uint8_t bVendorCode;
uint8_t iLandingPage;
} __attribute__((packed));
#define WEBUSB_PLATFORM_DESCRIPTOR_SIZE sizeof(struct webusb_platform_descriptor)
#define WEBUSB_UUID {0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65}
struct webusb_url_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bScheme;
char URL[];
} __attribute__((packed));
#define WEBUSB_DT_URL_DESCRIPTOR_SIZE 3
#endif

View File

@ -1,912 +0,0 @@
/*
* xxHash - Fast Hash algorithm
* Copyright (C) 2012-2016, Yann Collet
*
* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
*
* 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.
*
* 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
* OWNER 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.
*
* You can contact the author at :
* - xxHash homepage: http://www.xxhash.com
* - xxHash source repository : https://github.com/Cyan4973/xxHash
*/
/* *************************************
* Tuning parameters
***************************************/
/*!XXH_FORCE_MEMORY_ACCESS :
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
* The below switch allow to select different access method for improved performance.
* Method 0 (default) : use `memcpy()`. Safe and portable.
* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
* Method 2 : direct access. This method doesn't depend on compiler but violate C standard.
* It can generate buggy code on targets which do not support unaligned memory accesses.
* But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
* See http://stackoverflow.com/a/32095106/646947 for details.
* Prefer these methods in priority order (0 > 1 > 2)
*/
#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
|| defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
# define XXH_FORCE_MEMORY_ACCESS 2
# elif defined(__INTEL_COMPILER) || \
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
|| defined(__ARM_ARCH_7S__) ))
# define XXH_FORCE_MEMORY_ACCESS 1
# endif
#endif
/*!XXH_ACCEPT_NULL_INPUT_POINTER :
* If input pointer is NULL, xxHash default behavior is to dereference it, triggering a segfault.
* When this macro is enabled, xxHash actively checks input for null pointer.
* It it is, result for null input pointers is the same as a null-length input.
*/
#ifndef XXH_ACCEPT_NULL_INPUT_POINTER /* can be defined externally */
# define XXH_ACCEPT_NULL_INPUT_POINTER 0
#endif
/*!XXH_FORCE_NATIVE_FORMAT :
* By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
* Results are therefore identical for little-endian and big-endian CPU.
* This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
* Should endian-independence be of no importance for your application, you may set the #define below to 1,
* to improve speed for Big-endian CPU.
* This option has no impact on Little_Endian CPU.
*/
#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */
# define XXH_FORCE_NATIVE_FORMAT 0
#endif
/*!XXH_FORCE_ALIGN_CHECK :
* This is a minor performance trick, only useful with lots of very small keys.
* It means : check for aligned/unaligned input.
* The check costs one initial branch per hash;
* set it to 0 when the input is guaranteed to be aligned,
* or when alignment doesn't matter for performance.
*/
#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */
# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
# define XXH_FORCE_ALIGN_CHECK 0
# else
# define XXH_FORCE_ALIGN_CHECK 1
# endif
#endif
/* *************************************
* Includes & Memory related functions
***************************************/
/*! Modify the local functions below should you wish to use some other memory routines
* for malloc(), free() */
#include <stdlib.h>
static void* XXH_malloc(size_t s) { return malloc(s); }
static void XXH_free (void* p) { free(p); }
/*! and for memcpy() */
#include <string.h>
static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
#define XXH_STATIC_LINKING_ONLY
#include "xxhash.h"
/* *************************************
* Compiler Specific Options
***************************************/
#ifdef _MSC_VER /* Visual Studio */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# define FORCE_INLINE static __forceinline
#else
# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
# ifdef __GNUC__
# define FORCE_INLINE static inline __attribute__((always_inline))
# else
# define FORCE_INLINE static inline
# endif
# else
# define FORCE_INLINE static
# endif /* __STDC_VERSION__ */
#endif
/* *************************************
* Basic Types
***************************************/
#ifndef MEM_MODULE
# if !defined (__VMS) \
&& (defined (__cplusplus) \
|| (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
# include <stdint.h>
typedef uint8_t BYTE;
typedef uint16_t U16;
typedef uint32_t U32;
# else
typedef unsigned char BYTE;
typedef unsigned short U16;
typedef unsigned int U32;
# endif
#endif
#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; }
#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
/* currently only defined for gcc and icc */
typedef union { U32 u32; } __attribute__((packed)) unalign;
static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
#else
/* portable and safe solution. Generally efficient.
* see : http://stackoverflow.com/a/32095106/646947
*/
static U32 XXH_read32(const void* memPtr)
{
U32 val;
memcpy(&val, memPtr, sizeof(val));
return val;
}
#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
/* ****************************************
* Compiler-specific Functions and Macros
******************************************/
#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
#if defined(_MSC_VER)
# define XXH_rotl32(x,r) _rotl(x,r)
# define XXH_rotl64(x,r) _rotl64(x,r)
#else
# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
#endif
#if defined(_MSC_VER) /* Visual Studio */
# define XXH_swap32 _byteswap_ulong
#elif XXH_GCC_VERSION >= 403
# define XXH_swap32 __builtin_bswap32
#else
static U32 XXH_swap32 (U32 x)
{
return ((x << 24) & 0xff000000 ) |
((x << 8) & 0x00ff0000 ) |
((x >> 8) & 0x0000ff00 ) |
((x >> 24) & 0x000000ff );
}
#endif
/* *************************************
* Architecture Macros
***************************************/
typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */
#ifndef XXH_CPU_LITTLE_ENDIAN
static const int g_one = 1;
# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&g_one))
#endif
/* ***************************
* Memory reads
*****************************/
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
{
if (align==XXH_unaligned)
return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
else
return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);
}
FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
{
return XXH_readLE32_align(ptr, endian, XXH_unaligned);
}
static U32 XXH_readBE32(const void* ptr)
{
return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);
}
/* *************************************
* Macros
***************************************/
#define XXH_STATIC_ASSERT(c) { enum { XXH_sa = 1/(int)(!!(c)) }; } /* use after variable declarations */
XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }
/* *******************************************************************
* 32-bit hash functions
*********************************************************************/
static const U32 PRIME32_1 = 2654435761U;
static const U32 PRIME32_2 = 2246822519U;
static const U32 PRIME32_3 = 3266489917U;
static const U32 PRIME32_4 = 668265263U;
static const U32 PRIME32_5 = 374761393U;
static U32 XXH32_round(U32 seed, U32 input)
{
seed += input * PRIME32_2;
seed = XXH_rotl32(seed, 13);
seed *= PRIME32_1;
return seed;
}
FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
{
const BYTE* p = (const BYTE*)input;
const BYTE* bEnd = p + len;
U32 h32;
#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
if (p==NULL) {
len=0;
bEnd=p=(const BYTE*)(size_t)16;
}
#endif
if (len>=16) {
const BYTE* const limit = bEnd - 16;
U32 v1 = seed + PRIME32_1 + PRIME32_2;
U32 v2 = seed + PRIME32_2;
U32 v3 = seed + 0;
U32 v4 = seed - PRIME32_1;
do {
v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4;
v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4;
v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4;
v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4;
} while (p<=limit);
h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
} else {
h32 = seed + PRIME32_5;
}
h32 += (U32) len;
while (p+4<=bEnd) {
h32 += XXH_get32bits(p) * PRIME32_3;
h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
p+=4;
}
while (p<bEnd) {
h32 += (*p) * PRIME32_5;
h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
p++;
}
h32 ^= h32 >> 15;
h32 *= PRIME32_2;
h32 ^= h32 >> 13;
h32 *= PRIME32_3;
h32 ^= h32 >> 16;
return h32;
}
XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed)
{
#if 0
/* Simple version, good for code maintenance, but unfortunately slow for small inputs */
XXH32_state_t state;
XXH32_reset(&state, seed);
XXH32_update(&state, input, len);
return XXH32_digest(&state);
#else
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if (XXH_FORCE_ALIGN_CHECK) {
if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
else
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
} }
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
else
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
#endif
}
/*====== Hash streaming ======*/
XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void)
{
return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
}
XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
{
XXH_free(statePtr);
return XXH_OK;
}
XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState)
{
memcpy(dstState, srcState, sizeof(*dstState));
}
XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed)
{
XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
memset(&state, 0, sizeof(state));
state.v1 = seed + PRIME32_1 + PRIME32_2;
state.v2 = seed + PRIME32_2;
state.v3 = seed + 0;
state.v4 = seed - PRIME32_1;
/* do not write into reserved, planned to be removed in a future version */
memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved));
return XXH_OK;
}
FORCE_INLINE
XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian)
{
const BYTE* p = (const BYTE*)input;
const BYTE* const bEnd = p + len;
if (input==NULL)
#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
return XXH_OK;
#else
return XXH_ERROR;
#endif
state->total_len_32 += (unsigned)len;
state->large_len |= (len>=16) | (state->total_len_32>=16);
if (state->memsize + len < 16) { /* fill in tmp buffer */
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
state->memsize += (unsigned)len;
return XXH_OK;
}
if (state->memsize) { /* some data left from previous update */
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
{ const unsigned* p32 = state->mem32;
state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++;
state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++;
state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++;
state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian));
}
p += 16-state->memsize;
state->memsize = 0;
}
if (p <= bEnd-16) {
const BYTE* const limit = bEnd - 16;
U32 v1 = state->v1;
U32 v2 = state->v2;
U32 v3 = state->v3;
U32 v4 = state->v4;
do {
v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4;
v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4;
v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4;
v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4;
} while (p<=limit);
state->v1 = v1;
state->v2 = v2;
state->v3 = v3;
state->v4 = v4;
}
if (p < bEnd) {
XXH_memcpy(state->mem32, p, (size_t)(bEnd-p));
state->memsize = (unsigned)(bEnd-p);
}
return XXH_OK;
}
XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
{
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
else
return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
}
FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian)
{
const BYTE * p = (const BYTE*)state->mem32;
const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize;
U32 h32;
if (state->large_len) {
h32 = XXH_rotl32(state->v1, 1)
+ XXH_rotl32(state->v2, 7)
+ XXH_rotl32(state->v3, 12)
+ XXH_rotl32(state->v4, 18);
} else {
h32 = state->v3 /* == seed */ + PRIME32_5;
}
h32 += state->total_len_32;
while (p+4<=bEnd) {
h32 += XXH_readLE32(p, endian) * PRIME32_3;
h32 = XXH_rotl32(h32, 17) * PRIME32_4;
p+=4;
}
while (p<bEnd) {
h32 += (*p) * PRIME32_5;
h32 = XXH_rotl32(h32, 11) * PRIME32_1;
p++;
}
h32 ^= h32 >> 15;
h32 *= PRIME32_2;
h32 ^= h32 >> 13;
h32 *= PRIME32_3;
h32 ^= h32 >> 16;
return h32;
}
XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in)
{
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH32_digest_endian(state_in, XXH_littleEndian);
else
return XXH32_digest_endian(state_in, XXH_bigEndian);
}
/*====== Canonical representation ======*/
/*! Default XXH result types are basic unsigned 32 and 64 bits.
* The canonical representation follows human-readable write convention, aka big-endian (large digits first).
* These functions allow transformation of hash result into and from its canonical format.
* This way, hash values can be written into a file or buffer, remaining comparable across different systems.
*/
XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)
{
XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));
if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);
memcpy(dst, &hash, sizeof(*dst));
}
XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)
{
return XXH_readBE32(src);
}
#ifndef XXH_NO_LONG_LONG
/* *******************************************************************
* 64-bit hash functions
*********************************************************************/
/*====== Memory access ======*/
#ifndef MEM_MODULE
# define MEM_MODULE
# if !defined (__VMS) \
&& (defined (__cplusplus) \
|| (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
# include <stdint.h>
typedef uint64_t U64;
# else
/* if compiler doesn't support unsigned long long, replace by another 64-bit type */
typedef unsigned long long U64;
# endif
#endif
#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; }
#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
/* currently only defined for gcc and icc */
typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign64;
static U64 XXH_read64(const void* ptr) { return ((const unalign64*)ptr)->u64; }
#else
/* portable and safe solution. Generally efficient.
* see : http://stackoverflow.com/a/32095106/646947
*/
static U64 XXH_read64(const void* memPtr)
{
U64 val;
memcpy(&val, memPtr, sizeof(val));
return val;
}
#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
#if defined(_MSC_VER) /* Visual Studio */
# define XXH_swap64 _byteswap_uint64
#elif XXH_GCC_VERSION >= 403
# define XXH_swap64 __builtin_bswap64
#else
static U64 XXH_swap64 (U64 x)
{
return ((x << 56) & 0xff00000000000000ULL) |
((x << 40) & 0x00ff000000000000ULL) |
((x << 24) & 0x0000ff0000000000ULL) |
((x << 8) & 0x000000ff00000000ULL) |
((x >> 8) & 0x00000000ff000000ULL) |
((x >> 24) & 0x0000000000ff0000ULL) |
((x >> 40) & 0x000000000000ff00ULL) |
((x >> 56) & 0x00000000000000ffULL);
}
#endif
FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
{
if (align==XXH_unaligned)
return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
else
return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);
}
FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
{
return XXH_readLE64_align(ptr, endian, XXH_unaligned);
}
static U64 XXH_readBE64(const void* ptr)
{
return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);
}
/*====== xxh64 ======*/
static const U64 PRIME64_1 = 11400714785074694791ULL;
static const U64 PRIME64_2 = 14029467366897019727ULL;
static const U64 PRIME64_3 = 1609587929392839161ULL;
static const U64 PRIME64_4 = 9650029242287828579ULL;
static const U64 PRIME64_5 = 2870177450012600261ULL;
static U64 XXH64_round(U64 acc, U64 input)
{
acc += input * PRIME64_2;
acc = XXH_rotl64(acc, 31);
acc *= PRIME64_1;
return acc;
}
static U64 XXH64_mergeRound(U64 acc, U64 val)
{
val = XXH64_round(0, val);
acc ^= val;
acc = acc * PRIME64_1 + PRIME64_4;
return acc;
}
FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
{
const BYTE* p = (const BYTE*)input;
const BYTE* bEnd = p + len;
U64 h64;
#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
if (p==NULL) {
len=0;
bEnd=p=(const BYTE*)(size_t)32;
}
#endif
if (len>=32) {
const BYTE* const limit = bEnd - 32;
U64 v1 = seed + PRIME64_1 + PRIME64_2;
U64 v2 = seed + PRIME64_2;
U64 v3 = seed + 0;
U64 v4 = seed - PRIME64_1;
do {
v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8;
v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8;
v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8;
v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8;
} while (p<=limit);
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
h64 = XXH64_mergeRound(h64, v1);
h64 = XXH64_mergeRound(h64, v2);
h64 = XXH64_mergeRound(h64, v3);
h64 = XXH64_mergeRound(h64, v4);
} else {
h64 = seed + PRIME64_5;
}
h64 += (U64) len;
while (p+8<=bEnd) {
U64 const k1 = XXH64_round(0, XXH_get64bits(p));
h64 ^= k1;
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
p+=8;
}
if (p+4<=bEnd) {
h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
p+=4;
}
while (p<bEnd) {
h64 ^= (*p) * PRIME64_5;
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
p++;
}
h64 ^= h64 >> 33;
h64 *= PRIME64_2;
h64 ^= h64 >> 29;
h64 *= PRIME64_3;
h64 ^= h64 >> 32;
return h64;
}
XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
{
#if 0
/* Simple version, good for code maintenance, but unfortunately slow for small inputs */
XXH64_state_t state;
XXH64_reset(&state, seed);
XXH64_update(&state, input, len);
return XXH64_digest(&state);
#else
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if (XXH_FORCE_ALIGN_CHECK) {
if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
else
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
} }
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
else
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
#endif
}
/*====== Hash Streaming ======*/
XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)
{
return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
}
XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
{
XXH_free(statePtr);
return XXH_OK;
}
XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState)
{
memcpy(dstState, srcState, sizeof(*dstState));
}
XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed)
{
XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
memset(&state, 0, sizeof(state));
state.v1 = seed + PRIME64_1 + PRIME64_2;
state.v2 = seed + PRIME64_2;
state.v3 = seed + 0;
state.v4 = seed - PRIME64_1;
/* do not write into reserved, planned to be removed in a future version */
memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved));
return XXH_OK;
}
FORCE_INLINE
XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian)
{
const BYTE* p = (const BYTE*)input;
const BYTE* const bEnd = p + len;
if (input==NULL)
#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
return XXH_OK;
#else
return XXH_ERROR;
#endif
state->total_len += len;
if (state->memsize + len < 32) { /* fill in tmp buffer */
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
state->memsize += (U32)len;
return XXH_OK;
}
if (state->memsize) { /* tmp buffer is full */
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian));
state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian));
state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian));
state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian));
p += 32-state->memsize;
state->memsize = 0;
}
if (p+32 <= bEnd) {
const BYTE* const limit = bEnd - 32;
U64 v1 = state->v1;
U64 v2 = state->v2;
U64 v3 = state->v3;
U64 v4 = state->v4;
do {
v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8;
v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8;
v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8;
v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8;
} while (p<=limit);
state->v1 = v1;
state->v2 = v2;
state->v3 = v3;
state->v4 = v4;
}
if (p < bEnd) {
XXH_memcpy(state->mem64, p, (size_t)(bEnd-p));
state->memsize = (unsigned)(bEnd-p);
}
return XXH_OK;
}
XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
{
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
else
return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
}
FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian)
{
const BYTE * p = (const BYTE*)state->mem64;
const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize;
U64 h64;
if (state->total_len >= 32) {
U64 const v1 = state->v1;
U64 const v2 = state->v2;
U64 const v3 = state->v3;
U64 const v4 = state->v4;
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
h64 = XXH64_mergeRound(h64, v1);
h64 = XXH64_mergeRound(h64, v2);
h64 = XXH64_mergeRound(h64, v3);
h64 = XXH64_mergeRound(h64, v4);
} else {
h64 = state->v3 + PRIME64_5;
}
h64 += (U64) state->total_len;
while (p+8<=bEnd) {
U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian));
h64 ^= k1;
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
p+=8;
}
if (p+4<=bEnd) {
h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
p+=4;
}
while (p<bEnd) {
h64 ^= (*p) * PRIME64_5;
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
p++;
}
h64 ^= h64 >> 33;
h64 *= PRIME64_2;
h64 ^= h64 >> 29;
h64 *= PRIME64_3;
h64 ^= h64 >> 32;
return h64;
}
XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in)
{
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH64_digest_endian(state_in, XXH_littleEndian);
else
return XXH64_digest_endian(state_in, XXH_bigEndian);
}
/*====== Canonical representation ======*/
XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash)
{
XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));
if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);
memcpy(dst, &hash, sizeof(*dst));
}
XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src)
{
return XXH_readBE64(src);
}
#endif /* XXH_NO_LONG_LONG */

View File

@ -1,294 +0,0 @@
/*
xxHash - Extremely Fast Hash algorithm
Header File
Copyright (C) 2012-2016, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
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.
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
OWNER 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.
You can contact the author at :
- xxHash source repository : https://github.com/Cyan4973/xxHash
*/
/* Notice extracted from xxHash homepage :
xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
It also successfully passes all tests from the SMHasher suite.
Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
Name Speed Q.Score Author
xxHash 5.4 GB/s 10
CrapWow 3.2 GB/s 2 Andrew
MumurHash 3a 2.7 GB/s 10 Austin Appleby
SpookyHash 2.0 GB/s 10 Bob Jenkins
SBox 1.4 GB/s 9 Bret Mulvey
Lookup3 1.2 GB/s 9 Bob Jenkins
SuperFastHash 1.2 GB/s 1 Paul Hsieh
CityHash64 1.05 GB/s 10 Pike & Alakuijala
FNV 0.55 GB/s 5 Fowler, Noll, Vo
CRC32 0.43 GB/s 9
MD5-32 0.33 GB/s 10 Ronald L. Rivest
SHA1-32 0.28 GB/s 10
Q.Score is a measure of quality of the hash function.
It depends on successfully passing SMHasher test set.
10 is a perfect score.
A 64-bit version, named XXH64, is available since r35.
It offers much better speed, but for 64-bit applications only.
Name Speed on 64 bits Speed on 32 bits
XXH64 13.8 GB/s 1.9 GB/s
XXH32 6.8 GB/s 6.0 GB/s
*/
#ifndef XXHASH_H_5627135585666179
#define XXHASH_H_5627135585666179 1
#if defined (__cplusplus)
extern "C" {
#endif
/* ****************************
* Definitions
******************************/
#include <stddef.h> /* size_t */
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
/* ****************************
* API modifier
******************************/
/** XXH_PRIVATE_API
* This is useful to include xxhash functions in `static` mode
* in order to inline them, and remove their symbol from the public list.
* Methodology :
* #define XXH_PRIVATE_API
* #include "xxhash.h"
* `xxhash.c` is automatically included.
* It's not useful to compile and link it as a separate module.
*/
#ifdef XXH_PRIVATE_API
# ifndef XXH_STATIC_LINKING_ONLY
# define XXH_STATIC_LINKING_ONLY
# endif
# if defined(__GNUC__)
# define XXH_PUBLIC_API static __inline __attribute__((unused))
# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
# define XXH_PUBLIC_API static inline
# elif defined(_MSC_VER)
# define XXH_PUBLIC_API static __inline
# else
/* this version may generate warnings for unused static functions */
# define XXH_PUBLIC_API static
# endif
#else
# define XXH_PUBLIC_API /* do nothing */
#endif /* XXH_PRIVATE_API */
/*!XXH_NAMESPACE, aka Namespace Emulation :
If you want to include _and expose_ xxHash functions from within your own library,
but also want to avoid symbol collisions with other libraries which may also include xxHash,
you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library
with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values).
Note that no change is required within the calling program as long as it includes `xxhash.h` :
regular symbol name will be automatically translated by this header.
*/
#ifdef XXH_NAMESPACE
# define XXH_CAT(A,B) A##B
# define XXH_NAME2(A,B) XXH_CAT(A,B)
# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber)
# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)
# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState)
# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState)
# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset)
# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)
# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)
# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState)
# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash)
# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical)
# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64)
# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState)
# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState)
# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset)
# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update)
# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest)
# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState)
# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash)
# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical)
#endif
/* *************************************
* Version
***************************************/
#define XXH_VERSION_MAJOR 0
#define XXH_VERSION_MINOR 6
#define XXH_VERSION_RELEASE 4
#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)
XXH_PUBLIC_API unsigned XXH_versionNumber (void);
/*-**********************************************************************
* 32-bit hash
************************************************************************/
typedef unsigned int XXH32_hash_t;
/*! XXH32() :
Calculate the 32-bit hash of sequence "length" bytes stored at memory address "input".
The memory between input & input+length must be valid (allocated and read-accessible).
"seed" can be used to alter the result predictably.
Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s */
XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed);
/*====== Streaming ======*/
typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */
XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void);
XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state);
XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed);
XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr);
/*
These functions generate the xxHash of an input provided in multiple segments.
Note that, for small input, they are slower than single-call functions, due to state management.
For small input, prefer `XXH32()` and `XXH64()` .
XXH state must first be allocated, using XXH*_createState() .
Start a new hash by initializing state with a seed, using XXH*_reset().
Then, feed the hash state by calling XXH*_update() as many times as necessary.
Obviously, input must be allocated and read accessible.
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
Finally, a hash value can be produced anytime, by using XXH*_digest().
This function returns the nn-bits hash as an int or long long.
It's still possible to continue inserting input into the hash state after a digest,
and generate some new hashes later on, by calling again XXH*_digest().
When done, free XXH state space if it was allocated dynamically.
*/
/*====== Canonical representation ======*/
typedef struct { unsigned char digest[4]; } XXH32_canonical_t;
XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash);
XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src);
/* Default result type for XXH functions are primitive unsigned 32 and 64 bits.
* The canonical representation uses human-readable write convention, aka big-endian (large digits first).
* These functions allow transformation of hash result into and from its canonical format.
* This way, hash values can be written into a file / memory, and remain comparable on different systems and programs.
*/
#ifndef XXH_NO_LONG_LONG
/*-**********************************************************************
* 64-bit hash
************************************************************************/
typedef unsigned long long XXH64_hash_t;
/*! XXH64() :
Calculate the 64-bit hash of sequence of length "len" stored at memory address "input".
"seed" can be used to alter the result predictably.
This function runs faster on 64-bit systems, but slower on 32-bit systems (see benchmark).
*/
XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed);
/*====== Streaming ======*/
typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */
XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void);
XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state);
XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr);
/*====== Canonical representation ======*/
typedef struct { unsigned char digest[8]; } XXH64_canonical_t;
XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash);
XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src);
#endif /* XXH_NO_LONG_LONG */
#ifdef XXH_STATIC_LINKING_ONLY
/* ================================================================================================
This section contains declarations which are not guaranteed to remain stable.
They may change in future versions, becoming incompatible with a different version of the library.
These declarations should only be used with static linking.
Never use them in association with dynamic linking !
=================================================================================================== */
/* These definitions are only meant to make possible
static allocation of XXH state, on stack or in a struct for example.
Never use members directly. */
struct XXH32_state_s {
unsigned total_len_32;
unsigned large_len;
unsigned v1;
unsigned v2;
unsigned v3;
unsigned v4;
unsigned mem32[4]; /* buffer defined as U32 for alignment */
unsigned memsize;
unsigned reserved; /* never read nor write, will be removed in a future version */
}; /* typedef'd to XXH32_state_t */
#ifndef XXH_NO_LONG_LONG /* remove 64-bit support */
struct XXH64_state_s {
unsigned long long total_len;
unsigned long long v1;
unsigned long long v2;
unsigned long long v3;
unsigned long long v4;
unsigned long long mem64[4]; /* buffer defined as U64 for alignment */
unsigned memsize;
unsigned reserved[2]; /* never read nor write, will be removed in a future version */
}; /* typedef'd to XXH64_state_t */
#endif
#ifdef XXH_PRIVATE_API
# include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */
#endif
#endif /* XXH_STATIC_LINKING_ONLY */
#if defined (__cplusplus)
}
#endif
#endif /* XXHASH_H_5627135585666179 */

View File

@ -1,56 +0,0 @@
INCLUDE output_format.ld
ENTRY(_start)
__DYNAMIC = 0;
INCLUDE regions.ld
SECTIONS
{
.text :
{
_ftext = .;
*(.text.start)
*(.text .stub .text.* .gnu.linkonce.t.*)
_etext = .;
} > rom
.rodata :
{
. = ALIGN(4);
_frodata = .;
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.rodata1)
*(.srodata)
_erodata = .;
} > rom
.data : AT (ADDR(.rodata) + SIZEOF (.rodata))
{
. = ALIGN(4);
_fdata = .;
*(.data .data.* .gnu.linkonce.d.*)
*(.data1)
*(.ramtext .ramtext.*)
_gp = ALIGN(16);
*(.sdata .sdata.* .gnu.linkonce.s.* .sdata2 .sdata2.*)
_edata = ALIGN(16); /* Make sure _edata is >= _gp. */
} > sram
.bss :
{
. = ALIGN(4);
_fbss = .;
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
_end = .;
} > sram
}
PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram) - 4);

View File

@ -1 +0,0 @@
OUTPUT_FORMAT("elf32-littleriscv")

View File

@ -1,4 +0,0 @@
MEMORY {
sram : ORIGIN = 0x10000000, LENGTH = 128k
rom : ORIGIN = 0x20000000 + 0x1a00, LENGTH = 0xc000
}

View File

@ -1,61 +0,0 @@
#include <crc.h>
#ifdef CRC16_FAST
static const unsigned int crc16_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
unsigned short crc16(const unsigned char *buffer, int len)
{
return 0;
unsigned short crc;
crc = 0;
while(len-- > 0)
crc = crc16_table[((crc >> 8) ^ (*buffer++)) & 0xFF] ^ (crc << 8);
return crc;
}
#else
unsigned short crc16(const unsigned char* data_p, int length) {
unsigned char x;
unsigned short crc = 0;
while (length--){
x = crc >> 8 ^ *data_p++;
x ^= x>>4;
crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x <<5)) ^ ((unsigned short)x);
}
return crc;
}
#endif

View File

@ -1,103 +0,0 @@
/* crc32.c -- compute the CRC-32 of a data stream
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <crc.h>
#ifdef CRC32_FAST
static const unsigned int crc_table[256] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
#define DO2(buf) DO1(buf); DO1(buf);
#define DO4(buf) DO2(buf); DO2(buf);
#define DO8(buf) DO4(buf); DO4(buf);
unsigned int crc32(const unsigned char *buffer, unsigned int len)
{
return 0;
unsigned int crc;
crc = 0;
crc = crc ^ 0xffffffffL;
while(len >= 8) {
DO8(buffer);
len -= 8;
}
if(len) do {
DO1(buffer);
} while(--len);
return crc ^ 0xffffffffL;
}
#else
unsigned int crc32(const unsigned char *message, unsigned int len) {
int j;
unsigned int i;
unsigned int byte, crc, mask;
i = 0;
crc = 0xFFFFFFFF;
while (i < len) {
byte = message[i]; // Get next byte.
crc = crc ^ byte;
for (j = 7; j >= 0; j--) { // Do eight times.
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
i = i + 1;
}
return ~crc;
}
#endif

View File

@ -1,83 +0,0 @@
.global main
.global isr
.section .text.start
.global _start
_start:
j crt_init
.word 0x032bd37d // Magic number indicating this is a valid FBM
crt_init:
la sp, _fstack + 4
la a0, trap_entry
csrw mtvec, a0
bss_init:
la a0, _fbss
la a1, _ebss
bss_loop:
beq a0,a1,bss_done
sw zero,0(a0)
add a0,a0,4
j bss_loop
bss_done:
// Load DATA section
la t0, _erodata
la t1, _fdata
la t2, _edata
3:
lw t3, 0(t0)
sw t3, 0(t1)
// _edata is aligned to 16 bytes. Use word-xfers.
addi t0, t0, 4
addi t1, t1, 4
bltu t1, t2, 3b
// 880 enable timer + external interrupt sources.
// Until mstatus.MIE is set, they will never trigger an interrupt.
li a0, 0x880
csrw mie,a0
call main
.section .ramtext
.global trap_entry
trap_entry:
sw x1, - 1*4(sp)
sw x5, - 2*4(sp)
sw x6, - 3*4(sp)
sw x7, - 4*4(sp)
sw x10, - 5*4(sp)
sw x11, - 6*4(sp)
sw x12, - 7*4(sp)
sw x13, - 8*4(sp)
sw x14, - 9*4(sp)
sw x15, -10*4(sp)
sw x16, -11*4(sp)
sw x17, -12*4(sp)
sw x28, -13*4(sp)
sw x29, -14*4(sp)
sw x30, -15*4(sp)
sw x31, -16*4(sp)
addi sp,sp,-16*4
call isr
lw x1 , 15*4(sp)
lw x5, 14*4(sp)
lw x6, 13*4(sp)
lw x7, 12*4(sp)
lw x10, 11*4(sp)
lw x11, 10*4(sp)
lw x12, 9*4(sp)
lw x13, 8*4(sp)
lw x14, 7*4(sp)
lw x15, 6*4(sp)
lw x16, 5*4(sp)
lw x17, 4*4(sp)
lw x28, 3*4(sp)
lw x29, 2*4(sp)
lw x30, 1*4(sp)
lw x31, 0*4(sp)
addi sp,sp,16*4
mret

View File

@ -1,121 +0,0 @@
.text
.align 2
#ifndef __riscv64
/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines. */
# define __udivdi3 __udivsi3
# define __umoddi3 __umodsi3
# define __divdi3 __divsi3
# define __moddi3 __modsi3
#else
.globl __udivsi3
__udivsi3:
/* Compute __udivdi3(a0 << 32, a1 << 32); cast result to uint32_t. */
sll a0, a0, 32
sll a1, a1, 32
move t0, ra
jal __udivdi3
sext.w a0, a0
jr t0
.globl __umodsi3
__umodsi3:
/* Compute __udivdi3((uint32_t)a0, (uint32_t)a1); cast a1 to uint32_t. */
sll a0, a0, 32
sll a1, a1, 32
srl a0, a0, 32
srl a1, a1, 32
move t0, ra
jal __udivdi3
sext.w a0, a1
jr t0
.globl __modsi3
__modsi3 = __moddi3
.globl __divsi3
__divsi3:
/* Check for special case of INT_MIN/-1. Otherwise, fall into __divdi3. */
li t0, -1
beq a1, t0, .L20
#endif
.globl __divdi3
__divdi3:
bltz a0, .L10
bltz a1, .L11
/* Since the quotient is positive, fall into __udivdi3. */
.globl __udivdi3
__udivdi3:
mv a2, a1
mv a1, a0
li a0, -1
beqz a2, .L5
li a3, 1
bgeu a2, a1, .L2
.L1:
blez a2, .L2
slli a2, a2, 1
slli a3, a3, 1
bgtu a1, a2, .L1
.L2:
li a0, 0
.L3:
bltu a1, a2, .L4
sub a1, a1, a2
or a0, a0, a3
.L4:
srli a3, a3, 1
srli a2, a2, 1
bnez a3, .L3
.L5:
ret
.globl __umoddi3
__umoddi3:
/* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */
move t0, ra
jal __udivdi3
move a0, a1
jr t0
/* Handle negative arguments to __divdi3. */
.L10:
neg a0, a0
bgez a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */
neg a1, a1
j __divdi3 /* Compute __udivdi3(-a0, -a1). */
.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */
neg a1, a1
.L12:
move t0, ra
jal __divdi3
neg a0, a0
jr t0
.globl __moddi3
__moddi3:
move t0, ra
bltz a1, .L31
bltz a0, .L32
.L30:
jal __udivdi3 /* The dividend is not negative. */
move a0, a1
jr t0
.L31:
neg a1, a1
bgez a0, .L30
.L32:
neg a0, a0
jal __udivdi3 /* The dividend is hella negative. */
neg a0, a1
jr t0
#ifdef __riscv64
/* continuation of __divsi3 */
.L20:
sll t0, t0, 31
bne a0, t0, __divdi3
ret
#endif

View File

@ -1,117 +0,0 @@
/* $OpenBSD: strlen.c,v 1.8 2014/06/10 04:17:37 deraadt Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*/
#include <string.h>
size_t
strlen(const char *str)
{
const char *s;
for (s = str; *s; ++s)
;
return (s - str);
}
/**
* memcpy - Copies one area of memory to another
* @dest: Destination
* @src: Source
* @n: The size to copy.
*/
void *memcpy(void *to, const void *from, size_t n)
{
void *xto = to;
size_t temp;
if(!n)
return xto;
if((long)to & 1) {
char *cto = to;
const char *cfrom = from;
*cto++ = *cfrom++;
to = cto;
from = cfrom;
n--;
}
if((long)from & 1) {
char *cto = to;
const char *cfrom = from;
for (; n; n--)
*cto++ = *cfrom++;
return xto;
}
if(n > 2 && (long)to & 2) {
short *sto = to;
const short *sfrom = from;
*sto++ = *sfrom++;
to = sto;
from = sfrom;
n -= 2;
}
if((long)from & 2) {
short *sto = to;
const short *sfrom = from;
temp = n >> 1;
for (; temp; temp--)
*sto++ = *sfrom++;
to = sto;
from = sfrom;
if(n & 1) {
char *cto = to;
const char *cfrom = from;
*cto = *cfrom;
}
return xto;
}
temp = n >> 2;
if(temp) {
long *lto = to;
const long *lfrom = from;
for(; temp; temp--)
*lto++ = *lfrom++;
to = lto;
from = lfrom;
}
if(n & 2) {
short *sto = to;
const short *sfrom = from;
*sto++ = *sfrom++;
to = sto;
from = sfrom;
}
if(n & 1) {
char *cto = to;
const char *cfrom = from;
*cto = *cfrom;
}
return xto;
}

View File

@ -1,130 +0,0 @@
#include <stdio.h>
#include <irq.h>
#include <uart.h>
#include <usb.h>
#include <time.h>
#include <rgb.h>
#include <spi.h>
#include <generated/csr.h>
struct ff_spi *spi;
__attribute__((section(".ramtext")))
void isr(void)
{
unsigned int irqs;
irqs = irq_pending() & irq_getmask();
if (irqs & (1 << USB_INTERRUPT))
usb_isr();
}
void reboot(void) {
irq_setie(0);
irq_setmask(0);
uint32_t reboot_addr = 262144;
uint32_t boot_config = 0;
// Free the SPI controller, which returns it to memory-mapped mode.
spiFree();
// Scan for configuration data.
int i;
int riscv_boot = 1;
uint32_t *destination_array = (uint32_t *)reboot_addr;
reboot_addr_write(reboot_addr);
for (i = 0; i < 32; i++) {
// Look for FPGA sync pulse.
if ((destination_array[i] == 0x7e99aa7e)
|| (destination_array[i] == 0x7eaa997e)) {
riscv_boot = 0;
break;
}
// Look for "boot config" word
else if (destination_array[i] == 0xb469075a) {
boot_config = destination_array[i + 1];
}
}
// If requested, just let USB be idle. Otherwise, reset it.
if (boot_config & 0x00000020) // NO_USB_RESET
usb_idle();
else
usb_disconnect();
// Figure out what mode to put SPI flash into.
if (boot_config & 0x00000001) { // QPI_EN
spiEnableQuad();
picorvspi_cfg3_write(picorvspi_cfg3_read() | 0x20);
}
if (boot_config & 0x00000002) // DDR_EN
picorvspi_cfg3_write(picorvspi_cfg3_read() | 0x40);
if (boot_config & 0x00000002) // CFM_EN
picorvspi_cfg3_write(picorvspi_cfg3_read() | 0x10);
rgb_mode_error();
// Vexriscv requires three extra nop cycles to flush the cache.
if (boot_config & 0x00000010) { // FLUSH_CACHE
asm("fence.i");
asm("nop");
asm("nop");
asm("nop");
}
if (riscv_boot) {
// Reset the Return Address, zero out some registers, and return.
asm volatile(
"mv ra,%0\n\t" /* x1 */
"mv sp,zero\n\t" /* x2 */
"mv gp,zero\n\t" /* x3 */
"mv tp,zero\n\t" /* x4 */
"mv t0,zero\n\t" /* x5 */
"mv t1,zero\n\t" /* x6 */
"mv t2,zero\n\t" /* x7 */
"mv x8,zero\n\t" /* x8 */
"mv s1,zero\n\t" /* x9 */
"mv a0,zero\n\t" /* x10 */
"mv a1,zero\n\t" /* x11 */
"ret\n\t"
:
: "r"(reboot_addr)
);
}
else {
// Issue a reboot
warmboot_to_image(2);
}
__builtin_unreachable();
}
static void init(void)
{
#ifdef CSR_UART_BASE
init_printf(NULL, rv_putchar);
#endif
irq_setmask(0);
irq_setie(1);
uart_init();
usb_init();
time_init();
rgb_init();
}
__attribute__((section(".ramtext")))
int main(int argc, char **argv)
{
(void)argc;
(void)argv;
init();
usb_connect();
while (1)
{
usb_poll();
}
return 0;
}

View File

@ -1,26 +0,0 @@
.text
.align 2
#ifdef __riscv64
#define _RISCV_SZPTR 64
#define _RISCV_SZINT 64
#else
/* Our RV64 64-bit routine is equivalent to our RV32 32-bit routine. */
# define __muldi3 __mulsi3
#define _RISCV_SZPTR 32
#define _RISCV_SZINT 32
#endif
.globl __muldi3
__muldi3:
mv a2, a0
li a0, 0
.L1:
slli a3, a1, _RISCV_SZPTR-1
bgez a3, .L2
add a0, a0, a2
.L2:
srli a1, a1, 1
slli a2, a2, 1
bnez a1, .L1
ret

View File

@ -1,215 +0,0 @@
/****************************************************************************
* lib/stdlib/lib_qsort.c
*
* Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Leveraged from:
*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
****************************************************************************/
#include <stdlib.h>
#define min(a, b) ((unsigned)(a)) < (((unsigned)(b))) ? ((unsigned)(a)) : ((unsigned)(b))
#define swapcode(TYPE, parmi, parmj, n) \
{ \
long i = (n) / sizeof (TYPE); \
register TYPE *pi = (TYPE *) (parmi); \
register TYPE *pj = (TYPE *) (parmj); \
do { \
register TYPE t = *pi; \
*pi++ = *pj; \
*pj++ = t; \
} while (--i > 0); \
}
#define SWAPINIT(a, size) \
swaptype = ((char *)a - (char *)0) % sizeof(long) || \
size % sizeof(long) ? 2 : size == sizeof(long)? 0 : 1;
#define swap(a, b) \
if (swaptype == 0) \
{ \
long t = *(long *)(a); \
*(long *)(a) = *(long *)(b); \
*(long *)(b) = t; \
} \
else \
{ \
swapfunc(a, b, size, swaptype); \
}
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
static inline void swapfunc(char *a, char *b, int n, int swaptype);
static inline char *med3(char *a, char *b, char *c,
int (*compar)(const void *, const void *));
static inline void swapfunc(char *a, char *b, int n, int swaptype)
{
if(swaptype <= 1)
{
swapcode(long, a, b, n)
}
else
{
swapcode(char, a, b, n)
}
}
static inline char *med3(char *a, char *b, char *c,
int (*compar)(const void *, const void *))
{
return compar(a, b) < 0 ?
(compar(b, c) < 0 ? b : (compar(a, c) < 0 ? c : a ))
:(compar(b, c) > 0 ? b : (compar(a, c) < 0 ? a : c ));
}
/****************************************************************************
* Name: qsort
*
* Description:
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
*
****************************************************************************/
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *))
{
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
int d, r, swaptype, swap_cnt;
loop:
SWAPINIT(base, size);
swap_cnt = 0;
if (nmemb < 7)
{
for (pm = (char *) base + size; pm < (char *) base + nmemb * size; pm += size)
{
for (pl = pm; pl > (char *) base && compar(pl - size, pl) > 0; pl -= size)
{
swap(pl, pl - size);
}
}
return;
}
pm = (char *) base + (nmemb / 2) * size;
if (nmemb > 7)
{
pl = base;
pn = (char *) base + (nmemb - 1) * size;
if (nmemb > 40)
{
d = (nmemb / 8) * size;
pl = med3(pl, pl + d, pl + 2 * d, compar);
pm = med3(pm - d, pm, pm + d, compar);
pn = med3(pn - 2 * d, pn - d, pn, compar);
}
pm = med3(pl, pm, pn, compar);
}
swap(base, pm);
pa = pb = (char *) base + size;
pc = pd = (char *) base + (nmemb - 1) * size;
for (;;)
{
while (pb <= pc && (r = compar(pb, base)) <= 0)
{
if (r == 0)
{
swap_cnt = 1;
swap(pa, pb);
pa += size;
}
pb += size;
}
while (pb <= pc && (r = compar(pc, base)) >= 0)
{
if (r == 0)
{
swap_cnt = 1;
swap(pc, pd);
pd -= size;
}
pc -= size;
}
if (pb > pc)
{
break;
}
swap(pb, pc);
swap_cnt = 1;
pb += size;
pc -= size;
}
if (swap_cnt == 0)
{
/* Switch to insertion sort */
for (pm = (char *) base + size; pm < (char *) base + nmemb * size; pm += size)
{
for (pl = pm; pl > (char *) base && compar(pl - size, pl) > 0; pl -= size)
{
swap(pl, pl - size);
}
}
return;
}
pn = (char *) base + nmemb * size;
r = min(pa - (char *)base, pb - pa);
vecswap(base, pb - r, r);
r = min(pd - pc, pn - pd - size);
vecswap(pb, pn - r, r);
if ((r = pb - pa) > (int)size)
{
qsort(base, r / size, size, compar);
}
if ((r = pd - pc) > (int)size)
{
/* Iterate rather than recurse to save stack space */
base = pn - r;
nmemb = r / size;
goto loop;
}
}

View File

@ -1,89 +0,0 @@
#include <rgb.h>
#include <generated/csr.h>
enum led_registers {
LEDDCR0 = 8,
LEDDBR = 9,
LEDDONR = 10,
LEDDOFR = 11,
LEDDBCRR = 5,
LEDDBCFR = 6,
LEDDPWRR = 1,
LEDDPWRG = 2,
LEDDPWRB = 3,
};
#define BREATHE_ENABLE (1 << 7)
#define BREATHE_EDGE_ON (0 << 6)
#define BREATHE_EDGE_BOTH (1 << 6)
#define BREATHE_MODE_MODULATE (1 << 5)
#define BREATHE_RATE(x) ((x & 7) << 0)
#define RGB_SWITCH_MODE(x) do { \
if (rgb_mode == x) \
return; \
rgb_mode = x; \
/* Toggle LEDD_EXE to force the mode to switch */ \
rgb_ctrl_write( (1 << 1) | (1 << 2)); \
rgb_ctrl_write((1 << 0) | (1 << 1) | (1 << 2)); \
} while(0)
static enum {
INVALID = 0,
IDLE,
WRITING,
ERROR,
DONE,
} rgb_mode;
static void rgb_write(uint8_t value, uint8_t addr) {
rgb_addr_write(addr);
rgb_dat_write(value);
}
void rgb_init(void) {
// Turn on the RGB block and current enable, as well as enabling led control
rgb_ctrl_write((1 << 0) | (1 << 1) | (1 << 2));
// Enable the LED driver, and set 250 Hz mode.
// Also set quick stop, which we'll use to switch patterns quickly.
rgb_write((1 << 7) | (1 << 6) | (1 << 3), LEDDCR0);
// Set clock register to 12 MHz / 64 kHz - 1
rgb_write((12000000/64000)-1, LEDDBR);
rgb_mode_idle();
}
static void rgb_switch_mode(uint8_t mode,
uint8_t onr, uint8_t ofr,
uint8_t onrate, uint8_t offrate,
uint8_t r, uint8_t g, uint8_t b) {
RGB_SWITCH_MODE(mode);
rgb_write(onr, LEDDONR);
rgb_write(ofr, LEDDOFR);
rgb_write(BREATHE_ENABLE | BREATHE_EDGE_BOTH
| BREATHE_MODE_MODULATE | BREATHE_RATE(onrate), LEDDBCRR);
rgb_write(BREATHE_ENABLE | BREATHE_MODE_MODULATE | BREATHE_RATE(offrate), LEDDBCFR);
rgb_write(r, LEDDPWRG); // Red
rgb_write(g, LEDDPWRB); // Green
rgb_write(b, LEDDPWRR); // Blue
}
void rgb_mode_idle(void) {
rgb_switch_mode(IDLE, 18, 5, 20, 3, 0x00/4, 0x7a/4, 0x31/4);
}
void rgb_mode_writing(void) {
rgb_switch_mode(WRITING, 1, 2, 1, 3, 0x00/4, 0x7a/4, 0x51/4);
}
void rgb_mode_error(void) {
rgb_switch_mode(ERROR, 3, 3, 2, 3, 0xf0/4, 0x0a/4, 0x01/4);
}
void rgb_mode_done(void) {
rgb_switch_mode(DONE, 8, 8, 2, 3, 0x14/4, 0xff/4, 0x44/4);
}

View File

@ -1,824 +0,0 @@
#include <stdint.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <generated/csr.h>
#include "spi.h"
#define fprintf(...) do {} while(0)
static uint8_t do_mirror;
static uint8_t oe_mirror;
#define PI_OUTPUT 1
#define PI_INPUT 0
#define PI_ALT0 PI_INPUT
static void gpioSetMode(int pin, int mode) {
if (mode)
oe_mirror |= 1 << pin;
else
oe_mirror &= ~(1 << pin);
picorvspi_cfg2_write(oe_mirror);
}
static void gpioWrite(int pin, int val) {
if (val)
do_mirror |= 1 << pin;
else
do_mirror &= ~(1 << pin);
picorvspi_cfg1_write(do_mirror);
}
static int gpioRead(int pin) {
return !!(picorvspi_stat1_read() & (1 << pin));
}
static void gpioSync(void) {
// bbspi_do_write(do_mirror);
}
#define SPI_ONLY_SINGLE
enum ff_spi_quirks {
// There is no separate "Write SR 2" command. Instead,
// you must write SR2 after writing SR1
SQ_SR2_FROM_SR1 = (1 << 0),
// Don't issue a "Write Enable" command prior to writing
// a status register
SQ_SKIP_SR_WEL = (1 << 1),
// Security registers are shifted up by 4 bits
SQ_SECURITY_NYBBLE_SHIFT = (1 << 2),
};
struct ff_spi {
enum spi_state state;
enum spi_type type;
enum spi_type desired_type;
struct spi_id id;
enum ff_spi_quirks quirks;
int size_override;
struct {
int clk;
int d0;
int d1;
int d2;
int d3;
int wp;
int hold;
int cs;
int miso;
int mosi;
} pins;
};
static void spi_get_id(struct ff_spi *spi);
static void spi_set_state(struct ff_spi *spi, enum spi_state state) {
return;
if (spi->state == state)
return;
#ifndef SPI_ONLY_SINGLE
switch (state) {
case SS_SINGLE:
#endif
gpioSetMode(spi->pins.clk, PI_OUTPUT); // CLK
gpioSetMode(spi->pins.cs, PI_OUTPUT); // CE0#
gpioSetMode(spi->pins.mosi, PI_OUTPUT); // MOSI
gpioSetMode(spi->pins.miso, PI_INPUT); // MISO
gpioSetMode(spi->pins.hold, PI_OUTPUT);
gpioSetMode(spi->pins.wp, PI_OUTPUT);
#ifndef SPI_ONLY_SINGLE
break;
case SS_DUAL_RX:
gpioSetMode(spi->pins.clk, PI_OUTPUT); // CLK
gpioSetMode(spi->pins.cs, PI_OUTPUT); // CE0#
gpioSetMode(spi->pins.mosi, PI_INPUT); // MOSI
gpioSetMode(spi->pins.miso, PI_INPUT); // MISO
gpioSetMode(spi->pins.hold, PI_OUTPUT);
gpioSetMode(spi->pins.wp, PI_OUTPUT);
break;
case SS_DUAL_TX:
gpioSetMode(spi->pins.clk, PI_OUTPUT); // CLK
gpioSetMode(spi->pins.cs, PI_OUTPUT); // CE0#
gpioSetMode(spi->pins.mosi, PI_OUTPUT); // MOSI
gpioSetMode(spi->pins.miso, PI_OUTPUT); // MISO
gpioSetMode(spi->pins.hold, PI_OUTPUT);
gpioSetMode(spi->pins.wp, PI_OUTPUT);
break;
case SS_QUAD_RX:
gpioSetMode(spi->pins.clk, PI_OUTPUT); // CLK
gpioSetMode(spi->pins.cs, PI_OUTPUT); // CE0#
gpioSetMode(spi->pins.mosi, PI_INPUT); // MOSI
gpioSetMode(spi->pins.miso, PI_INPUT); // MISO
gpioSetMode(spi->pins.hold, PI_INPUT);
gpioSetMode(spi->pins.wp, PI_INPUT);
break;
case SS_QUAD_TX:
gpioSetMode(spi->pins.clk, PI_OUTPUT); // CLK
gpioSetMode(spi->pins.cs, PI_OUTPUT); // CE0#
gpioSetMode(spi->pins.mosi, PI_OUTPUT); // MOSI
gpioSetMode(spi->pins.miso, PI_OUTPUT); // MISO
gpioSetMode(spi->pins.hold, PI_OUTPUT);
gpioSetMode(spi->pins.wp, PI_OUTPUT);
break;
case SS_HARDWARE:
gpioSetMode(spi->pins.clk, PI_ALT0); // CLK
gpioSetMode(spi->pins.cs, PI_ALT0); // CE0#
gpioSetMode(spi->pins.mosi, PI_ALT0); // MOSI
gpioSetMode(spi->pins.miso, PI_ALT0); // MISO
gpioSetMode(spi->pins.hold, PI_OUTPUT);
gpioSetMode(spi->pins.wp, PI_OUTPUT);
break;
default:
fprintf(stderr, "Unrecognized spi state\n");
return;
}
#endif
spi->state = state;
}
void spiPause(struct ff_spi *spi) {
(void)spi;
gpioSync();
// usleep(1);
return;
}
void spiBegin(struct ff_spi *spi) {
spi_set_state(spi, SS_SINGLE);
if ((spi->type == ST_SINGLE) || (spi->type == ST_DUAL)) {
gpioWrite(spi->pins.wp, 1);
gpioWrite(spi->pins.hold, 1);
}
gpioWrite(spi->pins.cs, 0);
}
void spiEnd(struct ff_spi *spi) {
(void)spi;
gpioWrite(spi->pins.cs, 1);
}
static uint8_t spiXfer(struct ff_spi *spi, uint8_t out) {
int bit;
uint8_t in = 0;
for (bit = 7; bit >= 0; bit--) {
if (out & (1 << bit)) {
gpioWrite(spi->pins.mosi, 1);
}
else {
gpioWrite(spi->pins.mosi, 0);
}
gpioWrite(spi->pins.clk, 1);
spiPause(spi);
in |= ((!!gpioRead(spi->pins.miso)) << bit);
gpioWrite(spi->pins.clk, 0);
spiPause(spi);
}
return in;
}
static void spiSingleTx(struct ff_spi *spi, uint8_t out) {
spi_set_state(spi, SS_SINGLE);
spiXfer(spi, out);
}
static uint8_t spiSingleRx(struct ff_spi *spi) {
spi_set_state(spi, SS_SINGLE);
return spiXfer(spi, 0xff);
}
static void spiDualTx(struct ff_spi *spi, uint8_t out) {
int bit;
spi_set_state(spi, SS_DUAL_TX);
for (bit = 7; bit >= 0; bit -= 2) {
if (out & (1 << (bit - 1))) {
gpioWrite(spi->pins.d0, 1);
}
else {
gpioWrite(spi->pins.d0, 0);
}
if (out & (1 << (bit - 0))) {
gpioWrite(spi->pins.d1, 1);
}
else {
gpioWrite(spi->pins.d1, 0);
}
gpioWrite(spi->pins.clk, 1);
spiPause(spi);
gpioWrite(spi->pins.clk, 0);
spiPause(spi);
}
}
static void spiQuadTx(struct ff_spi *spi, uint8_t out) {
int bit;
spi_set_state(spi, SS_QUAD_TX);
for (bit = 7; bit >= 0; bit -= 4) {
if (out & (1 << (bit - 3))) {
gpioWrite(spi->pins.d0, 1);
}
else {
gpioWrite(spi->pins.d0, 0);
}
if (out & (1 << (bit - 2))) {
gpioWrite(spi->pins.d1, 1);
}
else {
gpioWrite(spi->pins.d1, 0);
}
if (out & (1 << (bit - 1))) {
gpioWrite(spi->pins.d2, 1);
}
else {
gpioWrite(spi->pins.d2, 0);
}
if (out & (1 << (bit - 0))) {
gpioWrite(spi->pins.d3, 1);
}
else {
gpioWrite(spi->pins.d3, 0);
}
gpioWrite(spi->pins.clk, 1);
spiPause(spi);
gpioWrite(spi->pins.clk, 0);
spiPause(spi);
}
}
static uint8_t spiDualRx(struct ff_spi *spi) {
int bit;
uint8_t in = 0;
spi_set_state(spi, SS_QUAD_RX);
for (bit = 7; bit >= 0; bit -= 2) {
gpioWrite(spi->pins.clk, 1);
spiPause(spi);
in |= ((!!gpioRead(spi->pins.d0)) << (bit - 1));
in |= ((!!gpioRead(spi->pins.d1)) << (bit - 0));
gpioWrite(spi->pins.clk, 0);
spiPause(spi);
}
return in;
}
static uint8_t spiQuadRx(struct ff_spi *spi) {
int bit;
uint8_t in = 0;
spi_set_state(spi, SS_QUAD_RX);
for (bit = 7; bit >= 0; bit -= 4) {
gpioWrite(spi->pins.clk, 1);
spiPause(spi);
in |= ((!!gpioRead(spi->pins.d0)) << (bit - 3));
in |= ((!!gpioRead(spi->pins.d1)) << (bit - 2));
in |= ((!!gpioRead(spi->pins.d2)) << (bit - 1));
in |= ((!!gpioRead(spi->pins.d3)) << (bit - 0));
gpioWrite(spi->pins.clk, 0);
spiPause(spi);
}
return in;
}
int spiTx(struct ff_spi *spi, uint8_t word) {
switch (spi->type) {
case ST_SINGLE:
spiSingleTx(spi, word);
break;
case ST_DUAL:
spiDualTx(spi, word);
break;
case ST_QUAD:
case ST_QPI:
spiQuadTx(spi, word);
break;
default:
return -1;
}
return 0;
}
uint8_t spiRx(struct ff_spi *spi) {
switch (spi->type) {
case ST_SINGLE:
return spiSingleRx(spi);
case ST_DUAL:
return spiDualRx(spi);
case ST_QUAD:
case ST_QPI:
return spiQuadRx(spi);
default:
return 0xff;
}
}
void spiCommand(struct ff_spi *spi, uint8_t cmd) {
if (spi->type == ST_QPI)
spiQuadTx(spi, cmd);
else
spiSingleTx(spi, cmd);
}
uint8_t spiCommandRx(struct ff_spi *spi) {
if (spi->type == ST_QPI)
return spiQuadRx(spi);
else
return spiSingleRx(spi);
}
uint8_t spiReadStatus(struct ff_spi *spi, uint8_t sr) {
uint8_t val = 0xff;
(void)sr;
#if 0
switch (sr) {
case 1:
#endif
spiBegin(spi);
spiCommand(spi, 0x05);
val = spiCommandRx(spi);
spiEnd(spi);
#if 0
break;
case 2:
spiBegin(spi);
spiCommand(spi, 0x35);
val = spiCommandRx(spi);
spiEnd(spi);
break;
case 3:
spiBegin(spi);
spiCommand(spi, 0x15);
val = spiCommandRx(spi);
spiEnd(spi);
break;
default:
fprintf(stderr, "unrecognized status register: %d\n", sr);
break;
}
#endif
return val;
}
void spiWriteSecurity(struct ff_spi *spi, uint8_t sr, uint8_t security[256]) {
if (spi->quirks & SQ_SECURITY_NYBBLE_SHIFT)
sr <<= 4;
spiBegin(spi);
spiCommand(spi, 0x06);
spiEnd(spi);
// erase the register
spiBegin(spi);
spiCommand(spi, 0x44);
spiCommand(spi, 0x00); // A23-16
spiCommand(spi, sr); // A15-8
spiCommand(spi, 0x00); // A0-7
spiEnd(spi);
spi_get_id(spi);
sleep(1);
// write enable
spiBegin(spi);
spiCommand(spi, 0x06);
spiEnd(spi);
spiBegin(spi);
spiCommand(spi, 0x42);
spiCommand(spi, 0x00); // A23-16
spiCommand(spi, sr); // A15-8
spiCommand(spi, 0x00); // A0-7
int i;
for (i = 0; i < 256; i++)
spiCommand(spi, security[i]);
spiEnd(spi);
spi_get_id(spi);
}
void spiReadSecurity(struct ff_spi *spi, uint8_t sr, uint8_t security[256]) {
if (spi->quirks & SQ_SECURITY_NYBBLE_SHIFT)
sr <<= 4;
spiBegin(spi);
spiCommand(spi, 0x48); // Read security registers
spiCommand(spi, 0x00); // A23-16
spiCommand(spi, sr); // A15-8
spiCommand(spi, 0x00); // A0-7
int i;
for (i = 0; i < 256; i++)
security[i] = spiCommandRx(spi);
spiEnd(spi);
}
void spiWriteStatus(struct ff_spi *spi, uint8_t sr, uint8_t val) {
switch (sr) {
case 1:
if (!(spi->quirks & SQ_SKIP_SR_WEL)) {
spiBegin(spi);
spiCommand(spi, 0x06);
spiEnd(spi);
}
spiBegin(spi);
spiCommand(spi, 0x50);
spiEnd(spi);
spiBegin(spi);
spiCommand(spi, 0x01);
spiCommand(spi, val);
spiEnd(spi);
break;
case 2: {
uint8_t sr1 = 0x00;
if (spi->quirks & SQ_SR2_FROM_SR1)
sr1 = spiReadStatus(spi, 1);
if (!(spi->quirks & SQ_SKIP_SR_WEL)) {
spiBegin(spi);
spiCommand(spi, 0x06);
spiEnd(spi);
}
spiBegin(spi);
spiCommand(spi, 0x50);
spiEnd(spi);
spiBegin(spi);
if (spi->quirks & SQ_SR2_FROM_SR1) {
spiCommand(spi, 0x01);
spiCommand(spi, sr1);
spiCommand(spi, val);
}
else {
spiCommand(spi, 0x31);
spiCommand(spi, val);
}
spiEnd(spi);
break;
}
case 3:
if (!(spi->quirks & SQ_SKIP_SR_WEL)) {
spiBegin(spi);
spiCommand(spi, 0x06);
spiEnd(spi);
}
spiBegin(spi);
spiCommand(spi, 0x50);
spiEnd(spi);
spiBegin(spi);
spiCommand(spi, 0x11);
spiCommand(spi, val);
spiEnd(spi);
break;
default:
fprintf(stderr, "unrecognized status register: %d\n", sr);
break;
}
}
#if 0
struct spi_id spiId(struct ff_spi *spi) {
return spi->id;
}
static void spi_decode_id(struct ff_spi *spi) {
spi->id.bytes = -1; // unknown
if (spi->id.manufacturer_id == 0xef) {
// spi->id.manufacturer = "Winbond";
if ((spi->id.memory_type == 0x70)
&& (spi->id.memory_size == 0x18)) {
// spi->id.model = "W25Q128JV";
// spi->id.capacity = "128 Mbit";
spi->id.bytes = 16 * 1024 * 1024;
}
}
if (spi->id.manufacturer_id == 0x1f) {
// spi->id.manufacturer = "Adesto";
if ((spi->id.memory_type == 0x86)
&& (spi->id.memory_size == 0x01)) {
// spi->id.model = "AT25SF161";
// spi->id.capacity = "16 Mbit";
spi->id.bytes = 1 * 1024 * 1024;
}
}
return;
}
#endif
static void spi_get_id(struct ff_spi *spi) {
spiBegin(spi);
spiCommand(spi, 0x90); // Read manufacturer ID
spiCommand(spi, 0x00); // Dummy byte 1
spiCommand(spi, 0x00); // Dummy byte 2
spiCommand(spi, 0x00); // Dummy byte 3
spi->id.manufacturer_id = spiCommandRx(spi);
spi->id.device_id = spiCommandRx(spi);
spiEnd(spi);
return;
#if 0
spiBegin(spi);
spiCommand(spi, 0x9f); // Read device id
spi->id._manufacturer_id = spiCommandRx(spi);
spi->id.memory_type = spiCommandRx(spi);
spi->id.memory_size = spiCommandRx(spi);
spiEnd(spi);
spiBegin(spi);
spiCommand(spi, 0xab); // Read electronic signature
spiCommand(spi, 0x00); // Dummy byte 1
spiCommand(spi, 0x00); // Dummy byte 2
spiCommand(spi, 0x00); // Dummy byte 3
spi->id.signature = spiCommandRx(spi);
spiEnd(spi);
spiBegin(spi);
spiCommand(spi, 0x4b); // Read unique ID
spiCommand(spi, 0x00); // Dummy byte 1
spiCommand(spi, 0x00); // Dummy byte 2
spiCommand(spi, 0x00); // Dummy byte 3
spiCommand(spi, 0x00); // Dummy byte 4
spi->id.serial[0] = spiCommandRx(spi);
spi->id.serial[1] = spiCommandRx(spi);
spi->id.serial[2] = spiCommandRx(spi);
spi->id.serial[3] = spiCommandRx(spi);
spiEnd(spi);
spi_decode_id(spi);
return;
#endif
}
#if 0
void spiOverrideSize(struct ff_spi *spi, uint32_t size) {
spi->size_override = size;
// If size is 0, re-read the capacity
if (!size)
spi_decode_id(spi);
else
spi->id.bytes = size;
}
#endif
int spiSetType(struct ff_spi *spi, enum spi_type type) {
if (spi->type == type)
return 0;
#ifndef SPI_ONLY_SINGLE
switch (type) {
case ST_SINGLE:
#endif
if (spi->type == ST_QPI) {
spiBegin(spi);
spiCommand(spi, 0xff); // Exit QPI Mode
spiEnd(spi);
}
spi->type = type;
spi_set_state(spi, SS_SINGLE);
#ifndef SPI_ONLY_SINGLE
break;
case ST_DUAL:
if (spi->type == ST_QPI) {
spiBegin(spi);
spiCommand(spi, 0xff); // Exit QPI Mode
spiEnd(spi);
}
spi->type = type;
spi_set_state(spi, SS_DUAL_TX);
break;
case ST_QUAD:
if (spi->type == ST_QPI) {
spiBegin(spi);
spiCommand(spi, 0xff); // Exit QPI Mode
spiEnd(spi);
}
// Enable QE bit
spiWriteStatus(spi, 2, spiReadStatus(spi, 2) | (1 << 1));
spi->type = type;
spi_set_state(spi, SS_QUAD_TX);
break;
case ST_QPI:
// Enable QE bit
spiWriteStatus(spi, 2, spiReadStatus(spi, 2) | (1 << 1));
spiBegin(spi);
spiCommand(spi, 0x38); // Enter QPI Mode
spiEnd(spi);
spi->type = type;
spi_set_state(spi, SS_QUAD_TX);
break;
default:
fprintf(stderr, "Unrecognized SPI type: %d\n", type);
return 1;
}
#endif
return 0;
}
int spiIsBusy(struct ff_spi *spi) {
return spiReadStatus(spi, 1) & (1 << 0);
}
int spiBeginErase32(struct ff_spi *spi, uint32_t erase_addr) {
// Enable Write-Enable Latch (WEL)
spiBegin(spi);
spiCommand(spi, 0x06);
spiEnd(spi);
spiBegin(spi);
spiCommand(spi, 0x52);
spiCommand(spi, erase_addr >> 16);
spiCommand(spi, erase_addr >> 8);
spiCommand(spi, erase_addr >> 0);
spiEnd(spi);
return 0;
}
int spiBeginErase64(struct ff_spi *spi, uint32_t erase_addr) {
// Enable Write-Enable Latch (WEL)
spiBegin(spi);
spiCommand(spi, 0x06);
spiEnd(spi);
spiBegin(spi);
spiCommand(spi, 0xD8);
spiCommand(spi, erase_addr >> 16);
spiCommand(spi, erase_addr >> 8);
spiCommand(spi, erase_addr >> 0);
spiEnd(spi);
return 0;
}
int spiBeginWrite(struct ff_spi *spi, uint32_t addr, const void *v_data, unsigned int count) {
const uint8_t write_cmd = 0x02;
const uint8_t *data = v_data;
unsigned int i;
// Enable Write-Enable Latch (WEL)
spiBegin(spi);
spiCommand(spi, 0x06);
spiEnd(spi);
// uint8_t sr1 = spiReadStatus(spi, 1);
// if (!(sr1 & (1 << 1)))
// fprintf(stderr, "error: write-enable latch (WEL) not set, write will probably fail\n");
spiBegin(spi);
spiCommand(spi, write_cmd);
spiCommand(spi, addr >> 16);
spiCommand(spi, addr >> 8);
spiCommand(spi, addr >> 0);
for (i = 0; (i < count) && (i < 256); i++)
spiTx(spi, *data++);
spiEnd(spi);
return 0;
}
uint8_t spiReset(struct ff_spi *spi) {
// XXX You should check the "Ready" bit before doing this!
// Shift to QPI mode, then back to Single mode, to ensure
// we're actually in Single mode.
spiSetType(spi, ST_QPI);
spiSetType(spi, ST_SINGLE);
spiBegin(spi);
spiCommand(spi, 0x66); // "Enable Reset" command
spiEnd(spi);
spiBegin(spi);
spiCommand(spi, 0x99); // "Reset Device" command
spiEnd(spi);
// msleep(30);
spiBegin(spi);
spiCommand(spi, 0xab); // "Resume from Deep Power-Down" command
spiEnd(spi);
return 0;
}
int spiInit(struct ff_spi *spi) {
spi->state = SS_UNCONFIGURED;
spi->type = ST_UNCONFIGURED;
// Disable memory-mapped mode and enable bit-bang mode
picorvspi_cfg4_write(0);
// Reset the SPI flash, which will return it to SPI mode even
// if it's in QPI mode.
spiReset(spi);
spiSetType(spi, ST_SINGLE);
// Have the SPI flash pay attention to us
gpioWrite(spi->pins.hold, 1);
// Disable WP
gpioWrite(spi->pins.wp, 1);
gpioSetMode(spi->pins.clk, PI_OUTPUT); // CLK
gpioSetMode(spi->pins.cs, PI_OUTPUT); // CE0#
gpioSetMode(spi->pins.mosi, PI_OUTPUT); // MOSI
gpioSetMode(spi->pins.miso, PI_INPUT); // MISO
gpioSetMode(spi->pins.hold, PI_OUTPUT);
gpioSetMode(spi->pins.wp, PI_OUTPUT);
spi_get_id(spi);
spi->quirks |= SQ_SR2_FROM_SR1;
if (spi->id.manufacturer_id == 0xef)
spi->quirks |= SQ_SKIP_SR_WEL | SQ_SECURITY_NYBBLE_SHIFT;
return 0;
}
void spiEnableQuad(void) {
struct ff_spi *spi = spiAlloc();
spiInit(spi);
spiWriteStatus(spi, 2, spiReadStatus(spi, 2) | (1 << 1));
spiFree();
}
struct ff_spi *spiAlloc(void) {
static struct ff_spi spi;
return &spi;
}
void spiSetPin(struct ff_spi *spi, enum spi_pin pin, int val) {
switch (pin) {
case SP_MOSI: spi->pins.mosi = val; break;
case SP_MISO: spi->pins.miso = val; break;
case SP_HOLD: spi->pins.hold = val; break;
case SP_WP: spi->pins.wp = val; break;
case SP_CS: spi->pins.cs = val; break;
case SP_CLK: spi->pins.clk = val; break;
case SP_D0: spi->pins.d0 = val; break;
case SP_D1: spi->pins.d1 = val; break;
case SP_D2: spi->pins.d2 = val; break;
case SP_D3: spi->pins.d3 = val; break;
default: fprintf(stderr, "unrecognized pin: %d\n", pin); break;
}
}
void spiHold(struct ff_spi *spi) {
spiBegin(spi);
spiCommand(spi, 0xb9);
spiEnd(spi);
}
void spiUnhold(struct ff_spi *spi) {
spiBegin(spi);
spiCommand(spi, 0xab);
spiEnd(spi);
}
void spiFree(void) {
// Re-enable memory-mapped mode
picorvspi_cfg4_write(0x80);
}

View File

@ -1,43 +0,0 @@
#include <generated/csr.h>
#include <time.h>
void time_init(void)
{
int t;
timer0_en_write(0);
t = 2*SYSTEM_CLOCK_FREQUENCY;
timer0_reload_write(t);
timer0_load_write(t);
timer0_en_write(1);
}
int elapsed(int *last_event, int period)
{
int t, dt;
timer0_update_value_write(1);
t = timer0_reload_read() - timer0_value_read();
if(period < 0) {
*last_event = t;
return 1;
}
dt = t - *last_event;
if(dt < 0)
dt += timer0_reload_read();
if((dt > period) || (dt < 0)) {
*last_event = t;
return 1;
} else
return 0;
}
void msleep(int ms)
{
timer0_en_write(0);
timer0_reload_write(0);
timer0_load_write(SYSTEM_CLOCK_FREQUENCY/1000*ms);
timer0_en_write(1);
timer0_update_value_write(1);
while(timer0_value_read()) timer0_update_value_write(1);
}

View File

@ -1,115 +0,0 @@
#include <uart.h>
#include <irq.h>
#include <generated/csr.h>
#include <hw/flags.h>
#ifdef CSR_UART_BASE
/*
* Buffer sizes must be a power of 2 so that modulos can be computed
* with logical AND.
*/
#define UART_RINGBUFFER_SIZE_RX 128
#define UART_RINGBUFFER_MASK_RX (UART_RINGBUFFER_SIZE_RX-1)
static char rx_buf[UART_RINGBUFFER_SIZE_RX];
static volatile unsigned int rx_produce;
static unsigned int rx_consume;
#define UART_RINGBUFFER_SIZE_TX 128
#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1)
static char tx_buf[UART_RINGBUFFER_SIZE_TX];
static unsigned int tx_produce;
static volatile unsigned int tx_consume;
void uart_isr(void)
{
unsigned int stat, rx_produce_next;
stat = uart_ev_pending_read();
if(stat & UART_EV_RX) {
while(!uart_rxempty_read()) {
rx_produce_next = (rx_produce + 1) & UART_RINGBUFFER_MASK_RX;
if(rx_produce_next != rx_consume) {
rx_buf[rx_produce] = uart_rxtx_read();
rx_produce = rx_produce_next;
}
uart_ev_pending_write(UART_EV_RX);
}
}
if(stat & UART_EV_TX) {
uart_ev_pending_write(UART_EV_TX);
while((tx_consume != tx_produce) && !uart_txfull_read()) {
uart_rxtx_write(tx_buf[tx_consume]);
tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX;
}
}
}
/* Do not use in interrupt handlers! */
char uart_read(void)
{
char c;
if (irq_getie()) {
while (rx_consume == rx_produce);
} else if (rx_consume == rx_produce) {
return 0;
}
c = rx_buf[rx_consume];
rx_consume = (rx_consume + 1) & UART_RINGBUFFER_MASK_RX;
return c;
}
int uart_read_nonblock(void)
{
return (rx_consume != rx_produce);
}
void uart_write(char c)
{
unsigned int oldmask;
unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX;
if (irq_getie()) {
while(tx_produce_next == tx_consume);
} else if(tx_produce_next == tx_consume) {
return;
}
oldmask = irq_getmask();
irq_setmask(oldmask & ~(1 << UART_INTERRUPT));
if ((tx_consume != tx_produce) || uart_txfull_read()) {
tx_buf[tx_produce] = c;
tx_produce = tx_produce_next;
} else {
uart_rxtx_write(c);
}
irq_setmask(oldmask);
}
void uart_init(void)
{
rx_produce = 0;
rx_consume = 0;
tx_produce = 0;
tx_consume = 0;
uart_ev_pending_write(uart_ev_pending_read());
uart_ev_enable_write(UART_EV_TX | UART_EV_RX);
irq_setmask(irq_getmask() | (1 << UART_INTERRUPT));
}
void uart_sync(void)
{
while(tx_consume != tx_produce);
}
#else /* !CSR_UART_BASE */
void uart_init(void) {}
void uart_isr(void) {}
#endif

View File

@ -1,252 +0,0 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
*
* 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, 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:
*
* 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
*
* 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 AUTHORS OR 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.
*/
#include <usb-desc.h>
// USB Descriptors are binary data which the USB host reads to
// automatically detect a USB device's capabilities. The format
// and meaning of every field is documented in numerous USB
// standards. When working with USB descriptors, despite the
// complexity of the standards and poor writing quality in many
// of those documents, remember descriptors are nothing more
// than constant binary data that tells the USB host what the
// device can do. Computers will load drivers based on this data.
// Those drivers then communicate on the endpoints specified by
// the descriptors.
// To configure a new combination of interfaces or make minor
// changes to existing configuration (eg, change the name or ID
// numbers), usually you would edit "usb_desc.h". This file
// is meant to be configured by the header, so generally it is
// only edited to add completely new USB interfaces or features.
// **************************************************************
// USB Device
// **************************************************************
#define LSB(n) ((n) & 255)
#define MSB(n) (((n) >> 8) & 255)
#define USB_DT_BOS_SIZE 5
#define USB_DT_BOS 0xf
#define USB_DT_DEVICE_CAPABILITY 0x10
#define USB_DC_PLATFORM 5
struct usb_bos_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumDeviceCaps;
} __attribute__((packed));
// USB Device Descriptor. The USB host reads this first, to learn
// what type of device is connected.
static const uint8_t device_descriptor[] = {
18, // bLength
1, // bDescriptorType
0x01, 0x02, // bcdUSB
0x08, /* MSC */ // bDeviceClass
0, // bDeviceSubClass
0, // bDeviceProtocol
EP0_SIZE, // bMaxPacketSize0
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
LSB(DEVICE_VER), MSB(DEVICE_VER), // bcdDevice
1, // iManufacturer
2, // iProduct
3, // iSerialNumber
1 // bNumConfigurations
};
// These descriptors must NOT be "const", because the USB DMA
// has trouble accessing flash memory with enough bandwidth
// while the processor is executing from flash.
// **************************************************************
// USB Configuration
// **************************************************************
// USB Configuration Descriptor. This huge descriptor tells all
// of the devices capbilities.
#define CONFIG_DESC_SIZE (9+9+USB_DT_ENDPOINT_SIZE+USB_DT_ENDPOINT_SIZE)
static const uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
9, // bLength;
2, // bDescriptorType;
LSB(CONFIG_DESC_SIZE), // wTotalLength
MSB(CONFIG_DESC_SIZE),
1, // bNumInterfaces
1, // bConfigurationValue
0, // iConfiguration
0x80, // bmAttributes
50, // bMaxPower
// interface descriptor, DFU Mode (DFU spec Table 4.4)
9, // bLength
4, // bDescriptorType
0, // bInterfaceNumber
0, // bAlternateSetting
2, // bNumEndpoints
0x08, /* IFACE_CLASS_MASS_STORAGE */ // bInterfaceClass
0x06, /* SCSI subclass */ // bInterfaceSubClass
0x50, /* BBB interface */ // bInterfaceProtocol
0, // iInterface
// Endpoint descriptor
USB_DT_ENDPOINT_SIZE, // bLength
USB_DT_ENDPOINT, // bDescriptorType
0x82, // bEndpointAddress
USB_ENDPOINT_ATTR_BULK, // bmAttributes
LSB(64), // wMaxPacketSize
MSB(64), // wMaxPacketSize
0, // bInterval
// Endpoint descriptor
USB_DT_ENDPOINT_SIZE, // bLength
USB_DT_ENDPOINT, // bDescriptorType
0x02, // bEndpointAddress
USB_ENDPOINT_ATTR_BULK, // bmAttributes
LSB(64), // wMaxPacketSize
MSB(64), // wMaxPacketSize
0, // bInterval
};
// **************************************************************
// String Descriptors
// **************************************************************
// The descriptors above can provide human readable strings,
// referenced by index numbers. These descriptors are the
// actual string data
static const struct usb_string_descriptor_struct string0 = {
4,
3,
{0x0409}
};
// Microsoft OS String Descriptor. See: https://github.com/pbatard/libwdi/wiki/WCID-Devices
static const struct usb_string_descriptor_struct usb_string_microsoft = {
18, 3,
{'M','S','F','T','1','0','0', MSFT_VENDOR_CODE}
};
// Microsoft WCID
const uint8_t usb_microsoft_wcid[MSFT_WCID_LEN] = {
MSFT_WCID_LEN, 0, 0, 0, // Length
0x00, 0x01, // Version
0x04, 0x00, // Compatibility ID descriptor index
0x01, // Number of sections
0, 0, 0, 0, 0, 0, 0, // Reserved (7 bytes)
0, // Interface number
0x01, // Reserved
'W','I','N','U','S','B',0,0, // Compatible ID
0,0,0,0,0,0,0,0, // Sub-compatible ID (unused)
0,0,0,0,0,0, // Reserved
};
static const struct webusb_url_descriptor landing_url_descriptor = {
.bLength = LANDING_PAGE_DESCRIPTOR_SIZE,
.bDescriptorType = WEBUSB_DT_URL,
.bScheme = WEBUSB_URL_SCHEME_HTTPS,
.URL = LANDING_PAGE_URL
};
const uint8_t *get_landing_url_descriptor(uint32_t *datalen) {
// Return landing page URL descriptor
*datalen = LANDING_PAGE_DESCRIPTOR_SIZE;
return (const uint8_t*)&landing_url_descriptor;
}
struct full_bos {
struct usb_bos_descriptor bos;
struct webusb_platform_descriptor webusb;
};
static const struct full_bos full_bos = {
.bos = {
.bLength = USB_DT_BOS_SIZE,
.bDescriptorType = USB_DT_BOS,
.wTotalLength = USB_DT_BOS_SIZE + WEBUSB_PLATFORM_DESCRIPTOR_SIZE,
.bNumDeviceCaps = 1,
},
.webusb = {
.bLength = WEBUSB_PLATFORM_DESCRIPTOR_SIZE,
.bDescriptorType = USB_DT_DEVICE_CAPABILITY,
.bDevCapabilityType = USB_DC_PLATFORM,
.bReserved = 0,
.platformCapabilityUUID = WEBUSB_UUID,
.bcdVersion = 0x0100,
.bVendorCode = WEBUSB_VENDOR_CODE,
.iLandingPage = 1,
},
};
__attribute__((aligned(4)))
static const struct usb_string_descriptor_struct usb_string_manufacturer_name = {
2 + MANUFACTURER_NAME_LEN,
3,
MANUFACTURER_NAME
};
__attribute__((aligned(4)))
struct usb_string_descriptor_struct usb_string_product_name = {
2 + PRODUCT_NAME_LEN,
3,
PRODUCT_NAME
};
__attribute__((aligned(4)))
static const struct usb_string_descriptor_struct usb_string_serial_number = {
2 + SERIAL_NUMBER_LEN,
3,
SERIAL_NUMBER
};
// **************************************************************
// Descriptors List
// **************************************************************
// This table provides access to all the descriptor data above.
const usb_descriptor_list_t usb_descriptor_list[] = {
{0x0100, sizeof(device_descriptor), device_descriptor},
{0x0200, sizeof(config_descriptor), config_descriptor},
{0x0300, 0, (const uint8_t *)&string0},
{0x0301, 0, (const uint8_t *)&usb_string_manufacturer_name},
{0x0302, 0, (const uint8_t *)&usb_string_product_name},
{0x0303, 0, (const uint8_t *)&usb_string_serial_number},
{0x03EE, 0, (const uint8_t *)&usb_string_microsoft},
{0x0F00, sizeof(full_bos), (const uint8_t *)&full_bos},
{0, 0, NULL}
};

View File

@ -1,155 +0,0 @@
#include <stdint.h>
#include <unistd.h>
#include <usb.h>
#include <system.h>
#include <usb-desc.h>
#include <usb-msc.h>
static uint8_t reply_buffer[8];
static uint8_t usb_configuration = 0;
#define USB_MAX_PACKET_SIZE 64
static uint32_t rx_buffer[USB_MAX_PACKET_SIZE/4];
uint16_t last_request_and_type;
__attribute__((section(".ramtext")))
void usb_setup(const struct usb_setup_request *setup)
{
const uint8_t *data = NULL;
uint32_t datalen = 0;
const usb_descriptor_list_t *list;
last_request_and_type = setup->wRequestAndType;
switch (setup->wRequestAndType)
{
case 0xfea1: // Get Max LUN
if (usb_msc_setup(setup))
return;
break;
case 0x0500: // SET_ADDRESS
case 0x0b01: // SET_INTERFACE
break;
case 0x0900: // SET_CONFIGURATION
usb_configuration = setup->wValue;
break;
case 0x0880: // GET_CONFIGURATION
reply_buffer[0] = usb_configuration;
datalen = 1;
data = reply_buffer;
break;
case 0x0080: // GET_STATUS (device)
reply_buffer[0] = 0;
reply_buffer[1] = 0;
datalen = 2;
data = reply_buffer;
break;
case 0x0082: // GET_STATUS (endpoint)
if (setup->wIndex > 0)
{
usb_stall(0x80);
return;
}
reply_buffer[0] = 0;
reply_buffer[1] = 0;
// XXX handle endpoint stall here
// if (USB->DIEP0CTL & USB_DIEP_CTL_STALL)
// reply_buffer[0] = 1;
data = reply_buffer;
datalen = 2;
break;
case 0x0102: // CLEAR_FEATURE (endpoint)
if (setup->wIndex > 0 || setup->wValue != 0)
{
// TODO: do we need to handle IN vs OUT here?
usb_stall(0x80);
return;
}
// XXX: Should we clear the stall bit?
// USB->DIEP0CTL &= ~USB_DIEP_CTL_STALL;
// TODO: do we need to clear the data toggle here?
break;
case 0x0302: // SET_FEATURE (endpoint)
if (setup->wIndex > 0 || setup->wValue != 0)
{
// TODO: do we need to handle IN vs OUT here?
usb_stall(0x80);
return;
}
// XXX: Should we set the stall bit?
// USB->DIEP0CTL |= USB_DIEP_CTL_STALL;
// TODO: do we need to clear the data toggle here?
break;
case 0x0680: // GET_DESCRIPTOR
case 0x0681:
for (list = usb_descriptor_list; 1; list++)
{
if (list->addr == NULL)
break;
if (setup->wValue == list->wValue)
{
data = list->addr;
if ((setup->wValue >> 8) == 3)
{
// for string descriptors, use the descriptor's
// length field, allowing runtime configured
// length.
datalen = *(list->addr);
}
else
{
datalen = list->length;
}
goto send;
}
}
usb_stall(0x80);
return;
case (MSFT_VENDOR_CODE << 8) | 0xC0: // Get Microsoft descriptor
case (MSFT_VENDOR_CODE << 8) | 0xC1:
if (setup->wIndex == 0x0004)
{
// Return WCID descriptor
data = usb_microsoft_wcid;
datalen = MSFT_WCID_LEN;
break;
}
usb_stall(0x80);
return;
case (WEBUSB_VENDOR_CODE << 8) | 0xC0: // Get WebUSB descriptor
if (setup->wIndex == 0x0002)
{
if (setup->wValue == 0x0001)
{
data = get_landing_url_descriptor(&datalen);
break;
}
}
usb_stall(0x80);
return;
default:
usb_stall(0x80);
return;
}
send:
if (data && datalen) {
if (datalen > setup->wLength)
datalen = setup->wLength;
usb_send(0, data, datalen);
}
else
usb_ack(0x80);
return;
}

View File

@ -1,465 +0,0 @@
#include <usb.h>
#include <irq.h>
#include <generated/csr.h>
#include <string.h>
#include <usb.h>
#include <usb-msc.h>
#define EP0OUT_BUFFERS 4
#define EP2OUT_BUFFERS 4
__attribute__((aligned(4)))
static uint8_t volatile usb_ep0out_buffer_len[EP0OUT_BUFFERS];
static uint8_t volatile usb_ep0out_buffer[EP0OUT_BUFFERS][256];
static uint8_t volatile usb_ep0out_last_tok[EP0OUT_BUFFERS];
static volatile uint8_t usb_ep0out_wr_ptr;
static volatile uint8_t usb_ep0out_rd_ptr;
__attribute__((aligned(4)))
static uint8_t volatile usb_ep2out_buffer_len[EP2OUT_BUFFERS];
static uint8_t volatile usb_ep2out_buffer[EP2OUT_BUFFERS][256];
static volatile uint8_t usb_ep2out_wr_ptr;
static volatile uint8_t usb_ep2out_rd_ptr;
static const int max_byte_length = 64;
static const uint8_t * volatile current_data_0;
static volatile int current_length_0;
static volatile int data_offset_0;
static volatile int data_to_send_0;
static int next_packet_is_empty_0;
static const uint8_t * volatile current_data_2;
static volatile int current_length_2;
static volatile int data_offset_2;
static volatile int data_to_send_2;
static int next_packet_is_empty_2;
static void *ep2_more_data_ptr;
static volatile uint8_t ep2_more_data_bfr[64];
static int (*ep2_more_data)(uint8_t *bfr, size_t len, void *ptr);
// Note that our PIDs are only bits 2 and 3 of the token,
// since all other bits are effectively redundant at this point.
enum USB_PID {
USB_PID_OUT = 0,
USB_PID_SOF = 1,
USB_PID_IN = 2,
USB_PID_SETUP = 3,
};
enum epfifo_response {
EPF_ACK = 0,
EPF_NAK = 1,
EPF_NONE = 2,
EPF_STALL = 3,
};
#define USB_EV_ERROR 1
#define USB_EV_PACKET 2
static void process_tx(void);
void usb_idle(void) {
usb_ep_0_out_ev_enable_write(0);
usb_ep_0_in_ev_enable_write(0);
// Reject all incoming data, since there is no handler anymore
usb_ep_0_out_respond_write(EPF_NAK);
// Reject outgoing data, since we don't have any to give.
usb_ep_0_in_respond_write(EPF_NAK);
irq_setmask(irq_getmask() & ~(1 << USB_INTERRUPT));
}
void usb_disconnect(void) {
usb_ep_0_out_ev_enable_write(0);
usb_ep_0_in_ev_enable_write(0);
irq_setmask(irq_getmask() & ~(1 << USB_INTERRUPT));
usb_pullup_out_write(0);
}
__attribute__((section(".ramtext")))
void usb_connect(void) {
usb_ep_0_out_ev_pending_write(usb_ep_0_out_ev_enable_read());
usb_ep_0_in_ev_pending_write(usb_ep_0_in_ev_pending_read());
usb_ep_0_out_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR);
usb_ep_0_in_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR);
usb_ep_2_out_ev_pending_write(usb_ep_2_out_ev_enable_read());
usb_ep_2_in_ev_pending_write(usb_ep_2_in_ev_pending_read());
usb_ep_2_out_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR);
usb_ep_2_in_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR);
// Accept incoming data by default.
usb_ep_0_out_respond_write(EPF_ACK);
usb_ep_2_out_respond_write(EPF_ACK);
// Reject outgoing data, since we have none to give yet.
usb_ep_0_in_respond_write(EPF_NAK);
usb_ep_2_in_respond_write(EPF_NAK);
usb_ep_2_in_dtb_write(1);
usb_pullup_out_write(1);
irq_setmask(irq_getmask() | (1 << USB_INTERRUPT));
}
void usb_init(void) {
usb_ep0out_wr_ptr = 0;
usb_ep0out_rd_ptr = 0;
usb_ep2out_wr_ptr = 0;
usb_ep2out_wr_ptr = 0;
usb_pullup_out_write(0);
return;
}
__attribute__((section(".ramtext")))
void usb_isr(void) {
uint8_t ep0o_pending = usb_ep_0_out_ev_pending_read();
uint8_t ep0i_pending = usb_ep_0_in_ev_pending_read();
uint8_t ep2o_pending = usb_ep_2_out_ev_pending_read();
uint8_t ep2i_pending = usb_ep_2_in_ev_pending_read();
// We got an OUT or a SETUP packet. Copy it to usb_ep0out_buffer
// and clear the "pending" bit.
if (ep0o_pending) {
uint8_t last_tok = usb_ep_0_out_last_tok_read();
int byte_count = 0;
usb_ep0out_last_tok[usb_ep0out_wr_ptr] = last_tok;
volatile uint8_t * obuf = usb_ep0out_buffer[usb_ep0out_wr_ptr];
while (!usb_ep_0_out_obuf_empty_read()) {
obuf[byte_count++] = usb_ep_0_out_obuf_head_read();
usb_ep_0_out_obuf_head_write(0);
}
/* Strip off CRC16 */
if (byte_count >= 2)
byte_count -= 2;
usb_ep0out_buffer_len[usb_ep0out_wr_ptr] = byte_count;
if (byte_count)
usb_ep0out_wr_ptr = (usb_ep0out_wr_ptr + 1) & (EP0OUT_BUFFERS-1);
if (last_tok == USB_PID_SETUP) {
usb_ep_0_in_dtb_write(1);
data_offset_0 = 0;
current_length_0 = 0;
current_data_0 = NULL;
}
usb_ep_0_out_ev_pending_write(ep0o_pending);
usb_ep_0_out_respond_write(EPF_ACK);
}
// We got an OUT or a SETUP packet. Copy it to usb_ep0out_buffer
// and clear the "pending" bit.
if (ep2o_pending) {
uint8_t byte_count = 0;
volatile uint8_t * obuf = usb_ep2out_buffer[usb_ep2out_wr_ptr];
while (!usb_ep_2_out_obuf_empty_read()) {
obuf[byte_count++] = usb_ep_2_out_obuf_head_read();
usb_ep_2_out_obuf_head_write(0);
}
/* Strip off CRC16 */
if (byte_count >= 2)
byte_count -= 2;
usb_ep2out_buffer_len[usb_ep2out_wr_ptr] = byte_count;
if (byte_count)
usb_ep2out_wr_ptr = (usb_ep2out_wr_ptr + 1) & (EP2OUT_BUFFERS-1);
usb_ep_2_out_ev_pending_write(ep2o_pending);
usb_ep_2_out_respond_write(EPF_ACK);
}
// We just got an "IN" token. Send data if we have it.
if (ep0i_pending) {
usb_ep_0_in_respond_write(EPF_NAK);
usb_ep_0_in_ev_pending_write(ep0i_pending);
}
// We just got an "IN" token. Send data if we have it.
if (ep2i_pending) {
usb_ep_2_in_respond_write(EPF_NAK);
usb_ep_2_in_ev_pending_write(ep2i_pending);
process_tx();
}
}
static void process_tx_0(void) {
// Don't allow requeueing -- only queue more data if we're
// currently set up to respond NAK.
if (usb_ep_0_in_respond_read() != EPF_NAK) {
return;
}
// Prevent us from double-filling the buffer.
if (!usb_ep_0_in_ibuf_empty_read()) {
return;
}
if (!current_data_0 || !current_length_0) {
return;
}
data_offset_0 += data_to_send_0;
data_to_send_0 = current_length_0 - data_offset_0;
// Clamp the data to the maximum packet length
if (data_to_send_0 > max_byte_length) {
data_to_send_0 = max_byte_length;
next_packet_is_empty_0 = 0;
}
else if (data_to_send_0 == max_byte_length) {
next_packet_is_empty_0 = 1;
}
else if (next_packet_is_empty_0) {
next_packet_is_empty_0 = 0;
data_to_send_0 = 0;
}
else if (current_data_0 == NULL || data_to_send_0 <= 0) {
next_packet_is_empty_0 = 0;
current_data_0 = NULL;
current_length_0 = 0;
data_offset_0 = 0;
data_to_send_0 = 0;
return;
}
int this_offset_0;
for (this_offset_0 = data_offset_0; this_offset_0 < (data_offset_0 + data_to_send_0); this_offset_0++) {
usb_ep_0_in_ibuf_head_write(current_data_0[this_offset_0]);
}
usb_ep_0_in_respond_write(EPF_ACK);
return;
}
static void process_tx_2(void) {
// Don't allow requeueing -- only queue more data if we're
// currently set up to respond NAK.
if (usb_ep_2_in_respond_read() != EPF_NAK) {
return;
}
// Prevent us from double-filling the buffer.
if (!usb_ep_2_in_ibuf_empty_read()) {
return;
}
// If we have a callback, use that.
if (ep2_more_data) {
uint8_t data_bfr[64];
int new_bytes = ep2_more_data(data_bfr, sizeof(data_bfr), ep2_more_data_ptr);
if (new_bytes == 0) {
usb_ep_2_in_respond_write(EPF_ACK);
ep2_more_data_ptr = NULL;
ep2_more_data = NULL;
}
else if (new_bytes == -1) {
ep2_more_data_ptr = NULL;
ep2_more_data = NULL;
}
else if (new_bytes < -1) {
usb_ep_2_in_respond_write(EPF_STALL);
ep2_more_data_ptr = NULL;
ep2_more_data = NULL;
}
else {
int off;
for (off = 0; off < new_bytes; off++)
usb_ep_2_in_ibuf_head_write(data_bfr[off]);
usb_ep_2_in_respond_write(EPF_ACK);
}
return;
}
if (!current_data_2 || !current_length_2) {
return;
}
data_offset_2 += data_to_send_2;
data_to_send_2 = current_length_2 - data_offset_2;
// Clamp the data to the maximum packet length
if (data_to_send_2 > max_byte_length) {
data_to_send_2 = max_byte_length;
next_packet_is_empty_2 = 0;
}
else if (data_to_send_2 == max_byte_length) {
next_packet_is_empty_2 = 1;
}
else if (next_packet_is_empty_2) {
next_packet_is_empty_2 = 0;
data_to_send_2 = 0;
}
else if (current_data_2 == NULL || data_to_send_2 <= 0) {
next_packet_is_empty_2 = 0;
current_data_2 = NULL;
current_length_2 = 0;
data_offset_2 = 0;
data_to_send_2 = 0;
return;
}
int this_offset_2;
for (this_offset_2 = data_offset_2; this_offset_2 < (data_offset_2 + data_to_send_2); this_offset_2++) {
usb_ep_2_in_ibuf_head_write(current_data_2[this_offset_2]);
}
usb_ep_2_in_respond_write(EPF_ACK);
return;
}
static void process_tx(void) {
process_tx_0();
process_tx_2();
}
void usb_wait_for_send_done(void) {
while (current_data_0 && current_length_0)
usb_poll();
while ((usb_ep_0_in_dtb_read() & 1) == 1)
usb_poll();
}
void usb_ack(int epnum) {
switch (epnum) {
case 0x00:
while (usb_ep_0_out_respond_read() == EPF_ACK)
;
usb_ep_0_out_respond_write(EPF_ACK);
break;
case 0x80:
while (usb_ep_0_in_respond_read() == EPF_ACK)
;
usb_ep_0_in_respond_write(EPF_ACK);
break;
case 0x02:
while (usb_ep_2_out_respond_read() == EPF_ACK)
;
usb_ep_2_out_respond_write(EPF_ACK);
break;
case 0x82:
while (usb_ep_2_in_respond_read() == EPF_ACK)
;
usb_ep_2_in_respond_write(EPF_ACK);
break;
}
}
void usb_stall(int epnum) {
switch (epnum) {
case 0x00:
usb_ep_0_out_respond_write(EPF_STALL);
break;
case 0x80:
usb_ep_0_in_respond_write(EPF_STALL);
break;
case 0x02:
usb_ep_2_out_respond_write(EPF_STALL);
break;
case 0x82:
usb_ep_2_in_respond_write(EPF_STALL);
break;
}
}
void usb_send_cb(int epnum, int (*cb)(uint8_t *, size_t, void *), void *ptr) {
if (epnum == 2) {
ep2_more_data = cb;
ep2_more_data_ptr = ptr;
process_tx();
}
}
__attribute__((section(".ramtext")))
void usb_send(int epnum, const void *data, size_t total_count) {
switch (epnum) {
case 0:
while ((usb_ep_0_in_respond_read() == EPF_ACK) && (current_length_0 != 0) && (current_data_0 != 0))
;
current_data_0 = (uint8_t *)data;
current_length_0 = total_count;
data_offset_0 = 0;
data_to_send_0 = 0;
if (!total_count)
usb_ep_0_in_respond_write(EPF_ACK);
break;
case 2:
while ((usb_ep_2_in_respond_read() == EPF_ACK) && (current_length_2 != 0) && (current_data_2 != 0))
;
if (!total_count) {
usb_ep_2_in_respond_write(EPF_ACK);
}
else {
current_data_2 = (uint8_t *)data;
current_length_2 = total_count;
data_offset_2 = 0;
data_to_send_2 = 0;
}
break;
}
process_tx();
}
int usb_recv(void *buffer, unsigned int buffer_len) {
// Set the OUT response to ACK, since we are in a position to receive data now.
usb_ep_0_out_respond_write(EPF_ACK);
while (1) {
if (usb_ep0out_rd_ptr != usb_ep0out_wr_ptr) {
if (usb_ep0out_last_tok[usb_ep0out_rd_ptr] == USB_PID_OUT) {
unsigned int ep0_buffer_len = usb_ep0out_buffer_len[usb_ep0out_rd_ptr];
if (ep0_buffer_len < buffer_len)
buffer_len = ep0_buffer_len;
// usb_ep0out_buffer_len[usb_ep0out_rd_ptr] = 0;
memcpy(buffer, (void *)&usb_ep0out_buffer[usb_ep0out_rd_ptr], buffer_len);
usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1);
return buffer_len;
}
usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1);
}
}
return 0;
}
__attribute__((section(".ramtext")))
void usb_poll(void) {
// If some data was received, then process it.
while (usb_ep0out_rd_ptr != usb_ep0out_wr_ptr) {
const struct usb_setup_request *request = (const struct usb_setup_request *)(usb_ep0out_buffer[usb_ep0out_rd_ptr]);
// uint8_t len = usb_ep0out_buffer_len[usb_ep0out_rd_ptr];
uint8_t last_tok = usb_ep0out_last_tok[usb_ep0out_rd_ptr];
// usb_ep0out_buffer_len[usb_ep0out_rd_ptr] = 0;
usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1);
if (last_tok == USB_PID_SETUP) {
usb_setup(request);
}
}
while (usb_ep2out_rd_ptr != usb_ep2out_wr_ptr) {
const uint8_t *data = (const void *)(usb_ep2out_buffer[usb_ep2out_rd_ptr]);
uint8_t len = usb_ep2out_buffer_len[usb_ep2out_rd_ptr];
// usb_send(2, data, len);
usb_msc_out(data, len);
usb_ep2out_buffer_len[usb_ep2out_rd_ptr] = 0;
usb_ep2out_rd_ptr = (usb_ep2out_rd_ptr + 1) & (EP2OUT_BUFFERS-1);
}
process_tx();
}

View File

@ -1,295 +0,0 @@
#include <stdint.h>
#include "usb-desc.h"
#include "usb-msc.h"
#include "usb.h"
static const uint8_t max_lun = 0;
#define DISK_SIZE 117760 // ~112 kilobytes
#define BLOCK_SIZE 512
#define BLOCK_COUNT (DISK_SIZE / BLOCK_SIZE)
static uint32_t memory_backing[DISK_SIZE/4];
static uint32_t swap32(uint32_t x) {
return ((x << 24) & 0xff000000) |
((x << 8) & 0x00ff0000) |
((x >> 8) & 0x0000ff00) |
((x >> 24) & 0x000000ff);
}
static uint8_t sbc_sense_key;
static uint8_t sbc_asc;
static uint8_t sbc_ascq;
static struct usb_msc_csw csw;
static int (*usb_write_cb)(const uint8_t *data, size_t count, void *ptr);
static void *usb_write_cb_ptr = NULL;
static void set_sbc_status(enum sbc_sense_key key,
enum sbc_asc asc,
enum sbc_ascq ascq) {
sbc_sense_key = (uint8_t) key;
sbc_asc = (uint8_t) asc;
sbc_ascq = (uint8_t) ascq;
}
static void set_sbc_status_good(void) {
set_sbc_status(SBC_SENSE_KEY_NO_SENSE,
SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION,
SBC_ASCQ_NA);
}
static const char *error_reason = NULL;
static const void *parse_cbw(const void *data, size_t len, struct cbw *cbw_dest) {
const struct cbw *cbw_src = data;
unsigned int i;
// Check for the signature
uint8_t sig_test[4] = {'U', 'S', 'B', 'C'};
for (i = 0; i < sizeof(sig_test); i++) {
if (sig_test[i] != cbw_src->signature[i]) {
error_reason = "Signature Mismatch";
return NULL;
}
}
// Make sure the size at least makes sense.
if (len < sizeof(*cbw_dest)) {
error_reason = "Too short";
return NULL;
}
// Copy over data and un-swap words.
cbw_dest->tag = cbw_src->tag; // Don't swap, since we reply with this
cbw_dest->length = swap32(cbw_src->length);
cbw_dest->flags = cbw_src->flags;
cbw_dest->lun = cbw_src->lun;
cbw_dest->cbLength = cbw_src->cbLength;
if (!cbw_src->data) {
error_reason = "Data NULL";
}
return cbw_src->data;
}
static int reply_scsi_inquiry(const void *data) {
static struct scsi_inquiry_data udi_msc_inquiry_data = {
.pq_pdt = SCSI_INQ_PQ_CONNECTED | SCSI_INQ_DT_DIR_ACCESS,
.version = 2, // SCSI_INQ_VER_SPC,
.flags1 = SCSI_INQ_RMB,
.flags3 = SCSI_INQ_RSP_SPC2,
.addl_len = 36 - 4, // SCSI_INQ_ADDL_LEN(sizeof(struct scsi_inquiry_data)),
// Linux displays this; Windows shows it in Dev Mgr
.vendor_id = "VENDOR",
.product_id = "SOMETHING",
.product_rev = {'1', '.', '0', '0'},
};
set_sbc_status_good();
csw.dCSWDataResidue = sizeof(udi_msc_inquiry_data);
usb_send(2, &udi_msc_inquiry_data, sizeof(udi_msc_inquiry_data));
return 0;
}
static int reply_scsi_read_capacity(const void *payload) {
uint8_t bfr[8];
bfr[0] = 0xff & (BLOCK_COUNT >> 24);
bfr[1] = 0xff & (BLOCK_COUNT >> 16);
bfr[2] = 0xff & (BLOCK_COUNT >> 8);
bfr[3] = 0xff & (BLOCK_COUNT >> 0);
bfr[4] = 0xff & (BLOCK_SIZE >> 24);
bfr[5] = 0xff & (BLOCK_SIZE >> 16);
bfr[6] = 0xff & (BLOCK_SIZE >> 8);
bfr[7] = 0xff & (BLOCK_SIZE >> 0);
usb_send(2, bfr, sizeof(bfr));
return 0;
}
static void reply_csw(struct cbw *cbw, const void *payload, int result) {
(void)payload;
csw.dCSWSignature = CSW_SIGNATURE;
csw.bCSWStatus = result;
usb_send(2, &csw, sizeof(csw));
}
static int reply_scsi_mode_sense_6(const void *payload) {
const uint8_t *p = payload;
uint8_t inf_bfr[4];
// switch (p[2]) {
// case 0x1c: // Informational
inf_bfr[0] = 3; /* Num bytes that follow */
inf_bfr[1] = 0; /* Medium Type */
inf_bfr[2] = 0; /* Device specific param */
inf_bfr[3] = 0;
csw.dCSWDataResidue = 4;
usb_send(2, inf_bfr, sizeof(inf_bfr));
// break;
// case 0x01: // Error recovery
// break;
// case 0x3f:
// break;
// default:
// return 1;
// }
return 0;
}
static inline void memset(uint8_t *data, int val, size_t len) {
unsigned int i;
for (i = 0; i < len; i++)
data[i] = val;
}
static size_t read_remaining;
static size_t read_offset;
static int csw_sent;
static int read_cb(uint8_t *bfr, size_t max, void *ptr) {
(void)ptr;
if (!read_remaining) {
if (!csw_sent) {
csw_sent = 1;
memcpy(bfr, &csw, sizeof(csw));
return sizeof(csw);
}
else {
return -1;
}
}
csw_sent = 0;
size_t to_read = read_remaining;
if (to_read > max)
to_read = max;
memcpy(bfr, ((void *)memory_backing) + read_offset, to_read);
read_remaining -= to_read;
read_offset += to_read;
return to_read;
}
static int reply_scsi_read_10(const void *payload) {
const uint8_t *p = payload;
uint32_t lba_start = (p[2] << 24)
| (p[3] << 16)
| (p[4] << 8)
| (p[5] << 0);
uint32_t block_count = (p[7] << 8) | p[8];
read_remaining = block_count * BLOCK_SIZE;
read_offset = lba_start * BLOCK_SIZE;
csw.dCSWDataResidue = BLOCK_SIZE * block_count;
usb_send_cb(2, read_cb, NULL);
return 0;
}
static size_t write_remaining;
static size_t write_offset;
static int write_cb(const uint8_t *bfr, size_t max, void *ptr) {
(void)ptr;
size_t to_write = write_remaining;
if (to_write > max)
to_write = max;
memcpy(((void *)memory_backing) + write_offset, bfr, to_write);
write_remaining -= to_write;
write_offset += to_write;
if (!write_remaining) {
usb_send(2, &csw, sizeof(csw));
}
return write_remaining;
}
static int reply_scsi_write_10(const void *payload) {
const uint8_t *p = payload;
uint32_t lba_start = (p[2] << 24)
| (p[3] << 16)
| (p[4] << 8)
| (p[5] << 0);
uint32_t block_count = (p[7] << 8) | p[8];
write_remaining = block_count * BLOCK_SIZE;
write_offset = lba_start * BLOCK_SIZE;
usb_write_cb = write_cb;
usb_write_cb_ptr = NULL;
return 0;
}
// Receive an OUT packet from the host
void usb_msc_out(const void *data, size_t len) {
struct cbw cbw;
const void *payload;
int result;
if (usb_write_cb) {
int res = usb_write_cb(data, len, usb_write_cb_ptr);
if (res > 0)
return;
usb_write_cb = NULL;
usb_write_cb_ptr = NULL;
if (res == 0)
return;
}
payload = parse_cbw(data, len, &cbw);
if (!payload) {
usb_stall(0x82);
return;
}
csw.dCSWDataResidue = 0;
csw.dCSWTag = cbw.tag;
const uint8_t *char_view = payload;
switch (char_view[0]) {
case 0x00: // TEST_UNIT_READY
result = 0;
break;
case 0x12: // SCSI_INQUIRY
result = reply_scsi_inquiry(payload);
break;
case 0x25: // READ_CAPACITY
result = reply_scsi_read_capacity(payload);
break;
case 0x1a: // MODE_SENSE_6
result = reply_scsi_mode_sense_6(payload);
break;
case 0x1e: // PREVENT_ALLOW_MEDIUM_REMOVAL
result = 0;
break;
case 0x28: // READ_10
reply_scsi_read_10(payload);
return;
case 0x2a: // WRITE_10
reply_scsi_write_10(payload);
return;
default:
result = 1;
break;
}
reply_csw(&cbw, payload, result);
}
// Receive an IN packet from the host
void usb_msc_in(void) {
}
int usb_msc_setup(const struct usb_setup_request *setup) {
if (setup->wRequestAndType == 0xfea1) {
usb_send(0, &max_lun, sizeof(max_lun));
return 1;
}
return 0;
}