├── .gitignore ├── Makefile ├── New_SAROO.jpg ├── Readme.md ├── board.png ├── cherryusb ├── Makefile ├── agrv2k_hcd.c ├── inc │ ├── usb_def.h │ ├── usb_ehci_priv.h │ ├── usb_errno.h │ ├── usb_hc.h │ ├── usb_hc_ehci.h │ ├── usb_hid.h │ ├── usb_hub.h │ ├── usb_list.h │ ├── usb_log.h │ ├── usb_mem.h │ ├── usb_msc.h │ ├── usb_osal.h │ ├── usb_scsi.h │ ├── usb_util.h │ ├── usbh_core.h │ ├── usbh_hid.h │ ├── usbh_hub.h │ └── usbh_msc.h ├── usb_config.h ├── usb_hc_ehci.c ├── usb_osal_xos.c ├── usbh_core.c ├── usbh_hid.c ├── usbh_hub.c └── usbh_msc.c ├── coremark ├── Makefile ├── core_list_join.c ├── core_main.c ├── core_matrix.c ├── core_portme.c ├── core_portme.h ├── core_state.c ├── core_util.c ├── coremark.h └── npk.yml ├── fpga ├── Makefile ├── tools │ ├── gen_logic.tcl │ ├── gen_vlog │ └── pre_logic.tcl ├── top.ve └── ulogic │ ├── sync_dpram.v │ ├── top.sdc │ ├── tpsram.v │ └── ulogic.v ├── inc ├── agrv.h ├── main.h ├── riscv.h └── xos.h ├── main ├── Makefile ├── cpu_agrv.c ├── heap.c ├── ld.S ├── ld_ram.S ├── main.c ├── printk.c ├── printk_i.c ├── shell.c ├── spi_sd.c ├── start.S ├── string.c └── xos_core.c └── tntfs ├── Makefile ├── fs_fat.c ├── fs_ntfs.c ├── fs_util.c └── tntfs.h /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /*.o 3 | /*.bin 4 | /*.dump 5 | /objs/ 6 | 7 | /fpga/ulogic/* 8 | !/fpga/ulogic/ulogic.v 9 | !/fpga/ulogic/tpsram.v 10 | !/fpga/ulogic/sync_dpram.v 11 | !/fpga/ulogic/top.sdc 12 | 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | ################################################################ 4 | 5 | OO_DIR = /e/AGRV/AgRV_pio/packages/tool-agrv_logic/openocd/ 6 | OPENOCD = $(OO_DIR)/bin/openocd.exe -c "set ADAPTER cmsis-dap; set CONNECT_UNDER_RESET 1" -f $(OO_DIR)/agrv2k.cfg 7 | CROSS = riscv64-unknown-elf- 8 | 9 | CC = $(CROSS)gcc 10 | AS = $(CROSS)gcc 11 | LD = $(CROSS)gcc 12 | OBJCOPY = $(CROSS)objcopy 13 | OBJDUMP = $(CROSS)objdump 14 | GDB = $(CROSS)gdb 15 | 16 | 17 | TARGET = agrv32.elf 18 | 19 | modules = main cherryusb tntfs 20 | 21 | ################################################################ 22 | 23 | make_module_dirs := $(shell mkdir -p $(addprefix objs/, $(modules)) ) 24 | 25 | 26 | OBJS := 27 | INCDIR := -Iinc 28 | DEFS := 29 | 30 | LDFLAGS := -fno-builtin -nostartfiles -nodefaultlibs 31 | 32 | include $(addsuffix /Makefile, $(modules)) 33 | 34 | CFLAGS := -Wall -g -MMD -fno-builtin $(DEFS) $(INCDIR) 35 | 36 | TOBJS = $(addprefix objs/, $(OBJS)) 37 | DEPENDS = $(patsubst %.o, %.d, $(TOBJS)) 38 | 39 | all: $(TARGET) 40 | 41 | clean: 42 | rm -f $(TOBJS) $(TARGET) $(TARGET).bin $(TARGET).dump 43 | 44 | 45 | $(TARGET): $(TOBJS) 46 | ifeq ($(V), 1) 47 | @echo $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) 48 | @echo $(OBJDUMP) -xd $@ >$@.dump 49 | @echo $(OBJCOPY) -O binary -R .comment -R .note* $@ $@.bin 50 | else 51 | @echo linking $@ ... 52 | endif 53 | @$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) 54 | @$(OBJDUMP) -xd $@ >$@.dump 55 | @$(OBJCOPY) -O binary -R .comment -R .note* $@ $@.bin 56 | 57 | 58 | -include $(DEPENDS) 59 | 60 | objs/%.o: %.c 61 | ifeq ($(V), 1) 62 | @echo $(CC) $(CFLAGS) -c $< -o $@ 63 | else 64 | @echo Compile $< ... 65 | endif 66 | @$(CC) $(CFLAGS) -c $< -o $@ 67 | 68 | objs/%.o: %.S 69 | ifeq ($(V), 1) 70 | @echo $(CC) -D__ASSEMBLY__ $(CFLAGS) $(ASFLAG) -c $< -o $@ 71 | else 72 | @echo Compile $< ... 73 | endif 74 | @$(CC) -D__ASSEMBLY__ $(CFLAGS) $(ASFLAG) -c $< -o $@ 75 | 76 | 77 | ################################################################ 78 | 79 | 80 | dl: $(TARGET) 81 | $(OPENOCD) -c "flash write_image erase agrv32.elf.bin 0x80000000" -c "reset" -c "exit" 82 | 83 | gdb: 84 | start $(OPENOCD) 85 | $(GDB) --tui -ex "target remote 127.0.0.1:3333" agrv32.elf 86 | 87 | oohlp: 88 | $(OPENOCD) -c "help" -c "exit" 89 | 90 | 91 | -------------------------------------------------------------------------------- /New_SAROO.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpunix/AGRV2K_go/c486c796c332301ef3710fabb833f163d5d7041d/New_SAROO.jpg -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 2 | # AGRV2K裸奔测试工程 3 | 4 | AGRV2K(AG32VF407),内置主频可达240M的RISC-V,并自带2K的FPGA逻辑,很适合做一些小规模的逻辑产品。 5 | 它的价格更是只有16.8元,十分良心。 6 | 7 | AGRV2K的FPGA开发流程稍微有点复杂。它需要先用第三方工具(比如Quartus)进行综合,输出网表文件,然后再由 8 | 它自己的Supra工具进行转换与布线等,最后输出可下载的bin文件。 9 | 10 | 官方推出的开发环境是VSCode+PlatformIO,里面有各种MCU和FPGA的例子可供学习研究。它的下载工具可以使用USB-Blaster,也可以使用两线的JLink等,还算方便的。但AGM的开发资料比较混乱。各种零碎的文档混合在一起,需要你慢慢的去发掘。 11 | 12 | ------ 13 | 本工程基于裸奔原则,只用Makefile来做MCU与FPGA的开发,给你带来清爽的感觉。 14 | 15 | 开发板: 16 |   是用某STM32F407板子直接改的。AGRV32和STM32F407是引脚兼容的,可以直接替换。 17 |   ![ ](board.png) 18 | 19 |   这是自己打的板子。 20 |   ![ ](New_SAROO.jpg) 21 | 22 | MCU部分: 23 |   初始化串口与时钟,跑起一个简单的串口shell,可以读写地址做各种测试。 24 |   简单的中断系统。 25 |   可以coremark跑分。 26 |   使用CherryUSB驱动EHCI。 27 |   简单的文件系统与RTOS。 28 | FPGA部分: 29 |   实现了简单的AHB接口,可以访问FPGA上的外设寄存器。 30 |   实现了简单的SPI PSRAM控制器。 31 |   实现了简单的SDCard控制器。 32 | 33 | 如何编译: 34 |   MCU: 35 |     make 36 |     make dl 37 |   FPGA: 38 |     cd fpga 39 |     make proj 40 |     用quatrus打开工程,tools->tcl script->af_quartus.tcl,完成编译。 41 |     make genbin 42 |     make dl 43 | 44 | ------ 45 | ### FPGA开发主意事项: 46 | 47 | - 第一步是编辑ve文件。 这一步可参考文档《AGRV2k逻辑设置.pdf》。但这个文档写的还是不太完全,还有些关于PLL的功能没写。更完全的文档要看tools/gen_vlog这个文档。 48 | 49 | - 有时候MCU程序跑飞了,此时openocd会连接不上。此时需要把NRST脚连接到JLink,就可以连接上了。 50 | 51 | - MCU主频240M,据说可以跑到300M以上。但与FPGA相连的AHB接口与MCU是同频的,太高的频率会导致各种时序问题。所以建议MCU跑个200M就差不多了。 52 | 53 | - 测试中发现,在verilog中直接把clk输出到引脚(assign clk_out = bus_clk)会导致Supra崩溃。变通的做法是在VE文件中直接把PLL时钟指定到引脚。或者用AGM提供的IP来输出? 54 | 55 | - 待续...... 56 | 57 | ------ 58 | ### 一些关于AGM的逆向的项目: 59 | - https://github.com/pablomarx/rodinia 60 | AGM bitstream utilities and decoded files from Supra 61 | 62 | - https://github.com/gabonator/Education/tree/master/2021/AltaGateReverse 63 | Alta-gate Supra reverse engineering 64 | -------------------------------------------------------------------------------- /board.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpunix/AGRV2K_go/c486c796c332301ef3710fabb833f163d5d7041d/board.png -------------------------------------------------------------------------------- /cherryusb/Makefile: -------------------------------------------------------------------------------- 1 | 2 | LDIR = cherryusb 3 | 4 | LOBJS = usbh_core.o usb_hc_ehci.o usb_osal_xos.o usbh_hub.o usbh_msc.o agrv2k_hcd.o 5 | 6 | OBJS += $(addprefix $(LDIR)/, $(LOBJS)) 7 | 8 | INCDIR += -Icherryusb -Icherryusb/inc 9 | -------------------------------------------------------------------------------- /cherryusb/agrv2k_hcd.c: -------------------------------------------------------------------------------- 1 | 2 | #include "main.h" 3 | #include "xos.h" 4 | #include "tntfs.h" 5 | #include "usbh_core.h" 6 | #include "usbh_msc.h" 7 | 8 | /******************************************************************************/ 9 | 10 | void USBH_IRQHandler(void); 11 | 12 | int usb_hc_low_level_init() 13 | { 14 | SYS->AHB_CLKENABLE |= AHB_MASK_USB0; 15 | usb_osal_msleep(10); 16 | 17 | USB->USBMODE |= 0x03; // Host mode 18 | USB->OTGSC |= 0x44; // Auto reset 19 | 20 | int_request(USB0_IRQn, USBH_IRQHandler, NULL); 21 | int_enable(USB0_IRQn); 22 | 23 | return 0; 24 | } 25 | 26 | int usb_hc_low_level2_init(void) 27 | { 28 | USB->USBMODE |= 0x03; // Host mode 29 | USB->OTGSC |= 0x44; // Auto reset 30 | return 0; 31 | } 32 | 33 | 34 | u8 usbh_get_port_speed(const u8 port) 35 | { 36 | u8 speed = (USB->PORTSC>>26)&3; 37 | if (speed == 0x00) { 38 | return USB_SPEED_FULL; 39 | } 40 | if (speed == 0x01) { 41 | return USB_SPEED_LOW; 42 | } 43 | if (speed == 0x02) { 44 | return USB_SPEED_HIGH; 45 | } 46 | 47 | return 0; 48 | } 49 | 50 | 51 | int cherryusb_start(void) 52 | { 53 | return usbh_initialize(); 54 | } 55 | 56 | 57 | /******************************************************************************/ 58 | 59 | 60 | static int usb_msc_read_sector(void *itf, u8 *buf, u32 start, int size) 61 | { 62 | return usbh_msc_scsi_read10((struct usbh_msc*)itf, start, buf, size); 63 | } 64 | 65 | 66 | static int usb_msc_write_sector(void *itf, u8 *buf, u32 start, int size) 67 | { 68 | return usbh_msc_scsi_write10((struct usbh_msc*)itf, start, buf, size); 69 | } 70 | 71 | 72 | void usbh_msc_run(struct usbh_msc *msc_class) 73 | { 74 | BLKDEV *bdev; 75 | int retv; 76 | 77 | bdev = xos_malloc(sizeof(BLKDEV)); 78 | memset(bdev, 0, sizeof(BLKDEV)); 79 | msc_class->user = bdev; 80 | 81 | bdev->itf = msc_class; 82 | bdev->sectors = msc_class->blocknum; 83 | bdev->read_sector = usb_msc_read_sector; 84 | bdev->write_sector = usb_msc_write_sector; 85 | 86 | retv = f_initdev(bdev, "usb", 0); 87 | if(retv) 88 | return; 89 | 90 | retv = f_mount(bdev, 0); 91 | if(retv==0){ 92 | f_list("usb0:/"); 93 | printk("\n"); 94 | } 95 | } 96 | 97 | 98 | void usbh_msc_stop(struct usbh_msc *msc_class) 99 | { 100 | BLKDEV *bdev = (BLKDEV*)msc_class->user; 101 | 102 | if(bdev){ 103 | f_removedev(bdev); 104 | xos_free(bdev); 105 | } 106 | } 107 | 108 | 109 | /******************************************************************************/ 110 | 111 | 112 | -------------------------------------------------------------------------------- /cherryusb/inc/usb_ehci_priv.h: -------------------------------------------------------------------------------- 1 | #ifndef _USB_EHCI_PRIV_H 2 | #define _USB_EHCI_PRIV_H 3 | 4 | #include "usbh_core.h" 5 | #include "usbh_hub.h" 6 | #include "usb_hc_ehci.h" 7 | 8 | #ifndef USBH_IRQHandler 9 | #define USBH_IRQHandler USBH_IRQHandler 10 | #endif 11 | 12 | #define EHCI_HCCR ((struct ehci_hccr *)CONFIG_USB_EHCI_HCCR_BASE) 13 | #define EHCI_HCOR ((struct ehci_hcor *)CONFIG_USB_EHCI_HCOR_BASE) 14 | 15 | #define EHCI_PTR2ADDR(x) ((uint32_t)(x) & ~0x1F) 16 | #define EHCI_ADDR2QH(x) ((struct ehci_qh_hw *)((uint32_t)(x) & ~0x1F)) 17 | #define EHCI_ADDR2QTD(x) ((struct ehci_qtd_hw *)((uint32_t)(x) & ~0x1F)) 18 | #define EHCI_ADDR2ITD(x) ((struct ehci_itd_hw *)((uint32_t)(x) & ~0x1F)) 19 | 20 | #if CONFIG_USB_EHCI_FRAME_LIST_SIZE == 1024 21 | #define EHCI_PERIOIDIC_QH_NUM 11 22 | #elif CONFIG_USB_EHCI_FRAME_LIST_SIZE == 512 23 | #define EHCI_PERIOIDIC_QH_NUM 10 24 | #elif CONFIG_USB_EHCI_FRAME_LIST_SIZE == 256 25 | #define EHCI_PERIOIDIC_QH_NUM 9 26 | #else 27 | #error Unsupported frame size list size 28 | #endif 29 | 30 | #define CONFIG_USB_EHCI_QH_NUM CONFIG_USBHOST_PIPE_NUM 31 | #define CONFIG_USB_EHCI_QTD_NUM (CONFIG_USBHOST_PIPE_NUM * 3) 32 | #define CONFIG_USB_EHCI_ITD_NUM 20 33 | 34 | extern uint8_t usbh_get_port_speed(const uint8_t port); 35 | 36 | struct ehci_qh_hw { 37 | struct ehci_qh hw; 38 | uint32_t first_qtd; 39 | struct usbh_urb *urb; 40 | uint8_t remove_in_iaad; 41 | usb_osal_sem_t waitsem; 42 | } __attribute__((aligned(32))); 43 | 44 | struct ehci_qtd_hw { 45 | struct ehci_qtd hw; 46 | struct usbh_urb *urb; 47 | uint32_t total_len; 48 | } __attribute__((aligned(32))); 49 | 50 | struct ehci_itd_hw { 51 | struct ehci_itd hw; 52 | struct usbh_urb *urb; 53 | uint16_t start_frame; 54 | uint8_t mf_unmask; 55 | uint8_t mf_valid; 56 | uint32_t pkt_idx[8]; 57 | usb_slist_t list; 58 | } __attribute__((aligned(32))); 59 | 60 | struct ehci_hcd { 61 | bool ehci_qh_used[CONFIG_USB_EHCI_QH_NUM]; 62 | bool ehci_qtd_used[CONFIG_USB_EHCI_QTD_NUM]; 63 | bool ehci_itd_used[CONFIG_USB_EHCI_ITD_NUM]; 64 | }; 65 | 66 | extern struct ehci_hcd g_ehci_hcd; 67 | extern uint32_t g_framelist[]; 68 | 69 | int ehci_iso_urb_init(struct usbh_urb *urb); 70 | void ehci_remove_itd_urb(struct usbh_urb *urb); 71 | void ehci_scan_isochronous_list(void); 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /cherryusb/inc/usb_hc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #ifndef USB_HC_H 7 | #define USB_HC_H 8 | 9 | #include 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | typedef void (*usbh_complete_callback_t)(void *arg, int nbytes); 16 | 17 | /** 18 | * @brief USB Iso Configuration. 19 | * 20 | * Structure containing the USB Iso configuration. 21 | */ 22 | struct usbh_iso_frame_packet { 23 | uint8_t *transfer_buffer; 24 | uint32_t transfer_buffer_length; 25 | uint32_t actual_length; 26 | int errorcode; 27 | }; 28 | 29 | /** 30 | * @brief USB Urb Configuration. 31 | * 32 | * Structure containing the USB Urb configuration. 33 | */ 34 | struct usbh_urb { 35 | void *hcpriv; 36 | struct usbh_hubport *hport; 37 | struct usb_endpoint_descriptor *ep; 38 | uint8_t data_toggle; 39 | struct usb_setup_packet *setup; 40 | uint8_t *transfer_buffer; 41 | uint32_t transfer_buffer_length; 42 | int transfer_flags; 43 | uint32_t actual_length; 44 | uint32_t timeout; 45 | int errorcode; 46 | uint32_t num_of_iso_packets; 47 | uint32_t start_frame; 48 | usbh_complete_callback_t complete; 49 | void *arg; 50 | #if defined(__ICCARM__) || defined(__ICCRISCV__) || defined(__ICCRX__) 51 | struct usbh_iso_frame_packet *iso_packet; 52 | #else 53 | struct usbh_iso_frame_packet iso_packet[0]; 54 | #endif 55 | }; 56 | 57 | /** 58 | * @brief usb host controller hardware init. 59 | * 60 | * @return On success will return 0, and others indicate fail. 61 | */ 62 | int usb_hc_init(void); 63 | 64 | /** 65 | * @brief Get frame number. 66 | * 67 | * @return frame number. 68 | */ 69 | uint16_t usbh_get_frame_number(void); 70 | /** 71 | * @brief control roothub. 72 | * 73 | * @param setup setup request buffer. 74 | * @param buf buf for reading response or write data. 75 | * @return On success will return 0, and others indicate fail. 76 | */ 77 | int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf); 78 | 79 | /** 80 | * @brief Submit a usb transfer request to an endpoint. 81 | * 82 | * If timeout is not zero, this function will be in poll transfer mode, 83 | * otherwise will be in async transfer mode. 84 | * 85 | * @param urb Usb request block. 86 | * @return On success will return 0, and others indicate fail. 87 | */ 88 | int usbh_submit_urb(struct usbh_urb *urb); 89 | 90 | /** 91 | * @brief Cancel a transfer request. 92 | * 93 | * This function will call When calls usbh_submit_urb and return -ETIMEOUT or -ESHUTDOWN. 94 | * 95 | * @param urb Usb request block. 96 | * @return On success will return 0, and others indicate fail. 97 | */ 98 | int usbh_kill_urb(struct usbh_urb *urb); 99 | 100 | #ifdef __cplusplus 101 | } 102 | #endif 103 | 104 | #endif /* USB_HC_H */ 105 | -------------------------------------------------------------------------------- /cherryusb/inc/usb_hub.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #ifndef USB_HUB_H 7 | #define USB_HUB_H 8 | 9 | /* HUB Class Descriptor Types */ 10 | #define HUB_DESCRIPTOR_TYPE_HUB 0x29 11 | #define HUB_DESCRIPTOR_TYPE_HUB3 0x2A 12 | 13 | /* Hub class requests */ 14 | #define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS 15 | #define HUB_REQUEST_CLEAR_FEATURE USB_REQUEST_CLEAR_FEATURE 16 | #define HUB_REQUEST_SET_FEATURE USB_REQUEST_SET_FEATURE 17 | #define HUB_REQUEST_GET_DESCRIPTOR USB_REQUEST_GET_DESCRIPTOR 18 | #define HUB_REQUEST_SET_DESCRIPTOR USB_REQUEST_SET_DESCRIPTOR 19 | #define HUB_REQUEST_CLEAR_TT_BUFFER (0x08) 20 | #define HUB_REQUEST_RESET_TT (0x09) 21 | #define HUB_REQUEST_GET_TT_STATE (0x0a) 22 | #define HUB_REQUEST_STOP_TT (0x0b) 23 | #define HUB_REQUEST_SET_HUB_DEPTH (0x0C) 24 | 25 | /* Hub class features */ 26 | #define HUB_FEATURE_HUB_C_LOCALPOWER (0x0) 27 | #define HUB_FEATURE_HUB_C_OVERCURRENT (0x1) 28 | 29 | /* Port features */ 30 | #define HUB_PORT_FEATURE_CONNECTION (0x00) 31 | #define HUB_PORT_FEATURE_ENABLE (0x01) 32 | #define HUB_PORT_FEATURE_SUSPEND (0x02) 33 | #define HUB_PORT_FEATURE_OVERCURRENT (0x03) 34 | #define HUB_PORT_FEATURE_RESET (0x04) 35 | #define HUB_PORT_FEATURE_L1 (0x05) 36 | #define HUB_PORT_FEATURE_POWER (0x08) 37 | #define HUB_PORT_FEATURE_LOWSPEED (0x09) 38 | #define HUB_PORT_FEATURE_HIGHSPEED (0x0a) 39 | #define HUB_PORT_FEATURE_C_CONNECTION (0x10) 40 | #define HUB_PORT_FEATURE_C_ENABLE (0x11) 41 | #define HUB_PORT_FEATURE_C_SUSPEND (0x12) 42 | #define HUB_PORT_FEATURE_C_OVER_CURREN (0x13) 43 | #define HUB_PORT_FEATURE_C_RESET (0x14) 44 | #define HUB_PORT_FEATURE_TEST (0x15) 45 | #define HUB_PORT_FEATURE_INDICATOR (0x16) 46 | #define HUB_PORT_FEATURE_C_PORTL1 (0x17) 47 | 48 | /* Hub status */ 49 | #define HUB_STATUS_LOCALPOWER (1 << 0) 50 | #define HUB_STATUS_OVERCURRENT (1 << 1) 51 | 52 | /* Hub status change */ 53 | #define HUB_STATUS_C_LOCALPOWER (1 << 0) 54 | #define HUB_STATUS_C_OVERCURRENT (1 << 1) 55 | 56 | /* Hub port status */ 57 | #define HUB_PORT_STATUS_CONNECTION (1 << 0) 58 | #define HUB_PORT_STATUS_ENABLE (1 << 1) 59 | #define HUB_PORT_STATUS_SUSPEND (1 << 2) 60 | #define HUB_PORT_STATUS_OVERCURRENT (1 << 3) 61 | #define HUB_PORT_STATUS_RESET (1 << 4) 62 | #define HUB_PORT_STATUS_L1 (1 << 5) 63 | #define HUB_PORT_STATUS_POWER (1 << 8) 64 | #define HUB_PORT_STATUS_LOW_SPEED (1 << 9) 65 | #define HUB_PORT_STATUS_HIGH_SPEED (1 << 10) 66 | #define HUB_PORT_STATUS_TEST (1 << 11) 67 | #define HUB_PORT_STATUS_INDICATOR (1 << 12) 68 | 69 | /* Hub port status change */ 70 | #define HUB_PORT_STATUS_C_CONNECTION (1 << 0) 71 | #define HUB_PORT_STATUS_C_ENABLE (1 << 1) 72 | #define HUB_PORT_STATUS_C_SUSPEND (1 << 2) 73 | #define HUB_PORT_STATUS_C_OVERCURRENT (1 << 3) 74 | #define HUB_PORT_STATUS_C_RESET (1 << 4) 75 | #define HUB_PORT_STATUS_C_L1 (1 << 5) 76 | 77 | /* Hub characteristics */ 78 | #define HUB_CHAR_LPSM_SHIFT (0) /* Bits 0-1: Logical Power Switching Mode */ 79 | #define HUB_CHAR_LPSM_MASK (3 << HUB_CHAR_LPSM_SHIFT) 80 | #define HUB_CHAR_LPSM_GANGED (0 << HUB_CHAR_LPSM_SHIFT) 81 | #define HUB_CHAR_LPSM_INDIVIDUAL (1 << HUB_CHAR_LPSM_SHIFT) 82 | #define HUB_CHAR_COMPOUND (1 << 2) /* Bit 2: Compound device */ 83 | #define HUB_CHAR_OCPM_SHIFT (3) /* Bits 3-4: Over-current Protection Mode */ 84 | #define HUB_CHAR_OCPM_MASK (3 << HUB_CHAR_OCPM_SHIFT) 85 | #define HUB_CHAR_OCPM_GLOBAL (0 << HUB_CHAR_OCPM_SHIFT) 86 | #define HUB_CHAR_OCPM_INDIVIDUAL (1 << HUB_CHAR_OCPM_SHIFT) 87 | #define HUB_CHAR_TTTT_SHIFT (5) /* Bits 5-6: TT Think Time */ 88 | #define HUB_CHAR_TTTT_MASK (3 << HUB_CHAR_TTTT_SHIFT) 89 | #define HUB_CHAR_TTTT_8_BITS (0 << HUB_CHAR_TTTT_SHIFT) 90 | #define HUB_CHAR_TTTT_16_BITS (1 << HUB_CHAR_TTTT_SHIFT) 91 | #define HUB_CHAR_TTTT_24_BITS (2 << HUB_CHAR_TTTT_SHIFT) 92 | #define HUB_CHAR_TTTT_32_BITS (3 << HUB_CHAR_TTTT_SHIFT) 93 | #define HUB_CHAR_PORTIND (1 << 7) /* Bit 7: Port Indicators Supported */ 94 | 95 | /* Hub descriptor */ 96 | struct usb_hub_descriptor { 97 | uint8_t bLength; 98 | uint8_t bDescriptorType; 99 | uint8_t bNbrPorts; 100 | uint16_t wHubCharacteristics; 101 | uint8_t bPwrOn2PwrGood; 102 | uint8_t bHubContrCurrent; 103 | uint8_t DeviceRemovable; 104 | uint8_t PortPwrCtrlMask; 105 | } __PACKED; 106 | 107 | #define USB_SIZEOF_HUB_DESC 9 108 | 109 | /* Hub status */ 110 | struct hub_status { 111 | uint16_t wPortStatus; 112 | uint16_t wPortChange; 113 | }; 114 | 115 | /* Hub port status */ 116 | struct hub_port_status { 117 | uint16_t wPortStatus; 118 | uint16_t wPortChange; 119 | }; 120 | 121 | #endif /* USB_HUB_H */ 122 | -------------------------------------------------------------------------------- /cherryusb/inc/usb_log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #ifndef USB_LOG_H 7 | #define USB_LOG_H 8 | 9 | //#include 10 | 11 | /* DEBUG level */ 12 | #define USB_DBG_ERROR 0 13 | #define USB_DBG_WARNING 1 14 | #define USB_DBG_INFO 2 15 | #define USB_DBG_LOG 3 16 | 17 | #ifndef USB_DBG_TAG 18 | #define USB_DBG_TAG "USB" 19 | #endif 20 | /* 21 | * The color for terminal (foreground) 22 | * BLACK 30 23 | * RED 31 24 | * GREEN 32 25 | * YELLOW 33 26 | * BLUE 34 27 | * PURPLE 35 28 | * CYAN 36 29 | * WHITE 37 30 | */ 31 | 32 | #ifdef CONFIG_USB_PRINTF_COLOR_ENABLE 33 | #define _USB_DBG_COLOR(n) CONFIG_USB_PRINTF("\033[" #n "m") 34 | #define _USB_DBG_LOG_HDR(lvl_name, color_n) \ 35 | CONFIG_USB_PRINTF("\033[" #color_n "m[" lvl_name "/" USB_DBG_TAG "] ") 36 | #define _USB_DBG_LOG_X_END \ 37 | CONFIG_USB_PRINTF("\033[0m") 38 | #else 39 | #define _USB_DBG_COLOR(n) 40 | #define _USB_DBG_LOG_HDR(lvl_name, color_n) \ 41 | CONFIG_USB_PRINTF("[" lvl_name "/" USB_DBG_TAG "] ") 42 | #define _USB_DBG_LOG_X_END 43 | #endif 44 | 45 | #define usb_dbg_log_line(lvl, color_n, fmt, ...) \ 46 | do { \ 47 | _USB_DBG_LOG_HDR(lvl, color_n); \ 48 | CONFIG_USB_PRINTF(fmt, ##__VA_ARGS__); \ 49 | _USB_DBG_LOG_X_END; \ 50 | } while (0) 51 | 52 | #if (CONFIG_USB_DBG_LEVEL >= USB_DBG_LOG) 53 | #define USB_LOG_DBG(fmt, ...) usb_dbg_log_line("D", 0, fmt, ##__VA_ARGS__) 54 | #else 55 | #define USB_LOG_DBG(...) {} 56 | #endif 57 | 58 | #if (CONFIG_USB_DBG_LEVEL >= USB_DBG_INFO) 59 | #define USB_LOG_INFO(fmt, ...) usb_dbg_log_line("I", 32, fmt, ##__VA_ARGS__) 60 | #else 61 | #define USB_LOG_INFO(...) {} 62 | #endif 63 | 64 | #if (CONFIG_USB_DBG_LEVEL >= USB_DBG_WARNING) 65 | #define USB_LOG_WRN(fmt, ...) usb_dbg_log_line("W", 33, fmt, ##__VA_ARGS__) 66 | #else 67 | #define USB_LOG_WRN(...) {} 68 | #endif 69 | 70 | #if (CONFIG_USB_DBG_LEVEL >= USB_DBG_ERROR) 71 | #define USB_LOG_ERR(fmt, ...) usb_dbg_log_line("E", 31, fmt, ##__VA_ARGS__) 72 | #else 73 | #define USB_LOG_ERR(...) {} 74 | #endif 75 | 76 | #define USB_LOG_RAW(...) CONFIG_USB_PRINTF(__VA_ARGS__) 77 | 78 | void usb_assert(const char *filename, int linenum); 79 | #define USB_ASSERT(f) \ 80 | do { \ 81 | if (!(f)) \ 82 | usb_assert(__FILE__, __LINE__); \ 83 | } while (0) 84 | 85 | #endif /* USB_LOG_H */ 86 | -------------------------------------------------------------------------------- /cherryusb/inc/usb_mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #ifndef USB_MEM_H 7 | #define USB_MEM_H 8 | 9 | #define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE))) 10 | 11 | #if (CONFIG_USB_ALIGN_SIZE > 4) 12 | static inline void *usb_iomalloc(size_t size) 13 | { 14 | void *ptr; 15 | void *align_ptr; 16 | int uintptr_size; 17 | size_t align_size; 18 | uint32_t align = CONFIG_USB_ALIGN_SIZE; 19 | 20 | /* sizeof pointer */ 21 | uintptr_size = sizeof(void *); 22 | uintptr_size -= 1; 23 | 24 | /* align the alignment size to uintptr size byte */ 25 | align = ((align + uintptr_size) & ~uintptr_size); 26 | 27 | /* get total aligned size */ 28 | align_size = ((size + uintptr_size) & ~uintptr_size) + align; 29 | /* allocate memory block from heap */ 30 | ptr = usb_malloc(align_size); 31 | if (ptr != NULL) { 32 | /* the allocated memory block is aligned */ 33 | if (((unsigned long)ptr & (align - 1)) == 0) { 34 | align_ptr = (void *)((unsigned long)ptr + align); 35 | } else { 36 | align_ptr = (void *)(((unsigned long)ptr + (align - 1)) & ~(align - 1)); 37 | } 38 | 39 | /* set the pointer before alignment pointer to the real pointer */ 40 | *((unsigned long *)((unsigned long)align_ptr - sizeof(void *))) = (unsigned long)ptr; 41 | 42 | ptr = align_ptr; 43 | } 44 | 45 | return ptr; 46 | } 47 | 48 | static inline void usb_iofree(void *ptr) 49 | { 50 | void *real_ptr; 51 | 52 | real_ptr = (void *)*(unsigned long *)((unsigned long)ptr - sizeof(void *)); 53 | usb_free(real_ptr); 54 | } 55 | #else 56 | #define usb_iomalloc(size) usb_malloc(size) 57 | #define usb_iofree(ptr) usb_free(ptr) 58 | #endif 59 | 60 | #endif /* USB_MEM_H */ 61 | -------------------------------------------------------------------------------- /cherryusb/inc/usb_msc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #ifndef USB_MSC_H 7 | #define USB_MSC_H 8 | 9 | /* MSC Subclass Codes */ 10 | #define MSC_SUBCLASS_RBC 0x01 /* Reduced block commands (e.g., flash devices) */ 11 | #define MSC_SUBCLASS_SFF8020I_MMC2 0x02 /* SFF-8020i/MMC-2 (ATAPI) (e.g., C/DVD) */ 12 | #define MSC_SUBCLASS_QIC157 0x03 /* QIC-157 (e.g., tape device) */ 13 | #define MSC_SUBCLASS_UFI 0x04 /* e.g. floppy device */ 14 | #define MSC_SUBCLASS_SFF8070I 0x05 /* SFF-8070i (e.g. floppy disk) */ 15 | #define MSC_SUBCLASS_SCSI 0x06 /* SCSI transparent */ 16 | 17 | /* MSC Protocol Codes */ 18 | #define MSC_PROTOCOL_CBI_INT 0x00 /* CBI transport with command completion interrupt */ 19 | #define MSC_PROTOCOL_CBI_NOINT 0x01 /* CBI transport without command completion interrupt */ 20 | #define MSC_PROTOCOL_BULK_ONLY 0x50 /* Bulk only transport */ 21 | 22 | /* MSC Request Codes */ 23 | #define MSC_REQUEST_RESET 0xFF 24 | #define MSC_REQUEST_GET_MAX_LUN 0xFE 25 | 26 | /** MSC Command Block Wrapper (CBW) Signature */ 27 | #define MSC_CBW_Signature 0x43425355 28 | /** Bulk-only Command Status Wrapper (CSW) Signature */ 29 | #define MSC_CSW_Signature 0x53425355 30 | 31 | /** MSC Command Block Status Values */ 32 | #define CSW_STATUS_CMD_PASSED 0x00 33 | #define CSW_STATUS_CMD_FAILED 0x01 34 | #define CSW_STATUS_PHASE_ERROR 0x02 35 | 36 | #define MSC_MAX_CDB_LEN (16) /* Max length of SCSI Command Data Block */ 37 | 38 | /** MSC Bulk-Only Command Block Wrapper (CBW) */ 39 | struct CBW { 40 | uint32_t dSignature; /* 'USBC' = 0x43425355 */ 41 | uint32_t dTag; /* Depends on command id */ 42 | uint32_t dDataLength; /* Number of bytes that host expects to transfer */ 43 | uint8_t bmFlags; /* Bit 7: Direction=IN (other obsolete or reserved) */ 44 | uint8_t bLUN; /* LUN (normally 0) */ 45 | uint8_t bCBLength; /* len of cdb[] */ 46 | uint8_t CB[MSC_MAX_CDB_LEN]; /* Command Data Block */ 47 | } __PACKED; 48 | 49 | #define USB_SIZEOF_MSC_CBW 31 50 | 51 | /** MSC Bulk-Only Command Status Wrapper (CSW) */ 52 | struct CSW { 53 | uint32_t dSignature; /* 'USBS' = 0x53425355 */ 54 | uint32_t dTag; /* Same tag as original command */ 55 | uint32_t dDataResidue; /* Amount not transferred */ 56 | uint8_t bStatus; /* Status of transfer */ 57 | } __PACKED; 58 | 59 | #define USB_SIZEOF_MSC_CSW 13 60 | 61 | /*Length of template descriptor: 23 bytes*/ 62 | #define MSC_DESCRIPTOR_LEN (9 + 7 + 7) 63 | // clang-format off 64 | #define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, wMaxPacketSize, str_idx) \ 65 | /* Interface */ \ 66 | 0x09, /* bLength */ \ 67 | USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ 68 | bFirstInterface, /* bInterfaceNumber */ \ 69 | 0x00, /* bAlternateSetting */ \ 70 | 0x02, /* bNumEndpoints */ \ 71 | USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \ 72 | MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */ \ 73 | MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */ \ 74 | str_idx, /* iInterface */ \ 75 | 0x07, /* bLength */ \ 76 | USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ 77 | out_ep, /* bEndpointAddress */ \ 78 | 0x02, /* bmAttributes */ \ 79 | WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \ 80 | 0x00, /* bInterval */ \ 81 | 0x07, /* bLength */ \ 82 | USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ 83 | in_ep, /* bEndpointAddress */ \ 84 | 0x02, /* bmAttributes */ \ 85 | WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \ 86 | 0x00 /* bInterval */ 87 | // clang-format on 88 | 89 | #endif /* USB_MSC_H */ 90 | -------------------------------------------------------------------------------- /cherryusb/inc/usb_osal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #ifndef USB_OSAL_H 7 | #define USB_OSAL_H 8 | 9 | #include 10 | 11 | #define USB_OSAL_WAITING_FOREVER (0xFFFFFFFFU) 12 | 13 | typedef void *usb_osal_thread_t; 14 | typedef void *usb_osal_sem_t; 15 | typedef void *usb_osal_mutex_t; 16 | typedef void *usb_osal_mq_t; 17 | typedef void (*usb_thread_entry_t)(void *argument); 18 | 19 | /* 20 | * Task with smaller priority value indicates higher task priority 21 | */ 22 | usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args); 23 | void usb_osal_thread_delete(usb_osal_thread_t thread); 24 | 25 | usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count); 26 | void usb_osal_sem_delete(usb_osal_sem_t sem); 27 | int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout); 28 | int usb_osal_sem_give(usb_osal_sem_t sem); 29 | 30 | usb_osal_mutex_t usb_osal_mutex_create(void); 31 | void usb_osal_mutex_delete(usb_osal_mutex_t mutex); 32 | int usb_osal_mutex_take(usb_osal_mutex_t mutex); 33 | int usb_osal_mutex_give(usb_osal_mutex_t mutex); 34 | 35 | usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs); 36 | int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr); 37 | int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout); 38 | 39 | int usb_osal_enter_critical_section(void); 40 | void usb_osal_leave_critical_section(int flag); 41 | 42 | void usb_osal_msleep(uint32_t delay); 43 | 44 | #endif /* USB_OSAL_H */ 45 | -------------------------------------------------------------------------------- /cherryusb/inc/usb_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022-2023, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #ifndef USB_UTIL_H 7 | #define USB_UTIL_H 8 | 9 | #if defined(__CC_ARM) 10 | #ifndef __USED 11 | #define __USED __attribute__((used)) 12 | #endif 13 | #ifndef __WEAK 14 | #define __WEAK __attribute__((weak)) 15 | #endif 16 | #ifndef __PACKED 17 | #define __PACKED __attribute__((packed)) 18 | #endif 19 | #ifndef __PACKED_STRUCT 20 | #define __PACKED_STRUCT __packed struct 21 | #endif 22 | #ifndef __PACKED_UNION 23 | #define __PACKED_UNION __packed union 24 | #endif 25 | #ifndef __ALIGNED 26 | #define __ALIGNED(x) __attribute__((aligned(x))) 27 | #endif 28 | #elif defined(__GNUC__) 29 | #ifndef __USED 30 | #define __USED __attribute__((used)) 31 | #endif 32 | #ifndef __WEAK 33 | #define __WEAK __attribute__((weak)) 34 | #endif 35 | #ifndef __PACKED 36 | #define __PACKED __attribute__((packed, aligned(1))) 37 | #endif 38 | #ifndef __PACKED_STRUCT 39 | #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) 40 | #endif 41 | #ifndef __PACKED_UNION 42 | #define __PACKED_UNION union __attribute__((packed, aligned(1))) 43 | #endif 44 | #ifndef __ALIGNED 45 | #define __ALIGNED(x) __attribute__((aligned(x))) 46 | #endif 47 | #elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__) 48 | #ifndef __USED 49 | #if defined(__ICCARM_V8) || defined (__ICCRISCV__) 50 | #define __USED __attribute__((used)) 51 | #else 52 | #define __USED __root 53 | #endif 54 | #endif 55 | 56 | #ifndef __WEAK 57 | #if defined(__ICCARM_V8) || defined (__ICCRISCV__) 58 | #define __WEAK __attribute__((weak)) 59 | #else 60 | #define __WEAK _Pragma("__weak") 61 | #endif 62 | #endif 63 | 64 | #ifndef __PACKED 65 | #if defined(__ICCARM_V8) || defined (__ICCRISCV__) 66 | #define __PACKED __attribute__((packed, aligned(1))) 67 | #else 68 | /* Needs IAR language extensions */ 69 | #define __PACKED __packed 70 | #endif 71 | #endif 72 | 73 | #ifndef __PACKED_STRUCT 74 | #if defined(__ICCARM_V8) || defined (__ICCRISCV__) 75 | #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) 76 | #else 77 | /* Needs IAR language extensions */ 78 | #define __PACKED_STRUCT __packed struct 79 | #endif 80 | #endif 81 | 82 | #ifndef __PACKED_UNION 83 | #if defined(__ICCARM_V8) || defined (__ICCRISCV__) 84 | #define __PACKED_UNION union __attribute__((packed, aligned(1))) 85 | #else 86 | /* Needs IAR language extensions */ 87 | #define __PACKED_UNION __packed union 88 | #endif 89 | #endif 90 | 91 | #ifndef __ALIGNED 92 | #if defined(__ICCARM_V8) || defined (__ICCRISCV__) 93 | #define __ALIGNED(x) __attribute__((aligned(x))) 94 | #elif (__VER__ >= 7080000) 95 | /* Needs IAR language extensions */ 96 | #define __ALIGNED(x) __attribute__((aligned(x))) 97 | #else 98 | #warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored. 99 | #define __ALIGNED(x) 100 | #endif 101 | #endif 102 | 103 | #endif 104 | 105 | #ifndef __ALIGN_BEGIN 106 | #define __ALIGN_BEGIN 107 | #endif 108 | #ifndef __ALIGN_END 109 | #define __ALIGN_END __attribute__((aligned(4))) 110 | #endif 111 | 112 | #ifndef ARG_UNUSED 113 | #define ARG_UNUSED(x) (void)(x) 114 | #endif 115 | 116 | #ifndef LO_BYTE 117 | #define LO_BYTE(x) ((uint8_t)(x & 0x00FF)) 118 | #endif 119 | 120 | #ifndef HI_BYTE 121 | #define HI_BYTE(x) ((uint8_t)((x & 0xFF00) >> 8)) 122 | #endif 123 | 124 | #ifndef MAX 125 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 126 | #endif 127 | 128 | #ifndef MIN 129 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 130 | #endif 131 | 132 | #ifndef BCD 133 | #define BCD(x) ((((x) / 10) << 4) | ((x) % 10)) 134 | #endif 135 | 136 | #ifdef BIT 137 | #undef BIT 138 | #define BIT(n) (1UL << (n)) 139 | #else 140 | #define BIT(n) (1UL << (n)) 141 | #endif 142 | 143 | #ifndef ARRAY_SIZE 144 | #define ARRAY_SIZE(array) \ 145 | ((int)((sizeof(array) / sizeof((array)[0])))) 146 | #endif 147 | 148 | #ifndef BSWAP16 149 | #define BSWAP16(u16) (__builtin_bswap16(u16)) 150 | #endif 151 | #ifndef BSWAP32 152 | #define BSWAP32(u32) (__builtin_bswap32(u32)) 153 | #endif 154 | 155 | #define GET_BE16(field) \ 156 | (((uint16_t)(field)[0] << 8) | ((uint16_t)(field)[1])) 157 | 158 | #define GET_BE32(field) \ 159 | (((uint32_t)(field)[0] << 24) | ((uint32_t)(field)[1] << 16) | ((uint32_t)(field)[2] << 8) | ((uint32_t)(field)[3] << 0)) 160 | 161 | #define SET_BE16(field, value) \ 162 | do { \ 163 | (field)[0] = (uint8_t)((value) >> 8); \ 164 | (field)[1] = (uint8_t)((value) >> 0); \ 165 | } while (0) 166 | 167 | #define SET_BE24(field, value) \ 168 | do { \ 169 | (field)[0] = (uint8_t)((value) >> 16); \ 170 | (field)[1] = (uint8_t)((value) >> 8); \ 171 | (field)[2] = (uint8_t)((value) >> 0); \ 172 | } while (0) 173 | 174 | #define SET_BE32(field, value) \ 175 | do { \ 176 | (field)[0] = (uint8_t)((value) >> 24); \ 177 | (field)[1] = (uint8_t)((value) >> 16); \ 178 | (field)[2] = (uint8_t)((value) >> 8); \ 179 | (field)[3] = (uint8_t)((value) >> 0); \ 180 | } while (0) 181 | 182 | #define WBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF) 183 | #define DBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF), ((x >> 16) & 0xFF), ((x >> 24) & 0xFF) 184 | 185 | #define PP_NARG(...) \ 186 | PP_NARG_(__VA_ARGS__, PP_RSEQ_N()) 187 | #define PP_NARG_(...) \ 188 | PP_ARG_N(__VA_ARGS__) 189 | #define PP_ARG_N( \ 190 | _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ 191 | _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ 192 | _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ 193 | _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ 194 | _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ 195 | _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ 196 | _61, _62, _63, N, ...) N 197 | #define PP_RSEQ_N() \ 198 | 63, 62, 61, 60, \ 199 | 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \ 200 | 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \ 201 | 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \ 202 | 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \ 203 | 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \ 204 | 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 205 | 206 | #endif /* USB_UTIL_H */ 207 | -------------------------------------------------------------------------------- /cherryusb/inc/usbh_core.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #ifndef USBH_CORE_H 7 | #define USBH_CORE_H 8 | 9 | #include 10 | #include 11 | #include 12 | //#include 13 | 14 | #include "usb_config.h" 15 | #include "usb_util.h" 16 | #include "usb_errno.h" 17 | #include "usb_def.h" 18 | #include "usb_list.h" 19 | #include "usb_mem.h" 20 | #include "usb_log.h" 21 | #include "usb_hc.h" 22 | #include "usb_osal.h" 23 | #include "usb_hub.h" 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | #define USB_CLASS_MATCH_VENDOR 0x0001 30 | #define USB_CLASS_MATCH_PRODUCT 0x0002 31 | #define USB_CLASS_MATCH_INTF_CLASS 0x0004 32 | #define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008 33 | #define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010 34 | 35 | #define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i)) 36 | #define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i)) 37 | 38 | #ifdef __ARMCC_VERSION /* ARM C Compiler */ 39 | #define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1) 40 | #elif defined(__GNUC__) 41 | #define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1) 42 | #elif defined(__ICCARM__) || defined(__ICCRX__) 43 | #pragma section = "usbh_class_info" 44 | #define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1) 45 | #endif 46 | 47 | #define USBH_EP_INIT(ep, ep_desc) \ 48 | do { \ 49 | ep = ep_desc; \ 50 | USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n", \ 51 | ep_desc->bEndpointAddress, \ 52 | USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes), \ 53 | USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize), \ 54 | ep_desc->bInterval, \ 55 | USB_GET_MULT(ep_desc->bmAttributes)); \ 56 | } while (0) 57 | 58 | struct usbh_class_info { 59 | uint8_t match_flags; /* Used for product specific matches; range is inclusive */ 60 | uint8_t class; /* Base device class code */ 61 | uint8_t subclass; /* Sub-class, depends on base class. Eg. */ 62 | uint8_t protocol; /* Protocol, depends on base class. Eg. */ 63 | uint16_t vid; /* Vendor ID (for vendor/product specific devices) */ 64 | uint16_t pid; /* Product ID (for vendor/product specific devices) */ 65 | const struct usbh_class_driver *class_driver; 66 | }; 67 | 68 | struct usbh_hubport; 69 | struct usbh_class_driver { 70 | const char *driver_name; 71 | int (*connect)(struct usbh_hubport *hport, uint8_t intf); 72 | int (*disconnect)(struct usbh_hubport *hport, uint8_t intf); 73 | }; 74 | 75 | struct usbh_endpoint { 76 | struct usb_endpoint_descriptor ep_desc; 77 | }; 78 | 79 | struct usbh_interface_altsetting { 80 | struct usb_interface_descriptor intf_desc; 81 | struct usbh_endpoint ep[CONFIG_USBHOST_MAX_ENDPOINTS]; 82 | }; 83 | 84 | struct usbh_interface { 85 | char devname[CONFIG_USBHOST_DEV_NAMELEN]; 86 | struct usbh_class_driver *class_driver; 87 | void *priv; 88 | struct usbh_interface_altsetting altsetting[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS]; 89 | uint8_t altsetting_num; 90 | }; 91 | 92 | struct usbh_configuration { 93 | struct usb_configuration_descriptor config_desc; 94 | struct usbh_interface intf[CONFIG_USBHOST_MAX_INTERFACES]; 95 | }; 96 | 97 | struct usbh_hubport { 98 | bool connected; /* True: device connected; false: disconnected */ 99 | uint8_t port; /* Hub port index */ 100 | uint8_t dev_addr; /* device address */ 101 | uint8_t speed; /* device speed */ 102 | struct usb_endpoint_descriptor ep0; 103 | struct usb_device_descriptor device_desc; 104 | struct usbh_configuration config; 105 | const char *iManufacturer; 106 | const char *iProduct; 107 | const char *iSerialNumber; 108 | uint8_t *raw_config_desc; 109 | struct usb_setup_packet *setup; 110 | struct usbh_hub *parent; 111 | #ifdef CONFIG_USBHOST_XHCI 112 | uint32_t protocol; /* port protocol, for xhci, some ports are USB2.0, others are USB3.0 */ 113 | #endif 114 | usb_osal_thread_t thread; 115 | }; 116 | 117 | struct usbh_hub { 118 | usb_slist_t list; 119 | bool connected; 120 | bool is_roothub; 121 | uint8_t index; 122 | uint8_t hub_addr; 123 | struct usb_endpoint_descriptor *intin; 124 | uint8_t *int_buffer; 125 | struct usbh_urb intin_urb; 126 | struct usb_hub_descriptor hub_desc; 127 | struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS]; 128 | struct usbh_hubport *parent; 129 | }; 130 | 131 | static inline void usbh_control_urb_fill(struct usbh_urb *urb, 132 | struct usbh_hubport *hport, 133 | struct usb_setup_packet *setup, 134 | uint8_t *transfer_buffer, 135 | uint32_t transfer_buffer_length, 136 | uint32_t timeout, 137 | usbh_complete_callback_t complete, 138 | void *arg) 139 | { 140 | urb->hport = hport; 141 | urb->ep = &hport->ep0; 142 | urb->setup = setup; 143 | urb->transfer_buffer = transfer_buffer; 144 | urb->transfer_buffer_length = transfer_buffer_length; 145 | urb->timeout = timeout; 146 | urb->complete = complete; 147 | urb->arg = arg; 148 | } 149 | 150 | static inline void usbh_bulk_urb_fill(struct usbh_urb *urb, 151 | struct usbh_hubport *hport, 152 | struct usb_endpoint_descriptor *ep, 153 | uint8_t *transfer_buffer, 154 | uint32_t transfer_buffer_length, 155 | uint32_t timeout, 156 | usbh_complete_callback_t complete, 157 | void *arg) 158 | { 159 | urb->hport = hport; 160 | urb->ep = ep; 161 | urb->setup = NULL; 162 | urb->transfer_buffer = transfer_buffer; 163 | urb->transfer_buffer_length = transfer_buffer_length; 164 | urb->timeout = timeout; 165 | urb->complete = complete; 166 | urb->arg = arg; 167 | } 168 | 169 | static inline void usbh_int_urb_fill(struct usbh_urb *urb, 170 | struct usbh_hubport *hport, 171 | struct usb_endpoint_descriptor *ep, 172 | uint8_t *transfer_buffer, 173 | uint32_t transfer_buffer_length, 174 | uint32_t timeout, 175 | usbh_complete_callback_t complete, 176 | void *arg) 177 | { 178 | urb->hport = hport; 179 | urb->ep = ep; 180 | urb->setup = NULL; 181 | urb->transfer_buffer = transfer_buffer; 182 | urb->transfer_buffer_length = transfer_buffer_length; 183 | urb->timeout = timeout; 184 | urb->complete = complete; 185 | urb->arg = arg; 186 | } 187 | 188 | /** 189 | * @brief Submit an control transfer to an endpoint. 190 | * This is a blocking method; this method will not return until the transfer has completed. 191 | * Default timeout is 500ms. 192 | * 193 | * @param pipe The control endpoint to send/receive the control request. 194 | * @param setup Setup packet to be sent. 195 | * @param buffer buffer used for sending the request and for returning any responses. 196 | * @return On success will return 0, and others indicate fail. 197 | */ 198 | int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer); 199 | 200 | /** 201 | * @brief Retrieves a USB string descriptor from a specific hub port. 202 | * 203 | * This function is responsible for retrieving the USB string descriptor 204 | * with the specified index from the USB device connected to the given hub port. 205 | * The retrieved descriptor is stored in the output buffer provided. 206 | * 207 | * @param hport Pointer to the USB hub port structure. 208 | * @param index Index of the string descriptor to retrieve. 209 | * @param output Pointer to the buffer where the retrieved descriptor will be stored. 210 | * @return On success will return 0, and others indicate fail. 211 | */ 212 | int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output); 213 | 214 | /** 215 | * @brief Sets the alternate setting for a USB interface on a specific hub port. 216 | * 217 | * This function is responsible for setting the alternate setting of the 218 | * specified USB interface on the USB device connected to the given hub port. 219 | * The interface and alternate setting are identified by the respective parameters. 220 | * 221 | * @param hport Pointer to the USB hub port structure. 222 | * @param intf Interface number to set the alternate setting for. 223 | * @param altsetting Alternate setting value to set for the interface. 224 | * @return On success will return 0, and others indicate fail. 225 | */ 226 | int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting); 227 | 228 | int usbh_initialize(void); 229 | void *usbh_find_class_instance(const char *devname); 230 | 231 | int lsusb(int argc, char **argv); 232 | 233 | #ifdef __cplusplus 234 | } 235 | #endif 236 | 237 | #endif /* USBH_CORE_H */ 238 | -------------------------------------------------------------------------------- /cherryusb/inc/usbh_hid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #ifndef USBH_HID_H 7 | #define USBH_HID_H 8 | 9 | #include "usb_hid.h" 10 | 11 | struct usbh_hid { 12 | struct usbh_hubport *hport; 13 | struct usb_endpoint_descriptor *intin; /* INTR IN endpoint */ 14 | struct usb_endpoint_descriptor *intout; /* INTR OUT endpoint */ 15 | struct usbh_urb intin_urb; /* INTR IN urb */ 16 | struct usbh_urb intout_urb; /* INTR OUT urb */ 17 | 18 | uint8_t report_desc[128]; 19 | uint8_t intf; /* interface number */ 20 | uint8_t minor; 21 | }; 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration); 28 | int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer); 29 | 30 | void usbh_hid_run(struct usbh_hid *hid_class); 31 | void usbh_hid_stop(struct usbh_hid *hid_class); 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | #endif /* USBH_HID_H */ 38 | -------------------------------------------------------------------------------- /cherryusb/inc/usbh_hub.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #ifndef USBH_HUB_H 7 | #define USBH_HUB_H 8 | 9 | #include "usbh_core.h" 10 | #include "usb_hub.h" 11 | 12 | #define USBH_HUB_MAX_PORTS 4 13 | /* Maximum size of an interrupt IN transfer */ 14 | #define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3) 15 | 16 | extern usb_slist_t hub_class_head; 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | void usbh_roothub_thread_wakeup(uint8_t port); 22 | int usbh_hub_initialize(void); 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif /* USBH_HUB_H */ 28 | -------------------------------------------------------------------------------- /cherryusb/inc/usbh_msc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #ifndef USBH_MSC_H 7 | #define USBH_MSC_H 8 | 9 | #include "usb_msc.h" 10 | #include "usb_scsi.h" 11 | 12 | struct usbh_msc { 13 | struct usbh_hubport *hport; 14 | struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ 15 | struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ 16 | struct usbh_urb bulkin_urb; /* Bulk IN urb */ 17 | struct usbh_urb bulkout_urb; /* Bulk OUT urb */ 18 | 19 | uint8_t intf; /* Data interface number */ 20 | uint8_t sdchar; 21 | uint32_t blocknum; /* Number of blocks on the USB mass storage device */ 22 | uint16_t blocksize; /* Block size of USB mass storage device */ 23 | 24 | void *user; 25 | }; 26 | 27 | struct usbh_msc_modeswitch_config { 28 | const char *name; 29 | uint16_t vid; /* Vendor ID (for vendor/product specific devices) */ 30 | uint16_t pid; /* Product ID (for vendor/product specific devices) */ 31 | const uint8_t *message_content; 32 | }; 33 | 34 | void usbh_msc_modeswitch_enable(struct usbh_msc_modeswitch_config *config); 35 | int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors); 36 | int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors); 37 | 38 | void usbh_msc_run(struct usbh_msc *msc_class); 39 | void usbh_msc_stop(struct usbh_msc *msc_class); 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | 49 | #endif /* USBH_MSC_H */ 50 | -------------------------------------------------------------------------------- /cherryusb/usb_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #ifndef CHERRYUSB_CONFIG_H 7 | #define CHERRYUSB_CONFIG_H 8 | 9 | 10 | #define CHERRYUSB_VERSION 0x001002 11 | 12 | /* ================ USB common Configuration ================ */ 13 | 14 | int printk(char *fmt, ...); 15 | int snprintf(char *sbuf, int len, const char *fmt, ...); 16 | void *xos_malloc(int size); 17 | void xos_free(void *p); 18 | 19 | 20 | #define CONFIG_USB_PRINTF(...) printk(__VA_ARGS__) 21 | 22 | #define usb_malloc(size) xos_malloc(size) 23 | #define usb_free(ptr) xos_free(ptr) 24 | 25 | #ifndef CONFIG_USB_DBG_LEVEL 26 | #define CONFIG_USB_DBG_LEVEL USB_DBG_INFO 27 | #endif 28 | 29 | /* Enable print with color */ 30 | #define CONFIG_USB_PRINTF_COLOR_ENABLE 31 | 32 | /* data align size when use dma */ 33 | #ifndef CONFIG_USB_ALIGN_SIZE 34 | #define CONFIG_USB_ALIGN_SIZE 4 35 | #endif 36 | 37 | /* attribute data into no cache ram */ 38 | #define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) 39 | 40 | /* ================= USB Device Stack Configuration ================ */ 41 | 42 | /* Ep0 max transfer buffer, specially for receiving data from ep0 out */ 43 | #define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256 44 | 45 | /* Setup packet log for debug */ 46 | // #define CONFIG_USBDEV_SETUP_LOG_PRINT 47 | 48 | /* Check if the input descriptor is correct */ 49 | // #define CONFIG_USBDEV_DESC_CHECK 50 | 51 | /* Enable test mode */ 52 | // #define CONFIG_USBDEV_TEST_MODE 53 | 54 | #ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE 55 | #define CONFIG_USBDEV_MSC_BLOCK_SIZE 512 56 | #endif 57 | 58 | #ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING 59 | #define CONFIG_USBDEV_MSC_MANUFACTURER_STRING "" 60 | #endif 61 | 62 | #ifndef CONFIG_USBDEV_MSC_PRODUCT_STRING 63 | #define CONFIG_USBDEV_MSC_PRODUCT_STRING "" 64 | #endif 65 | 66 | #ifndef CONFIG_USBDEV_MSC_VERSION_STRING 67 | #define CONFIG_USBDEV_MSC_VERSION_STRING "0.01" 68 | #endif 69 | 70 | // #define CONFIG_USBDEV_MSC_THREAD 71 | 72 | #ifndef CONFIG_USBDEV_MSC_PRIO 73 | #define CONFIG_USBDEV_MSC_PRIO 4 74 | #endif 75 | 76 | #ifndef CONFIG_USBDEV_MSC_STACKSIZE 77 | #define CONFIG_USBDEV_MSC_STACKSIZE 2048 78 | #endif 79 | 80 | #ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 81 | #define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156 82 | #endif 83 | 84 | #ifndef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 85 | #define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1536 86 | #endif 87 | 88 | #ifndef CONFIG_USBDEV_RNDIS_VENDOR_ID 89 | #define CONFIG_USBDEV_RNDIS_VENDOR_ID 0x0000ffff 90 | #endif 91 | 92 | #ifndef CONFIG_USBDEV_RNDIS_VENDOR_DESC 93 | #define CONFIG_USBDEV_RNDIS_VENDOR_DESC "CherryUSB" 94 | #endif 95 | 96 | #define CONFIG_USBDEV_RNDIS_USING_LWIP 97 | 98 | /* ================ USB HOST Stack Configuration ================== */ 99 | 100 | #define CONFIG_USBHOST_MAX_RHPORTS 1 101 | #define CONFIG_USBHOST_MAX_EXTHUBS 1 102 | #define CONFIG_USBHOST_MAX_EHPORTS 4 103 | #define CONFIG_USBHOST_MAX_INTERFACES 6 104 | #define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1 105 | #define CONFIG_USBHOST_MAX_ENDPOINTS 4 106 | 107 | #define CONFIG_USBHOST_MAX_CDC_ACM_CLASS 4 108 | #define CONFIG_USBHOST_MAX_HID_CLASS 4 109 | #define CONFIG_USBHOST_MAX_MSC_CLASS 2 110 | #define CONFIG_USBHOST_MAX_AUDIO_CLASS 1 111 | #define CONFIG_USBHOST_MAX_VIDEO_CLASS 1 112 | 113 | #define CONFIG_USBHOST_DEV_NAMELEN 16 114 | 115 | #ifndef CONFIG_USBHOST_PSC_PRIO 116 | #define CONFIG_USBHOST_PSC_PRIO 4 117 | #endif 118 | #ifndef CONFIG_USBHOST_PSC_STACKSIZE 119 | #define CONFIG_USBHOST_PSC_STACKSIZE 2048 120 | #endif 121 | 122 | //#define CONFIG_USBHOST_GET_STRING_DESC 123 | 124 | // #define CONFIG_USBHOST_MSOS_ENABLE 125 | #define CONFIG_USBHOST_MSOS_VENDOR_CODE 0x00 126 | 127 | /* Ep0 max transfer buffer */ 128 | #define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512 129 | 130 | #ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 131 | #define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500 132 | #endif 133 | 134 | #ifndef CONFIG_USBHOST_MSC_TIMEOUT 135 | #define CONFIG_USBHOST_MSC_TIMEOUT 5000 136 | #endif 137 | 138 | /* ================ USB Device Port Configuration ================*/ 139 | 140 | //#define USBD_IRQHandler USBD_IRQHandler 141 | //#define USB_BASE (0x40080000UL) 142 | //#define USB_NUM_BIDIR_ENDPOINTS 4 143 | 144 | /* ================ USB Host Port Configuration ==================*/ 145 | 146 | #define CONFIG_USBHOST_PIPE_NUM 10 147 | 148 | /* ================ EHCI Configuration ================ */ 149 | 150 | #define CONFIG_USB_EHCI_HCCR_BASE (0x41001100) 151 | #define CONFIG_USB_EHCI_HCOR_BASE (0x41001140) 152 | #define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024 153 | // #define CONFIG_USB_EHCI_INFO_ENABLE 154 | // #define CONFIG_USB_EHCI_HCOR_RESERVED_DISABLE 155 | // #define CONFIG_USB_EHCI_CONFIGFLAG 156 | #define CONFIG_USB_EHCI_PORT_POWER 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /cherryusb/usb_osal_xos.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #include "usb_osal.h" 7 | #include "usb_errno.h" 8 | #include "xos.h" 9 | 10 | /******************************************************************************/ 11 | 12 | usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args) 13 | { 14 | task_t task_handle = xos_task_create((char*)name, entry, args, prio+DEFAULT_TASK_PRIO-4, stack_size); 15 | return (usb_osal_thread_t)task_handle; 16 | } 17 | 18 | void usb_osal_thread_delete(usb_osal_thread_t thread) 19 | { 20 | xos_task_exit(); 21 | } 22 | 23 | /******************************************************************************/ 24 | 25 | usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count) 26 | { 27 | SEM *sem = NULL; 28 | 29 | sem = xos_malloc(sizeof(SEM)); 30 | xos_sem_init(sem, initial_count); 31 | 32 | return (usb_osal_sem_t)sem; 33 | } 34 | 35 | void usb_osal_sem_delete(usb_osal_sem_t sem) 36 | { 37 | xos_free(sem); 38 | } 39 | 40 | int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout) 41 | { 42 | if (timeout == USB_OSAL_WAITING_FOREVER) { 43 | return xos_sem_take((SEM*)sem, -1); 44 | } else { 45 | return xos_sem_take((SEM*)sem, timeout); 46 | } 47 | } 48 | 49 | int usb_osal_sem_give(usb_osal_sem_t sem) 50 | { 51 | xos_sem_give((SEM*)sem); 52 | return 0; 53 | } 54 | 55 | /******************************************************************************/ 56 | 57 | int usb_osal_enter_critical_section(void) 58 | { 59 | return spin_lock_irq(); 60 | } 61 | 62 | void usb_osal_leave_critical_section(int flag) 63 | { 64 | spin_unlock_irq(flag); 65 | } 66 | 67 | void usb_osal_msleep(uint32_t delay) 68 | { 69 | delay /= 10; 70 | delay += 1; 71 | xos_task_delay(delay); 72 | } 73 | 74 | /******************************************************************************/ 75 | 76 | -------------------------------------------------------------------------------- /cherryusb/usbh_hid.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, sakumisu 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | #include "usbh_core.h" 7 | #include "usbh_hid.h" 8 | 9 | #define DEV_FORMAT "/dev/input%d" 10 | 11 | USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128]; 12 | 13 | static struct usbh_hid g_hid_class[CONFIG_USBHOST_MAX_HID_CLASS]; 14 | static uint32_t g_devinuse = 0; 15 | 16 | static struct usbh_hid *usbh_hid_class_alloc(void) 17 | { 18 | int devno; 19 | 20 | for (devno = 0; devno < CONFIG_USBHOST_MAX_HID_CLASS; devno++) { 21 | if ((g_devinuse & (1 << devno)) == 0) { 22 | g_devinuse |= (1 << devno); 23 | memset(&g_hid_class[devno], 0, sizeof(struct usbh_hid)); 24 | g_hid_class[devno].minor = devno; 25 | return &g_hid_class[devno]; 26 | } 27 | } 28 | return NULL; 29 | } 30 | 31 | static void usbh_hid_class_free(struct usbh_hid *hid_class) 32 | { 33 | int devno = hid_class->minor; 34 | 35 | if (devno >= 0 && devno < 32) { 36 | g_devinuse &= ~(1 << devno); 37 | } 38 | memset(hid_class, 0, sizeof(struct usbh_hid)); 39 | } 40 | 41 | static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer) 42 | { 43 | struct usb_setup_packet *setup = hid_class->hport->setup; 44 | int ret; 45 | 46 | setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE; 47 | setup->bRequest = USB_REQUEST_GET_DESCRIPTOR; 48 | setup->wValue = HID_DESCRIPTOR_TYPE_HID_REPORT << 8; 49 | setup->wIndex = hid_class->intf; 50 | setup->wLength = 128; 51 | 52 | ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf); 53 | if (ret < 0) { 54 | return ret; 55 | } 56 | memcpy(buffer, g_hid_buf, ret - 8); 57 | return ret; 58 | } 59 | 60 | int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration) 61 | { 62 | struct usb_setup_packet *setup = hid_class->hport->setup; 63 | 64 | setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; 65 | setup->bRequest = HID_REQUEST_SET_IDLE; 66 | setup->wValue = (duration << 8) | report_id; 67 | setup->wIndex = hid_class->intf; 68 | setup->wLength = 0; 69 | 70 | return usbh_control_transfer(hid_class->hport, setup, NULL); 71 | } 72 | 73 | int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer) 74 | { 75 | struct usb_setup_packet *setup = hid_class->hport->setup; 76 | int ret; 77 | 78 | setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; 79 | setup->bRequest = HID_REQUEST_GET_IDLE; 80 | setup->wValue = 0; 81 | setup->wIndex = hid_class->intf; 82 | setup->wLength = 1; 83 | 84 | ret = usbh_control_transfer(hid_class->hport, setup, g_hid_buf); 85 | if (ret < 0) { 86 | return ret; 87 | } 88 | memcpy(buffer, g_hid_buf, 1); 89 | return ret; 90 | } 91 | 92 | int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol) 93 | { 94 | struct usb_setup_packet *setup = hid_class->hport->setup; 95 | 96 | setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; 97 | setup->bRequest = HID_REQUEST_SET_PROTOCOL; 98 | setup->wValue = protocol; 99 | setup->wIndex = 0; 100 | setup->wLength = 0; 101 | 102 | return usbh_control_transfer(hid_class->hport, setup, NULL); 103 | } 104 | 105 | int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf) 106 | { 107 | struct usb_endpoint_descriptor *ep_desc; 108 | int ret; 109 | 110 | struct usbh_hid *hid_class = usbh_hid_class_alloc(); 111 | if (hid_class == NULL) { 112 | USB_LOG_ERR("Fail to alloc hid_class\r\n"); 113 | return -ENOMEM; 114 | } 115 | 116 | hid_class->hport = hport; 117 | hid_class->intf = intf; 118 | 119 | hport->config.intf[intf].priv = hid_class; 120 | 121 | // /* 0x0 = boot protocol, 0x1 = report protocol */ 122 | // ret = usbh_hid_set_protocol(hid_class, 0x1); 123 | // if (ret < 0) { 124 | // return ret; 125 | // } 126 | 127 | ret = usbh_hid_set_idle(hid_class, 0, 0); 128 | if (ret < 0) { 129 | USB_LOG_WRN("Do not support set idle\r\n"); 130 | } 131 | 132 | ret = usbh_hid_get_report_descriptor(hid_class, hid_class->report_desc); 133 | if (ret < 0) { 134 | return ret; 135 | } 136 | 137 | for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { 138 | ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; 139 | if (ep_desc->bEndpointAddress & 0x80) { 140 | USBH_EP_INIT(hid_class->intin, ep_desc); 141 | } else { 142 | USBH_EP_INIT(hid_class->intout, ep_desc); 143 | } 144 | } 145 | 146 | snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hid_class->minor); 147 | 148 | USB_LOG_INFO("Register HID Class:%s\r\n", hport->config.intf[intf].devname); 149 | 150 | usbh_hid_run(hid_class); 151 | return ret; 152 | } 153 | 154 | int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf) 155 | { 156 | int ret = 0; 157 | 158 | struct usbh_hid *hid_class = (struct usbh_hid *)hport->config.intf[intf].priv; 159 | 160 | if (hid_class) { 161 | if (hid_class->intin) { 162 | usbh_kill_urb(&hid_class->intin_urb); 163 | } 164 | 165 | if (hid_class->intout) { 166 | usbh_kill_urb(&hid_class->intout_urb); 167 | } 168 | 169 | if (hport->config.intf[intf].devname[0] != '\0') { 170 | USB_LOG_INFO("Unregister HID Class:%s\r\n", hport->config.intf[intf].devname); 171 | usbh_hid_stop(hid_class); 172 | } 173 | 174 | usbh_hid_class_free(hid_class); 175 | } 176 | 177 | return ret; 178 | } 179 | 180 | __WEAK void usbh_hid_run(struct usbh_hid *hid_class) 181 | { 182 | } 183 | 184 | __WEAK void usbh_hid_stop(struct usbh_hid *hid_class) 185 | { 186 | } 187 | 188 | const struct usbh_class_driver hid_class_driver = { 189 | .driver_name = "hid", 190 | .connect = usbh_hid_connect, 191 | .disconnect = usbh_hid_disconnect 192 | }; 193 | 194 | CLASS_INFO_DEFINE const struct usbh_class_info hid_custom_class_info = { 195 | .match_flags = USB_CLASS_MATCH_INTF_CLASS, 196 | .class = USB_DEVICE_CLASS_HID, 197 | .subclass = 0x00, 198 | .protocol = 0x00, 199 | .vid = 0x00, 200 | .pid = 0x00, 201 | .class_driver = &hid_class_driver 202 | }; 203 | -------------------------------------------------------------------------------- /coremark/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = coremark 2 | 3 | HBIRD_SDK_ROOT = ../../../.. 4 | 5 | COMMON_FLAGS := -O2 -flto -funroll-all-loops -finline-limit=600 -ftree-dominator-opts -fno-if-conversion2 -fselective-scheduling -fno-code-hoisting -fno-common -funroll-loops -finline-functions -falign-functions=4 -falign-jumps=4 -falign-loops=4 6 | #COMMON_FLAGS := -O3 -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las 7 | # Optimize just for code size 8 | #COMMON_FLAGS := -Os -flto 9 | 10 | COMMON_FLAGS += -DFLAGS_STR=\""$(COMMON_FLAGS)"\" 11 | COMMON_FLAGS += -DITERATIONS=500 -DPERFORMANCE_RUN=1 12 | 13 | PFLOAT = 1 14 | 15 | SRCDIRS = . 16 | 17 | INCDIRS = . 18 | 19 | include $(HBIRD_SDK_ROOT)/Build/Makefile.base 20 | -------------------------------------------------------------------------------- /coremark/core_matrix.c: -------------------------------------------------------------------------------- 1 | /* 2 | Author : Shay Gal-On, EEMBC 3 | 4 | This file is part of EEMBC(R) and CoreMark(TM), which are Copyright (C) 2009 5 | All rights reserved. 6 | 7 | EEMBC CoreMark Software is a product of EEMBC and is provided under the terms of the 8 | CoreMark License that is distributed with the official EEMBC COREMARK Software release. 9 | If you received this EEMBC CoreMark Software without the accompanying CoreMark License, 10 | you must discontinue use and download the official release from www.coremark.org. 11 | 12 | Also, if you are publicly displaying scores generated from the EEMBC CoreMark software, 13 | make sure that you are in compliance with Run and Reporting rules specified in the accompanying readme.txt file. 14 | 15 | EEMBC 16 | 4354 Town Center Blvd. Suite 114-200 17 | El Dorado Hills, CA, 95762 18 | */ 19 | #include "coremark.h" 20 | /* 21 | Topic: Description 22 | Matrix manipulation benchmark 23 | 24 | This very simple algorithm forms the basis of many more complex algorithms. 25 | 26 | The tight inner loop is the focus of many optimizations (compiler as well as hardware based) 27 | and is thus relevant for embedded processing. 28 | 29 | The total available data space will be divided to 3 parts: 30 | NxN Matrix A - initialized with small values (upper 3/4 of the bits all zero). 31 | NxN Matrix B - initialized with medium values (upper half of the bits all zero). 32 | NxN Matrix C - used for the result. 33 | 34 | The actual values for A and B must be derived based on input that is not available at compile time. 35 | */ 36 | ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val); 37 | ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval); 38 | void matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val); 39 | void matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B); 40 | void matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B); 41 | void matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B); 42 | void matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val); 43 | 44 | #define matrix_test_next(x) (x+1) 45 | #define matrix_clip(x,y) ((y) ? (x) & 0x0ff : (x) & 0x0ffff) 46 | #define matrix_big(x) (0xf000 | (x)) 47 | #define bit_extract(x,from,to) (((x)>>(from)) & (~(0xffffffff << (to)))) 48 | 49 | #if CORE_DEBUG 50 | void printmat(MATDAT *A, ee_u32 N, char *name) { 51 | ee_u32 i,j; 52 | ee_printf("Matrix %s [%dx%d]:\n",name,N,N); 53 | for (i=0; i N times, 79 | changing the matrix values slightly by a constant amount each time. 80 | */ 81 | ee_u16 core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc) { 82 | ee_u32 N=p->N; 83 | MATRES *C=p->C; 84 | MATDAT *A=p->A; 85 | MATDAT *B=p->B; 86 | MATDAT val=(MATDAT)seed; 87 | 88 | crc=crc16(matrix_test(N,C,A,B,val),crc); 89 | 90 | return crc; 91 | } 92 | 93 | /* Function: matrix_test 94 | Perform matrix manipulation. 95 | 96 | Parameters: 97 | N - Dimensions of the matrix. 98 | C - memory for result matrix. 99 | A - input matrix 100 | B - operator matrix (not changed during operations) 101 | 102 | Returns: 103 | A CRC value that captures all results calculated in the function. 104 | In particular, crc of the value calculated on the result matrix 105 | after each step by . 106 | 107 | Operation: 108 | 109 | 1 - Add a constant value to all elements of a matrix. 110 | 2 - Multiply a matrix by a constant. 111 | 3 - Multiply a matrix by a vector. 112 | 4 - Multiply a matrix by a matrix. 113 | 5 - Add a constant value to all elements of a matrix. 114 | 115 | After the last step, matrix A is back to original contents. 116 | */ 117 | ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val) { 118 | ee_u16 crc=0; 119 | MATDAT clipval=matrix_big(val); 120 | 121 | matrix_add_const(N,A,val); /* make sure data changes */ 122 | #if CORE_DEBUG 123 | printmat(A,N,"matrix_add_const"); 124 | #endif 125 | matrix_mul_const(N,C,A,val); 126 | crc=crc16(matrix_sum(N,C,clipval),crc); 127 | #if CORE_DEBUG 128 | printmatC(C,N,"matrix_mul_const"); 129 | #endif 130 | matrix_mul_vect(N,C,A,B); 131 | crc=crc16(matrix_sum(N,C,clipval),crc); 132 | #if CORE_DEBUG 133 | printmatC(C,N,"matrix_mul_vect"); 134 | #endif 135 | matrix_mul_matrix(N,C,A,B); 136 | crc=crc16(matrix_sum(N,C,clipval),crc); 137 | #if CORE_DEBUG 138 | printmatC(C,N,"matrix_mul_matrix"); 139 | #endif 140 | matrix_mul_matrix_bitextract(N,C,A,B); 141 | crc=crc16(matrix_sum(N,C,clipval),crc); 142 | #if CORE_DEBUG 143 | printmatC(C,N,"matrix_mul_matrix_bitextract"); 144 | #endif 145 | 146 | matrix_add_const(N,A,-val); /* return matrix to initial value */ 147 | return crc; 148 | } 149 | 150 | /* Function : matrix_init 151 | Initialize the memory block for matrix benchmarking. 152 | 153 | Parameters: 154 | blksize - Size of memory to be initialized. 155 | memblk - Pointer to memory block. 156 | seed - Actual values chosen depend on the seed parameter. 157 | p - pointers to containing initialized matrixes. 158 | 159 | Returns: 160 | Matrix dimensions. 161 | 162 | Note: 163 | The seed parameter MUST be supplied from a source that cannot be determined at compile time 164 | */ 165 | ee_u32 core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p) { 166 | ee_u32 N=0; 167 | MATDAT *A; 168 | MATDAT *B; 169 | ee_s32 order=1; 170 | MATDAT val; 171 | ee_u32 i=0,j=0; 172 | if (seed==0) 173 | seed=1; 174 | while (jA=A; 196 | p->B=B; 197 | p->C=(MATRES *)align_mem(B+N*N); 198 | p->N=N; 199 | #if CORE_DEBUG 200 | printmat(A,N,"A"); 201 | printmat(B,N,"B"); 202 | #endif 203 | return N; 204 | } 205 | 206 | /* Function: matrix_sum 207 | Calculate a function that depends on the values of elements in the matrix. 208 | 209 | For each element, accumulate into a temporary variable. 210 | 211 | As long as this value is under the parameter clipval, 212 | add 1 to the result if the element is bigger then the previous. 213 | 214 | Otherwise, reset the accumulator and add 10 to the result. 215 | */ 216 | ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval) { 217 | MATRES tmp=0,prev=0,cur=0; 218 | ee_s16 ret=0; 219 | ee_u32 i,j; 220 | for (i=0; iclipval) { 225 | ret+=10; 226 | tmp=0; 227 | } else { 228 | ret += (cur>prev) ? 1 : 0; 229 | } 230 | prev=cur; 231 | } 232 | } 233 | return ret; 234 | } 235 | 236 | /* Function: matrix_mul_const 237 | Multiply a matrix by a constant. 238 | This could be used as a scaler for instance. 239 | */ 240 | void matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val) { 241 | ee_u32 i,j; 242 | for (i=0; i 23 | #include 24 | 25 | #define HAS_FLOAT 1 26 | 27 | #define HAS_TIME_H 1 28 | 29 | #define USE_CLOCK 1 30 | 31 | #define HAS_STDIO 0 32 | 33 | #define HAS_PRINTF 0 34 | #define ee_printf printk 35 | int printk(char *fmt, ...); 36 | 37 | #define SEED_METHOD SEED_VOLATILE 38 | #define CORE_TICKS uint32_t 39 | #define ee_u8 uint8_t 40 | #define ee_u16 uint16_t 41 | #if defined(__riscv_xlen) && (__riscv_xlen == 64) 42 | // Trick used for RISC-V 64-bit coremark: 43 | // Defining ee_u32 to be signed int instead of unsigned int, 44 | // as 32-bit values on a 64-bit RISC-V must always be signed extended, 45 | // so this avoids some useless sign extension shifts while still giving the correct result 46 | // See https://forums.sifive.com/t/how-can-i-repeat-the-coremark-score/1947/3 47 | #define ee_u32 int32_t 48 | #else 49 | #define ee_u32 uint32_t 50 | #endif 51 | #define ee_s16 int16_t 52 | #define ee_s32 int32_t 53 | #define ee_ptr_int uintptr_t 54 | #define ee_size_t size_t 55 | #define COMPILER_FLAGS FLAGS_STR 56 | 57 | #define align_mem(x) (void *)(((ee_ptr_int)(x) + sizeof(ee_u32) - 1) & -sizeof(ee_u32)) 58 | 59 | #ifdef __GNUC__ 60 | # define COMPILER_VERSION "GCC"__VERSION__ 61 | #else 62 | # error 63 | #endif 64 | 65 | #define MEM_METHOD MEM_STACK 66 | #define MEM_LOCATION "STACK" 67 | 68 | #define MAIN_HAS_NOARGC 1 69 | #define MAIN_HAS_NORETURN 0 70 | 71 | #define MULTITHREAD 1 72 | #define USE_PTHREAD 0 73 | #define USE_FORK 0 74 | #define USE_SOCKET 0 75 | 76 | #define default_num_contexts MULTITHREAD 77 | 78 | typedef int core_portable; 79 | static void portable_init(core_portable *p, int *argc, char *argv[]) {} 80 | static void portable_fini(core_portable *p) {} 81 | 82 | #if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) && !defined(VALIDATION_RUN) 83 | #if (TOTAL_DATA_SIZE==1200) 84 | #define PROFILE_RUN 1 85 | #elif (TOTAL_DATA_SIZE==2000) 86 | #define PERFORMANCE_RUN 1 87 | #else 88 | #define VALIDATION_RUN 1 89 | #endif 90 | #endif 91 | 92 | #endif 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /coremark/core_state.c: -------------------------------------------------------------------------------- 1 | /* 2 | Author : Shay Gal-On, EEMBC 3 | 4 | This file is part of EEMBC(R) and CoreMark(TM), which are Copyright (C) 2009 5 | All rights reserved. 6 | 7 | EEMBC CoreMark Software is a product of EEMBC and is provided under the terms of the 8 | CoreMark License that is distributed with the official EEMBC COREMARK Software release. 9 | If you received this EEMBC CoreMark Software without the accompanying CoreMark License, 10 | you must discontinue use and download the official release from www.coremark.org. 11 | 12 | Also, if you are publicly displaying scores generated from the EEMBC CoreMark software, 13 | make sure that you are in compliance with Run and Reporting rules specified in the accompanying readme.txt file. 14 | 15 | EEMBC 16 | 4354 Town Center Blvd. Suite 114-200 17 | El Dorado Hills, CA, 95762 18 | */ 19 | #include "coremark.h" 20 | /* local functions */ 21 | enum CORE_STATE core_state_transition( ee_u8 **instr , ee_u32 *transition_count); 22 | 23 | /* 24 | Topic: Description 25 | Simple state machines like this one are used in many embedded products. 26 | 27 | For more complex state machines, sometimes a state transition table implementation is used instead, 28 | trading speed of direct coding for ease of maintenance. 29 | 30 | Since the main goal of using a state machine in CoreMark is to excercise the switch/if behaviour, 31 | we are using a small moore machine. 32 | 33 | In particular, this machine tests type of string input, 34 | trying to determine whether the input is a number or something else. 35 | (see core_state.png). 36 | */ 37 | 38 | /* Function: core_bench_state 39 | Benchmark function 40 | 41 | Go over the input twice, once direct, and once after introducing some corruption. 42 | */ 43 | ee_u16 core_bench_state(ee_u32 blksize, ee_u8 *memblock, 44 | ee_s16 seed1, ee_s16 seed2, ee_s16 step, ee_u16 crc) 45 | { 46 | ee_u32 final_counts[NUM_CORE_STATES]; 47 | ee_u32 track_counts[NUM_CORE_STATES]; 48 | ee_u8 *p=memblock; 49 | ee_u32 i; 50 | 51 | 52 | #if CORE_DEBUG 53 | ee_printf("State Bench: %d,%d,%d,%04x\n",seed1,seed2,step,crc); 54 | #endif 55 | for (i=0; i0) { 127 | for(i=0;i>3) & 0x3]; 138 | next=4; 139 | break; 140 | case 3: /* float */ 141 | case 4: /* float */ 142 | buf=floatpat[(seed>>3) & 0x3]; 143 | next=8; 144 | break; 145 | case 5: /* scientific */ 146 | case 6: /* scientific */ 147 | buf=scipat[(seed>>3) & 0x3]; 148 | next=8; 149 | break; 150 | case 7: /* invalid */ 151 | buf=errpat[(seed>>3) & 0x3]; 152 | next=8; 153 | break; 154 | default: /* Never happen, just to make some compilers happy */ 155 | break; 156 | } 157 | } 158 | size++; 159 | while (total='0') & (c<='9')) ? 1 : 0; 171 | return retval; 172 | } 173 | 174 | /* Function: core_state_transition 175 | Actual state machine. 176 | 177 | The state machine will continue scanning until either: 178 | 1 - an invalid input is detcted. 179 | 2 - a valid number has been detected. 180 | 181 | The input pointer is updated to point to the end of the token, and the end state is returned (either specific format determined or invalid). 182 | */ 183 | 184 | enum CORE_STATE core_state_transition( ee_u8 **instr , ee_u32 *transition_count) { 185 | ee_u8 *str=*instr; 186 | ee_u8 NEXT_SYMBOL; 187 | enum CORE_STATE state=CORE_START; 188 | for( ; *str && state != CORE_INVALID; str++ ) { 189 | NEXT_SYMBOL = *str; 190 | if (NEXT_SYMBOL==',') /* end of this input */ { 191 | str++; 192 | break; 193 | } 194 | switch(state) { 195 | case CORE_START: 196 | if(ee_isdigit(NEXT_SYMBOL)) { 197 | state = CORE_INT; 198 | } 199 | else if( NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-' ) { 200 | state = CORE_S1; 201 | } 202 | else if( NEXT_SYMBOL == '.' ) { 203 | state = CORE_FLOAT; 204 | } 205 | else { 206 | state = CORE_INVALID; 207 | transition_count[CORE_INVALID]++; 208 | } 209 | transition_count[CORE_START]++; 210 | break; 211 | case CORE_S1: 212 | if(ee_isdigit(NEXT_SYMBOL)) { 213 | state = CORE_INT; 214 | transition_count[CORE_S1]++; 215 | } 216 | else if( NEXT_SYMBOL == '.' ) { 217 | state = CORE_FLOAT; 218 | transition_count[CORE_S1]++; 219 | } 220 | else { 221 | state = CORE_INVALID; 222 | transition_count[CORE_S1]++; 223 | } 224 | break; 225 | case CORE_INT: 226 | if( NEXT_SYMBOL == '.' ) { 227 | state = CORE_FLOAT; 228 | transition_count[CORE_INT]++; 229 | } 230 | else if(!ee_isdigit(NEXT_SYMBOL)) { 231 | state = CORE_INVALID; 232 | transition_count[CORE_INT]++; 233 | } 234 | break; 235 | case CORE_FLOAT: 236 | if( NEXT_SYMBOL == 'E' || NEXT_SYMBOL == 'e' ) { 237 | state = CORE_S2; 238 | transition_count[CORE_FLOAT]++; 239 | } 240 | else if(!ee_isdigit(NEXT_SYMBOL)) { 241 | state = CORE_INVALID; 242 | transition_count[CORE_FLOAT]++; 243 | } 244 | break; 245 | case CORE_S2: 246 | if( NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-' ) { 247 | state = CORE_EXPONENT; 248 | transition_count[CORE_S2]++; 249 | } 250 | else { 251 | state = CORE_INVALID; 252 | transition_count[CORE_S2]++; 253 | } 254 | break; 255 | case CORE_EXPONENT: 256 | if(ee_isdigit(NEXT_SYMBOL)) { 257 | state = CORE_SCIENTIFIC; 258 | transition_count[CORE_EXPONENT]++; 259 | } 260 | else { 261 | state = CORE_INVALID; 262 | transition_count[CORE_EXPONENT]++; 263 | } 264 | break; 265 | case CORE_SCIENTIFIC: 266 | if(!ee_isdigit(NEXT_SYMBOL)) { 267 | state = CORE_INVALID; 268 | transition_count[CORE_INVALID]++; 269 | } 270 | break; 271 | default: 272 | break; 273 | } 274 | } 275 | *instr=str; 276 | return state; 277 | } 278 | -------------------------------------------------------------------------------- /coremark/core_util.c: -------------------------------------------------------------------------------- 1 | /* 2 | Author : Shay Gal-On, EEMBC 3 | 4 | This file is part of EEMBC(R) and CoreMark(TM), which are Copyright (C) 2009 5 | All rights reserved. 6 | 7 | EEMBC CoreMark Software is a product of EEMBC and is provided under the terms of the 8 | CoreMark License that is distributed with the official EEMBC COREMARK Software release. 9 | If you received this EEMBC CoreMark Software without the accompanying CoreMark License, 10 | you must discontinue use and download the official release from www.coremark.org. 11 | 12 | Also, if you are publicly displaying scores generated from the EEMBC CoreMark software, 13 | make sure that you are in compliance with Run and Reporting rules specified in the accompanying readme.txt file. 14 | 15 | EEMBC 16 | 4354 Town Center Blvd. Suite 114-200 17 | El Dorado Hills, CA, 95762 18 | */ 19 | #include "coremark.h" 20 | /* Function: get_seed 21 | Get a values that cannot be determined at compile time. 22 | 23 | Since different embedded systems and compilers are used, 3 different methods are provided: 24 | 1 - Using a volatile variable. This method is only valid if the compiler is forced to generate code that 25 | reads the value of a volatile variable from memory at run time. 26 | Please note, if using this method, you would need to modify core_portme.c to generate training profile. 27 | 2 - Command line arguments. This is the preferred method if command line arguments are supported. 28 | 3 - System function. If none of the first 2 methods is available on the platform, 29 | a system function which is not a stub can be used. 30 | 31 | e.g. read the value on GPIO pins connected to switches, or invoke special simulator functions. 32 | */ 33 | #if (SEED_METHOD==SEED_VOLATILE) 34 | extern volatile ee_s32 seed1_volatile; 35 | extern volatile ee_s32 seed2_volatile; 36 | extern volatile ee_s32 seed3_volatile; 37 | extern volatile ee_s32 seed4_volatile; 38 | extern volatile ee_s32 seed5_volatile; 39 | ee_s32 get_seed_32(int i) { 40 | ee_s32 retval; 41 | switch (i) { 42 | case 1: 43 | retval=seed1_volatile; 44 | break; 45 | case 2: 46 | retval=seed2_volatile; 47 | break; 48 | case 3: 49 | retval=seed3_volatile; 50 | break; 51 | case 4: 52 | retval=seed4_volatile; 53 | break; 54 | case 5: 55 | retval=seed5_volatile; 56 | break; 57 | default: 58 | retval=0; 59 | break; 60 | } 61 | return retval; 62 | } 63 | #elif (SEED_METHOD==SEED_ARG) 64 | ee_s32 parseval(char *valstring) { 65 | ee_s32 retval=0; 66 | ee_s32 neg=1; 67 | int hexmode=0; 68 | if (*valstring == '-') { 69 | neg=-1; 70 | valstring++; 71 | } 72 | if ((valstring[0] == '0') && (valstring[1] == 'x')) { 73 | hexmode=1; 74 | valstring+=2; 75 | } 76 | /* first look for digits */ 77 | if (hexmode) { 78 | while (((*valstring >= '0') && (*valstring <= '9')) || ((*valstring >= 'a') && (*valstring <= 'f'))) { 79 | ee_s32 digit=*valstring-'0'; 80 | if (digit>9) 81 | digit=10+*valstring-'a'; 82 | retval*=16; 83 | retval+=digit; 84 | valstring++; 85 | } 86 | } else { 87 | while ((*valstring >= '0') && (*valstring <= '9')) { 88 | ee_s32 digit=*valstring-'0'; 89 | retval*=10; 90 | retval+=digit; 91 | valstring++; 92 | } 93 | } 94 | /* now add qualifiers */ 95 | if (*valstring=='K') 96 | retval*=1024; 97 | if (*valstring=='M') 98 | retval*=1024*1024; 99 | 100 | retval*=neg; 101 | return retval; 102 | } 103 | 104 | ee_s32 get_seed_args(int i, int argc, char *argv[]) { 105 | if (argc>i) 106 | return parseval(argv[i]); 107 | return 0; 108 | } 109 | 110 | #elif (SEED_METHOD==SEED_FUNC) 111 | /* If using OS based function, you must define and implement the functions below in core_portme.h and core_portme.c ! */ 112 | ee_s32 get_seed_32(int i) { 113 | ee_s32 retval; 114 | switch (i) { 115 | case 1: 116 | retval=portme_sys1(); 117 | break; 118 | case 2: 119 | retval=portme_sys2(); 120 | break; 121 | case 3: 122 | retval=portme_sys3(); 123 | break; 124 | case 4: 125 | retval=portme_sys4(); 126 | break; 127 | case 5: 128 | retval=portme_sys5(); 129 | break; 130 | default: 131 | retval=0; 132 | break; 133 | } 134 | return retval; 135 | } 136 | #endif 137 | 138 | /* Function: crc* 139 | Service functions to calculate 16b CRC code. 140 | 141 | */ 142 | ee_u16 crcu8(ee_u8 data, ee_u16 crc ) 143 | { 144 | ee_u8 i=0,x16=0,carry=0; 145 | 146 | for (i = 0; i < 8; i++) 147 | { 148 | x16 = (ee_u8)((data & 1) ^ ((ee_u8)crc & 1)); 149 | data >>= 1; 150 | 151 | if (x16 == 1) 152 | { 153 | crc ^= 0x4002; 154 | carry = 1; 155 | } 156 | else 157 | carry = 0; 158 | crc >>= 1; 159 | if (carry) 160 | crc |= 0x8000; 161 | else 162 | crc &= 0x7fff; 163 | } 164 | return crc; 165 | } 166 | ee_u16 crcu16(ee_u16 newval, ee_u16 crc) { 167 | crc=crcu8( (ee_u8) (newval) ,crc); 168 | crc=crcu8( (ee_u8) ((newval)>>8) ,crc); 169 | return crc; 170 | } 171 | ee_u16 crcu32(ee_u32 newval, ee_u16 crc) { 172 | crc=crc16((ee_s16) newval ,crc); 173 | crc=crc16((ee_s16) (newval>>16) ,crc); 174 | return crc; 175 | } 176 | ee_u16 crc16(ee_s16 newval, ee_u16 crc) { 177 | return crcu16((ee_u16)newval, crc); 178 | } 179 | 180 | ee_u8 check_data_types() { 181 | ee_u8 retval=0; 182 | if (sizeof(ee_u8) != 1) { 183 | ee_printf("ERROR: ee_u8 is not an 8b datatype!\n"); 184 | retval++; 185 | } 186 | if (sizeof(ee_u16) != 2) { 187 | ee_printf("ERROR: ee_u16 is not a 16b datatype!\n"); 188 | retval++; 189 | } 190 | if (sizeof(ee_s16) != 2) { 191 | ee_printf("ERROR: ee_s16 is not a 16b datatype!\n"); 192 | retval++; 193 | } 194 | if (sizeof(ee_s32) != 4) { 195 | ee_printf("ERROR: ee_s32 is not a 32b datatype!\n"); 196 | retval++; 197 | } 198 | if (sizeof(ee_u32) != 4) { 199 | ee_printf("ERROR: ee_u32 is not a 32b datatype!\n"); 200 | retval++; 201 | } 202 | if (sizeof(ee_ptr_int) != sizeof(int *)) { 203 | ee_printf("ERROR: ee_ptr_int is not a datatype that holds an int pointer!\n"); 204 | retval++; 205 | } 206 | if (retval>0) { 207 | ee_printf("ERROR: Please modify the datatypes in core_portme.h!\n"); 208 | } 209 | return retval; 210 | } 211 | -------------------------------------------------------------------------------- /coremark/coremark.h: -------------------------------------------------------------------------------- 1 | /* 2 | Author : Shay Gal-On, EEMBC 3 | 4 | This file is part of EEMBC(R) and CoreMark(TM), which are Copyright (C) 2009 5 | All rights reserved. 6 | 7 | EEMBC CoreMark Software is a product of EEMBC and is provided under the terms of the 8 | CoreMark License that is distributed with the official EEMBC COREMARK Software release. 9 | If you received this EEMBC CoreMark Software without the accompanying CoreMark License, 10 | you must discontinue use and download the official release from www.coremark.org. 11 | 12 | Also, if you are publicly displaying scores generated from the EEMBC CoreMark software, 13 | make sure that you are in compliance with Run and Reporting rules specified in the accompanying readme.txt file. 14 | 15 | EEMBC 16 | 4354 Town Center Blvd. Suite 114-200 17 | El Dorado Hills, CA, 95762 18 | */ 19 | /* Topic: Description 20 | This file contains declarations of the various benchmark functions. 21 | */ 22 | 23 | /* Configuration: TOTAL_DATA_SIZE 24 | Define total size for data algorithms will operate on 25 | */ 26 | #ifndef COREMARK_H 27 | #define COREMARK_H 28 | 29 | #ifndef TOTAL_DATA_SIZE 30 | #define TOTAL_DATA_SIZE 2*1000 31 | #endif 32 | 33 | #define SEED_ARG 0 34 | #define SEED_FUNC 1 35 | #define SEED_VOLATILE 2 36 | 37 | #define MEM_STATIC 0 38 | #define MEM_MALLOC 1 39 | #define MEM_STACK 2 40 | 41 | #include "core_portme.h" 42 | 43 | #if HAS_STDIO 44 | #include 45 | #endif 46 | #if HAS_PRINTF 47 | #define ee_printf printf 48 | #endif 49 | 50 | /* Actual benchmark execution in iterate */ 51 | void *iterate(void *pres); 52 | 53 | /* Typedef: secs_ret 54 | For machines that have floating point support, get number of seconds as a double. 55 | Otherwise an unsigned int. 56 | */ 57 | #if HAS_FLOAT 58 | typedef double secs_ret; 59 | #else 60 | typedef ee_u32 secs_ret; 61 | #endif 62 | 63 | #if MAIN_HAS_NORETURN 64 | #define MAIN_RETURN_VAL 65 | #define MAIN_RETURN_TYPE void 66 | #else 67 | #define MAIN_RETURN_VAL 0 68 | #define MAIN_RETURN_TYPE int 69 | #endif 70 | 71 | void start_time(void); 72 | void stop_time(void); 73 | CORE_TICKS get_time(void); 74 | secs_ret time_in_secs(CORE_TICKS ticks); 75 | 76 | /* Misc useful functions */ 77 | ee_u16 crcu8(ee_u8 data, ee_u16 crc); 78 | ee_u16 crc16(ee_s16 newval, ee_u16 crc); 79 | ee_u16 crcu16(ee_u16 newval, ee_u16 crc); 80 | ee_u16 crcu32(ee_u32 newval, ee_u16 crc); 81 | ee_u8 check_data_types(); 82 | void *portable_malloc(ee_size_t size); 83 | void portable_free(void *p); 84 | ee_s32 parseval(char *valstring); 85 | 86 | /* Algorithm IDS */ 87 | #define ID_LIST (1<<0) 88 | #define ID_MATRIX (1<<1) 89 | #define ID_STATE (1<<2) 90 | #define ALL_ALGORITHMS_MASK (ID_LIST|ID_MATRIX|ID_STATE) 91 | #define NUM_ALGORITHMS 3 92 | 93 | /* list data structures */ 94 | typedef struct list_data_s { 95 | ee_s16 data16; 96 | ee_s16 idx; 97 | } list_data; 98 | 99 | typedef struct list_head_s { 100 | struct list_head_s *next; 101 | struct list_data_s *info; 102 | } list_head; 103 | 104 | 105 | /*matrix benchmark related stuff */ 106 | #define MATDAT_INT 1 107 | #if MATDAT_INT 108 | typedef ee_s16 MATDAT; 109 | typedef ee_s32 MATRES; 110 | #else 111 | typedef ee_f16 MATDAT; 112 | typedef ee_f32 MATRES; 113 | #endif 114 | 115 | typedef struct MAT_PARAMS_S { 116 | int N; 117 | MATDAT *A; 118 | MATDAT *B; 119 | MATRES *C; 120 | } mat_params; 121 | 122 | /* state machine related stuff */ 123 | /* List of all the possible states for the FSM */ 124 | typedef enum CORE_STATE { 125 | CORE_START=0, 126 | CORE_INVALID, 127 | CORE_S1, 128 | CORE_S2, 129 | CORE_INT, 130 | CORE_FLOAT, 131 | CORE_EXPONENT, 132 | CORE_SCIENTIFIC, 133 | NUM_CORE_STATES 134 | } core_state_e ; 135 | 136 | 137 | /* Helper structure to hold results */ 138 | typedef struct RESULTS_S { 139 | /* inputs */ 140 | ee_s16 seed1; /* Initializing seed */ 141 | ee_s16 seed2; /* Initializing seed */ 142 | ee_s16 seed3; /* Initializing seed */ 143 | void *memblock[4]; /* Pointer to safe memory location */ 144 | ee_u32 size; /* Size of the data */ 145 | ee_u32 iterations; /* Number of iterations to execute */ 146 | ee_u32 execs; /* Bitmask of operations to execute */ 147 | struct list_head_s *list; 148 | mat_params mat; 149 | /* outputs */ 150 | ee_u16 crc; 151 | ee_u16 crclist; 152 | ee_u16 crcmatrix; 153 | ee_u16 crcstate; 154 | ee_s16 err; 155 | /* ultithread specific */ 156 | core_portable port; 157 | } core_results; 158 | 159 | /* Multicore execution handling */ 160 | #if (MULTITHREAD>1) 161 | ee_u8 core_start_parallel(core_results *res); 162 | ee_u8 core_stop_parallel(core_results *res); 163 | #endif 164 | 165 | /* list benchmark functions */ 166 | list_head *core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed); 167 | ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx); 168 | 169 | /* state benchmark functions */ 170 | void core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p); 171 | ee_u16 core_bench_state(ee_u32 blksize, ee_u8 *memblock, 172 | ee_s16 seed1, ee_s16 seed2, ee_s16 step, ee_u16 crc); 173 | 174 | /* matrix benchmark functions */ 175 | ee_u32 core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p); 176 | ee_u16 core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc); 177 | 178 | #endif 179 | -------------------------------------------------------------------------------- /coremark/npk.yml: -------------------------------------------------------------------------------- 1 | ## Package Base Information 2 | name: app-hsdk_coremark 3 | owner: nuclei 4 | version: 5 | description: Coremark Benchmark 6 | type: app 7 | keywords: 8 | - app 9 | - risc-v 10 | license: Apache-2.0 11 | homepage: https://www.eembc.org/coremark/ 12 | 13 | ## Package Dependency 14 | dependencies: 15 | - name: sdk-hbird_sdk 16 | version: 17 | 18 | ## Package Configurations 19 | configuration: 20 | app_commonflags: 21 | value: >- 22 | -O2 -funroll-all-loops -finline-limit=600 -ftree-dominator-opts 23 | -fno-if-conversion2 -fselective-scheduling -fno-code-hoisting 24 | -fno-common -funroll-loops -finline-functions -falign-functions=4 25 | -falign-jumps=4 -falign-loops=4 26 | type: text 27 | description: Application Compile Flags 28 | 29 | ## Set Configuration for other packages 30 | setconfig: 31 | - config: newlibsel 32 | value: nano_with_printfloat 33 | 34 | ## Source Code Management 35 | codemanage: 36 | copyfiles: 37 | - path: ["*.c", "*.h"] 38 | incdirs: 39 | - path: ["./"] 40 | libdirs: 41 | ldlibs: 42 | 43 | ## Build Configuration 44 | buildconfig: 45 | - type: gcc 46 | common_flags: # flags need to be combined together across all packages 47 | - flags: ${app_commonflags} 48 | ldflags: 49 | cflags: 50 | asmflags: 51 | cxxflags: 52 | cdefines: 53 | - defines: FLAGS_STR=\""${app_commonflags}"\" 54 | - defines: ITERATIONS=500 55 | - defines: PERFORMANCE_RUN=1 56 | prebuild_steps: # could be override by app/bsp type 57 | command: 58 | description: 59 | postbuild_steps: # could be override by app/bsp type 60 | command: 61 | description: 62 | -------------------------------------------------------------------------------- /fpga/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # 指定Supra的安装目录。可以用AgRV_pio里面带的supra,也可以用Supra安装包。 3 | 4 | #SUPRA_DIR = /e/AGRV/AgRV_pio/packages/tool-agrv_logic 5 | SUPRA_DIR = /e//AGRV/Supra 6 | 7 | AF = $(SUPRA_DIR)/bin/af.exe 8 | OPENOCD = $(SUPRA_DIR)/openocd/bin/openocd.exe -c "set CONNECT_UNDER_RESET 1" -f $(SUPRA_DIR)/openocd//agrv2k.cfg 9 | GEN_VLOG = tools/gen_vlog 10 | 11 | DEVICE = AGRV2KL100 12 | 13 | 14 | proj: prevlog preip 15 | 16 | 17 | # 第一步: 根据ve文件,生成顶层模块以及user模板。你可以在生成的ulogic.v基础上进行开发。 18 | prevlog: 19 | $(GEN_VLOG) -s -d $(DEVICE) -c ulogic/top.hx -m ulogic/ulogic.v top.ve ulogic/top.v 20 | 21 | 22 | # 第二步: 生成quartus工程. 需要编译生成netlist. 23 | preip: 24 | $(AF) \ 25 | -L ulogic/preip_log.txt \ 26 | -X "set LOGIC_DEVICE $(DEVICE)" \ 27 | -X "set LOGIC_DESIGN top" \ 28 | -X "set LOGIC_DIR ulogic" \ 29 | -X "set LOGIC_VV top.v" \ 30 | -X "set LOGIC_ASF {top.asf}" \ 31 | -X "set LOGIC_PRE {}" \ 32 | -X "set LOGIC_POST {}" \ 33 | -X "set LOGIC_FORCE {false}" \ 34 | -X "set IP_VV {ulogic.v}" \ 35 | -X "set ORIGINAL_PIN {-}" \ 36 | -F tools/pre_logic.tcl 37 | 38 | 39 | 40 | # 第三步: 调用Supra工具,编译转换netlist文件,生成烧写文件。 41 | genbin: 42 | cd ulogic; $(AF) -B --batch --mode QUARTUS -X "set QUARTUS_SDC true" -X "set FITTING Auto" -X "set FITTER full" -X "set EFFORT high" -X "set HOLDX default" -X "set SKEW basic" 43 | 44 | 45 | # 第四步: 调用OpenOCD写入。 46 | dl: 47 | $(OPENOCD) -c "agrv write_fpga_config ulogic/top.bin" -c "reset" -c "exit" 48 | 49 | -------------------------------------------------------------------------------- /fpga/tools/gen_logic.tcl: -------------------------------------------------------------------------------- 1 | set sh_continue_on_error false 2 | set sh_echo_on_source true 3 | set sh_quiet_on_source true 4 | set cc_critical_as_fatal true 5 | set ta_report_auto_constraints 1 6 | 7 | set db_io_name_priority true 8 | set ip_pll_vco_lowpower true 9 | 10 | set_seed_rand 10 11 | if { ! [info exists LOGIC_DB] } { 12 | set LOGIC_DB logic_db 13 | } 14 | if { ! [info exists LOGIC_DEVICE] } { 15 | set LOGIC_DEVICE AGRV2KL100 16 | } 17 | if { ! [info exists LOGIC_MODULE] } { 18 | set LOGIC_MODULE top 19 | } 20 | if { ! [info exists LOGIC_DIR] } { 21 | set LOGIC_DIR . 22 | } 23 | if { ! [info exists LOGIC_VX] } { 24 | set LOGIC_VX logic.vx 25 | } 26 | if { ! [info exists LOGIC_ASF] } { 27 | set LOGIC_ASF "" 28 | } 29 | if { ! [info exists LOGIC_PRE] } { 30 | set LOGIC_PRE "" 31 | } 32 | if { ! [info exists LOGIC_POST] } { 33 | set LOGIC_POST "" 34 | } 35 | if { ! [info exists DESIGN_ASF] } { 36 | set DESIGN_ASF "" 37 | } 38 | if { ! [info exists DESIGN_PRE] } { 39 | set DESIGN_PRE "" 40 | } 41 | if { ! [info exists DESIGN_POST] } { 42 | set DESIGN_POST "" 43 | } 44 | if { ! [info exists IP_ASF] } { 45 | set IP_ASF "" 46 | } 47 | if { ! [info exists IP_PRE] } { 48 | set IP_PRE "" 49 | } 50 | if { ! [info exists IP_POST] } { 51 | set IP_POST "" 52 | } 53 | if { ! [info exists LOGIC_BIN] } { 54 | set LOGIC_BIN logic.bin 55 | } 56 | if { ! [info exists LOGIC_COMPRESS] } { 57 | set LOGIC_COMPRESS false 58 | } 59 | if { ! [info exists IP_SDC] } { 60 | set IP_SDC "" 61 | } 62 | 63 | cd $LOGIC_DIR 64 | 65 | if { $LOGIC_COMPRESS } { 66 | set_global_assignment -name ON_CHIP_BITSTREAM_DECOMPRESSION "ON" 67 | } else { 68 | set_global_assignment -name ON_CHIP_BITSTREAM_DECOMPRESSION "OFF" 69 | } 70 | 71 | set logic_hx ${LOGIC_DESIGN}.hx 72 | set hx_fp [open $logic_hx r] 73 | set hsi_freq 0 74 | set hse_freq 0 75 | while { [gets $hx_fp line] >= 0 } { 76 | set words [split $line] 77 | if { [lindex $words 0] == "#define" } { 78 | if { [lindex $words 1] == "BOARD_HSI_FREQUENCY" } { 79 | set hsi_freq [lindex $words 2] 80 | } 81 | if { [lindex $words 1] == "BOARD_HSE_FREQUENCY" } { 82 | set hse_freq [lindex $words 2] 83 | } 84 | if { [lindex $words 1] == "USB0_MODE" } { 85 | set USB0_MODE [lindex $words 2] 86 | } 87 | } 88 | } 89 | close $hx_fp 90 | 91 | alta::set_verbose_cmd false 92 | set ::alta_work $LOGIC_DB 93 | 94 | if { "$LOGIC_PRE" != "" } { 95 | alta::tcl_print "Processing $LOGIC_PRE ...\n" 96 | source "$LOGIC_PRE" 97 | } 98 | if { "$IP_PRE" != "" } { 99 | alta::tcl_print "Processing $IP_PRE ...\n" 100 | source "$IP_PRE" 101 | } 102 | if { "$DESIGN_PRE" != "" } { 103 | alta::tcl_print "Processing $DESIGN_PRE ...\n" 104 | source "$DESIGN_PRE" 105 | } 106 | load_architect -type $LOGIC_DEVICE 107 | read_design -top $LOGIC_MODULE -ve "" -qsf "" $LOGIC_VX -hierachy 1 108 | 109 | if { "$IP_SDC" != "" } { 110 | if { $hsi_freq != 0 } { 111 | set ::HSI_PERIOD [expr 1000000000.0/$hsi_freq] 112 | } 113 | if { $hse_freq != 0 } { 114 | set ::HSE_PERIOD [expr 1000000000.0/$hse_freq] 115 | } 116 | alta::tcl_print "Processing $IP_SDC ...\n" 117 | read_sdc "$IP_SDC" 118 | } else { 119 | derive_pll_clocks -create_base_clocks 120 | } 121 | 122 | set_mode -skew basic -effort high -fitting auto -fitter full 123 | 124 | if { "$LOGIC_ASF" != "" } { 125 | alta::tcl_print "Processing $LOGIC_ASF ...\n" 126 | source "$LOGIC_ASF" 127 | } 128 | if { "$IP_ASF" != "" } { 129 | alta::tcl_print "Processing $IP_ASF ...\n" 130 | source "$IP_ASF" 131 | } 132 | if { "$DESIGN_ASF" != "" } { 133 | alta::tcl_print "Processing $DESIGN_ASF ...\n" 134 | source "$DESIGN_ASF" 135 | } 136 | 137 | place_pseudo -user_io -place_io -place_pll -place_gclk -warn_io 138 | 139 | set rt_max_iter "150 1 750 50 2 2" 140 | place_and_route_design -quiet -retry 3 141 | 142 | report_timing -verbose 2 -setup -file $::alta_work/setup.rpt.gz 143 | report_timing -verbose 2 -setup -brief -file $::alta_work/setup_summary.rpt.gz 144 | report_timing -verbose 2 -hold -file $::alta_work/hold.rpt.gz 145 | report_timing -verbose 2 -hold -brief -file $::alta_work/hold_summary.rpt.gz 146 | 147 | set ta_report_auto_constraints 0 148 | report_timing -fmax -file $::alta_work/fmax.rpt 149 | report_timing -xfer -file $::alta_work/xfer.rpt 150 | set ta_report_auto_constraints 1 151 | 152 | set ta_dump_uncovered 1 153 | report_timing -verbose 1 -coverage >! $::alta_work/coverage.rpt.gz 154 | unset ta_dump_uncovered 155 | 156 | set logic_routed ${LOGIC_DESIGN}_routed.v 157 | write_routed_design $logic_routed 158 | 159 | bitgen normal -bin $LOGIC_BIN 160 | 161 | if { "$LOGIC_POST" != "" } { 162 | alta::tcl_print "Processing $LOGIC_POST ...\n" 163 | source "$LOGIC_POST" 164 | } 165 | if { "$IP_POST" != "" } { 166 | alta::tcl_print "Processing $IP_POST ...\n" 167 | source "$IP_POST" 168 | } 169 | if { "$DESIGN_POST" != "" } { 170 | alta::tcl_print "Processing $DESIGN_POST ...\n" 171 | source "$DESIGN_POST" 172 | } 173 | 174 | exit 175 | -------------------------------------------------------------------------------- /fpga/top.ve: -------------------------------------------------------------------------------- 1 | 2 | ######## System Pins ######## 3 | 4 | SYSCLK 200 5 | BUSCLK 100 6 | PLLCLK4 100 7 | PLLCLK4_PHASE 180 8 | HSECLK 16 9 | USB0 host 10 | 11 | 12 | ######## UserLogic Pins ######## 13 | 14 | soc_led PIN_91:OUTPUT 15 | 16 | PLL_CLKOUT4 PIN_2:OUTPUT 17 | 18 | # soc PSRAM 19 | soc_spi_csn PIN_4:OUTPUT 20 | soc_spi_clk PIN_88:OUTPUT 21 | soc_spi_io0 PIN_1 22 | soc_spi_io1 PIN_5 23 | soc_spi_io2 PIN_7 24 | soc_spi_io3 PIN_3 25 | 26 | # soc SDCARD 27 | soc_sd_clk PIN_83:OUTPUT 28 | soc_sd_cmd PIN_82 29 | soc_sd_d0 PIN_84 30 | soc_sd_d1 PIN_85 31 | soc_sd_d2 PIN_80 32 | soc_sd_d3 PIN_81 33 | soc_sd_cd PIN_86:INPUT 34 | 35 | # Saturn ABUS 36 | ss_reset PIN_15:INPUT 37 | ss_spclk PIN_16:INPUT 38 | ss_ssel PIN_18:OUTPUT 39 | ss_isd PIN_23:OUTPUT 40 | ss_ibck PIN_24:OUTPUT 41 | ss_ilrck PIN_25:OUTPUT 42 | 43 | ss_dataoe PIN_51:OUTPUT 44 | ss_datadir PIN_48:OUTPUT 45 | ss_addroe PIN_39:OUTPUT 46 | ss_outen PIN_30:OUTPUT 47 | ss_await PIN_26:OUTPUT 48 | ss_airq PIN_29:OUTPUT 49 | 50 | ss_cs0 PIN_41:INPUT 51 | ss_cs1 PIN_42:INPUT 52 | ss_cs2 PIN_43:INPUT 53 | ss_rd PIN_40:INPUT 54 | ss_wr0 PIN_45:INPUT 55 | ss_wr1 PIN_44:INPUT 56 | ss_fc0 PIN_47:INPUT 57 | ss_fc1 PIN_46:INPUT 58 | 59 | ss_ad[0] PIN_53 60 | ss_ad[1] PIN_55 61 | ss_ad[2] PIN_57 62 | ss_ad[3] PIN_59 63 | ss_ad[4] PIN_58 64 | ss_ad[5] PIN_56 65 | ss_ad[6] PIN_54 66 | ss_ad[7] PIN_52 67 | ss_ad[8] PIN_61 68 | ss_ad[9] PIN_63 69 | ss_ad[10] PIN_65 70 | ss_ad[11] PIN_67 71 | ss_ad[12] PIN_66 72 | ss_ad[13] PIN_64 73 | ss_ad[14] PIN_62 74 | ss_ad[15] PIN_60 75 | ss_ah[0] PIN_38:INPUT 76 | ss_ah[1] PIN_37:INPUT 77 | ss_ah[2] PIN_36:INPUT 78 | ss_ah[3] PIN_35:INPUT 79 | ss_ah[4] PIN_34:INPUT 80 | ss_ah[5] PIN_33:INPUT 81 | ss_ah[6] PIN_32:INPUT 82 | ss_ah[7] PIN_31:INPUT 83 | 84 | 85 | ######## MCU Pins ######## 86 | 87 | # LED1 88 | GPIO2_0 PIN_68 89 | 90 | # debuf UART 91 | UART0_UARTRXD PIN_78 92 | UART0_UARTTXD PIN_79 93 | 94 | # mcu PSRAM 95 | SPI0_CSN PIN_96 96 | SPI0_SCK PIN_93 97 | SPI0_SI_IO0 PIN_92 98 | SPI0_SO_IO1 PIN_97 99 | SPI0_WPN_IO2 PIN_98 100 | SPI0_HOLDN_IO3 PIN_95 101 | 102 | 103 | -------------------------------------------------------------------------------- /fpga/ulogic/sync_dpram.v: -------------------------------------------------------------------------------- 1 | // megafunction wizard: %RAM: 2-PORT% 2 | // GENERATION: STANDARD 3 | // VERSION: WM1.0 4 | // MODULE: altsyncram 5 | 6 | // ============================================================ 7 | // File Name: sync_dpram.v 8 | // Megafunction Name(s): 9 | // altsyncram 10 | // 11 | // Simulation Library Files(s): 12 | // altera_mf 13 | // ============================================================ 14 | // ************************************************************ 15 | // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! 16 | // 17 | // 14.1.1 Build 190 01/19/2015 SJ Full Version 18 | // ************************************************************ 19 | 20 | 21 | //Copyright (C) 1991-2015 Altera Corporation. All rights reserved. 22 | //Your use of Altera Corporation's design tools, logic functions 23 | //and other software and tools, and its AMPP partner logic 24 | //functions, and any output files from any of the foregoing 25 | //(including device programming or simulation files), and any 26 | //associated documentation or information are expressly subject 27 | //to the terms and conditions of the Altera Program License 28 | //Subscription Agreement, the Altera Quartus II License Agreement, 29 | //the Altera MegaCore Function License Agreement, or other 30 | //applicable license agreement, including, without limitation, 31 | //that your use is for the sole purpose of programming logic 32 | //devices manufactured by Altera and sold by Altera or its 33 | //authorized distributors. Please refer to the applicable 34 | //agreement for further details. 35 | 36 | 37 | // synopsys translate_off 38 | `timescale 1 ps / 1 ps 39 | // synopsys translate_on 40 | module sync_dpram ( 41 | byteena_a, 42 | clock, 43 | data, 44 | rdaddress, 45 | rden, 46 | wraddress, 47 | wren, 48 | q); 49 | 50 | input [3:0] byteena_a; 51 | input clock; 52 | input [31:0] data; 53 | input [7:0] rdaddress; 54 | input rden; 55 | input [7:0] wraddress; 56 | input wren; 57 | output [31:0] q; 58 | `ifndef ALTERA_RESERVED_QIS 59 | // synopsys translate_off 60 | `endif 61 | tri1 [3:0] byteena_a; 62 | tri1 clock; 63 | tri1 rden; 64 | tri0 wren; 65 | `ifndef ALTERA_RESERVED_QIS 66 | // synopsys translate_on 67 | `endif 68 | 69 | wire [31:0] sub_wire0; 70 | wire [31:0] q = sub_wire0[31:0]; 71 | 72 | altsyncram altsyncram_component ( 73 | .address_a (wraddress), 74 | .address_b (rdaddress), 75 | .byteena_a (byteena_a), 76 | .clock0 (clock), 77 | .data_a (data), 78 | .rden_b (rden), 79 | .wren_a (wren), 80 | .q_b (sub_wire0), 81 | .aclr0 (1'b0), 82 | .aclr1 (1'b0), 83 | .addressstall_a (1'b0), 84 | .addressstall_b (1'b0), 85 | .byteena_b (1'b1), 86 | .clock1 (1'b1), 87 | .clocken0 (1'b1), 88 | .clocken1 (1'b1), 89 | .clocken2 (1'b1), 90 | .clocken3 (1'b1), 91 | .data_b ({32{1'b1}}), 92 | .eccstatus (), 93 | .q_a (), 94 | .rden_a (1'b1), 95 | .wren_b (1'b0)); 96 | defparam 97 | altsyncram_component.address_aclr_b = "NONE", 98 | altsyncram_component.address_reg_b = "CLOCK0", 99 | altsyncram_component.byte_size = 8, 100 | altsyncram_component.clock_enable_input_a = "BYPASS", 101 | altsyncram_component.clock_enable_input_b = "BYPASS", 102 | altsyncram_component.clock_enable_output_b = "BYPASS", 103 | altsyncram_component.intended_device_family = "Cyclone IV E", 104 | altsyncram_component.lpm_type = "altsyncram", 105 | altsyncram_component.numwords_a = 256, 106 | altsyncram_component.numwords_b = 256, 107 | altsyncram_component.operation_mode = "DUAL_PORT", 108 | altsyncram_component.outdata_aclr_b = "NONE", 109 | altsyncram_component.outdata_reg_b = "UNREGISTERED", 110 | altsyncram_component.power_up_uninitialized = "FALSE", 111 | altsyncram_component.rdcontrol_reg_b = "CLOCK0", 112 | altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", 113 | altsyncram_component.widthad_a = 8, 114 | altsyncram_component.widthad_b = 8, 115 | altsyncram_component.width_a = 32, 116 | altsyncram_component.width_b = 32, 117 | altsyncram_component.width_byteena_a = 4; 118 | 119 | 120 | endmodule 121 | 122 | // ============================================================ 123 | // CNX file retrieval info 124 | // ============================================================ 125 | // Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" 126 | // Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0" 127 | // Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0" 128 | // Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0" 129 | // Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "1" 130 | // Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0" 131 | // Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" 132 | // Retrieval info: PRIVATE: BlankMemory NUMERIC "1" 133 | // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" 134 | // Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0" 135 | // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" 136 | // Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0" 137 | // Retrieval info: PRIVATE: CLRdata NUMERIC "0" 138 | // Retrieval info: PRIVATE: CLRq NUMERIC "0" 139 | // Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0" 140 | // Retrieval info: PRIVATE: CLRrren NUMERIC "0" 141 | // Retrieval info: PRIVATE: CLRwraddress NUMERIC "0" 142 | // Retrieval info: PRIVATE: CLRwren NUMERIC "0" 143 | // Retrieval info: PRIVATE: Clock NUMERIC "0" 144 | // Retrieval info: PRIVATE: Clock_A NUMERIC "0" 145 | // Retrieval info: PRIVATE: Clock_B NUMERIC "0" 146 | // Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" 147 | // Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0" 148 | // Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "0" 149 | // Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_B" 150 | // Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" 151 | // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" 152 | // Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" 153 | // Retrieval info: PRIVATE: JTAG_ID STRING "NONE" 154 | // Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" 155 | // Retrieval info: PRIVATE: MEMSIZE NUMERIC "8192" 156 | // Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" 157 | // Retrieval info: PRIVATE: MIFfilename STRING "" 158 | // Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "2" 159 | // Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0" 160 | // Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0" 161 | // Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" 162 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" 163 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" 164 | // Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3" 165 | // Retrieval info: PRIVATE: REGdata NUMERIC "1" 166 | // Retrieval info: PRIVATE: REGq NUMERIC "1" 167 | // Retrieval info: PRIVATE: REGrdaddress NUMERIC "1" 168 | // Retrieval info: PRIVATE: REGrren NUMERIC "1" 169 | // Retrieval info: PRIVATE: REGwraddress NUMERIC "1" 170 | // Retrieval info: PRIVATE: REGwren NUMERIC "1" 171 | // Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" 172 | // Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0" 173 | // Retrieval info: PRIVATE: UseDPRAM NUMERIC "1" 174 | // Retrieval info: PRIVATE: VarWidth NUMERIC "0" 175 | // Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "32" 176 | // Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "32" 177 | // Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "32" 178 | // Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "32" 179 | // Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0" 180 | // Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "0" 181 | // Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0" 182 | // Retrieval info: PRIVATE: enable NUMERIC "0" 183 | // Retrieval info: PRIVATE: rden NUMERIC "1" 184 | // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all 185 | // Retrieval info: CONSTANT: ADDRESS_ACLR_B STRING "NONE" 186 | // Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK0" 187 | // Retrieval info: CONSTANT: BYTE_SIZE NUMERIC "8" 188 | // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" 189 | // Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS" 190 | // Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS" 191 | // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" 192 | // Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" 193 | // Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256" 194 | // Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "256" 195 | // Retrieval info: CONSTANT: OPERATION_MODE STRING "DUAL_PORT" 196 | // Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE" 197 | // Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED" 198 | // Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" 199 | // Retrieval info: CONSTANT: RDCONTROL_REG_B STRING "CLOCK0" 200 | // Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_MIXED_PORTS STRING "DONT_CARE" 201 | // Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8" 202 | // Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "8" 203 | // Retrieval info: CONSTANT: WIDTH_A NUMERIC "32" 204 | // Retrieval info: CONSTANT: WIDTH_B NUMERIC "32" 205 | // Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "4" 206 | // Retrieval info: USED_PORT: byteena_a 0 0 4 0 INPUT VCC "byteena_a[3..0]" 207 | // Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" 208 | // Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL "data[31..0]" 209 | // Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL "q[31..0]" 210 | // Retrieval info: USED_PORT: rdaddress 0 0 8 0 INPUT NODEFVAL "rdaddress[7..0]" 211 | // Retrieval info: USED_PORT: rden 0 0 0 0 INPUT VCC "rden" 212 | // Retrieval info: USED_PORT: wraddress 0 0 8 0 INPUT NODEFVAL "wraddress[7..0]" 213 | // Retrieval info: USED_PORT: wren 0 0 0 0 INPUT GND "wren" 214 | // Retrieval info: CONNECT: @address_a 0 0 8 0 wraddress 0 0 8 0 215 | // Retrieval info: CONNECT: @address_b 0 0 8 0 rdaddress 0 0 8 0 216 | // Retrieval info: CONNECT: @byteena_a 0 0 4 0 byteena_a 0 0 4 0 217 | // Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 218 | // Retrieval info: CONNECT: @data_a 0 0 32 0 data 0 0 32 0 219 | // Retrieval info: CONNECT: @rden_b 0 0 0 0 rden 0 0 0 0 220 | // Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 221 | // Retrieval info: CONNECT: q 0 0 32 0 @q_b 0 0 32 0 222 | // Retrieval info: GEN_FILE: TYPE_NORMAL sync_dpram.v TRUE 223 | // Retrieval info: GEN_FILE: TYPE_NORMAL sync_dpram.inc FALSE 224 | // Retrieval info: GEN_FILE: TYPE_NORMAL sync_dpram.cmp FALSE 225 | // Retrieval info: GEN_FILE: TYPE_NORMAL sync_dpram.bsf FALSE 226 | // Retrieval info: GEN_FILE: TYPE_NORMAL sync_dpram_inst.v FALSE 227 | // Retrieval info: GEN_FILE: TYPE_NORMAL sync_dpram_bb.v FALSE 228 | // Retrieval info: LIB_FILE: altera_mf 229 | -------------------------------------------------------------------------------- /fpga/ulogic/top.sdc: -------------------------------------------------------------------------------- 1 | # pio_begin 2 | if { ! [info exists ::HSI_PERIOD] } { 3 | set ::HSI_PERIOD 100.0 4 | } 5 | create_clock -name PIN_HSI -period $::HSI_PERIOD [get_ports PIN_HSI] 6 | set_clock_groups -asynchronous -group PIN_HSI 7 | if { ! [info exists ::HSE_PERIOD] } { 8 | set ::HSE_PERIOD 62.5 9 | } 10 | create_clock -name PIN_HSE -period $::HSE_PERIOD [get_ports PIN_HSE] 11 | set_clock_groups -asynchronous -group PIN_HSE 12 | derive_pll_clocks -create_base_clocks 13 | # pio_end 14 | 15 | 16 | create_clock -name AHB_TRANS -period 10 [get_nets {mem_ahb_htrans[1]}] 17 | set SYS_CLK [get_clocks pll_inst|*clk*0*] 18 | set BUS_CLK [get_clocks pll_inst|*clk*3*] 19 | 20 | # Always make sure there is an extra cycle of margin for inter domain transfers between SYS_CLK 21 | # and BUS_CLK. The extra cycle is always in terms of the to (latching) clock. 22 | set_multicycle_path -from $SYS_CLK -to $BUS_CLK -setup 2 23 | set_multicycle_path -from $SYS_CLK -to $BUS_CLK -hold 1 24 | set_multicycle_path -from $BUS_CLK -to $SYS_CLK -setup 2 25 | set_multicycle_path -from $BUS_CLK -to $SYS_CLK -hold 1 26 | 27 | # These are for mem_ahb_hreadyout going into rv32, since it's ok for rv32 to receive 28 | # mem_ahb_hreadyout 1 cycle late. They theoretically should help useful skew. 29 | set_multicycle_path -from $SYS_CLK -to rv32 -setup 2 30 | set_multicycle_path -from $SYS_CLK -to rv32 -hold 1 31 | 32 | 33 | #set_false_path -from $SYS_CLK -to $BUS_CLK 34 | #set_false_path -from $BUS_CLK -to $SYS_CLK 35 | 36 | 37 | -------------------------------------------------------------------------------- /fpga/ulogic/tpsram.v: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////// 2 | // Module: Tiny PSRAM Controller // 3 | /////////////////////////////////////////////////////// 4 | 5 | module tpsram( 6 | reset, 7 | clk, 8 | clk2x, 9 | 10 | cmd_req, 11 | cmd_ack, 12 | cmd_size, 13 | cmd_addr, 14 | cmd_din, 15 | cmd_dout, 16 | data_valid, 17 | 18 | ps_cs, 19 | ps_din, 20 | ps_dout, 21 | ps_oe 22 | ); 23 | 24 | // cmd_req: 25 | // 00: nop 26 | // 01: write 27 | // 10: read 28 | // cmd_size: 29 | // 00: byte 30 | // 01: word 31 | // 10: dword 32 | 33 | 34 | input reset; 35 | input clk; 36 | input clk2x; 37 | 38 | input [ 1:0] cmd_req; 39 | output cmd_ack; 40 | input [ 1:0] cmd_size; 41 | input [23:0] cmd_addr; 42 | input [31:0] cmd_din; 43 | output[31:0] cmd_dout; 44 | output data_valid; 45 | 46 | output ps_cs; 47 | input [3:0] ps_din; 48 | output[3:0] ps_dout; 49 | output[3:0] ps_oe; 50 | 51 | 52 | /////////////////////////////////////////////////////// 53 | // QSPI state // 54 | /////////////////////////////////////////////////////// 55 | 56 | reg[3:0] p_state; 57 | reg[3:0] p_next; 58 | 59 | reg ps_cs; 60 | reg[3:0] ps_dout; 61 | reg[3:0] ps_oe; 62 | 63 | reg data_valid; 64 | reg cmd_ack; 65 | 66 | reg[31:0] p_cad; 67 | reg[7:0] ps_cmd; 68 | reg[3:0] por_cnt; 69 | reg[4:0] rw_cnt; 70 | reg[31:0] rdata; 71 | reg[31:0] wdata; 72 | reg[2:0] p_wcnt; 73 | 74 | 75 | localparam CMD_IDLE=2'd0, CMD_WRITE=2'd1, CMD_READ=2'd2; 76 | 77 | localparam P_IDLE=4'd0, P_POR=4'd1, P_CADDR=4'd2, P_READ_WAIT=4'd3, P_READ_DATA=4'd4, 78 | P_WRITE=4'd5, P_FINISH=4'd6; 79 | 80 | always @(negedge reset or posedge clk) 81 | begin 82 | if(reset==0) begin 83 | p_state <= P_POR; 84 | ps_oe <= 4'b0000; 85 | ps_cmd <= 8'h35; 86 | ps_cs <= 1'b1; 87 | por_cnt <= 4'd8; 88 | rw_cnt <= 5'b0; 89 | cmd_ack <= 1'b0; 90 | end else begin 91 | case(p_state) 92 | P_POR: begin 93 | ps_cs <= 1'b0; 94 | ps_oe <= 4'b0001; 95 | ps_dout[0] <= ps_cmd[7]; 96 | ps_cmd <= {ps_cmd[6:0], 1'b0}; 97 | por_cnt <= por_cnt-1'b1; 98 | if(por_cnt==0) begin 99 | ps_cs <= 1'b1; 100 | ps_oe <= 4'b0000; 101 | p_state <= P_IDLE; 102 | end 103 | end 104 | 105 | P_IDLE: begin 106 | rw_cnt <= 0; 107 | if(cmd_req==CMD_READ) begin 108 | cmd_ack <= 1; 109 | p_cad <= {8'heb, cmd_addr[23:0]}; 110 | p_state <= P_CADDR; 111 | p_next <= P_READ_WAIT; 112 | end else if(cmd_req==CMD_WRITE) begin 113 | cmd_ack <= 1; 114 | p_cad <= {8'h02, cmd_addr[23:0]}; 115 | wdata[ 7: 0] <= cmd_din[31:24]; 116 | wdata[15: 8] <= cmd_din[23:16]; 117 | wdata[23:16] <= (cmd_addr[1 ]==0)? cmd_din[15: 8] : cmd_din[31:24]; 118 | wdata[31:24] <= (cmd_addr[1:0]==0)? cmd_din[ 7: 0] : 119 | (cmd_addr[1:0]==1)? cmd_din[15: 8] : 120 | (cmd_addr[1:0]==2)? cmd_din[23:16] : 121 | cmd_din[31:24] ; 122 | p_wcnt <= (cmd_size==2)? 3'd7 : (cmd_size==1)? 3'd3 : 3'd1; 123 | p_state <= P_CADDR; 124 | p_next <= P_WRITE; 125 | end 126 | end 127 | 128 | P_CADDR: begin 129 | cmd_ack <= 0; 130 | ps_cs <= 1'b0; 131 | ps_oe <= 4'b1111; 132 | ps_dout <= p_cad[31:28]; 133 | p_cad <= {p_cad[27:0], 4'b0000}; 134 | if(rw_cnt==7) begin 135 | p_state <= p_next; 136 | end 137 | rw_cnt <= rw_cnt+1'b1; 138 | end 139 | 140 | P_READ_WAIT: begin 141 | ps_oe <= 4'b0000; 142 | rw_cnt <= rw_cnt+1'b1; 143 | if(rw_cnt==15) begin 144 | p_state <= P_READ_DATA; 145 | end 146 | end 147 | 148 | P_READ_DATA: begin 149 | rw_cnt <= rw_cnt+1'b1; 150 | data_valid <= (rw_cnt[2:0]==3'b110); 151 | if(rw_cnt==31) begin 152 | ps_cs <= 1'b1; 153 | p_state <= P_FINISH; 154 | end 155 | end 156 | 157 | P_WRITE: begin 158 | ps_dout <= wdata[31:28]; 159 | wdata <= {wdata[27:0], 4'b0000}; 160 | p_wcnt <= p_wcnt-1'b1; 161 | if(p_wcnt==0) 162 | p_state <= P_FINISH; 163 | end 164 | 165 | P_FINISH: begin 166 | data_valid <= 0; 167 | ps_cs <= 1'b1; 168 | ps_oe <= 4'b0000; 169 | p_state <= P_IDLE; 170 | end 171 | 172 | default: begin 173 | p_state <= P_IDLE; 174 | end 175 | endcase; 176 | 177 | end 178 | end 179 | 180 | // reg[3:0] ps_din_d; 181 | // always @(posedge clk2x) 182 | // begin 183 | // ps_din_d <= ps_din; 184 | // end 185 | 186 | always @(negedge clk) 187 | begin 188 | rdata <= {rdata[27:0], ps_din}; 189 | end 190 | 191 | assign cmd_dout = {rdata[7:0], rdata[15:8], rdata[23:16], rdata[31:24]}; 192 | 193 | endmodule 194 | 195 | -------------------------------------------------------------------------------- /fpga/ulogic/ulogic.v: -------------------------------------------------------------------------------- 1 | 2 | /////////////////////////////////////////////////////// 3 | // Module: user logic for AGRV2KL100 // 4 | /////////////////////////////////////////////////////// 5 | 6 | module ulogic ( 7 | // Debug LED 8 | output soc_led, 9 | // SDCard 10 | input soc_sd_cd, 11 | output soc_sd_clk, 12 | inout soc_sd_cmd, 13 | inout soc_sd_d0, 14 | inout soc_sd_d1, 15 | inout soc_sd_d2, 16 | inout soc_sd_d3, 17 | // SPI PSRAM 18 | output soc_spi_clk, 19 | output soc_spi_csn, 20 | inout soc_spi_io0, 21 | inout soc_spi_io1, 22 | inout soc_spi_io2, 23 | inout soc_spi_io3, 24 | // Saturn ABUS 25 | inout [15:0] ss_ad, 26 | output ss_addroe, 27 | input [7:0] ss_ah, 28 | output ss_airq, 29 | output ss_await, 30 | input ss_cs0, 31 | input ss_cs1, 32 | input ss_cs2, 33 | output ss_datadir, 34 | output ss_dataoe, 35 | input ss_fc0, 36 | input ss_fc1, 37 | output ss_ibck, 38 | output ss_ilrck, 39 | output ss_isd, 40 | output ss_outen, 41 | input ss_rd, 42 | input ss_reset, 43 | input ss_spclk, 44 | output ss_ssel, 45 | input ss_wr0, 46 | input ss_wr1, 47 | // from mcu system 48 | input sys_clock, 49 | input bus_clock, 50 | input resetn, 51 | input stop, 52 | // AHB slave 53 | input [1:0] mem_ahb_htrans, 54 | input mem_ahb_hready, 55 | input mem_ahb_hwrite, 56 | input [31:0] mem_ahb_haddr, 57 | input [2:0] mem_ahb_hsize, 58 | input [2:0] mem_ahb_hburst, 59 | input [31:0] mem_ahb_hwdata, 60 | output mem_ahb_hreadyout, 61 | output mem_ahb_hresp, 62 | output [31:0] mem_ahb_hrdata, 63 | // AHB master 64 | output slave_ahb_hsel, 65 | output tri1 slave_ahb_hready, 66 | input slave_ahb_hreadyout, 67 | output [1:0] slave_ahb_htrans, 68 | output [2:0] slave_ahb_hsize, 69 | output [2:0] slave_ahb_hburst, 70 | output slave_ahb_hwrite, 71 | output [31:0] slave_ahb_haddr, 72 | output [31:0] slave_ahb_hwdata, 73 | input slave_ahb_hresp, 74 | input [31:0] slave_ahb_hrdata, 75 | // DMA 76 | output [3:0] ext_dma_DMACBREQ, 77 | output [3:0] ext_dma_DMACLBREQ, 78 | output [3:0] ext_dma_DMACSREQ, 79 | output [3:0] ext_dma_DMACLSREQ, 80 | input [3:0] ext_dma_DMACCLR, 81 | input [3:0] ext_dma_DMACTC, 82 | // Interrupt 83 | output [3:0] local_int 84 | ); 85 | 86 | /////////////////////////////////////////////////////// 87 | // AHB Master // 88 | /////////////////////////////////////////////////////// 89 | 90 | 91 | wire aclk = sys_clock; 92 | wire bclk = bus_clock; 93 | 94 | // 高速AHB到低速BUSCLK的握手信号 95 | reg ahb_start; 96 | reg ahb_ack; 97 | reg ahb_ack_d; 98 | 99 | always @(posedge ahb_ack or posedge mem_ahb_htrans[1]) 100 | begin 101 | if(ahb_ack) begin 102 | ahb_start <= 1'b0; 103 | end else begin 104 | if(hreadyout) 105 | ahb_start <= 1'b1; 106 | end 107 | end 108 | 109 | always @(posedge bclk) 110 | begin 111 | ahb_ack <= ahb_start; 112 | ahb_ack_d <= ahb_ack; 113 | end 114 | 115 | 116 | reg hreadyout; 117 | reg ahb_rd; 118 | reg ahb_wr; 119 | reg[31:0] haddr; 120 | reg[1:0] hsize; 121 | wire[3:0] ahb_wb; 122 | wire ahb_ready; 123 | 124 | always @(negedge resetn or posedge aclk) 125 | begin 126 | if(resetn==0) begin 127 | hreadyout <= 1'b1; 128 | end else begin 129 | if(hreadyout && mem_ahb_htrans[1]) begin 130 | hreadyout <= 1'b0; 131 | ahb_rd <= !mem_ahb_hwrite; 132 | ahb_wr <= mem_ahb_hwrite; 133 | haddr <= mem_ahb_haddr; 134 | hsize <= mem_ahb_hsize[1:0]; 135 | end else if(ahb_ready) begin 136 | hreadyout <= 1'b1; 137 | end 138 | end 139 | end 140 | 141 | assign mem_ahb_hreadyout = hreadyout; 142 | 143 | assign ahb_wb[0] = ( (hsize==2) || (hsize==1 && haddr[1]==0) || (hsize==0 && haddr[1:0]==2'b00) ); 144 | assign ahb_wb[1] = ( (hsize==2) || (hsize==1 && haddr[1]==0) || (hsize==0 && haddr[1:0]==2'b01) ); 145 | assign ahb_wb[2] = ( (hsize==2) || (hsize==1 && haddr[1]==1) || (hsize==0 && haddr[1:0]==2'b10) ); 146 | assign ahb_wb[3] = ( (hsize==2) || (hsize==1 && haddr[1]==1) || (hsize==0 && haddr[1:0]==2'b11) ); 147 | 148 | // 0x60000000 149 | wire sram_cs = (haddr[28:27]==2'b00); 150 | // 0x68000000 151 | wire pram_cs = (haddr[28:27]==2'b01); 152 | // 0x70000000 153 | wire sys_cs = (haddr[28]==1 && haddr[11:8]==4'b0000); 154 | // 0x70000100 155 | wire sd_cs = (haddr[28]==1 && haddr[11:8]==4'b0001); 156 | 157 | assign mem_ahb_hrdata = 158 | (sram_cs)? sram_rdata : 159 | (pram_cs)? pram_rdata : 160 | (sys_cs )? sys_rdata : 161 | (sd_cs )? sd_rdata : 162 | 32'hffffffff; 163 | 164 | assign ahb_ready = sram_ready | sys_ready | pram_ready | sd_ready; 165 | assign mem_ahb_hresp = 1'b0; 166 | 167 | /////////////////////////////////////////////////////// 168 | // SD Ctrl // 169 | /////////////////////////////////////////////////////// 170 | 171 | wire sd_wr = (ahb_ack && sd_cs && ahb_wr); 172 | wire sd_rd = (ahb_ack && sd_cs && ahb_rd); 173 | wire[31:0] sd_rdata; 174 | wire sd_ready = sd_cs && ahb_ack_d; 175 | 176 | wire[3:0] sd_din = {soc_sd_d3, soc_sd_d2, soc_sd_d1, soc_sd_d0}; 177 | wire[3:0] sd_dout; 178 | wire[3:0] sd_doe; 179 | wire sd_coe; 180 | wire sd_cmdin = soc_sd_cmd; 181 | wire sd_irq; 182 | 183 | sdctrl sd0(resetn, bclk, 184 | sd_rd, sd_wr, haddr[7:0], mem_ahb_hwdata, sd_rdata, sd_irq, ext_dma_DMACBREQ[0], ext_dma_DMACCLR[0], 185 | soc_sd_cd, soc_sd_clk, sd_cmdin, sd_cmdout, sd_din, sd_dout, sd_coe, sd_doe 186 | ); 187 | 188 | assign soc_sd_cmd = (sd_coe )? sd_cmdout : 1'bz; 189 | assign soc_sd_d0 = (sd_doe[0])? sd_dout[0] : 1'bz; 190 | assign soc_sd_d1 = (sd_doe[1])? sd_dout[1] : 1'bz; 191 | assign soc_sd_d2 = (sd_doe[2])? sd_dout[2] : 1'bz; 192 | assign soc_sd_d3 = (sd_doe[3])? sd_dout[3] : 1'bz; 193 | 194 | assign local_int[0] = sd_irq; 195 | 196 | 197 | /////////////////////////////////////////////////////// 198 | // System Ctrl // 199 | /////////////////////////////////////////////////////// 200 | 201 | reg[31:0] treg0; 202 | reg[31:0] treg1; 203 | reg[31:0] treg2; 204 | reg[31:0] treg3; 205 | always @(negedge bclk) 206 | begin 207 | if(soc_spi_csn==0) begin 208 | treg0 <= {treg0[30:0], soc_spi_io0}; 209 | treg1 <= {treg1[30:0], soc_spi_io1}; 210 | treg2 <= {treg2[30:0], soc_spi_io2}; 211 | treg3 <= {treg3[30:0], soc_spi_io3}; 212 | end 213 | end 214 | 215 | wire sys_wr = (ahb_ack && sys_cs && ahb_wr); 216 | reg[31:0] sys_rdata; 217 | wire sys_ready = sys_cs && ahb_ack_d; 218 | 219 | always @(posedge bclk) 220 | begin 221 | case(haddr[4:2]) 222 | 3'd0: sys_rdata <= treg0; 223 | 3'd1: sys_rdata <= treg1; 224 | 3'd2: sys_rdata <= treg2; 225 | 3'd3: sys_rdata <= treg3; 226 | 3'd4: sys_rdata <= taddr1; 227 | 3'd6: sys_rdata <= sys_reg3; 228 | 3'd7: sys_rdata <= sys_reg4; 229 | default: sys_rdata <= 32'hffffffff; 230 | endcase 231 | end 232 | 233 | reg[31:0] sys_reg3; 234 | reg[31:0] sys_reg4; 235 | 236 | always @(negedge resetn or posedge bclk) 237 | begin 238 | if(resetn==0) begin 239 | sys_reg3 <= 32'h3456789a; 240 | sys_reg4 <= 32'h44556789; 241 | end else if(sys_wr) begin 242 | if(haddr[4:2]==3) sys_reg3 <= mem_ahb_hwdata; 243 | if(haddr[4:2]==4) sys_reg4 <= mem_ahb_hwdata; 244 | end 245 | end 246 | 247 | 248 | /////////////////////////////////////////////////////// 249 | // SRAM // 250 | /////////////////////////////////////////////////////// 251 | 252 | 253 | wire[3:0] sram_wb = ahb_wb; 254 | wire sram_wr = (ahb_ack && sram_cs && ahb_wr); 255 | wire[7:0] sram_waddr = haddr[9:2]; 256 | 257 | wire sram_rd = (ahb_ack && sram_cs && ahb_rd); 258 | wire[7:0] sram_raddr = haddr[9:2]; 259 | wire[31:0] sram_rdata; 260 | 261 | sync_dpram sram(sram_wb, bclk, mem_ahb_hwdata, sram_raddr, sram_rd, sram_waddr, sram_wr, sram_rdata); 262 | 263 | reg sram_ready; 264 | always @(posedge bclk) 265 | begin 266 | sram_ready <= sram_cs && ahb_ack; 267 | end 268 | 269 | 270 | /////////////////////////////////////////////////////// 271 | // SPI PSRAM // 272 | /////////////////////////////////////////////////////// 273 | 274 | 275 | reg pram_ready; 276 | reg[1:0] cmd_req; 277 | reg[31:0] pram_rdata; 278 | 279 | wire[31:0] cmd_dout; 280 | wire cmd_ack; 281 | wire data_valid; 282 | 283 | reg[31:0] taddr1; 284 | 285 | reg[1:0] pstate; 286 | localparam PS_IDLE=0, PS_WAITACK=1, PS_WAITDATA0=2, PS_WAITDATA1=3; 287 | 288 | always @(negedge resetn or posedge bclk) 289 | begin 290 | if(resetn==0) begin 291 | cmd_req <= 0; 292 | pstate <= PS_IDLE; 293 | pram_ready <= 0; 294 | end else begin 295 | case(pstate) 296 | PS_IDLE: begin 297 | pram_ready <= 0; 298 | if(ahb_ack && pram_cs) begin 299 | cmd_req <= (ahb_rd)? 2'd2: 2'd1; 300 | taddr1 <= haddr; 301 | pstate <= PS_WAITACK; 302 | end 303 | end 304 | PS_WAITACK: begin 305 | if(cmd_ack) begin 306 | cmd_req <= 0; 307 | if(cmd_req==2) begin 308 | pstate <= PS_WAITDATA0; 309 | end else begin 310 | pram_ready <= 1'b1; 311 | pstate <= PS_IDLE; 312 | end 313 | end 314 | end 315 | PS_WAITDATA0: begin 316 | if(data_valid) begin 317 | pram_rdata <= (hsize==0)? {cmd_dout[ 7:0], cmd_dout[ 7:0], cmd_dout[7:0], cmd_dout[7:0]} : 318 | (hsize==1)? {cmd_dout[15:0], cmd_dout[15:0]} : 319 | cmd_dout; 320 | pstate <= PS_WAITDATA1; 321 | end 322 | end 323 | PS_WAITDATA1: begin 324 | if(data_valid) begin 325 | pram_ready <= 1'b1; 326 | pstate <= PS_IDLE; 327 | end 328 | end 329 | default: begin 330 | pstate <= PS_IDLE; 331 | end 332 | endcase 333 | end 334 | end 335 | 336 | 337 | wire ps_cs; 338 | wire[3:0] ps_din = {soc_spi_io3, soc_spi_io2, soc_spi_io1, soc_spi_io0}; 339 | wire[3:0] ps_dout; 340 | wire[3:0] ps_oe; 341 | tpsram psram(resetn, bclk, aclk, 342 | cmd_req, cmd_ack, hsize, haddr[23:0], mem_ahb_hwdata, cmd_dout, data_valid, 343 | ps_cs, ps_din, ps_dout, ps_oe 344 | ); 345 | 346 | assign soc_spi_csn = ps_cs; 347 | //assign soc_spi_clk = ~bclk; 348 | assign soc_spi_clk = 1'bz; 349 | assign soc_spi_io0 = (ps_oe[0])? ps_dout[0] : 1'bz; 350 | assign soc_spi_io1 = (ps_oe[1])? ps_dout[1] : 1'bz; 351 | assign soc_spi_io2 = (ps_oe[2])? ps_dout[2] : 1'bz; 352 | assign soc_spi_io3 = (ps_oe[3])? ps_dout[3] : 1'bz; 353 | 354 | 355 | /////////////////////////////////////////////////////// 356 | // Saturn ABUS // 357 | /////////////////////////////////////////////////////// 358 | 359 | assign ss_outen = 1'b1; 360 | assign ss_dataoe = 1'b1; 361 | assign ss_addroe = 1'b1; 362 | 363 | endmodule 364 | -------------------------------------------------------------------------------- /inc/main.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MAIN_H_ 3 | #define _MAIN_H_ 4 | 5 | #include "agrv.h" 6 | #include "riscv.h" 7 | 8 | typedef unsigned char u8; 9 | typedef unsigned short u16; 10 | typedef unsigned int u32; 11 | typedef unsigned long long u64; 12 | 13 | #define NULL ((void*)0) 14 | 15 | #define REG(x) (*(volatile unsigned int*)(x)) 16 | 17 | /******************************************************************************/ 18 | 19 | 20 | 21 | #define SYSCLK_FREQ 200000000 22 | 23 | /******************************************************************************/ 24 | 25 | 26 | void system_init(void); 27 | 28 | #define TIMER_HZ 1000000 29 | 30 | u64 get_mcycle(void); 31 | void timer_init(void); 32 | void reset_timer(void); 33 | u32 get_timer(void); 34 | void udelay(int us); 35 | void mdelay(int ms); 36 | 37 | 38 | int int_request(int id, void *func, void *arg); 39 | int int_priorit(int id, int priorit); 40 | int int_enable(int id); 41 | int int_disable(int id); 42 | 43 | 44 | 45 | int rtc_getcnt(void); 46 | 47 | 48 | void uart0_init(int baudrate); 49 | int getc(int tmout); 50 | void putc(int ch); 51 | void puts(char *str); 52 | 53 | 54 | void gpio_af(int group, int bit, int en); 55 | void gpio_dir(int group, int bit, int dir); 56 | void gpio_set(int group, int bit, int val); 57 | int gpio_get(int group, int bit); 58 | 59 | 60 | void device_init(void); 61 | void trap_init(void); 62 | 63 | /******************************************************************************/ 64 | 65 | int sd_identify(void); 66 | int sd_read_blocks(u32 block, int count, u8 *buf); 67 | int sd_write_blocks(u32 block, int count, u8 *buf); 68 | 69 | 70 | 71 | int printk(char *fmt, ...); 72 | int sprintk(char *sbuf, const char *fmt, ...); 73 | int snprintf(char *sbuf, int len, const char *fmt, ...); 74 | void hex_dump(char *str, void *addr, int size); 75 | 76 | 77 | unsigned int strlen(const char *s); 78 | int strcmp(const char *s1, const char *s2); 79 | int strncmp(const char *s1, const char *s2, unsigned int n); 80 | int strcasecmp(const char *s1, const char *s2); 81 | char *strcpy(char *dst, const char *src); 82 | char *strncpy(char *dst, const char *src, unsigned int n); 83 | char *strchr(const char *s1, int ch); 84 | u32 strtoul(char *str, char **endptr, int requestedbase, int *ret); 85 | 86 | void *memset(void *s, int v, unsigned int n); 87 | void *memcpy(void *to, const void *from, unsigned int n); 88 | int memcmp(const void *dst, const void *src, unsigned int n); 89 | 90 | 91 | void simple_shell(void); 92 | 93 | 94 | /******************************************************************************/ 95 | 96 | 97 | 98 | 99 | 100 | 101 | #endif 102 | 103 | -------------------------------------------------------------------------------- /inc/riscv.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef RISCV_CSR_ENCODING_H 4 | #define RISCV_CSR_ENCODING_H 5 | 6 | #define MSTATUS_UIE 0x00000001 7 | #define MSTATUS_SIE 0x00000002 8 | #define MSTATUS_HIE 0x00000004 9 | #define MSTATUS_MIE 0x00000008 10 | #define MSTATUS_UPIE 0x00000010 11 | #define MSTATUS_SPIE 0x00000020 12 | #define MSTATUS_HPIE 0x00000040 13 | #define MSTATUS_MPIE 0x00000080 14 | #define MSTATUS_SPP 0x00000100 15 | #define MSTATUS_HPP 0x00000600 16 | #define MSTATUS_MPP 0x00001800 17 | #define MSTATUS_FS 0x00006000 18 | #define MSTATUS_XS 0x00018000 19 | #define MSTATUS_MPRV 0x00020000 20 | #define MSTATUS_SUM 0x00040000 21 | #define MSTATUS_MXR 0x00080000 22 | #define MSTATUS_TVM 0x00100000 23 | #define MSTATUS_TW 0x00200000 24 | #define MSTATUS_TSR 0x00400000 25 | #define MSTATUS32_SD 0x80000000 26 | #define MSTATUS_UXL 0x0000000300000000 27 | #define MSTATUS_SXL 0x0000000C00000000 28 | #define MSTATUS64_SD 0x8000000000000000 29 | 30 | #define SSTATUS_UIE 0x00000001 31 | #define SSTATUS_SIE 0x00000002 32 | #define SSTATUS_UPIE 0x00000010 33 | #define SSTATUS_SPIE 0x00000020 34 | #define SSTATUS_SPP 0x00000100 35 | #define SSTATUS_FS 0x00006000 36 | #define SSTATUS_XS 0x00018000 37 | #define SSTATUS_SUM 0x00040000 38 | #define SSTATUS_MXR 0x00080000 39 | #define SSTATUS32_SD 0x80000000 40 | #define SSTATUS_UXL 0x0000000300000000 41 | #define SSTATUS64_SD 0x8000000000000000 42 | 43 | #define DCSR_XDEBUGVER (3U<<30) 44 | #define DCSR_NDRESET (1<<29) 45 | #define DCSR_FULLRESET (1<<28) 46 | #define DCSR_EBREAKM (1<<15) 47 | #define DCSR_EBREAKH (1<<14) 48 | #define DCSR_EBREAKS (1<<13) 49 | #define DCSR_EBREAKU (1<<12) 50 | #define DCSR_STOPCYCLE (1<<10) 51 | #define DCSR_STOPTIME (1<<9) 52 | #define DCSR_CAUSE (7<<6) 53 | #define DCSR_DEBUGINT (1<<5) 54 | #define DCSR_HALT (1<<3) 55 | #define DCSR_STEP (1<<2) 56 | #define DCSR_PRV (3<<0) 57 | 58 | #define DCSR_CAUSE_NONE 0 59 | #define DCSR_CAUSE_SWBP 1 60 | #define DCSR_CAUSE_HWBP 2 61 | #define DCSR_CAUSE_DEBUGINT 3 62 | #define DCSR_CAUSE_STEP 4 63 | #define DCSR_CAUSE_HALT 5 64 | 65 | #define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4)) 66 | #define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5)) 67 | #define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11)) 68 | 69 | #define MCONTROL_SELECT (1<<19) 70 | #define MCONTROL_TIMING (1<<18) 71 | #define MCONTROL_ACTION (0x3f<<12) 72 | #define MCONTROL_CHAIN (1<<11) 73 | #define MCONTROL_MATCH (0xf<<7) 74 | #define MCONTROL_M (1<<6) 75 | #define MCONTROL_H (1<<5) 76 | #define MCONTROL_S (1<<4) 77 | #define MCONTROL_U (1<<3) 78 | #define MCONTROL_EXECUTE (1<<2) 79 | #define MCONTROL_STORE (1<<1) 80 | #define MCONTROL_LOAD (1<<0) 81 | 82 | #define MCONTROL_TYPE_NONE 0 83 | #define MCONTROL_TYPE_MATCH 2 84 | 85 | #define MCONTROL_ACTION_DEBUG_EXCEPTION 0 86 | #define MCONTROL_ACTION_DEBUG_MODE 1 87 | #define MCONTROL_ACTION_TRACE_START 2 88 | #define MCONTROL_ACTION_TRACE_STOP 3 89 | #define MCONTROL_ACTION_TRACE_EMIT 4 90 | 91 | #define MCONTROL_MATCH_EQUAL 0 92 | #define MCONTROL_MATCH_NAPOT 1 93 | #define MCONTROL_MATCH_GE 2 94 | #define MCONTROL_MATCH_LT 3 95 | #define MCONTROL_MATCH_MASK_LOW 4 96 | #define MCONTROL_MATCH_MASK_HIGH 5 97 | 98 | #define MIP_SSIP (1 << IRQ_S_SOFT) 99 | #define MIP_HSIP (1 << IRQ_H_SOFT) 100 | #define MIP_MSIP (1 << IRQ_M_SOFT) 101 | #define MIP_STIP (1 << IRQ_S_TIMER) 102 | #define MIP_HTIP (1 << IRQ_H_TIMER) 103 | #define MIP_MTIP (1 << IRQ_M_TIMER) 104 | #define MIP_SEIP (1 << IRQ_S_EXT) 105 | #define MIP_HEIP (1 << IRQ_H_EXT) 106 | #define MIP_MEIP (1 << IRQ_M_EXT) 107 | 108 | #define SIP_SSIP MIP_SSIP 109 | #define SIP_STIP MIP_STIP 110 | 111 | #define PRV_U 0 112 | #define PRV_S 1 113 | #define PRV_H 2 114 | #define PRV_M 3 115 | 116 | #define SATP32_MODE 0x80000000 117 | #define SATP32_ASID 0x7FC00000 118 | #define SATP32_PPN 0x003FFFFF 119 | #define SATP64_MODE 0xF000000000000000 120 | #define SATP64_ASID 0x0FFFF00000000000 121 | #define SATP64_PPN 0x00000FFFFFFFFFFF 122 | 123 | #define SATP_MODE_OFF 0 124 | #define SATP_MODE_SV32 1 125 | #define SATP_MODE_SV39 8 126 | #define SATP_MODE_SV48 9 127 | #define SATP_MODE_SV57 10 128 | #define SATP_MODE_SV64 11 129 | 130 | #define PMP_R 0x01 131 | #define PMP_W 0x02 132 | #define PMP_X 0x04 133 | #define PMP_A 0x18 134 | #define PMP_L 0x80 135 | #define PMP_SHIFT 2 136 | 137 | #define PMP_TOR 0x08 138 | #define PMP_NA4 0x10 139 | #define PMP_NAPOT 0x18 140 | 141 | #define IRQ_S_SOFT 1 142 | #define IRQ_H_SOFT 2 143 | #define IRQ_M_SOFT 3 144 | #define IRQ_S_TIMER 5 145 | #define IRQ_H_TIMER 6 146 | #define IRQ_M_TIMER 7 147 | #define IRQ_S_EXT 9 148 | #define IRQ_H_EXT 10 149 | #define IRQ_M_EXT 11 150 | #define IRQ_COP 12 151 | #define IRQ_HOST 13 152 | 153 | #define DEFAULT_RSTVEC 0x00001000 154 | #define CLINT_BASE 0x02000000 155 | #define CLINT_SIZE 0x000c0000 156 | #define EXT_IO_BASE 0x40000000 157 | #define DRAM_BASE 0x80000000 158 | 159 | // page table entry (PTE) fields 160 | #define PTE_V 0x001 // Valid 161 | #define PTE_R 0x002 // Read 162 | #define PTE_W 0x004 // Write 163 | #define PTE_X 0x008 // Execute 164 | #define PTE_U 0x010 // User 165 | #define PTE_G 0x020 // Global 166 | #define PTE_A 0x040 // Accessed 167 | #define PTE_D 0x080 // Dirty 168 | #define PTE_SOFT 0x300 // Reserved for Software 169 | 170 | #define PTE_PPN_SHIFT 10 171 | 172 | #define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V) 173 | 174 | #ifdef __riscv 175 | 176 | #if __riscv_xlen == 64 177 | # define MSTATUS_SD MSTATUS64_SD 178 | # define SSTATUS_SD SSTATUS64_SD 179 | # define RISCV_PGLEVEL_BITS 9 180 | # define SATP_MODE SATP64_MODE 181 | #else 182 | # define MSTATUS_SD MSTATUS32_SD 183 | # define SSTATUS_SD SSTATUS32_SD 184 | # define RISCV_PGLEVEL_BITS 10 185 | # define SATP_MODE SATP32_MODE 186 | #endif 187 | #define RISCV_PGSHIFT 12 188 | #define RISCV_PGSIZE (1 << RISCV_PGSHIFT) 189 | 190 | #ifndef __ASSEMBLER__ 191 | 192 | #ifdef __GNUC__ 193 | 194 | #define read_csr(reg) ({ unsigned long __tmp; \ 195 | asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ 196 | __tmp; }) 197 | 198 | #define write_csr(reg, val) ({ \ 199 | asm volatile ("csrw " #reg ", %0" :: "rK"(val)); }) 200 | 201 | #define swap_csr(reg, val) ({ unsigned long __tmp; \ 202 | asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "rK"(val)); \ 203 | __tmp; }) 204 | 205 | #define set_csr(reg, bit) ({ unsigned long __tmp; \ 206 | asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \ 207 | __tmp; }) 208 | 209 | #define clear_csr(reg, bit) ({ unsigned long __tmp; \ 210 | asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \ 211 | __tmp; }) 212 | 213 | 214 | #define WFI() ({ asm volatile ("wfi"); }) 215 | 216 | 217 | #define rdtime() read_csr(time) 218 | #define rdcycle() read_csr(cycle) 219 | #define rdinstret() read_csr(instret) 220 | 221 | #endif 222 | 223 | #endif 224 | 225 | #endif 226 | 227 | #endif 228 | 229 | -------------------------------------------------------------------------------- /inc/xos.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _XOS_H_ 3 | #define _XOS_H_ 4 | 5 | #include 6 | #include 7 | #include "main.h" 8 | 9 | /******************************************************************************/ 10 | 11 | #define MAX_PRIORITY 8 12 | 13 | #define DEFAULT_STACK_SIZE 4096 14 | #define DEFAULT_TASK_PRIO 4 15 | 16 | #define HZ 100 17 | 18 | 19 | typedef void (*ENTRY_FN)(void*); 20 | typedef struct tcb_t *task_t; 21 | typedef struct tcb_t TCB; 22 | 23 | 24 | typedef unsigned char u8; 25 | typedef unsigned short u16; 26 | typedef unsigned int u32; 27 | typedef unsigned long long u64; 28 | 29 | #ifndef NULL 30 | #define NULL (void*)0 31 | #endif 32 | 33 | /******************************************************************************/ 34 | 35 | typedef struct list_node_t { 36 | struct list_node_t *next; 37 | struct list_node_t *prev; 38 | }LIST_NODE; 39 | 40 | typedef struct list_t { 41 | struct list_node_t *head; 42 | int lock; 43 | }LIST; 44 | 45 | 46 | void list_init(LIST *list); 47 | void list_add(LIST *list, LIST_NODE *node); 48 | void list_remove(LIST *list, LIST_NODE *node); 49 | void list_insert_order(LIST *list, LIST_NODE *node, int (*cmp_func)(void *, void*)); 50 | 51 | #define list_entry(ptr, type, member) (type*)( ((uint8_t*)(ptr)) - __builtin_offsetof(type, member) ) 52 | 53 | #define atomic_add(a, b) __sync_add_and_fetch((a), (b)) 54 | #define atomic_sub(a, b) __sync_sub_and_fetch((a), (b)) 55 | 56 | int spin_lock_irq(void); 57 | void spin_unlock_irq(int key); 58 | void spin_lock(int *val); 59 | void spin_unlock(int *val); 60 | 61 | 62 | /******************************************************************************/ 63 | 64 | 65 | #if defined(ARCH_ARMV7) 66 | #elif defined(ARCH_ARMV7M) 67 | #elif defined(ARCH_RISCV) 68 | typedef struct { 69 | u32 x1; // ra 70 | u32 x2; // sp 71 | u32 x3; // gp 72 | u32 x4; // tp 73 | u32 x5; // t0 74 | u32 x6; // t1 75 | u32 x7; // t2 76 | u32 x8; // s0/fp 77 | u32 x9; // s1 78 | u32 x10; // a0 79 | u32 x11; // a1 80 | u32 x12; // a2 81 | u32 x13; // a3 82 | u32 x14; // a4 83 | u32 x15; // a5 84 | u32 x16; // a6 85 | u32 x17; // a7 86 | u32 x18; // s2 87 | u32 x19; // s3 88 | u32 x20; // s4 89 | u32 x21; // s5 90 | u32 x22; // s6 91 | u32 x23; // s7 92 | u32 x24; // s8 93 | u32 x25; // s9 94 | u32 x26; // s10 95 | u32 x27; // s11 96 | u32 x28; // t3 97 | u32 x29; // t4 98 | u32 x30; // t5 99 | u32 x31; // t6 100 | u32 pc; 101 | }RISCV_REGS; 102 | 103 | 104 | typedef struct tcb_arch_t { 105 | RISCV_REGS regs; 106 | }TCB_ARCH; 107 | #endif 108 | 109 | 110 | /******************************************************************************/ 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | /******************************************************************************/ 119 | 120 | 121 | // 任务状态 122 | #define T_IDLE 0 123 | #define T_READY 1 124 | #define T_RUN 2 125 | #define T_WAIT 3 126 | #define T_DEAD 4 127 | 128 | 129 | typedef struct tcb_t { 130 | TCB_ARCH arch; 131 | void (*entry)(void*); 132 | void *arg; 133 | u8 *stack; 134 | int stack_size; 135 | 136 | u8 prio; 137 | u8 state; 138 | u8 mask; 139 | u8 tid; 140 | 141 | int timeout; 142 | int retv; 143 | 144 | LIST_NODE node; 145 | char name[16]; 146 | }TCB; 147 | 148 | 149 | typedef struct sem_t { 150 | int lock; 151 | int value; 152 | TCB *tcb; 153 | }SEM; 154 | 155 | 156 | extern LIST g_list_ready; 157 | extern LIST g_list_sleep; 158 | extern LIST g_list_dead; 159 | 160 | 161 | extern uint32_t g_ticks; 162 | 163 | 164 | /******************************************************************************/ 165 | 166 | void _task_entry(void *arg); 167 | void _idle_task(void *arg); 168 | void _tick_handle(void); 169 | void __die(void); 170 | 171 | task_t xos_task_create(char *task_name, ENTRY_FN entry, void *arg, int priority, int stack_size); 172 | void xos_task_exit(void); 173 | void xos_task_delay(int ticks); 174 | void xos_task_yield(void); 175 | TCB *xos_task_self(void); 176 | void xos_init(void *first_entry); 177 | 178 | 179 | void xos_sem_init(SEM *sem, int val); 180 | void xos_sem_give(SEM *sem); 181 | int xos_sem_take(SEM *sem, int timeout); 182 | 183 | void xos_heap_init(u32 start, u32 size); 184 | void *xos_malloc(int size); 185 | void xos_free(void *ptr); 186 | 187 | void dump_task(void); 188 | 189 | /******************************************************************************/ 190 | 191 | int arch_in_isr(void); 192 | int arch_irq_lock(void); 193 | void arch_irq_unlock(int key); 194 | void arch_irq_enable(void); 195 | int arch_task_init(TCB *tcb); 196 | int arch_sys_init(void); 197 | void arch_timer_init(void); 198 | void arch_idle(void); 199 | void arch_putc(int); 200 | void arch_puts(char *); 201 | int arch_getc(void); 202 | 203 | void arch_swap_context(TCB *); 204 | void arch_set_context(TCB *); 205 | 206 | /******************************************************************************/ 207 | 208 | #endif 209 | 210 | -------------------------------------------------------------------------------- /main/Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | ################################################################ 4 | 5 | 6 | LDIR = main 7 | 8 | LOBJS = start.o cpu_agrv.o main.o shell.o spi_sd.o 9 | LOBJS += xos_core.o heap.o printk.o string.o 10 | 11 | OBJS += $(addprefix $(LDIR)/, $(LOBJS)) 12 | 13 | 14 | ################################################################ 15 | 16 | 17 | INCDIR += -Imain 18 | DEFS += -march=rv32imafc -mabi=ilp32f -fno-builtin -DARCH_RISCV 19 | LDFLAGS += -T $(LDIR)/ld.S -march=rv32imafc -mabi=ilp32f -Wl,--defsym,TEXT_START=0x80000000 20 | ASFLAG += -DRUN_FLASH 21 | 22 | ################################################################ 23 | 24 | 25 | -------------------------------------------------------------------------------- /main/cpu_agrv.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "main.h" 4 | #include "xos.h" 5 | 6 | 7 | /******************************************************************************/ 8 | 9 | 10 | u32 pclk_freq; 11 | u32 sclk_freq; 12 | 13 | 14 | void system_init(void) 15 | { 16 | u32 sclk_div = (SYSCLK_FREQ-1)/FLASH_MAX_FREQ; 17 | u32 clkctl = SYS->CLK_CNTL; 18 | 19 | // set sclk divider 20 | clkctl &= ~0xff00; 21 | clkctl |= (sclk_div<<8) | (sclk_div<<12); 22 | 23 | // enable HSE and PLL 24 | clkctl &= ~(1<<3); 25 | clkctl |= (1<<2) | (1<<5); 26 | SYS->CLK_CNTL = clkctl; 27 | 28 | // wait HSE and PLL 29 | while(!(SYS->CLK_CNTL & ((1<<4)|(1<<6)))); 30 | 31 | // Switch SYSCLK to PLL 32 | clkctl &= ~3; 33 | clkctl |= 2; 34 | SYS->CLK_CNTL = clkctl; 35 | 36 | pclk_freq = SYSCLK_FREQ/(SYS->PBUS_DIVIDER+1); 37 | sclk_freq = SYSCLK_FREQ/(sclk_div+1); 38 | 39 | RTC->BDCR = 0x8101; 40 | } 41 | 42 | 43 | /******************************************************************************/ 44 | 45 | 46 | u64 get_mcycle(void) 47 | { 48 | u32 h0, h1, low; 49 | 50 | do{ 51 | h0 = read_csr(mcycleh); 52 | low = read_csr(mcycle); 53 | h1 = read_csr(mcycleh); 54 | }while(h0!=h1); 55 | 56 | return ((u64)h0<<32) | low; 57 | } 58 | 59 | 60 | /******************************************************************************/ 61 | 62 | 63 | void timer_init(void) 64 | { 65 | reset_timer(); 66 | } 67 | 68 | 69 | void reset_timer(void) 70 | { 71 | SYS->MTIME_PSC = 0x40000000; 72 | CLINT->MTIME_LO = 0; 73 | CLINT->MTIME_HI = 0; 74 | SYS->MTIME_PSC = (SYSCLK_FREQ/1000000)-1; 75 | } 76 | 77 | 78 | u32 get_timer(void) 79 | { 80 | return CLINT->MTIME_LO; 81 | } 82 | 83 | 84 | void udelay(int us) 85 | { 86 | //reset_timer(); 87 | u32 end = get_timer() + us; 88 | while(get_timer()CNTL; 104 | int cnth = RTC->CNTH; 105 | return (cnth<<16)|cntl; 106 | } 107 | 108 | 109 | /******************************************************************************/ 110 | 111 | 112 | void uart0_init(int baudrate) 113 | { 114 | int div64; 115 | 116 | div64 = (pclk_freq*4 + baudrate/2)/baudrate; 117 | 118 | UART0->CR = 0; 119 | UART0->IBRD = (div64>>6); 120 | UART0->FBRD = (div64&0x3f); 121 | UART0->LCR_H = 0x0070; 122 | UART0->ICR = 0x07ff; 123 | UART0->IMSC = 0; 124 | UART0->DMACR = 0; 125 | UART0->CR = 0x0301; 126 | } 127 | 128 | 129 | int getc(int tmout) 130 | { 131 | while((UART0->FR&0x0010)){ 132 | xos_task_delay(5); 133 | }; 134 | return (UART0->DR)&0xff; 135 | } 136 | 137 | 138 | void putc(int ch) 139 | { 140 | while((UART0->FR&0x0020)); 141 | UART0->DR = ch; 142 | } 143 | 144 | void puts(char *str) 145 | { 146 | int ch; 147 | while((ch=*str++)){ 148 | if(ch=='\n') 149 | putc('\r'); 150 | putc(ch); 151 | } 152 | } 153 | 154 | 155 | /******************************************************************************/ 156 | 157 | 158 | void gpio_af(int group, int bit, int en) 159 | { 160 | volatile GPIO_TypeDef *gpio = (GPIO_TypeDef*)(0x40014000+group*0x1000); 161 | int mask = 1<AFSEL |= mask; 165 | }else{ 166 | gpio->AFSEL &= ~mask; 167 | } 168 | } 169 | 170 | 171 | void gpio_dir(int group, int bit, int dir) 172 | { 173 | volatile GPIO_TypeDef *gpio = (GPIO_TypeDef*)(0x40014000+group*0x1000); 174 | int mask = 1<DIR |= mask; 178 | }else{ 179 | gpio->DIR &= ~mask; 180 | } 181 | } 182 | 183 | 184 | void gpio_set(int group, int bit, int val) 185 | { 186 | volatile GPIO_TypeDef *gpio = (GPIO_TypeDef*)(0x40014000+group*0x1000); 187 | int mask = 1<DATA[mask] = (val)? mask : 0; 190 | } 191 | 192 | 193 | int gpio_get(int group, int bit) 194 | { 195 | volatile GPIO_TypeDef *gpio = (GPIO_TypeDef*)(0x40014000+group*0x1000); 196 | int mask = 1<DATA[mask] & mask) ? 1: 0; 199 | } 200 | 201 | /******************************************************************************/ 202 | 203 | 204 | void device_init(void) 205 | { 206 | SYS->AHB_CLKENABLE = 0x05; // CRC DMA 207 | SYS->APB_CLKENABLE = 0x00217ffc; // UART0 GTIM0 TIM0 GPIO[9:0] SPI1 SPI0 208 | 209 | GPIO6->AFSEL |= (1<<1); // UART0_RXD 210 | GPIO7->AFSEL |= (1<<6); // UART0_TXD 211 | 212 | GPIO4->AFSEL |= 0x80; // SPI1: SCK 213 | GPIO5->AFSEL |= 0x01; // SPI1: CSN 214 | GPIO0->AFSEL |= 0x30; // SPI1: SI SO 215 | 216 | GPIO2->DIR |= 0x01; 217 | 218 | uart0_init(115200); 219 | 220 | DMAC->IntTCClear = 0xff; 221 | DMAC->Config = 0x00000001; 222 | } 223 | 224 | 225 | /******************************************************************************/ 226 | 227 | static void *int_vectors[64]; 228 | static void *int_args[64]; 229 | 230 | int int_request(int id, void *func, void *arg) 231 | { 232 | int_vectors[id] = func; 233 | int_args[id] = arg; 234 | return 0; 235 | } 236 | 237 | 238 | int int_priorit(int id, int priorit) 239 | { 240 | if(id<48) 241 | PLIC->PRIORITY[id] = priorit; 242 | return 0; 243 | } 244 | 245 | 246 | int int_enable(int id) 247 | { 248 | if(id<48){ 249 | PLIC->ENABLE[id/32] |= (1<<(id%32)); 250 | }else{ 251 | if(id==48){ 252 | set_csr(mie, (1<ENABLE[id/32] &= ~(1<<(id%32)); 267 | }else{ 268 | if(id==48){ 269 | clear_csr(mie, (1<CLAIM; 289 | if(id==0) 290 | break; 291 | func = int_vectors[id]; 292 | if(func){ 293 | func(regs, int_args[id]); 294 | }else{ 295 | printk("\nEmpty Interrupt %d!\n", id); 296 | } 297 | PLIC->CLAIM = id; 298 | } 299 | }else{ 300 | // from CLINT 301 | if(cause==3){ 302 | id = 48; 303 | }else if(cause==7){ 304 | id = 49; 305 | }else if(cause>15){ 306 | id = cause-16+50; 307 | } 308 | 309 | func = int_vectors[id]; 310 | if(func){ 311 | func(regs, int_args[id]); 312 | }else{ 313 | printk("\nEmpty Interrupt %d!\n", id); 314 | } 315 | } 316 | } 317 | 318 | 319 | /******************************************************************************/ 320 | 321 | static char *excp_msg[16] = { 322 | "Inst Align", 323 | "Inst Fault", 324 | "Inst Illegal", 325 | "Breakpoint", 326 | "Load Align", 327 | "Load Fault", 328 | "Store Align", 329 | "Store Fault", 330 | "ECall_U", 331 | "ECall_S", 332 | "Reserved", 333 | "ECall_M", 334 | "IPage Fault", 335 | "LPage Fault", 336 | "Reserved", 337 | "SPage Fault", 338 | }; 339 | 340 | static char *reg_names[32] = { 341 | "x0", "ra", "sp", "gp", "tp", "t0", "t1", "t2", 342 | "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", 343 | "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", 344 | "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", 345 | }; 346 | 347 | int in_isr = 0; 348 | void trap_handle(u32 *regs, int cause) 349 | { 350 | int i; 351 | 352 | in_isr = 1; 353 | 354 | if(cause<0){ 355 | int_handle(regs, cause&0xff); 356 | in_isr = 0; 357 | return; 358 | }else{ 359 | printk("\n[%s!]: EPC=%08x TVAL=%08x CAUSE=%d\n", excp_msg[cause], regs[31], read_csr(mtval), cause); 360 | } 361 | 362 | printk(" x0=00000000 "); 363 | for(i=1; i<32; i++){ 364 | if((i%4)==0) 365 | printk("\n"); 366 | printk("%3s=%08x ", reg_names[i], regs[i-1]); 367 | } 368 | printk("\n"); 369 | 370 | 371 | while(1); 372 | } 373 | 374 | 375 | void _trap_entry(void); 376 | 377 | void trap_init(void) 378 | { 379 | int i; 380 | 381 | clear_csr(mstatus, MSTATUS_MIE); 382 | write_csr(mtvec, (u32)_trap_entry); 383 | 384 | // 貌似第一次enable一个外部中断,总会先触发一次。这里先统一触发清除一次。 385 | PLIC->ENABLE[0] = 0xffffffff; 386 | PLIC->ENABLE[1] = 0xffffffff; 387 | do{ 388 | i = PLIC->CLAIM; 389 | PLIC->CLAIM = i; 390 | }while(i); 391 | 392 | PLIC->ENABLE[0] = 0; 393 | PLIC->ENABLE[1] = 0; 394 | PLIC->THRESHOLD = 0; 395 | 396 | for(i=0; i<64; i++){ 397 | int_vectors[i] = NULL; 398 | int_args[i] = NULL; 399 | PLIC->PRIORITY[i] = 8; 400 | } 401 | 402 | set_csr(mie, (1<next = mb; 38 | head->prev = NULL; 39 | head->nf = mb; 40 | head->pf = NULL; 41 | 42 | mb->next = tail; 43 | mb->prev = head; 44 | mb->nf = NULL; 45 | mb->pf = head; 46 | 47 | tail->next = NULL; 48 | tail->prev = mb; 49 | } 50 | 51 | 52 | static int mblk_size(MBLK *m) 53 | { 54 | u32 next = (u32)m->next; 55 | 56 | int size = (next&~1) - (u32)m; 57 | return size-8; 58 | } 59 | 60 | 61 | void xos_dump(void) 62 | { 63 | MBLK *m = head; 64 | 65 | printk("\n"); 66 | while(m){ 67 | u32 next = (u32)m->next; 68 | printk("%08x: nb_%08x pb_%08x", m, next, m->prev); 69 | if((next&1)==0){ 70 | printk(" nf_%08x pf_%08x sz_%08x\n", m->nf, m->pf, mblk_size(m)); 71 | }else{ 72 | printk("\n"); 73 | } 74 | 75 | m = (MBLK*)(next&~1); 76 | } 77 | printk("\n"); 78 | } 79 | 80 | 81 | void *xos_malloc(int size) 82 | { 83 | MBLK *m = head->nf; 84 | MBLK *fit_mblk = NULL; 85 | int fit_size = 0x7fffffff; 86 | int bsize; 87 | 88 | //printk("xos_malloc: %d bytes\n", size); 89 | size = (size+7)&~7; 90 | 91 | int key = spin_lock_irq(); 92 | 93 | while(m){ 94 | bsize = mblk_size(m); 95 | if(bsize > size){ 96 | // 找最合适的块 97 | if(bsize < fit_size){ 98 | fit_size = bsize; 99 | fit_mblk = m; 100 | } 101 | #if 0 102 | // 找第一个块 103 | break; 104 | #endif 105 | } 106 | 107 | m = m->nf; 108 | } 109 | if(fit_mblk==NULL){ 110 | spin_unlock_irq(key); 111 | //printk("\n"); 112 | return NULL; 113 | } 114 | m = fit_mblk; 115 | bsize = fit_size; 116 | 117 | if(bsize-size>=16){ 118 | // m可分裂为两块 119 | MBLK *n = (MBLK*)((u8*)m+8+size); 120 | 121 | n->next = m->next; 122 | n->prev = m; 123 | if(n->next) 124 | n->next->prev = n; 125 | m->next = n; 126 | 127 | // n代替m,加入free列表中 128 | n->nf = m->nf; 129 | n->pf = m->pf; 130 | if(n->pf) 131 | n->pf->nf = n; 132 | if(n->nf) 133 | n->nf->pf = n; 134 | }else{ 135 | // m剩余空间不够分裂。将m从free列表移除 136 | if(m->pf) 137 | m->pf->nf = m->nf; 138 | if(m->nf) 139 | m->nf->pf = m->pf; 140 | } 141 | 142 | // next最低为标记为使用中 143 | m->next = (MBLK*)((u32)m->next | 1); 144 | 145 | spin_unlock_irq(key); 146 | 147 | //printk(" %08x\n", (u32)&(m->nf)); 148 | return (void*)&(m->nf); 149 | } 150 | 151 | 152 | static int is_free(MBLK *p) 153 | { 154 | u32 next = (u32)p->next; 155 | return (next && (next&1)==0)? 1: 0; 156 | } 157 | 158 | 159 | void xos_free(void *ptr) 160 | { 161 | int m_free = 0; 162 | MBLK *m = (MBLK*)((u8*)ptr-8); 163 | 164 | int key = spin_lock_irq(); 165 | 166 | m->next = (MBLK*)((u32)m->next & ~1); 167 | 168 | MBLK *n = m->next; 169 | if(n && is_free(n)){ 170 | // 与下一块合并(n并入m) 171 | m->next = n->next; 172 | if(n->next) 173 | n->next->prev = m; 174 | 175 | m->nf = n->nf; 176 | m->pf = n->pf; 177 | if(m->pf) 178 | m->pf->nf = m; 179 | if(m->nf) 180 | m->nf->pf = m; 181 | 182 | m_free = 1; 183 | } 184 | 185 | MBLK *p = m->prev; 186 | if(is_free(p)){ 187 | if(p==head){ 188 | // m是第一块 189 | m->nf = p->nf; 190 | m->pf = p; 191 | p->nf = m; 192 | if(m->nf) 193 | m->nf->pf = m; 194 | }else{ 195 | // 与上一块合并(m并入p) 196 | p->next = m->next; 197 | if(p->next) 198 | p->next->prev = p; 199 | if(m_free){ 200 | if(m->nf == p){ 201 | p->pf = m->pf; 202 | if(p->pf) 203 | p->pf->nf = p; 204 | }else{ 205 | p->nf = m->nf; 206 | if(p->nf) 207 | p->nf->pf = p; 208 | } 209 | } 210 | } 211 | }else if(m_free==0){ 212 | // 上一块使用中,直接替换head 213 | m->nf = head->nf; 214 | m->pf = head; 215 | m->nf->pf = m; 216 | head->nf = m; 217 | } 218 | 219 | spin_unlock_irq(key); 220 | 221 | } 222 | 223 | 224 | /******************************************************************************/ 225 | 226 | 227 | -------------------------------------------------------------------------------- /main/ld.S: -------------------------------------------------------------------------------- 1 | 2 | 3 | TEXT_START = DEFINED(TEXT_START) ? TEXT_START : 0x20000000; 4 | STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : 0x00001000; 5 | 6 | 7 | ENTRY(_start) 8 | 9 | MEMORY 10 | { 11 | FLASH (rx) : ORIGIN = 0x80000000, LENGTH = 1M 12 | SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K 13 | } 14 | 15 | SECTIONS 16 | { 17 | .text TEXT_START : 18 | { 19 | _text_start = .; 20 | *(.text.entry) 21 | *(.text) 22 | *(.text.*) 23 | _text_end = .; 24 | } >FLASH AT>FLASH 25 | 26 | .rodata : ALIGN(16) 27 | { 28 | _rodata_start = .; 29 | *(.rodata) 30 | *(.rodata.*) 31 | *(.rodata1) 32 | *(.sdata2) 33 | *(.sdata2.*) 34 | *(.sbss2) 35 | *(.sbss2.*) 36 | . = ALIGN(4); 37 | __usbh_class_info_start__ = .; 38 | KEEP(*(.usbh_class_info)) 39 | __usbh_class_info_end__ = .; 40 | } >FLASH AT>FLASH 41 | 42 | .data 0x20000000 : ALIGN(16) 43 | { 44 | _data_start = .; 45 | *(.data) 46 | *(.data.*) 47 | *(.data1) 48 | __global_pointer$ = . + 0x7f0; 49 | *(.sdata) 50 | *(.sdata.*) 51 | *(.got.plt) 52 | *(.got) 53 | *(.dynamic) 54 | *(.fixup); 55 | _data_end = .; 56 | } >SRAM AT>FLASH 57 | _data_start_lma = LOADADDR(.data); 58 | _data_end_lma = LOADADDR(.data) + SIZEOF(.data); 59 | 60 | .bss : ALIGN(16) 61 | { 62 | _bss_start = .; 63 | *(.sbss) 64 | *(.sbss.*) 65 | *(.scommon) 66 | *(.dynbss) 67 | *(.bss) 68 | *(.bss.*) 69 | . = ALIGN(16); 70 | _stack_start = .; 71 | . = . + STACK_SIZE; 72 | _stack_end = .; 73 | *(COMMON) ; 74 | _bss_end = . ; 75 | } >SRAM 76 | _end = .; 77 | 78 | . = ALIGN(256); 79 | _heap_start = .; 80 | _heap_size = ORIGIN(SRAM) + LENGTH(SRAM) - _heap_start; 81 | 82 | /* 83 | These debug sections are here for information only - they're not going to be 84 | included in the ROM-RAM copy because it only copies .text, .data, and .bss. 85 | */ 86 | .stab 0 : { *(.stab) } 87 | .stabstr 0 : { *(.stabstr) } 88 | 89 | /* DWARF debug sections */ 90 | .debug 0 : {*(.debug)} 91 | .debug_srcinfo 0 : {*(.debug_srcinfo)} 92 | .debug_aranges 0 : {*(.debug_aranges)} 93 | .debug_pubnames 0 : {*(.debug_pubnames)} 94 | .debug_sfnames 0 : {*(.debug_sfnames)} 95 | .line 0 : {*(.line)} 96 | .gnu : { *(.gnu*) } 97 | .note : { *(.note*) } 98 | 99 | .dynsym : { *(.dynsym) } 100 | .dynbss : { *(.dynbss) } 101 | .dynstr : { *(.dynstr*) } 102 | .dynamic : { *(.dynamic*) } 103 | .hash : { *(.hash*) } 104 | .plt : { *(.plt*) } 105 | .interp : { *(.interp*) } 106 | .gnu : { *(.gnu*) } 107 | } 108 | -------------------------------------------------------------------------------- /main/ld_ram.S: -------------------------------------------------------------------------------- 1 | 2 | 3 | TEXT_START = DEFINED(TEXT_START) ? TEXT_START : 0x20000000; 4 | STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : 0x00001000; 5 | 6 | 7 | ENTRY(_start) 8 | 9 | MEMORY 10 | { 11 | FLASH (rx) : ORIGIN = 0x80000000, LENGTH = 1M 12 | SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K 13 | } 14 | 15 | SECTIONS 16 | { 17 | .text TEXT_START : 18 | { 19 | _text_start = .; 20 | *(.text.entry) 21 | *(.text) 22 | *(.text.*) 23 | _text_end = .; 24 | } >SRAM 25 | 26 | . = ALIGN(16); 27 | .rodata : 28 | { 29 | *(.rodata) 30 | *(.rodata.*) 31 | *(.rodata1) 32 | *(.sdata2) 33 | *(.sdata2.*) 34 | *(.sbss2) 35 | *(.sbss2.*) 36 | } >SRAM 37 | 38 | . = ALIGN(16); 39 | .data : 40 | { 41 | _data_start = .; 42 | *(.data) 43 | *(.data.*) 44 | *(.data1) 45 | __global_pointer$ = . + 0x7f0; 46 | *(.sdata) 47 | *(.sdata.*) 48 | *(.got.plt) 49 | *(.got) 50 | *(.dynamic) 51 | *(.fixup); 52 | _data_end = .; 53 | } >SRAM 54 | 55 | . = ALIGN(16); 56 | .bss : 57 | { 58 | _bss_start = .; 59 | *(.sbss) 60 | *(.sbss.*) 61 | *(.scommon) 62 | *(.dynbss) 63 | *(.bss) 64 | *(.bss.*) 65 | . = ALIGN(16); 66 | _stack_start = .; 67 | . = . + STACK_SIZE; 68 | _stack_end = .; 69 | *(COMMON) ; 70 | _bss_end = . ; 71 | } >SRAM 72 | _end = .; 73 | 74 | /* 75 | These debug sections are here for information only - they're not going to be 76 | included in the ROM-RAM copy because it only copies .text, .data, and .bss. 77 | */ 78 | .stab 0 : { *(.stab) } 79 | .stabstr 0 : { *(.stabstr) } 80 | 81 | /* DWARF debug sections */ 82 | .debug 0 : {*(.debug)} 83 | .debug_srcinfo 0 : {*(.debug_srcinfo)} 84 | .debug_aranges 0 : {*(.debug_aranges)} 85 | .debug_pubnames 0 : {*(.debug_pubnames)} 86 | .debug_sfnames 0 : {*(.debug_sfnames)} 87 | .line 0 : {*(.line)} 88 | .gnu : { *(.gnu*) } 89 | .note : { *(.note*) } 90 | 91 | .dynsym : { *(.dynsym) } 92 | .dynbss : { *(.dynbss) } 93 | .dynstr : { *(.dynstr*) } 94 | .dynamic : { *(.dynamic*) } 95 | .hash : { *(.hash*) } 96 | .plt : { *(.plt*) } 97 | .interp : { *(.interp*) } 98 | .gnu : { *(.gnu*) } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /main/main.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "main.h" 4 | #include "xos.h" 5 | 6 | 7 | /******************************************************************************/ 8 | 9 | SEM tsem; 10 | 11 | void task8(void *arg) 12 | { 13 | printk("task8 running!\n"); 14 | 15 | while(1){ 16 | int retv = xos_sem_take(&tsem, 150); 17 | printk("task_8: get sem! retv=%d\n", retv); 18 | } 19 | } 20 | 21 | 22 | void task1(void *arg) 23 | { 24 | TCB *tcb = xos_task_self(); 25 | int id = (long)arg; 26 | tcb->mask = 1<<(id%4); 27 | printk("task_%d running! mask=%02x\n", id, tcb->mask); 28 | 29 | int cnt = 0; 30 | while(1){ 31 | printk("task_%d: cnt=%d\n", id, cnt); 32 | cnt += 1; 33 | xos_task_delay(200); 34 | } 35 | } 36 | 37 | 38 | void led_task(void *arg) 39 | { 40 | while(1){ 41 | gpio_set(2, 0, 0); 42 | xos_task_delay(50); 43 | gpio_set(2, 0, 1); 44 | xos_task_delay(50); 45 | } 46 | } 47 | 48 | 49 | void main_task(void *arg) 50 | { 51 | printk("main task running!\n"); 52 | 53 | xos_task_create("led", led_task, (void*)(long)8, DEFAULT_TASK_PRIO, 0); 54 | 55 | #if 0 56 | int i; 57 | 58 | for(i=0; i<8; i++){ 59 | char name[16]; 60 | sprintk(name, "task_%d", i); 61 | xos_task_create(name, task1, (void*)(long)i, DEFAULT_TASK_PRIO, 0); 62 | } 63 | 64 | xos_task_create("task_8", task8, (void*)(long)8, DEFAULT_TASK_PRIO, 0); 65 | 66 | 67 | xos_sem_init(&tsem, 0); 68 | 69 | int cnt = 0; 70 | while(1){ 71 | printk("\nmain: cnt=%d\n", cnt); 72 | cnt += 1; 73 | xos_task_delay(100); 74 | if((cnt%8)==0){ 75 | xos_sem_give(&tsem); 76 | } 77 | } 78 | #endif 79 | 80 | simple_shell(); 81 | } 82 | 83 | /******************************************************************************/ 84 | 85 | 86 | int main(void) 87 | { 88 | system_init(); 89 | device_init(); 90 | 91 | 92 | puts("\n\nAGRV2K start!\n"); 93 | printk(" mstatus: %08x\n", read_csr(mstatus)); 94 | printk(" mtvec: %08x\n", read_csr(mtvec)); 95 | printk(" mie: %08x\n", read_csr(mie)); 96 | printk(" mip: %08x\n", read_csr(mip)); 97 | 98 | xos_init(main_task); 99 | 100 | return 0; 101 | } 102 | 103 | 104 | /******************************************************************************/ 105 | 106 | -------------------------------------------------------------------------------- /main/printk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * printk.c 4 | * 5 | * printk for bootbox 6 | * 7 | * support format: 8 | * %c 9 | * %s 10 | * %[[0]n]x 11 | * %[[0]n]X 12 | * %[[0]n]d 13 | * 14 | */ 15 | 16 | #include 17 | 18 | #include "main.h" 19 | 20 | static int itostr(char *buf, int in_data, int base, int upper, int sign) 21 | { 22 | int res, len, i; 23 | unsigned int data; 24 | char *str; 25 | 26 | if(base==10 && sign && in_data<0){ 27 | data = -in_data; 28 | }else{ 29 | data = in_data; 30 | } 31 | 32 | str = buf; 33 | do{ 34 | res = data%base; 35 | data = data/base; 36 | if(res<10){ 37 | res += '0'; 38 | }else{ 39 | if(upper){ 40 | res += 'A'-10; 41 | }else{ 42 | res += 'a'-10; 43 | } 44 | } 45 | *str++ = res; 46 | }while(data); 47 | len = str-buf; 48 | 49 | /* reverse digital order */ 50 | for(i=0; i'0' && *fmt<='9'){ 131 | field_width = field_width*10+(*fmt-'0'); 132 | fmt++; 133 | } 134 | if(*fmt && *fmt=='.'){ 135 | fmt++; 136 | /* skip n */ 137 | while(*fmt && *fmt>'0' && *fmt<='9'){ 138 | fmt++; 139 | } 140 | } 141 | 142 | /* get format char */ 143 | upper = 0; 144 | base = 0; 145 | sign = 0; 146 | len = 0; 147 | s = digital_buf; 148 | while((ch=*fmt)!=0){ 149 | fmt++; 150 | switch(ch){ 151 | /* hexadecimal */ 152 | case 'p': 153 | case 'X': 154 | upper = 1; 155 | case 'x': 156 | base = 16; 157 | break; 158 | 159 | /* decimal */ 160 | case 'd': 161 | case 'i': 162 | sign = 1; 163 | case 'u': 164 | base = 10; 165 | break; 166 | 167 | /* octal */ 168 | case 'o': 169 | base = 8; 170 | break; 171 | 172 | /* character */ 173 | case 'c': 174 | digital_buf[0] = (unsigned char) va_arg(args, int); 175 | len = 1; 176 | break; 177 | 178 | /* string */ 179 | case 's': 180 | s = va_arg(args, char *); 181 | if(!s) s = ""; 182 | len = strlen(s); 183 | break; 184 | 185 | /* float format, skip it */ 186 | case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': case 'a': case 'A': 187 | (void)(va_arg(args, double)); 188 | s = NULL; 189 | break; 190 | 191 | /* length modifier */ 192 | case 'l': case 'L': case 'h': case 'j': case 'z': case 't': 193 | /* skip it */ 194 | continue; 195 | 196 | /* bad format */ 197 | default: 198 | s = sstr; 199 | len = fmt-sstr; 200 | break; 201 | } 202 | break; 203 | } 204 | 205 | if(base){ 206 | i = va_arg(args, int); 207 | if(base==10 && sign){ 208 | if(i<0){ 209 | add_sign = '-'; 210 | } 211 | }else{ 212 | add_sign = 0; 213 | } 214 | 215 | len = itostr(digital_buf, i, base, upper, sign); 216 | }else{ 217 | zero_pad = ' '; 218 | add_sign = 0; 219 | } 220 | 221 | if(s){ 222 | if(len>=field_width){ 223 | field_width = len; 224 | if(add_sign) 225 | field_width++; 226 | } 227 | for(i=0; i 17 | 18 | #include "main.h" 19 | 20 | static int itostr(char *buf, int in_data, int base, int upper, int sign) 21 | { 22 | int res, len, i; 23 | unsigned int data; 24 | char *str; 25 | 26 | if(base==10 && sign && in_data<0){ 27 | data = -in_data; 28 | }else{ 29 | data = in_data; 30 | } 31 | 32 | str = buf; 33 | do{ 34 | res = data%base; 35 | data = data/base; 36 | if(res<10){ 37 | res += '0'; 38 | }else{ 39 | if(upper){ 40 | res += 'A'-10; 41 | }else{ 42 | res += 'a'-10; 43 | } 44 | } 45 | *str++ = res; 46 | }while(data); 47 | len = str-buf; 48 | 49 | /* reverse digital order */ 50 | for(i=0; i'0' && *fmt<='9'){ 131 | field_width = field_width*10+(*fmt-'0'); 132 | fmt++; 133 | } 134 | if(*fmt && *fmt=='.'){ 135 | fmt++; 136 | /* skip n */ 137 | while(*fmt && *fmt>'0' && *fmt<='9'){ 138 | fmt++; 139 | } 140 | } 141 | 142 | /* get format char */ 143 | upper = 0; 144 | base = 0; 145 | sign = 0; 146 | len = 0; 147 | s = digital_buf; 148 | while((ch=*fmt)!=0){ 149 | fmt++; 150 | switch(ch){ 151 | /* hexadecimal */ 152 | case 'p': 153 | case 'X': 154 | upper = 1; 155 | case 'x': 156 | base = 16; 157 | break; 158 | 159 | /* decimal */ 160 | case 'd': 161 | case 'i': 162 | sign = 1; 163 | case 'u': 164 | base = 10; 165 | break; 166 | 167 | /* octal */ 168 | case 'o': 169 | base = 8; 170 | break; 171 | 172 | /* character */ 173 | case 'c': 174 | digital_buf[0] = (unsigned char) va_arg(args, int); 175 | len = 1; 176 | break; 177 | 178 | /* string */ 179 | case 's': 180 | s = va_arg(args, char *); 181 | if(!s) s = ""; 182 | len = strlen(s); 183 | break; 184 | 185 | /* float format, skip it */ 186 | case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': case 'a': case 'A': 187 | (void)(va_arg(args, double)); 188 | s = NULL; 189 | break; 190 | 191 | /* length modifier */ 192 | case 'l': case 'L': case 'h': case 'j': case 'z': case 't': 193 | /* skip it */ 194 | continue; 195 | 196 | /* bad format */ 197 | default: 198 | s = sstr; 199 | len = fmt-sstr; 200 | break; 201 | } 202 | break; 203 | } 204 | 205 | if(base){ 206 | i = va_arg(args, int); 207 | if(base==10 && sign){ 208 | if(i<0){ 209 | add_sign = '-'; 210 | } 211 | }else{ 212 | add_sign = 0; 213 | } 214 | 215 | len = itostr(digital_buf, i, base, upper, sign); 216 | }else{ 217 | zero_pad = ' '; 218 | add_sign = 0; 219 | } 220 | 221 | if(s){ 222 | if(len>=field_width){ 223 | field_width = len; 224 | if(add_sign) 225 | field_width++; 226 | } 227 | for(i=0; i "); 15 | n = 0; 16 | esc = 0; 17 | while(1){ 18 | while((ch=getc(1000))<0); 19 | if(ch==0x0d || ch==0x0a){ 20 | break; 21 | } 22 | 23 | if(esc==0 && ch==0x1b){ 24 | esc = 1; 25 | continue; 26 | } 27 | if(esc==1){ 28 | if(ch==0x5b){ 29 | esc = 2; 30 | }else{ 31 | printk("", ch); 32 | esc = 0; 33 | } 34 | continue; 35 | } 36 | if(esc==2){ 37 | esc = 0; 38 | if(ch==0x41 || ch==0x43){ 39 | // UP:0x41 RIGHT:0x43 40 | if(hblen){ 41 | int sn = n; 42 | n = hblen; 43 | memcpy(buf, hbuf, hblen); 44 | printk("\r" PROMPT "> %s", hbuf); 45 | while(hblen", ch); 55 | } 56 | }else if(ch==0x08){ 57 | if(n){ 58 | n -= 1; 59 | printk("\b \b"); 60 | } 61 | }else if(ch>=0x20){ 62 | printk("%c", ch); 63 | buf[n] = ch; 64 | n++; 65 | if(n==len) 66 | break; 67 | }else{ 68 | printk("{%02x}", ch); 69 | } 70 | } 71 | 72 | if(n){ 73 | memcpy(hbuf, buf, n); 74 | hbuf[n] = 0; 75 | hblen = n; 76 | } 77 | 78 | printk("\r\n"); 79 | buf[n] = 0; 80 | return n; 81 | } 82 | 83 | 84 | static int arg_base = 16; 85 | 86 | int str2hex(char *str, int *hex) 87 | { 88 | int n, p, ch, base; 89 | 90 | base = arg_base; 91 | n = 0; 92 | p = 0; 93 | hex[0] = 0; 94 | while(1){ 95 | ch = *str++; 96 | if(ch==' '){ 97 | if(p){ 98 | n++; 99 | hex[n] = 0; 100 | p = 0; 101 | } 102 | continue; 103 | }else if((ch=='0' && *str=='x')){ 104 | str += 1; 105 | base = 16; 106 | }else if((ch>='0' && ch<='9')){ 107 | ch -= '0'; 108 | }else if((base==16 && ch>='a' && ch<='f')){ 109 | ch = ch-'a'+10; 110 | }else if((base==16 && ch>='A' && ch<='F')){ 111 | ch = ch-'A'+10; 112 | }else{ 113 | if(p) 114 | n++; 115 | return n; 116 | } 117 | hex[n] = hex[n]*base + ch; 118 | p++; 119 | } 120 | } 121 | 122 | 123 | /**********************************************************/ 124 | 125 | static int dump_width = 4; 126 | static int dump_addr = 0; 127 | 128 | void dump(int argc, int *args, int width) 129 | { 130 | int i, c, p, addr, len; 131 | u32 d; 132 | u8 sbuf[16]; 133 | 134 | addr = (argc>=1)? args[0] : dump_addr; 135 | len = (argc>=2)? args[1] : 256; 136 | if(width==0) 137 | width = dump_width; 138 | 139 | c = 0; 140 | p = 0; 141 | while(1){ 142 | if((p%16)==0 || p>=len){ 143 | if(c){ 144 | printk(" "); 145 | for(i=0; i0x20 && sbuf[i]<0x80){ 147 | printk("%c", sbuf[i]); 148 | }else{ 149 | printk("."); 150 | } 151 | } 152 | c = 0; 153 | } 154 | if(p>=len){ 155 | printk("\n"); 156 | }else{ 157 | printk("\n%08x: ", addr); 158 | } 159 | }else if((p%8)==0){ 160 | printk("- "); 161 | } 162 | if(p>=len) 163 | break; 164 | 165 | if(width==1){ 166 | d = *(u8*)(addr); 167 | sbuf[c++] = d; 168 | printk("%02x ", d); 169 | }else if(width==2){ 170 | d = *(u16*)(addr); 171 | sbuf[c++] = d; // Little endian 172 | sbuf[c++] = d>>8; 173 | printk("%04x ", d); 174 | }else{ 175 | d = *(u32*)(addr); 176 | sbuf[c++] = d; // Little endian 177 | sbuf[c++] = d>>8; 178 | sbuf[c++] = d>>16; 179 | sbuf[c++] = d>>24; 180 | printk("%08x ", d); 181 | } 182 | p += width; 183 | addr += width; 184 | } 185 | 186 | dump_width = width; 187 | dump_addr = addr; 188 | } 189 | 190 | 191 | 192 | /******************************************************************************/ 193 | 194 | void memcmp32(void *dst_ptr, void *src_ptr, int len) 195 | { 196 | u32 *dst = (u32*)dst_ptr; 197 | u32 *src = (u32*)src_ptr; 198 | int i; 199 | 200 | for(i=0; i=len){ 213 | printk("memcmp OK!\n"); 214 | } 215 | } 216 | 217 | 218 | #define CMD_START if(0){} 219 | #define CMD(x) else if(strcmp(cmd, #x)==0) 220 | 221 | void simple_shell(void) 222 | { 223 | char cmd[128]; 224 | int argc, arg[4]; 225 | 226 | dump_addr = 0x08000000; 227 | 228 | while(1){ 229 | gets(cmd, 128); 230 | char *sp = strchr(cmd, ' '); 231 | if(sp){ 232 | *sp = 0; 233 | sp += 1; 234 | argc = str2hex(sp, arg); 235 | }else{ 236 | argc = 0; 237 | } 238 | 239 | CMD_START 240 | CMD(base16) { arg_base = 16; } 241 | CMD(base10) { arg_base = 10; } 242 | CMD(rb){ printk("%08x: %02x\n", arg[0], *(u8*)arg[0]); } 243 | CMD(rw){ printk("%08x: %04x\n", arg[0], *(u16*)arg[0]); } 244 | CMD(rd){ printk("%08x: %08x\n", arg[0], *(u32*)arg[0]); } 245 | CMD(wb){ printk("%08x= %02x\n", arg[0], (u8)arg[1]); *(u8*)arg[0] = arg[1]; } 246 | CMD(ww){ printk("%08x= %04x\n", arg[0], (u16)arg[1]); *(u16*)arg[0] = arg[1]; } 247 | CMD(wd){ printk("%08x= %08x\n", arg[0], (u32)arg[1]); *(u32*)arg[0] = arg[1]; } 248 | CMD(db){ dump(argc, arg, 1); } 249 | CMD(dw){ dump(argc, arg, 2); } 250 | CMD(dd){ dump(argc, arg, 4); } 251 | CMD(d) { dump(argc, arg, 0); } 252 | CMD(go){ void (*go)(void) = (void(*)(void))arg[0]; go(); } 253 | 254 | CMD(memset){ 255 | if(argc>=3){ 256 | memset((void*)arg[0], arg[1], arg[2]); 257 | }else{ 258 | printk("Wrong args!\n"); 259 | } 260 | } 261 | CMD(memcpy){ 262 | if(argc>=3){ 263 | memcpy((void*)arg[0], (void*)arg[1], arg[2]); 264 | }else{ 265 | printk("Wrong args!\n"); 266 | } 267 | } 268 | CMD(memcmp){ 269 | if(argc>=3){ 270 | memcmp32((void*)arg[0], (void*)arg[1], arg[2]); 271 | }else{ 272 | printk("Wrong args!\n"); 273 | } 274 | } 275 | 276 | CMD(cpmem){ 277 | memcpy((u8*)0x68000000, (u8*)0x80000000, 0x100000); 278 | } 279 | CMD(t){ 280 | memcmp32((u8*)0x68000000, (u8*)0x80000000, 0x100000); 281 | } 282 | 283 | CMD(df){ 284 | u32 t0 = REG(0x70000000); 285 | u32 t1 = REG(0x70000004); 286 | u32 t2 = REG(0x70000008); 287 | u32 t3 = REG(0x7000000c); 288 | int i; 289 | printk("\n%08x %08x %08x %08x\n", t0, t1, t2, t3); 290 | printk("--------------------------------\n"); 291 | for(i=0; i<32; i++){ if(t0&(1<<(31-i))) putc('1'); else putc('0'); } printk("\n"); 292 | for(i=0; i<32; i++){ if(t1&(1<<(31-i))) putc('1'); else putc('0'); } printk("\n"); 293 | for(i=0; i<32; i++){ if(t2&(1<<(31-i))) putc('1'); else putc('0'); } printk("\n"); 294 | for(i=0; i<32; i++){ if(t3&(1<<(31-i))) putc('1'); else putc('0'); } printk("\n"); 295 | printk("--------------------------------\n"); 296 | for(i=0; i<32; i++){ 297 | int b0 = (t0&(1<<(31-i)))? 1: 0; 298 | int b1 = (t1&(1<<(31-i)))? 2: 0; 299 | int b2 = (t2&(1<<(31-i)))? 4: 0; 300 | int b3 = (t3&(1<<(31-i)))? 8: 0; 301 | int nb = b3 | b2 | b1 | b0; 302 | printk("%x", nb); 303 | } 304 | printk("\n\n"); 305 | } 306 | 307 | CMD(sdinit){ 308 | void sd_init(void); 309 | sd_init(); 310 | } 311 | CMD(sdt){ 312 | void sd_test(void); 313 | sd_test(); 314 | } 315 | CMD(sdrt){ 316 | sd_read_blocks(arg[0], arg[1], (void*)arg[2]); 317 | } 318 | 319 | 320 | CMD(usb){ 321 | int cherryusb_start(void); 322 | int retv = cherryusb_start(); 323 | printk("usb_start:%d\n", retv); 324 | } 325 | CMD(xxx){ 326 | void dump_task(void); 327 | dump_task(); 328 | } 329 | 330 | CMD(mt){ 331 | int cnt=0; 332 | while(cnt<51){ 333 | printk("cnt: %d\n", cnt); 334 | gpio_set(2, 0, cnt&1); 335 | cnt += 1; 336 | udelay(1000000); 337 | } 338 | } 339 | 340 | CMD(q){ 341 | break; 342 | } 343 | } 344 | } 345 | 346 | -------------------------------------------------------------------------------- /main/start.S: -------------------------------------------------------------------------------- 1 | 2 | #include "riscv.h" 3 | 4 | .macro labs reg, symbol 5 | lui \reg, %hi(\symbol) 6 | addi \reg, \reg, %lo(\symbol) 7 | .endm 8 | 9 | .section ".text.entry" 10 | .globl _start 11 | _start: 12 | .option push 13 | .option norelax 14 | # reloc self 15 | #ifdef RUN_SRAM 16 | la a0, _text_start 17 | labs a2, _text_start 18 | la a1, _data_end 19 | #else 20 | la a0, _data_start_lma 21 | labs a2, _data_start 22 | #endif 23 | la a1, _data_end_lma 24 | 1: 25 | lw a3, (a0) 26 | sw a3, (a2) 27 | addi a0, a0, 4 28 | addi a2, a2, 4 29 | bltu a0, a1, 1b 30 | 31 | # clear bss 32 | labs a0, _bss_start 33 | labs a1, _bss_end 34 | 2: 35 | sw zero, (a0) 36 | addi a0, a0, 4 37 | bltu a0, a1, 2b 38 | 39 | # enable FPU and accelerator if present 40 | li t0, MSTATUS_FS | MSTATUS_XS 41 | csrs mstatus, t0 42 | 43 | # initialize global pointer 44 | labs gp, __global_pointer$ 45 | labs sp, _stack_end 46 | 47 | labs ra, main 48 | jr ra 49 | 50 | .option pop 51 | 52 | 53 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 54 | 55 | 56 | .global arch_set_context 57 | .global _trap_entry 58 | .extern task_current 59 | .align 4 60 | _trap_entry: 61 | csrrw a0, mscratch, a0 62 | lw a0, task_current 63 | 64 | sw x1, 0*4(a0) 65 | sw x2, 1*4(a0) 66 | sw x3, 2*4(a0) 67 | sw x4, 3*4(a0) 68 | sw x5, 4*4(a0) 69 | sw x6, 5*4(a0) 70 | sw x7, 6*4(a0) 71 | sw x8, 7*4(a0) 72 | sw x9, 8*4(a0) 73 | // sw x10, 9*4(a0) 74 | sw x11, 10*4(a0) 75 | sw x12, 11*4(a0) 76 | sw x13, 12*4(a0) 77 | sw x14, 13*4(a0) 78 | sw x15, 14*4(a0) 79 | sw x16, 15*4(a0) 80 | sw x17, 16*4(a0) 81 | sw x18, 17*4(a0) 82 | sw x19, 18*4(a0) 83 | sw x20, 19*4(a0) 84 | sw x21, 20*4(a0) 85 | sw x22, 21*4(a0) 86 | sw x23, 22*4(a0) 87 | sw x24, 23*4(a0) 88 | sw x25, 24*4(a0) 89 | sw x26, 25*4(a0) 90 | sw x27, 26*4(a0) 91 | sw x28, 27*4(a0) 92 | sw x29, 28*4(a0) 93 | sw x30, 29*4(a0) 94 | sw x31, 30*4(a0) 95 | 96 | csrrw a1, mscratch, a0 97 | sw a1, 9*4(a0) // a0 98 | csrr a1, mepc 99 | sw a1, 31*4(a0) // pc 100 | csrr a1, mcause 101 | call trap_handle 102 | 103 | lw a0, task_current 104 | 105 | arch_set_context: 106 | lw a1, 31*4(a0) // pc 107 | csrw mepc, a1 108 | lw x1, 0*4(a0) 109 | lw x2, 1*4(a0) 110 | lw x3, 2*4(a0) 111 | lw x4, 3*4(a0) 112 | lw x5, 4*4(a0) 113 | lw x6, 5*4(a0) 114 | lw x7, 6*4(a0) 115 | lw x8, 7*4(a0) 116 | lw x9, 8*4(a0) 117 | // lw x10, 9*4(a0) 118 | lw x11, 10*4(a0) 119 | lw x12, 11*4(a0) 120 | lw x13, 12*4(a0) 121 | lw x14, 13*4(a0) 122 | lw x15, 14*4(a0) 123 | lw x16, 15*4(a0) 124 | lw x17, 16*4(a0) 125 | lw x18, 17*4(a0) 126 | lw x19, 18*4(a0) 127 | lw x20, 19*4(a0) 128 | lw x21, 20*4(a0) 129 | lw x22, 21*4(a0) 130 | lw x23, 22*4(a0) 131 | lw x24, 23*4(a0) 132 | lw x25, 24*4(a0) 133 | lw x26, 25*4(a0) 134 | lw x27, 26*4(a0) 135 | lw x28, 27*4(a0) 136 | lw x29, 28*4(a0) 137 | lw x30, 29*4(a0) 138 | lw x31, 30*4(a0) 139 | lw x10, 9*4(a0) // a0 140 | mret 141 | 142 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 143 | 144 | .global arch_swap_context 145 | .align 4 146 | arch_swap_context: 147 | mv a1, a0 148 | lw a0, task_current 149 | 150 | sw x1, 0*4(a0) 151 | sw x2, 1*4(a0) 152 | sw x3, 2*4(a0) 153 | sw x4, 3*4(a0) 154 | sw x5, 4*4(a0) 155 | sw x6, 5*4(a0) 156 | sw x7, 6*4(a0) 157 | sw x8, 7*4(a0) 158 | sw x9, 8*4(a0) 159 | sw x10, 9*4(a0) 160 | sw x11, 10*4(a0) 161 | sw x12, 11*4(a0) 162 | sw x13, 12*4(a0) 163 | sw x14, 13*4(a0) 164 | sw x15, 14*4(a0) 165 | sw x16, 15*4(a0) 166 | sw x17, 16*4(a0) 167 | sw x18, 17*4(a0) 168 | sw x19, 18*4(a0) 169 | sw x20, 19*4(a0) 170 | sw x21, 20*4(a0) 171 | sw x22, 21*4(a0) 172 | sw x23, 22*4(a0) 173 | sw x24, 23*4(a0) 174 | sw x25, 24*4(a0) 175 | sw x26, 25*4(a0) 176 | sw x27, 26*4(a0) 177 | sw x28, 27*4(a0) 178 | sw x29, 28*4(a0) 179 | sw x30, 29*4(a0) 180 | sw x31, 30*4(a0) 181 | sw ra, 31*4(a0) // pc 182 | 183 | sw a1, task_current, a0 184 | mv a0, a1 185 | j arch_set_context 186 | 187 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 188 | 189 | -------------------------------------------------------------------------------- /main/string.c: -------------------------------------------------------------------------------- 1 | /* 2 | * string.c 3 | */ 4 | 5 | #include "main.h" 6 | 7 | void *memset(void *s, int v, unsigned int n) 8 | { 9 | register char *p = (char *)s; 10 | 11 | while(n){ 12 | *p++ = (char)v; 13 | n -= 1; 14 | } 15 | 16 | return s; 17 | } 18 | 19 | void *memcpy(void *to, const void *from, unsigned int n) 20 | { 21 | register char *t = (char *)to; 22 | 23 | while(n){ 24 | *t++ = *(char*)from++; 25 | n -= 1; 26 | } 27 | 28 | return to; 29 | } 30 | 31 | int memcmp(const void *dst, const void *src, unsigned int n) 32 | { 33 | register int i; 34 | register unsigned char *s = (unsigned char*)src; 35 | register unsigned char *d = (unsigned char*)dst; 36 | 37 | for(i=0; i='A' && t1<='Z') t1 = t1-'A'+'a'; 107 | if(t2>='A' && t2<='Z') t2 = t2-'A'+'a'; 108 | r = t1 - t2; 109 | if(r || t1==0) 110 | break; 111 | } 112 | 113 | return r; 114 | } 115 | 116 | int strncmp(const char *s1, const char *s2, unsigned int n) 117 | { 118 | register int r = 0; 119 | register int t; 120 | 121 | while(n){ 122 | t = (int)*s1++; 123 | r = t - (int)*s2++; 124 | if(r) 125 | break; 126 | if(t==0) 127 | break; 128 | n -= 1; 129 | } 130 | 131 | return r; 132 | } 133 | 134 | 135 | char *strchr(const char *s1, int ch) 136 | { 137 | while(1){ 138 | char t = *s1; 139 | if(t==0) 140 | return (char*)0; 141 | if(t==ch) 142 | return (char*)s1; 143 | s1++; 144 | } 145 | } 146 | 147 | 148 | unsigned int strlen(const char *s) 149 | { 150 | register const char *p = s; 151 | 152 | while(*p++); 153 | 154 | return p-s-1; 155 | } 156 | 157 | 158 | unsigned int strtoul(char *str, char **endptr, int requestedbase, int *ret) 159 | { 160 | unsigned int num = 0; 161 | int c, digit, retv; 162 | int base, nchars, leadingZero; 163 | 164 | base = 10; 165 | nchars = 0; 166 | leadingZero = 0; 167 | 168 | if(str==0 || *str==0){ 169 | retv = 2; 170 | goto exit; 171 | } 172 | retv = 0; 173 | 174 | if(requestedbase) 175 | base = requestedbase; 176 | 177 | while ((c = *str) != 0) { 178 | if (nchars == 0 && c == '0') { 179 | leadingZero = 1; 180 | goto step; 181 | } else if (leadingZero && nchars == 1) { 182 | if (c == 'x') { 183 | base = 16; 184 | goto step; 185 | } else if (c == 'o') { 186 | base = 8; 187 | goto step; 188 | } 189 | } 190 | if (c >= '0' && c <= '9') { 191 | digit = c - '0'; 192 | } else if (c >= 'a' && c <= 'z') { 193 | digit = c - 'a' + 10; 194 | } else if (c >= 'A' && c <= 'Z') { 195 | digit = c - 'A' + 10; 196 | } else { 197 | retv = 3; 198 | break; 199 | } 200 | if (digit >= base) { 201 | retv = 4; 202 | break; 203 | } 204 | num *= base; 205 | num += digit; 206 | step: 207 | str++; 208 | nchars++; 209 | } 210 | 211 | exit: 212 | if(ret) 213 | *ret = retv; 214 | if(endptr) 215 | *endptr = str; 216 | 217 | return num; 218 | } 219 | 220 | -------------------------------------------------------------------------------- /main/xos_core.c: -------------------------------------------------------------------------------- 1 | 2 | #include "main.h" 3 | #include "xos.h" 4 | #include "riscv.h" 5 | 6 | LIST g_list_ready; 7 | LIST g_list_sleep; 8 | LIST g_list_dead; 9 | 10 | TCB *task_current; 11 | 12 | uint32_t g_ticks; 13 | int nr_cpus; 14 | 15 | /******************************************************************************/ 16 | 17 | #if defined(ARCH_RISCV) 18 | 19 | extern int in_isr; 20 | 21 | inline int arch_in_isr(void) 22 | { 23 | return in_isr; 24 | } 25 | 26 | 27 | inline int arch_irq_lock(void) 28 | { 29 | int mstat = clear_csr(mstatus, MSTATUS_MIE); 30 | return mstat&MSTATUS_MIE; 31 | } 32 | 33 | 34 | inline void arch_irq_unlock(int key) 35 | { 36 | set_csr(mstatus, key&MSTATUS_MIE); 37 | } 38 | 39 | 40 | inline void arch_irq_enable(void) 41 | { 42 | set_csr(mstatus, MSTATUS_MIE); 43 | } 44 | 45 | 46 | inline void arch_idle(void) 47 | { 48 | WFI(); 49 | } 50 | 51 | extern int __global_pointer$; 52 | 53 | int arch_task_init(TCB *tcb) 54 | { 55 | TCB_ARCH *arch = &tcb->arch; 56 | 57 | arch->regs.x10 = (u32)tcb; 58 | arch->regs.x2 = (u32)(tcb->stack + tcb->stack_size); 59 | arch->regs.x3 = (u32)&__global_pointer$; 60 | arch->regs.pc = (u32)_task_entry; 61 | 62 | return 0; 63 | } 64 | 65 | 66 | static u64 mtime_inc; 67 | static u64 mtime_cmp; 68 | 69 | static void mtime_irq(u32 *regs, void *arg) 70 | { 71 | mtime_cmp += mtime_inc; 72 | CLINT->MTIMECMP_LO = mtime_cmp; 73 | CLINT->MTIMECMP_HI = mtime_cmp>>32; 74 | 75 | _tick_handle(); 76 | } 77 | 78 | 79 | void arch_timer_init(void) 80 | { 81 | mtime_inc = 10*1000; 82 | mtime_cmp = mtime_inc; 83 | 84 | SYS->MTIME_PSC = 0x40000000; 85 | CLINT->MTIME_LO = 0; 86 | CLINT->MTIME_HI = 0; 87 | CLINT->MTIMECMP_LO = mtime_cmp; 88 | CLINT->MTIMECMP_HI = mtime_cmp>>32; 89 | 90 | int_request(MTIMER_IRQn, mtime_irq, NULL); 91 | int_enable(MTIMER_IRQn); 92 | 93 | SYS->MTIME_PSC = 0x80000000 | (SYSCLK_FREQ/1000000 - 1); // 1us 94 | } 95 | 96 | #endif 97 | 98 | 99 | /******************************************************************************/ 100 | 101 | 102 | inline void list_init(LIST *list) 103 | { 104 | list->head = NULL; 105 | list->lock = 0; 106 | } 107 | 108 | 109 | inline void list_add(LIST *list, LIST_NODE *node) 110 | { 111 | LIST_NODE *next = list->head; 112 | node->next = next; 113 | node->prev = NULL; 114 | list->head = node; 115 | if(next){ 116 | next->prev = node; 117 | } 118 | } 119 | 120 | 121 | inline void list_remove(LIST *list, LIST_NODE *node) 122 | { 123 | LIST_NODE *next = node->next; 124 | LIST_NODE *prev = node->prev; 125 | 126 | if(next){ 127 | next->prev = prev; 128 | node->next = NULL; 129 | } 130 | 131 | if(prev){ 132 | prev->next = next; 133 | node->prev = NULL; 134 | }else{ 135 | list->head = next; 136 | } 137 | } 138 | 139 | 140 | // 按顺序插入。如果cmp返回1,则把node插入当前节点之前。 141 | void list_insert_order(LIST *list, LIST_NODE *node, int (*cmp_func)(void *, void*)) 142 | { 143 | LIST_NODE *p = list->head; 144 | LIST_NODE *prev = NULL; 145 | while(1){ 146 | if((p==NULL) || cmp_func(node, p)){ 147 | node->next = p; 148 | node->prev = prev; 149 | if(p) 150 | p->prev = node; 151 | if(prev) 152 | prev->next = node; 153 | else 154 | list->head = node; 155 | break; 156 | } 157 | prev = p; 158 | p = p->next; 159 | } 160 | } 161 | 162 | 163 | int spin_lock_irq(void) 164 | { 165 | return arch_irq_lock(); 166 | } 167 | 168 | 169 | void spin_unlock_irq(int key) 170 | { 171 | arch_irq_unlock(key); 172 | } 173 | 174 | 175 | /******************************************************************************/ 176 | 177 | TCB *xos_task_self(void) 178 | { 179 | return task_current; 180 | } 181 | 182 | 183 | static int cmp_prio(void *a, void *b) 184 | { 185 | TCB *ta = list_entry(a, TCB, node); 186 | TCB *tb = list_entry(b, TCB, node); 187 | 188 | return (ta->prio < tb->prio)? 1: 0; 189 | } 190 | 191 | 192 | void _task_ready(TCB *tcb) 193 | { 194 | int key = spin_lock_irq(); 195 | list_insert_order(&g_list_ready, &tcb->node, cmp_prio); 196 | tcb->state = T_READY; 197 | spin_unlock_irq(key); 198 | } 199 | 200 | 201 | void _task_free(TCB *tcb) 202 | { 203 | xos_free(tcb); 204 | } 205 | 206 | 207 | /******************************************************************************/ 208 | 209 | 210 | void dump_task(void) 211 | { 212 | LIST *list; 213 | LIST_NODE *p; 214 | 215 | printk("\n________________\n"); 216 | 217 | printk(" ready(%d):", g_list_ready.lock); 218 | list = &g_list_ready; 219 | p = list->head; 220 | while(p){ 221 | TCB *t = list_entry(p, TCB, node); 222 | printk(" ->(%s.%x)", t->name, t->state); 223 | p = p->next; 224 | } 225 | printk("\n"); 226 | 227 | printk(" sleep(%d):", g_list_sleep.lock); 228 | list = &g_list_sleep; 229 | p = list->head; 230 | while(p){ 231 | TCB *t = list_entry(p, TCB, node); 232 | printk(" ->(%s.%x)", t->name, t->state); 233 | p = p->next; 234 | } 235 | printk("\n"); 236 | 237 | TCB *t = task_current; 238 | printk(" current: (%s.%x)\n", t->name, t->state); 239 | printk("\n"); 240 | 241 | printk("________________\n"); 242 | } 243 | 244 | 245 | // 246 | // : 用户空间,新task创建后 247 | // : 执行了semGive 248 | // : 在中断中,有睡眠的task变为ready了。 249 | // 250 | void _task_switch(int in_isr, int self) 251 | { 252 | LIST *list = &g_list_ready; 253 | int key = spin_lock_irq(); 254 | 255 | // 最高优先级任务 256 | TCB *high = list_entry(list->head, TCB, node); 257 | //printk("task_switch(%d): cur=%s high=%s\n", in_isr, task_current->name, high->name); 258 | if(high && self==0 && task_current->prio < high->prio) 259 | goto _exit; 260 | 261 | if(task_current->state==T_RUN){ 262 | task_current->state = T_READY; 263 | } 264 | if(task_current->state==T_READY){ 265 | list_insert_order(list, &task_current->node, cmp_prio); 266 | } 267 | 268 | // 将high从ready中移出 269 | list_remove(list, &high->node); 270 | high->state = T_RUN; 271 | 272 | if(in_isr==0){ 273 | arch_swap_context(high); 274 | }else{ 275 | task_current = high; 276 | } 277 | 278 | _exit: 279 | spin_unlock_irq(key); 280 | } 281 | 282 | 283 | void __die(void) 284 | { 285 | g_list_ready.lock = 1; 286 | 287 | dump_task(); 288 | simple_shell(); 289 | while(1){ 290 | arch_idle(); 291 | } 292 | } 293 | 294 | 295 | void _tick_handle(void) 296 | { 297 | g_ticks += 1; 298 | 299 | LIST *list = &g_list_sleep; 300 | int key = spin_lock_irq(); 301 | 302 | int need_sched = 0; 303 | while(1){ 304 | LIST_NODE *p = list->head; 305 | if(p==NULL) 306 | break; 307 | 308 | TCB *t = list_entry(p, TCB, node); 309 | if(g_ticks < t->timeout) 310 | break; 311 | 312 | //printk("\n_tick_handle: g_ticks=%d tmout=%d tcb=%p(%s)\n", g_ticks, t->timeout, t, t->name); 313 | list_remove(list, p); 314 | t->timeout = 0; 315 | 316 | _task_ready(t); 317 | need_sched = 1; 318 | } 319 | 320 | spin_unlock_irq(key); 321 | 322 | if(need_sched){ 323 | _task_switch(1, 0); 324 | } 325 | } 326 | 327 | 328 | /******************************************************************************/ 329 | 330 | int g_tid = 0; 331 | 332 | task_t xos_task_create(char *task_name, ENTRY_FN entry, void *arg, int priority, int stack_size) 333 | { 334 | TCB *tcb; 335 | 336 | if(stack_size==0) 337 | stack_size = DEFAULT_STACK_SIZE; 338 | 339 | tcb = (TCB*)xos_malloc(sizeof(TCB)+stack_size); 340 | memset(tcb, 0, sizeof(TCB)+stack_size); 341 | 342 | strcpy(tcb->name, task_name); 343 | tcb->stack = (u8*)(tcb+1); 344 | tcb->stack_size = stack_size; 345 | tcb->entry = entry; 346 | tcb->arg = arg; 347 | tcb->tid = g_tid; 348 | atomic_add(&g_tid, 1); 349 | tcb->prio = priority; 350 | tcb->mask = 0xff; 351 | arch_task_init(tcb); 352 | 353 | printk("xos_task_create: tid=%d TCB=%p(%s)\n", tcb->tid, tcb, tcb->name); 354 | 355 | if(task_current==NULL){ 356 | tcb->state = T_RUN; 357 | task_current = tcb; 358 | }else{ 359 | _task_ready(tcb); 360 | _task_switch(0, 0); 361 | } 362 | 363 | return tcb; 364 | } 365 | 366 | 367 | void xos_task_exit(void) 368 | { 369 | int key = spin_lock_irq(); 370 | 371 | task_current->state = T_DEAD; 372 | list_add(&g_list_dead, &task_current->node); 373 | 374 | spin_unlock_irq(key); 375 | _task_switch(0, 1); 376 | } 377 | 378 | 379 | static int cmp_timeout(void *a, void *b) 380 | { 381 | TCB *ta = list_entry(a, TCB, node); 382 | TCB *tb = list_entry(b, TCB, node); 383 | 384 | return (ta->timeout < tb->timeout)? 1: 0; 385 | } 386 | 387 | 388 | void xos_task_delay(int ticks) 389 | { 390 | int key = spin_lock_irq(); 391 | 392 | task_current->state = T_WAIT; 393 | task_current->timeout = g_ticks + ticks; 394 | list_insert_order(&g_list_sleep, &task_current->node, cmp_timeout); 395 | 396 | spin_unlock_irq(key); 397 | _task_switch(0, 1); 398 | } 399 | 400 | 401 | void xos_task_yield(void) 402 | { 403 | int key = spin_lock_irq(); 404 | 405 | task_current->state = T_READY; 406 | 407 | spin_unlock_irq(key); 408 | _task_switch(0, 1); 409 | } 410 | 411 | 412 | /******************************************************************************/ 413 | 414 | void xos_sem_init(SEM *sem, int val) 415 | { 416 | sem->lock = 0; 417 | sem->value = val; 418 | sem->tcb = NULL; 419 | } 420 | 421 | 422 | // 释放信号量。可在中断中调用。 423 | void xos_sem_give(SEM *sem) 424 | { 425 | int key = spin_lock_irq(); 426 | 427 | TCB *tcb = sem->tcb; 428 | sem->tcb = NULL; 429 | if(tcb){ 430 | tcb->retv = 0; 431 | if(tcb->timeout > 0){ 432 | list_remove(&g_list_sleep, &tcb->node); 433 | tcb->timeout = 0; 434 | } 435 | }else{ 436 | atomic_add(&sem->value, 1); 437 | } 438 | 439 | spin_unlock_irq(key); 440 | 441 | if(tcb && tcb->state==T_WAIT){ 442 | _task_ready(tcb); 443 | _task_switch(arch_in_isr(), 0); 444 | } 445 | } 446 | 447 | 448 | // 获取信号量。不可在中断中调用。 449 | int xos_sem_take(SEM *sem, int timeout) 450 | { 451 | 452 | if(sem->value){ 453 | atomic_sub(&sem->value, 1); 454 | return 0; 455 | } 456 | if(timeout==0){ 457 | return -1; 458 | } 459 | 460 | int key = spin_lock_irq(); 461 | 462 | task_current->state = T_WAIT; 463 | 464 | // 再次检查,防止第一次检查到spin_lock之间value改变。 465 | if(sem->value){ 466 | atomic_sub(&sem->value, 1); 467 | task_current->state = T_RUN; 468 | spin_unlock_irq(key); 469 | return 0; 470 | } 471 | 472 | sem->tcb = task_current; 473 | task_current->timeout = 0; 474 | if(timeout>0){ 475 | task_current->timeout = g_ticks + timeout; 476 | task_current->retv = -1; 477 | list_insert_order(&g_list_sleep, &task_current->node, cmp_timeout); 478 | } 479 | 480 | spin_unlock_irq(key); 481 | _task_switch(0, 1); 482 | 483 | return task_current->retv; 484 | } 485 | 486 | 487 | /******************************************************************************/ 488 | 489 | void _log_task(void *arg); 490 | void _pk_putc(int ch); 491 | 492 | static void *_user_entry; 493 | 494 | void _idle_task(void *arg) 495 | { 496 | TCB *tcb = xos_task_self(); 497 | 498 | printk("\n%s running! tcb=%p\n", tcb->name, tcb); 499 | 500 | arch_timer_init(); 501 | 502 | xos_task_create("XosUser", _user_entry, NULL, DEFAULT_TASK_PRIO, 0); 503 | 504 | while(1){ 505 | LIST *list = &g_list_dead; 506 | 507 | int key = spin_lock_irq(); 508 | while(1){ 509 | LIST_NODE *p = list->head; 510 | if(p==NULL) 511 | break; 512 | list_remove(list, p); 513 | TCB *t = list_entry(p, TCB, node); 514 | _task_free(t); 515 | } 516 | 517 | spin_unlock_irq(key); 518 | 519 | arch_idle(); 520 | } 521 | 522 | } 523 | 524 | 525 | void _task_entry(void *arg) 526 | { 527 | TCB *tcb = (TCB*)arg; 528 | tcb->entry(tcb->arg); 529 | xos_task_exit(); 530 | } 531 | 532 | 533 | extern int _heap_start; 534 | extern int _heap_size; 535 | 536 | void xos_init(void *user_entry) 537 | { 538 | _user_entry = user_entry; 539 | g_ticks = 0; 540 | 541 | list_init(&g_list_ready); 542 | list_init(&g_list_sleep); 543 | list_init(&g_list_dead); 544 | 545 | xos_heap_init((u32)&_heap_start, (u32)&_heap_size); 546 | trap_init(); 547 | 548 | TCB *tcb = xos_task_create("IDLE", _idle_task, NULL, MAX_PRIORITY, 0); 549 | arch_set_context(tcb); 550 | } 551 | 552 | -------------------------------------------------------------------------------- /tntfs/Makefile: -------------------------------------------------------------------------------- 1 | 2 | LDIR = tntfs 3 | 4 | LOBJS = fs_fat.o fs_ntfs.o fs_util.o 5 | 6 | OBJS += $(addprefix $(LDIR)/, $(LOBJS)) 7 | 8 | INCDIR += -Itntfs 9 | -------------------------------------------------------------------------------- /tntfs/fs_util.c: -------------------------------------------------------------------------------- 1 | // 2 | // fs_util.c 3 | // 4 | // simple filessytem library 5 | // writen by tpu, 2019-7-1 6 | // 7 | 8 | #include "main.h" 9 | #include "tntfs.h" 10 | 11 | 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | u8 lfn_utf8[256]; 16 | int lfn_utf8_len; 17 | 18 | 19 | int unicode_to_utf8(u16 *u, int ulen, u8 *utf8) 20 | { 21 | u16 uc; 22 | u8 *d = utf8; 23 | int len = 0; 24 | 25 | while(ulen){ 26 | uc = *u++; 27 | ulen--; 28 | if(uc==0) 29 | break; 30 | 31 | if(uc<=0x007f){ 32 | *d++ = uc; 33 | len += 1; 34 | }else if(uc<0x07ff){ 35 | *d++ = 0xc0 | (uc>>6); 36 | *d++ = 0x80 | (uc&0x3f); 37 | len += 2; 38 | }else{ 39 | *d++ = 0xe0 | (uc>>12); 40 | *d++ = 0x80 | ((uc>>6)&0x3f); 41 | *d++ = 0x80 | (uc&0x3f); 42 | len += 3; 43 | } 44 | } 45 | 46 | utf8[len] = 0; 47 | return len; 48 | } 49 | 50 | 51 | u16 le16(void *p) 52 | { 53 | u8 *q = (u8*)p; 54 | return (q[1]<<8) | q[0]; 55 | } 56 | 57 | 58 | u32 le32(void *p) 59 | { 60 | u8 *q = (u8*)p; 61 | return (q[3]<<24) | (q[2]<<16) | (q[1]<<8) | q[0]; 62 | } 63 | 64 | 65 | /******************************************************************************/ 66 | 67 | static BLKDEV *devlist[8]; 68 | static BLKDEV *current_dev; 69 | 70 | u8 sector_buf[512]; 71 | 72 | 73 | int f_initdev(BLKDEV *bdev, char *devname, int index) 74 | { 75 | int i, p, retv; 76 | u32 start, size; 77 | 78 | 79 | for(i=0; i<8; i++){ 80 | if(devlist[i]==NULL){ 81 | devlist[i] = bdev; 82 | break; 83 | } 84 | } 85 | if(i==8){ 86 | return -1; 87 | } 88 | 89 | sprintk(bdev->name, "%s%d", devname, index); 90 | logmsg("\nBlock device %s: %d sectors.\n", bdev->name, bdev->sectors); 91 | 92 | // 先用parts[0]指向整个设备. 93 | bdev->parts[0].lba_start = 0; 94 | bdev->parts[0].lba_size = bdev->sectors; 95 | bdev->parts[1].lba_size = 0; 96 | bdev->parts[2].lba_size = 0; 97 | bdev->parts[3].lba_size = 0; 98 | 99 | retv = bdev->read_sector(bdev->itf, sector_buf, 0, 1); 100 | if(retv) 101 | return retv; 102 | if(sector_buf[510]!=0x55 || sector_buf[511]!=0xAA){ 103 | return 0; 104 | } 105 | 106 | // 扫描4个主分区表项. 当前不支持扩展分区. 107 | p = 0; 108 | for(i=0; i<4; i++){ 109 | u8 *pt = sector_buf+446+i*16; 110 | 111 | // 分区表项可以是全0 112 | if(le32(pt+0)==0 && le32(pt+4)==0 && le32(pt+8)==0 && le32(pt+12)==0) 113 | continue; 114 | 115 | start = le32(pt+8); 116 | size = le32(pt+12); 117 | if((pt[0]&0x7f) || (size==0) || (start > bdev->sectors) || (start+size) > bdev->sectors){ 118 | // 非法的分区表项. 可以认为没有分区表. 119 | return 0; 120 | } 121 | 122 | bdev->parts[p].lba_start = start; 123 | bdev->parts[p].lba_size = size; 124 | p += 1; 125 | logmsg("PART_%d: LBA=%08x SIZE=%08x\n", i, start, size); 126 | } 127 | 128 | return 0; 129 | } 130 | 131 | 132 | int f_removedev(BLKDEV *bdev) 133 | { 134 | int i; 135 | 136 | for(i=0; i<4; i++){ 137 | if(bdev->parts[i].fs){ 138 | f_umount(bdev, i); 139 | } 140 | } 141 | 142 | for(i=0; i<8; i++){ 143 | if(devlist[i]==bdev){ 144 | devlist[i] = NULL; 145 | break; 146 | } 147 | } 148 | 149 | return 0; 150 | } 151 | 152 | 153 | BLKDEV *f_getdev(char *path, int *part, char **rest_path) 154 | { 155 | char devname[8], *p; 156 | BLKDEV *bdev; 157 | int i; 158 | 159 | memcpy(devname, path, 8); 160 | p = strchr(devname, ':'); 161 | if(p==NULL) 162 | return current_dev; 163 | 164 | *p = 0; 165 | p += 1; 166 | 167 | if(*p>='0' && *p<='9'){ 168 | if(part){ 169 | *part = *p - '0'; 170 | } 171 | p += 1; 172 | }else{ 173 | if(part){ 174 | *part = 0; 175 | } 176 | } 177 | 178 | 179 | if(rest_path){ 180 | *rest_path = p; 181 | } 182 | 183 | for(i=0; i<8; i++){ 184 | bdev = devlist[i]; 185 | if(bdev==NULL) 186 | continue; 187 | 188 | if(strcmp(devname, bdev->name)==0){ 189 | return bdev; 190 | } 191 | } 192 | 193 | return NULL; 194 | } 195 | 196 | 197 | FSDESC *f_getfs(char *path, char **rest_path) 198 | { 199 | BLKDEV *bdev; 200 | int part = 0; 201 | 202 | bdev = f_getdev(path, &part, rest_path); 203 | if(bdev==NULL) 204 | return NULL; 205 | 206 | if(part>3) 207 | return NULL; 208 | 209 | return bdev->parts[part].fs; 210 | } 211 | 212 | 213 | /******************************************************************************/ 214 | 215 | 216 | static FSD f_find(FSDESC *cfs, char *file) 217 | { 218 | char tbuf[128], *p, *n; 219 | FSD dir; 220 | 221 | if(file==NULL) 222 | return NULL; 223 | 224 | strcpy(tbuf, file); 225 | p = tbuf; 226 | if(*p=='/') 227 | p++; 228 | 229 | dir = NULL; 230 | while(1){ 231 | n = strchr(p, '/'); 232 | if(n){ 233 | *n = 0; 234 | n += 1; 235 | } 236 | 237 | dir = cfs->find(cfs->super, dir, p, n, 0); 238 | if(dir==NULL) 239 | return NULL; 240 | 241 | if(n==NULL || *n==0) 242 | break; 243 | p = n; 244 | } 245 | 246 | return dir; 247 | } 248 | 249 | int f_list(char *file) 250 | { 251 | char *p; 252 | FSD fsd; 253 | FSDESC *cfs; 254 | 255 | logmsg("List %s\n", file); 256 | 257 | cfs = f_getfs(file, &file); 258 | if(cfs==NULL) 259 | return -ENODEV; 260 | 261 | p = file; 262 | if(p && *p=='/') 263 | p++; 264 | 265 | if(p==NULL || *p==0){ 266 | fsd= 0; // list root 267 | }else{ 268 | fsd = f_find(cfs, file); 269 | if(fsd==NULL) 270 | return 0; 271 | } 272 | 273 | fsd = cfs->find(cfs->super, fsd, NULL, NULL, 1); 274 | logmsg(" Total %4d Files\n", (int)fsd); 275 | 276 | return (int)fsd; 277 | } 278 | 279 | int f_stat(char *file, STAT_T *st) 280 | { 281 | FSD fsd; 282 | FSDESC *cfs; 283 | 284 | cfs = f_getfs(file, &file); 285 | if(cfs==NULL) 286 | return -ENODEV; 287 | 288 | fsd = f_find(cfs, file); 289 | if(fsd) 290 | return cfs->stat(cfs->super, fsd, st); 291 | 292 | return -ENOENT; 293 | } 294 | 295 | 296 | FD f_open(char *file) 297 | { 298 | FSD fsd; 299 | FSDESC *cfs; 300 | 301 | cfs = f_getfs(file, &file); 302 | if(cfs==NULL) 303 | return (void*)-ENODEV; 304 | 305 | fsd = f_find(cfs, file); 306 | if(fsd==NULL) 307 | return (void*)-ENOENT; 308 | 309 | cfs->fsd = fsd; 310 | cfs->open(cfs->super, fsd); 311 | 312 | return &cfs->fsd; 313 | } 314 | 315 | 316 | static FSDESC *fd2fs(FD fd) 317 | { 318 | return (FSDESC*)( (u32)fd - (u32)&((FSDESC*)0)->fsd ); 319 | } 320 | 321 | 322 | int f_close(FD fd) 323 | { 324 | FSDESC *cfs = fd2fs(fd); 325 | return cfs->close(cfs->super, (FSD)*fd); 326 | } 327 | 328 | 329 | SIZE_T f_lseek(FD fd, SIZE_T offset, int whence) 330 | { 331 | FSDESC *cfs = fd2fs(fd); 332 | return cfs->lseek(cfs->super, (FSD)*fd, offset, whence); 333 | } 334 | 335 | 336 | int f_read(FD fd, void *buf, int size) 337 | { 338 | FSDESC *cfs = fd2fs(fd); 339 | return cfs->read(cfs->super, (FSD)*fd, buf, size); 340 | } 341 | 342 | 343 | int f_write(FD fd, void *buf, int size) 344 | { 345 | FSDESC *cfs = fd2fs(fd); 346 | return cfs->write(cfs->super, (FSD)*fd, buf, size); 347 | } 348 | 349 | 350 | /******************************************************************************/ 351 | 352 | extern FSDESC fs_fat; 353 | extern FSDESC fs_ntfs; 354 | 355 | FSDESC *fs_list[] = { 356 | &fs_fat, 357 | &fs_ntfs, 358 | NULL, 359 | }; 360 | 361 | 362 | int f_mount(BLKDEV *bdev, int part) 363 | { 364 | FSDESC *cfs, *newfs; 365 | void *fs_super; 366 | int i; 367 | 368 | if(part>3) 369 | return -EINVAL; 370 | 371 | for(i=0;;i++){ 372 | cfs = fs_list[i]; 373 | if(cfs==NULL) 374 | break; 375 | 376 | fs_super = cfs->mount(bdev, part); 377 | if(fs_super) 378 | break; 379 | } 380 | if(fs_super==NULL) 381 | return -ENOSYS; 382 | 383 | newfs = (FSDESC*)FS_MALLOC(sizeof(FSDESC)); 384 | memcpy(newfs, cfs, sizeof(FSDESC)); 385 | newfs->super = fs_super; 386 | bdev->parts[part].fs = newfs; 387 | 388 | return 0; 389 | } 390 | 391 | 392 | int f_umount(BLKDEV *bdev, int part) 393 | { 394 | FSDESC *cfs; 395 | 396 | if(part>3) 397 | return -EINVAL; 398 | 399 | cfs = bdev->parts[part].fs; 400 | cfs->umount(cfs->super); 401 | FS_FREE(cfs); 402 | 403 | bdev->parts[part].fs = NULL; 404 | 405 | return 0; 406 | } 407 | 408 | 409 | /******************************************************************************/ 410 | 411 | 412 | -------------------------------------------------------------------------------- /tntfs/tntfs.h: -------------------------------------------------------------------------------- 1 | 2 | //#include 3 | //#include 4 | #include "main.h" 5 | #include "xos.h" 6 | 7 | /******************************************************************************/ 8 | 9 | #if 0 10 | typedef unsigned char u8; 11 | typedef unsigned short u16; 12 | typedef unsigned int u32; 13 | typedef unsigned long long u64; 14 | typedef long long s64; 15 | #endif 16 | 17 | //#define SIZE_T long long 18 | #define SIZE_T int 19 | 20 | 21 | int printk(char *fmt, ...); 22 | #define logmsg(...) printk(__VA_ARGS__) 23 | #define logerr(...) printk(__VA_ARGS__) 24 | 25 | 26 | #define FS_MALLOC(s) xos_malloc(s) 27 | #define FS_FREE(s) xos_free(s) 28 | 29 | 30 | /******************************************************************************/ 31 | 32 | 33 | extern u8 lfn_utf8[256]; 34 | extern int lfn_utf8_len; 35 | 36 | 37 | int unicode_to_utf8(u16 *u, int ulen, u8 *utf8); 38 | 39 | u16 le16(void *p); 40 | u32 le32(void *p); 41 | 42 | /******************************************************************************/ 43 | 44 | #define ENOENT 2 45 | #define EIO 5 46 | #define EBADF 9 47 | #define ENOMEM 12 48 | #define EACCES 13 49 | #define EFAULT 14 50 | #define ENODEV 19 51 | #define EINVAL 22 52 | #define ENOSYS 88 53 | 54 | 55 | 56 | typedef struct _partition_t 57 | { 58 | u32 lba_start; 59 | u32 lba_size; 60 | struct _filesystem_t *fs; 61 | }PARTITION; 62 | 63 | 64 | typedef struct _block_t 65 | { 66 | char name[8]; 67 | int sectors; 68 | 69 | PARTITION parts[4]; 70 | 71 | void *itf; 72 | int (*read_sector )(void *itf, u8 *buf, u32 start, int size); 73 | int (*write_sector)(void *itf, u8 *buf, u32 start, int size); 74 | }BLKDEV; 75 | 76 | 77 | #define SEEK_SET 0 78 | #define SEEK_CUR 1 79 | #define SEEK_END 2 80 | 81 | 82 | #define S_DIR 0x10000000 83 | #define S_RDONLY 0x00000001 84 | #define S_HIDDEN 0x00000002 85 | #define S_SYSTEM 0x00000004 86 | #define S_ARCHIVE 0x00000020 87 | 88 | 89 | typedef struct { 90 | u16 year; 91 | u8 mon, d; 92 | u8 h, m, s; 93 | u8 pad; 94 | }TIME; 95 | 96 | 97 | typedef struct _stat_t 98 | { 99 | SIZE_T size; 100 | TIME mtime; 101 | TIME ctime; 102 | int flags; 103 | }STAT_T; 104 | 105 | 106 | typedef void* FSD; 107 | typedef void** FD; 108 | 109 | 110 | typedef struct _filesystem_t 111 | { 112 | char *name; 113 | 114 | void *(*mount)(BLKDEV *bdev, int part); 115 | int (*umount)(void *fs_super); 116 | FSD (*find) (void *fs_super, FSD fsd, char *name, char *next, int do_list); 117 | int (*stat) (void *fs_super, FSD fsd, STAT_T *st); 118 | int (*open) (void *fs_super, FSD fsd); 119 | int (*close)(void *fs_super, FSD fsd); 120 | SIZE_T (*lseek)(void *fs_super, FSD fsd, SIZE_T offset, int whence); 121 | int (*read) (void *fs_super, FSD fsd, void *buf, int size); 122 | int (*write)(void *fs_super, FSD fsd, void *buf, int size); 123 | 124 | void *super; 125 | FSD fsd; 126 | 127 | }FSDESC; 128 | 129 | 130 | int f_list(char *file); 131 | int f_stat(char *file, STAT_T *st); 132 | FD f_open(char *file); 133 | int f_close(FD fd); 134 | SIZE_T f_lseek(FD, SIZE_T offset, int whence); 135 | int f_read (FD, void *buf, int size); 136 | int f_write(FD, void *buf, int size); 137 | 138 | int f_mount(BLKDEV *bdev, int part); 139 | int f_umount(BLKDEV *bdev, int part); 140 | 141 | int f_initdev(BLKDEV *bdev, char *devname, int index); 142 | int f_removedev(BLKDEV *bdev); 143 | 144 | --------------------------------------------------------------------------------